Last active
July 5, 2018 14:58
-
-
Save gfrison/276b4a50c1c0acfa8019c9b5d2b0d5ab to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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