docs: public EvolutionResult<G, C> evolve(final EvolutionStart<G, C> start) {
  		final Timer timer = Timer.of(_clock).start();
  
  		// Initial evaluation of the population.
  		final Timer evaluateTimer = Timer.of(_clock).start();
  		final ISeq<Phenotype<G, C>> evalPop =
  			_evaluator.evaluate(start.getPopulation());
  
  		if (start.getPopulation().size() != evalPop.size()) {
  			throw new IllegalStateException(format(
  				"Expected %d individuals, but got %d. " +
  				"Check your evaluator function.",
  				start.getPopulation().size(), evalPop.size()
  			));
  		}
  
  		evaluateTimer.stop();
  
  		// Select the offspring population.
  		final CompletableFuture<TimedResult<ISeq<Phenotype<G, C>>>> offspring =
  			_executor.async(() ->
  				selectOffspring(evalPop),
  				_clock
  			);
  
  		// Select the survivor population.
  		final CompletableFuture<TimedResult<ISeq<Phenotype<G, C>>>> survivors =
  			_executor.async(() ->
  				selectSurvivors(evalPop),
  				_clock
  			);
  
  		// Altering the offspring population.
  		final CompletableFuture<TimedResult<AltererResult<G, C>>> alteredOffspring =
  			_executor.thenApply(offspring, p ->
  				_alterer.alter(p.result, start.getGeneration()),
  				_clock
  			);
  
  		// Filter and replace invalid and old survivor individuals.
  		final CompletableFuture<TimedResult<FilterResult<G, C>>> filteredSurvivors =
  			_executor.thenApply(survivors, pop ->
  				filter(pop.result, start.getGeneration()),
  				_clock
  			);
  
  		// Filter and replace invalid and old offspring individuals.
  		final CompletableFuture<TimedResult<FilterResult<G, C>>> filteredOffspring =
  			_executor.thenApply(alteredOffspring, pop ->
  				filter(pop.result.getPopulation(), start.getGeneration()),
  				_clock
  			);
  
  		// Combining survivors and offspring to the new population.
  		final CompletableFuture<ISeq<Phenotype<G, C>>> population =
  			filteredSurvivors.thenCombineAsync(filteredOffspring, (s, o) ->
  					ISeq.of(s.result.population.append(o.result.population)),
  				_executor.get()
  			);
  
  		// Evaluate the fitness-function and wait for result.
  		final ISeq<Phenotype<G, C>> pop = population.join();
  		final TimedResult<ISeq<Phenotype<G, C>>> result = TimedResult
  			.of(() -> _evaluator.evaluate(pop), _clock)
  			.get();
  
  
  		final EvolutionDurations durations = EvolutionDurations.of(
  			offspring.join().duration,
  			survivors.join().duration,
  			alteredOffspring.join().duration,
  			filteredOffspring.join().duration,
  			filteredSurvivors.join().duration,
  			result.duration.plus(evaluateTimer.getTime()),
  			timer.stop().getTime()
  		);
  
  		final int killCount =
  			filteredOffspring.join().result.killCount +
  			filteredSurvivors.join().result.killCount;
  
  		final int invalidCount =
  			filteredOffspring.join().result.invalidCount +
  			filteredSurvivors.join().result.invalidCount;
  
  		return _mapper.apply(
  			EvolutionResult.of(
  				_optimize,
  				result.result,
  				start.getGeneration(),
  				durations,
  				killCount,
  				invalidCount,
  				alteredOffspring.join().result.getAlterations()
  			)
  		);
  	}