Interface EvolutionStream<G extends Gene<?,G>,C extends Comparable<? super C>>

All Superinterfaces:
AutoCloseable, BaseStream<EvolutionResult<G,C>,Stream<EvolutionResult<G,C>>>, Stream<EvolutionResult<G,C>>

public interface EvolutionStream<G extends Gene<?,G>,C extends Comparable<? super C>> extends Stream<EvolutionResult<G,C>>
The EvolutionStream class extends the Java Stream and adds a method for limiting the evolution by a given predicate.
Since:
3.0
Version:
6.0
See Also:
Implementation Note:
Collecting an empty EvolutionStream will return null.
final EvolutionResult<DoubleGene, Double> result = engine.stream()
    .limit(0)
    .collect(toBestEvolutionResult());

assert result == null;
  • Method Details

    • limit

      Returns a stream consisting of the elements of this stream, truncated when the given proceed predicate returns false.

      General usage example:

      final Phenotype<DoubleGene, Double> result = engine.stream()
           // Truncate the evolution stream after 5 "steady" generations.
          .limit(bySteadyFitness(5))
           // The evolution will stop after maximal 100 generations.
          .limit(100)
          .collect(toBestPhenotype());
      
      Note: The evolution result may be null, if your truncation predicate returns false for the initial population.
      final EvolutionResult<DoubleGene, Double> result = engine.stream()
          .limit(er -> false)
          .collect(toBestEvolutionResult());
      
      assert result == null;
      
      Parameters:
      proceed - the predicate which determines whether the stream is truncated or not. If the predicate returns false, the evolution stream is truncated.
      Returns:
      the new stream
      Throws:
      NullPointerException - if the given predicate is null.
      See Also:
    • ofEvolution

      static <G extends Gene<?, G>, C extends Comparable<? super C>> EvolutionStream<G,C> ofEvolution(Supplier<EvolutionStart<G,C>> start, Evolution<G,C> evolution)
      Create a new EvolutionStream from the given start population and evolution function. The main purpose of this factory method is to simplify the creation of an EvolutionStream from an own evolution (GA) engine.
      final Supplier<EvolutionStart<DoubleGene, Double>> start = ...;
      final EvolutionStream<DoubleGene, Double> stream =
          EvolutionStream.of(start, new MySpecialEngine());
      
      A more complete example for would look like as:
      public final class SpecialEngine {
      
          // The fitness function.
          private static Double fitness(final Genotype<DoubleGene> gt) {
              return gt.gene().allele();
          }
      
          // Create a new evolution start object.
          private static EvolutionStart<DoubleGene, Double>
          start(final int populationSize, final long generation) {
              final Population<DoubleGene, Double> population =
                  Genotype.of(DoubleChromosome.of(0, 1)).instances()
                      .map(gt -> Phenotype.of(gt, generation, SpecialEngine::fitness))
                      .limit(populationSize)
                      .collect(Population.toPopulation());
      
              return EvolutionStart.of(population, generation);
          }
      
          // The special evolution function.
          private static EvolutionResult<DoubleGene, Double>
          evolve(final EvolutionStart<DoubleGene, Double> start) {
              // Your special evolution implementation comes here!
              return null;
          }
      
          public static void main(final String[] args) {
              final Genotype<DoubleGene> best = EvolutionStream
                  .ofEvolution(() -> start(50, 0), SpecialEngine::evolve)
                  .limit(Limits.bySteadyFitness(10))
                  .limit(1000)
                  .collect(EvolutionResult.toBestGenotype());
      
              System.out.println(String.format("Best Genotype: %s", best));
          }
      }
      
      Type Parameters:
      G - the gene type
      C - the fitness type
      Parameters:
      start - the evolution start
      evolution - the evolution function
      Returns:
      a new EvolutionStream with the given start and evolution function
      Throws:
      NullPointerException - if one of the arguments is null
      Since:
      5.1
      See Also:
    • ofAdjustableEvolution

      static <G extends Gene<?, G>, C extends Comparable<? super C>> EvolutionStream<G,C> ofAdjustableEvolution(Supplier<EvolutionStart<G,C>> start, Function<? super EvolutionStart<G,C>,? extends Evolution<G,C>> evolution)
      Create a new evolution stream with an adjustable evolution function.
      public static void main(final String[] args) {
          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)
          );
      
          // Engine builder template.
          final Engine.Builder<DoubleGene, Double> builder = Engine
              .builder(problem)
              .minimizing();
      
          // Evolution used for low fitness variance.
          final Evolution<DoubleGene, Double> lowVar = builder.copy()
              .alterers(new Mutator<>(0.5))
              .selector(new MonteCarloSelector<>())
              .build();
      
          // Evolution used for high fitness variance.
          final Evolution<DoubleGene, Double> highVar = builder.copy()
              .alterers(
                  new Mutator<>(0.05),
                  new MeanAlterer<>())
              .selector(new RouletteWheelSelector<>())
              .build();
      
          final EvolutionStream<DoubleGene, Double> stream =
              EvolutionStream.ofAdjustableEvolution(
                  EvolutionStart::empty,
                  er -> var(er) < 0.2 ? lowVar : highVar
              );
      
          final Genotype<DoubleGene> result = stream
              .limit(Limits.bySteadyFitness(50))
              .collect(EvolutionResult.toBestGenotype());
      
          System.out.println(result + ": " +
              problem.fitness().apply(problem.codec().decode(result)));
      }
      
      private static double var(final EvolutionStart<DoubleGene, Double> result) {
          return result != null
              ? result.getPopulation().stream()
                  .map(Phenotype::fitness)
                  .collect(DoubleMoments.toDoubleMoments())
                  .variance()
              : 0.0;
      }
      
      Type Parameters:
      G - the gene type
      C - the fitness type
      Parameters:
      start - the evolution start object
      evolution - the adaptable evolution function
      Returns:
      a new EvolutionStream with the given start and evolution function
      Throws:
      NullPointerException - if one of the arguments is null
      See Also: