Class ConcatEngine<G extends Gene<?,​G>,​C extends Comparable<? super C>>

  • Type Parameters:
    G - the gene type
    C - the fitness type
    All Implemented Interfaces:
    EvolutionStreamable<G,​C>

    public final class ConcatEngine<G extends Gene<?,​G>,​C extends Comparable<? super C>>
    extends Object
    The ConcatEngine lets you concatenate two (or more) evolution Engine, with different configurations, and let it use as one engine EvolutionStreamable.
     
                      +----------+               +----------+
                      |       ES |               |       ES |
              +-------+----+     |       +-------+----+     |
      (Start) |            +-----+ Start |            +-----+
       ------>|  Engine 1  |------------>|  Engine 2  |----------->
              |            | Result      |            |      Result
              +------------+             +------------+
     
    The sketch above shows how the engine concatenation works. In this example, the evolution stream of the first engine is evaluated until it terminates. The result of the first stream is then used as start input of the second evolution stream, which then delivers the final result.

    Concatenating evolution engines might be useful, if you want to explore your search space with random search first and then start the real GA search.

    final Problem<double[], DoubleGene, Double> problem = Problem.of( v -> Math.sin(v[0])*Math.cos(v[1]), Codecs.ofVector(DoubleRange.of(0, 2*Math.PI), 2) ); final Engine<DoubleGene, Double> engine1 = Engine.builder(problem) .minimizing() .alterers(new Mutator<>(0.2)) .selector(new MonteCarloSelector<>()) .build(); final Engine<DoubleGene, Double> engine2 = Engine.builder(problem) .minimizing() .alterers( new Mutator<>(0.1), new MeanAlterer<>()) .selector(new RouletteWheelSelector<>()) .build(); final Genotype<DoubleGene> result = ConcatEngine.of( engine1.limit(50), engine2.limit(() -> Limits.bySteadyFitness(30))) .stream() .collect(EvolutionResult.toBestGenotype()); System.out.println(result + ": " + problem.fitness().apply(problem.codec().decode(result)));
    An essential part, when concatenating evolution engines, is to make sure your your engines are creating limited evolution streams. This is what the EvolutionStreamable.limit(Supplier) and EvolutionStreamable.limit(long) methods are for. Limiting an engine means, that this engine will surely create only streams, which are limited with the predicate/generation given to the engine. If you have limited your engines, it is no longer necessary to limit your final evolution stream, but your are still able to do so.
    Since:
    4.1
    Version:
    4.1
    See Also:
    CyclicEngine