Skip to content

Instantly share code, notes, and snippets.

@gfrison
Last active July 5, 2018 14:58
Show Gist options
  • Save gfrison/276b4a50c1c0acfa8019c9b5d2b0d5ab to your computer and use it in GitHub Desktop.
Save gfrison/276b4a50c1c0acfa8019c9b5d2b0d5ab to your computer and use it in GitHub Desktop.
static class CacheOp implements Op<Double> {
private final AtomicDouble ref;
public CacheOp(int i) {
ref = new AtomicDouble(i);
}
public CacheOp() {
this(0);
}
@Override
public String name() {
return "cache";
}
@Override
public int arity() {
return 1;
}
@Override
public Op<Double> get() {
return new CacheOp();
}
@Override
public Double apply(Double[] ts) {
return ref.getAndSet(ts[0]);
}
@Override
public String toString() {
return name();
}
public void reset() {
ref.set(0);
}
}
static final ISeq<Op<Double>> operations = ISeq.of(MathOp.ADD, MathOp.SUB, MathOp.MUL, MathOp.MAX, MathOp.MIN, MathOp.DIV, new CacheOp());
static final ISeq<Op<Double>> terminals = ISeq.of(Var.of("x", 0));
final static int seqLength = 3;
public static void main(String[] args) {
Engine<ProgramGene<Double>, Double> engine = Engine.builder(NumCollector::error, Codec.of(
Genotype.of(ProgramChromosome.of(
seqLength + 1,
ch -> ch.getRoot().size() <= seqLength * 2
&& ch.getTerminals().stream().filter(op -> op instanceof Var).count() > 0,
operations,
terminals
)), gt -> gt.toSeq().map(Chromosome::getGene)
))
.minimizing()
.alterers(new SingleNodeCrossover<>(),
new Mutator<>(),
new MathTreePruneAlterer<>(0.5))
.build();
Genotype<ProgramGene<Double>> p = engine.stream()
.limit(600000)
.collect(EvolutionResult.toBestGenotype());
ProgramGene<Double> g = p.getGene();
//reset all cache instances to zero.
g.breadthFirstStream().forEach(pg -> {
if (pg.getValue() instanceof CacheOp) {
((CacheOp) pg.getValue()).reset();
}
});
p.stream().map(Chromosome::getGene)
.map(Tree::toCompactString)
.forEach(s -> System.out.printf("gene:%s\n", s));
AtomicInteger c = new AtomicInteger();
Random rnd = RandomRegistry.getRandom();
range(0, seqLength)
.map(i -> rnd.nextInt(100))
.forEach(i -> {
long eval = round(Program.eval(g, (double) i));
System.out.printf("n:%s, predict:%s, actual:%s\n", i, eval, c.addAndGet(i));
});
}
static Random rnd = RandomRegistry.getRandom();
private static double error(final ISeq<Tree<Op<Double>, ?>> programs) {
Tree<Op<Double>, ?> g = programs.get(0);
Set<CacheOp> caches = g.breadthFirstStream()
.filter(s -> s.getClass().equals(CacheOp.class))
.map(x -> (CacheOp) x)
.collect(Collectors.toSet());
return range(0, 3)
.mapToDouble(b -> {
//reset all cache instances to zero.
caches.forEach(CacheOp::reset);
AtomicInteger c = new AtomicInteger();
double ret = range(0, seqLength)
.mapToDouble(i -> {
int r = rnd.nextInt(1000);
double eval = Program.eval(g, (double) r);
final int i2 = c.addAndGet(r);
final double err = pow(i2 - eval, 2) * 10 * (seqLength - i);
return err;
}).sum();
return ret;
}).sum();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment