@Override
	public EvolutionResult<G, C> evolve(final EvolutionStart<G, C> start) {
		final EvolutionTiming timing = new EvolutionTiming(_clock);
		timing.evolve.start();

		final EvolutionStart<G, C> interceptedStart = _interceptor.before(start);

		// Create initial population if `start` is empty.
		final EvolutionStart<G, C> es = interceptedStart.population().isEmpty()
			? evolutionStart(interceptedStart)
			: interceptedStart;

		// Initial evaluation of the population.
		final ISeq<Phenotype<G, C>> population = es.isDirty()
			? timing.evaluation.timing(() -> eval(es.population()))
			: es.population();

		// Select the offspring population.
		final CompletableFuture<ISeq<Phenotype<G, C>>> offspring =
			supplyAsync(() ->
				timing.offspringSelection.timing(() ->
					selectOffspring(population)
				),
				_executor
			);

		// Select the survivor population.
		final CompletableFuture<ISeq<Phenotype<G, C>>> survivors =
			supplyAsync(() ->
				timing.survivorsSelection.timing(() ->
					selectSurvivors(population)
				),
				_executor
			);

		// Altering the offspring population.
		final CompletableFuture<AltererResult<G, C>> alteredOffspring =
			offspring.thenApplyAsync(off ->
				timing.offspringAlter.timing(() ->
					_evolutionParams.alterer().alter(off, es.generation())
				),
				_executor
			);

		// Filter and replace invalid and old survivor individuals.
		final CompletableFuture<FilterResult<G, C>> filteredSurvivors =
			survivors.thenApplyAsync(sur ->
				timing.survivorFilter.timing(() ->
					filter(sur, es.generation())
				),
				_executor
			);

		// Filter and replace invalid and old offspring individuals.
		final CompletableFuture<FilterResult<G, C>> filteredOffspring =
			alteredOffspring.thenApplyAsync(off ->
				timing.offspringFilter.timing(() ->
					filter(off.population(), es.generation())
				),
				_executor
			);

		// Combining survivors and offspring to the new population.
		final CompletableFuture<ISeq<Phenotype<G, C>>> nextPopulation =
			filteredSurvivors.thenCombineAsync(
				filteredOffspring,
				(s, o) -> ISeq.of(s.population().append(o.population())),
				_executor
			);

		// Evaluate the fitness-function and wait for a result.
		final ISeq<Phenotype<G, C>> pop = nextPopulation.join();
		final ISeq<Phenotype<G, C>> result = timing.evaluation.timing(() ->
			eval(pop)
		);

		final int killCount =
			filteredOffspring.join().killCount() +
			filteredSurvivors.join().killCount();

		final int invalidCount =
			filteredOffspring.join().invalidCount() +
			filteredSurvivors.join().invalidCount();

		final int alterationCount = alteredOffspring.join().alterations();

		EvolutionResult<G, C> er = EvolutionResult.of(
			_optimize,
			result,
			es.generation(),
			timing.toDurations(),
			killCount,
			invalidCount,
			alterationCount
		);

		final EvolutionResult<G, C> interceptedResult = _interceptor.after(er);
		if (er != interceptedResult) {
			er = interceptedResult.withPopulation(
				timing.evaluation.timing(() ->
					eval(interceptedResult.population())
			));
		}

		timing.evolve.stop();

		return er
			.withDurations(timing.toDurations())
			.clean();
	}
Create a new GA engine with the given parameters.

@param evaluator the population fitness evaluator
@param genotypeFactory the genotype factory this GA is working with.
@param constraint phenotype constraint which can override the default
       implementation the {@link Phenotype#isValid()} method and repairs
       invalid phenotypes when needed.
@param optimize the kind of optimization (minimize or maximize)
@param evolutionParams the evolution parameters, which influences the
       evolution process
@param executor the executor used for executing the single evolved steps
@param clock the clock used for calculating the timing results
@param interceptor the evolution interceptor, which gives additional
       possibilities to influence the actual evolution
@throws NullPointerException if one of the arguments is {@code null}
@throws IllegalArgumentException if the given integer values are smaller
        than one.
jenetics/src/main/java/io/jenetics/engine/Engine.java