AbstractEAExecutionContext.java

package net.bmahe.genetics4j.core.spec;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ServiceLoader;
import java.util.random.RandomGenerator;

import org.immutables.value.Value;

import net.bmahe.genetics4j.core.chromosomes.Chromosome;
import net.bmahe.genetics4j.core.chromosomes.factory.ChromosomeFactoryProvider;
import net.bmahe.genetics4j.core.chromosomes.factory.ImmutableChromosomeFactoryProvider;
import net.bmahe.genetics4j.core.combination.ChromosomeCombinatorHandler;
import net.bmahe.genetics4j.core.combination.PickFirstParentHandler;
import net.bmahe.genetics4j.core.combination.erx.EdgeRecombinationCrossoverHandler;
import net.bmahe.genetics4j.core.combination.multicombinations.MultiCombinationsHandler;
import net.bmahe.genetics4j.core.combination.multipointarithmetic.MultiPointArithmeticCombinationHandler;
import net.bmahe.genetics4j.core.combination.multipointcrossover.MultiPointCrossoverCombinationHandler;
import net.bmahe.genetics4j.core.combination.ordercrossover.IntOrderCrossoverHandler;
import net.bmahe.genetics4j.core.combination.singlepointarithmetic.SinglePointArithmeticCombinationHandler;
import net.bmahe.genetics4j.core.combination.singlepointcrossover.SinglePointCrossoverHandler;
import net.bmahe.genetics4j.core.evolutionlisteners.EvolutionListener;
import net.bmahe.genetics4j.core.mutation.CreepMutationPolicyHandler;
import net.bmahe.genetics4j.core.mutation.MultiMutationsPolicyHandler;
import net.bmahe.genetics4j.core.mutation.MutationPolicyHandler;
import net.bmahe.genetics4j.core.mutation.PartialMutationPolicyHandler;
import net.bmahe.genetics4j.core.mutation.RandomMutationPolicyHandler;
import net.bmahe.genetics4j.core.mutation.SwapMutationPolicyHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.ChromosomeMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.ChromosomeMutationHandlerFactory;
import net.bmahe.genetics4j.core.mutation.chromosome.creepmutation.DoubleChromosomeCreepMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.creepmutation.FloatChromosomeCreepMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.creepmutation.IntChromosomeCreepMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.randommutation.BitChromosomeRandomMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.randommutation.DoubleChromosomeRandomMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.randommutation.FloatChromosomeRandomMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.randommutation.IntChromosomeRandomMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.swapmutation.BitChromosomeSwapMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.swapmutation.DoubleChromosomeSwapMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.swapmutation.FloatChromosomeSwapMutationHandler;
import net.bmahe.genetics4j.core.mutation.chromosome.swapmutation.IntChromosomeSwapMutationHandler;
import net.bmahe.genetics4j.core.replacement.ElitismReplacementStrategyHandler;
import net.bmahe.genetics4j.core.replacement.GenerationalReplacementStrategyHandler;
import net.bmahe.genetics4j.core.replacement.ReplacementStrategyHandler;
import net.bmahe.genetics4j.core.selection.MultiSelectionsPolicyHandler;
import net.bmahe.genetics4j.core.selection.MultiTournamentsSelectionPolicyHandler;
import net.bmahe.genetics4j.core.selection.ProportionalTournamentSelectionPolicyHandler;
import net.bmahe.genetics4j.core.selection.RandomSelectionPolicyHandler;
import net.bmahe.genetics4j.core.selection.SelectAllPolicyHandler;
import net.bmahe.genetics4j.core.selection.SelectionPolicyHandler;
import net.bmahe.genetics4j.core.selection.SelectiveRefinementTournamentPolicyHandler;
import net.bmahe.genetics4j.core.selection.TournamentSelectionPolicyHandler;

/**
 * Evolutionary Algorithm - Execution Context
 * <p>This defines how the Evolutionary Algorithm will be executed.
 *
 * @param <T> Type of the fitness measurement
 */
public abstract class AbstractEAExecutionContext<T extends Comparable<T>> {
	public static final int DEFAULT_POPULATION_SIZE = 100;

	@Value.Default
	public List<ChromosomeCombinatorHandler<T>> defaultChromosomeCombinatorHandlers() {
		return Arrays.asList(
				new MultiCombinationsHandler<T>(randomGenerator()),
					new IntOrderCrossoverHandler<T>(randomGenerator()),
					new MultiPointCrossoverCombinationHandler<T>(randomGenerator()),
					new MultiPointArithmeticCombinationHandler<T>(randomGenerator()),
					new SinglePointCrossoverHandler<T>(randomGenerator()),
					new SinglePointArithmeticCombinationHandler<T>(randomGenerator()),
					new EdgeRecombinationCrossoverHandler<T>(randomGenerator()),
					new PickFirstParentHandler<T>());
	}

	public abstract List<ChromosomeCombinatorHandlerFactory<T>> chromosomeCombinatorHandlerFactories();

	@SuppressWarnings("unchecked")
	@Value.Derived
	public List<ChromosomeCombinatorHandler<T>> chromosomeCombinatorHandlers() {

		final List<ChromosomeCombinatorHandler<T>> chromosomeCombinatorHandlers = new ArrayList<>();

		final List<ChromosomeCombinatorHandler<T>> defaultChromosomeCombinatorHandlers = defaultChromosomeCombinatorHandlers();
		if (defaultChromosomeCombinatorHandlers.isEmpty() == false) {
			chromosomeCombinatorHandlers.addAll(defaultChromosomeCombinatorHandlers);
		}

		chromosomeCombinatorHandlerFactories().stream()
				.map(factory -> factory.apply(this))
				.forEach(cch -> chromosomeCombinatorHandlers.add(cch));

		@SuppressWarnings("rawtypes")
		final ServiceLoader<ChromosomeCombinatorHandlerFactory> serviceLoader = ServiceLoader
				.load(ChromosomeCombinatorHandlerFactory.class);

		serviceLoader.stream()
				.map(provider -> provider.get())
				.map(factory -> (ChromosomeCombinatorHandler<T>) factory.apply(this))
				.forEach(cch -> chromosomeCombinatorHandlers.add(cch));

		return Collections.unmodifiableList(chromosomeCombinatorHandlers);
	}

	/////////////////////////////////////////

	/**
	 * Default list of SelectionPolicyHandler
	 */
	@Value.Default
	public List<SelectionPolicyHandler<T>> defaultSelectionPolicyHandlers() {
		return Arrays.asList(
				new RandomSelectionPolicyHandler<T>(randomGenerator()),
					new TournamentSelectionPolicyHandler<T>(randomGenerator()),
					new ProportionalTournamentSelectionPolicyHandler<T>(randomGenerator()),
					new MultiTournamentsSelectionPolicyHandler<T>(randomGenerator()),
					new MultiSelectionsPolicyHandler<T>(),
					new SelectAllPolicyHandler<T>(),
					new SelectiveRefinementTournamentPolicyHandler<T>(randomGenerator()));
	}

	public abstract List<SelectionPolicyHandlerFactory<T>> selectionPolicyHandlerFactories();

	@SuppressWarnings("unchecked")
	@Value.Derived
	public List<SelectionPolicyHandler<T>> selectionPolicyHandlers() {

		final List<SelectionPolicyHandler<T>> selectionPolicyHandlers = new ArrayList<>();

		final List<SelectionPolicyHandler<T>> defaultSelectionPolicyHandlers = defaultSelectionPolicyHandlers();
		if (defaultSelectionPolicyHandlers.isEmpty() == false) {
			selectionPolicyHandlers.addAll(defaultSelectionPolicyHandlers);
		}

		selectionPolicyHandlerFactories().stream()
				.map(factory -> factory.apply(this))
				.forEach(sph -> selectionPolicyHandlers.add(sph));

		@SuppressWarnings("rawtypes")
		final ServiceLoader<SelectionPolicyHandlerFactory> serviceLoader = ServiceLoader
				.load(SelectionPolicyHandlerFactory.class);

		serviceLoader.stream()
				.map(provider -> provider.get())
				.map(factory -> (SelectionPolicyHandler<T>) factory.apply(this))
				.forEach(cch -> selectionPolicyHandlers.add(cch));

		return Collections.unmodifiableList(selectionPolicyHandlers);
	}

	/////////////////////////////////////////

	/**
	 * Default list for MutationPolicyHandler
	 */
	@Value.Default
	public List<MutationPolicyHandler<T>> defaultMutationPolicyHandlers() {
		return Arrays.asList(
				new RandomMutationPolicyHandler<>(randomGenerator()),
					new SwapMutationPolicyHandler<>(randomGenerator()),
					new MultiMutationsPolicyHandler<>(randomGenerator()),
					new PartialMutationPolicyHandler<>(),
					new CreepMutationPolicyHandler<T>(randomGenerator()));
	}

	public abstract List<MutationPolicyHandlerFactory<T>> mutationPolicyHandlerFactories();

	@SuppressWarnings("unchecked")
	@Value.Derived
	public List<MutationPolicyHandler<T>> mutationPolicyHandlers() {

		final List<MutationPolicyHandler<T>> mutationPolicyHandlers = new ArrayList<>();

		final List<MutationPolicyHandler<T>> defaultMutationPolicyHandlers = defaultMutationPolicyHandlers();
		if (defaultMutationPolicyHandlers.isEmpty() == false) {
			mutationPolicyHandlers.addAll(defaultMutationPolicyHandlers);
		}

		mutationPolicyHandlerFactories().stream()
				.map(factory -> factory.apply(this))
				.forEach(mph -> mutationPolicyHandlers.add(mph));

		@SuppressWarnings("rawtypes")
		final ServiceLoader<MutationPolicyHandlerFactory> serviceLoader = ServiceLoader
				.load(MutationPolicyHandlerFactory.class);

		serviceLoader.stream()
				.map(provider -> provider.get())
				.map(factory -> (MutationPolicyHandler<T>) factory.apply(this))
				.forEach(cch -> mutationPolicyHandlers.add(cch));

		return Collections.unmodifiableList(mutationPolicyHandlers);
	}

	/////////////////////////////////////////

	/**
	 * Default list of ChromosomeMutationPolicyHandler
	 */
	@Value.Default
	public List<ChromosomeMutationHandler<? extends Chromosome>> defaultChromosomeMutationPolicyHandlers() {
		return Arrays.asList(
				new BitChromosomeRandomMutationHandler(randomGenerator()),
					new IntChromosomeRandomMutationHandler(randomGenerator()),
					new DoubleChromosomeRandomMutationHandler(randomGenerator()),
					new FloatChromosomeRandomMutationHandler(randomGenerator()),
					new BitChromosomeSwapMutationHandler(randomGenerator()),
					new IntChromosomeSwapMutationHandler(randomGenerator()),
					new DoubleChromosomeSwapMutationHandler(randomGenerator()),
					new FloatChromosomeSwapMutationHandler(randomGenerator()),
					new IntChromosomeCreepMutationHandler(randomGenerator()),
					new DoubleChromosomeCreepMutationHandler(randomGenerator()),
					new FloatChromosomeCreepMutationHandler(randomGenerator()));
	}

	public abstract List<ChromosomeMutationHandlerFactory<T>> chromosomeMutationPolicyHandlerFactories();

	@SuppressWarnings("unchecked")
	@Value.Derived
	public List<ChromosomeMutationHandler<? extends Chromosome>> chromosomeMutationPolicyHandlers() {

		final List<ChromosomeMutationHandler<? extends Chromosome>> chromosomeMutationPolicyHandlers = new ArrayList<>();

		final List<ChromosomeMutationHandler<? extends Chromosome>> defaultChromosomeMutationPolicyHandlers = defaultChromosomeMutationPolicyHandlers();
		if (defaultChromosomeMutationPolicyHandlers.isEmpty() == false) {
			chromosomeMutationPolicyHandlers.addAll(defaultChromosomeMutationPolicyHandlers);
		}

		chromosomeMutationPolicyHandlerFactories().stream()
				.map(factory -> factory.apply(this))
				.forEach(cmh -> chromosomeMutationPolicyHandlers.add(cmh));

		@SuppressWarnings("rawtypes")
		final ServiceLoader<ChromosomeMutationHandlerFactory> serviceLoader = ServiceLoader
				.load(ChromosomeMutationHandlerFactory.class);

		serviceLoader.stream()
				.map(provider -> provider.get())
				.map(factory -> (ChromosomeMutationHandler<? extends Chromosome>) factory.apply(this))
				.forEach(cch -> chromosomeMutationPolicyHandlers.add(cch));

		return Collections.unmodifiableList(chromosomeMutationPolicyHandlers);
	}

	/////////////////////////////////////////

	/**
	 * Default list of ReplacementStrategyHandler
	 */
	@Value.Default
	public List<ReplacementStrategyHandler<T>> defaultReplacementStrategyHandlers() {
		return List.of(new ElitismReplacementStrategyHandler<>(), new GenerationalReplacementStrategyHandler<>());
	}

	public abstract List<ReplacementStrategyHandlerFactory<T>> replacementStrategyHandlerFactories();

	@SuppressWarnings("unchecked")
	@Value.Derived
	public List<ReplacementStrategyHandler<T>> replacementStrategyHandlers() {
		final List<ReplacementStrategyHandler<T>> replacementStrategyHandlers = new ArrayList<>();

		final List<ReplacementStrategyHandler<T>> defaultReplacementStrategyHandlers = defaultReplacementStrategyHandlers();
		if (defaultReplacementStrategyHandlers.isEmpty() == false) {
			replacementStrategyHandlers.addAll(defaultReplacementStrategyHandlers);
		}

		replacementStrategyHandlerFactories().stream()
				.map(factory -> factory.apply(this))
				.forEach(esh -> replacementStrategyHandlers.add(esh));

		@SuppressWarnings("rawtypes")
		final ServiceLoader<ReplacementStrategyHandlerFactory> serviceLoader = ServiceLoader
				.load(ReplacementStrategyHandlerFactory.class);

		serviceLoader.stream()
				.map(provider -> provider.get())
				.map(factory -> (ReplacementStrategyHandler<T>) factory.apply(this))
				.forEach(cch -> replacementStrategyHandlers.add(cch));

		return Collections.unmodifiableList(replacementStrategyHandlers);
	}

	/////////////////////////////////////////

	/**
	 * Default Random Generator
	 */
	@Value.Default
	public RandomGenerator randomGenerator() {
		return RandomGenerator.getDefault();
	}

	@Value.Default
	public int populationSize() {
		return DEFAULT_POPULATION_SIZE;
	}

	@Value.Default
	public ChromosomeFactoryProvider chromosomeFactoryProvider() {
		return ImmutableChromosomeFactoryProvider.builder().randomGenerator(randomGenerator()).build();
	}

	@Value.Default
	public List<EvolutionListener<T>> evolutionListeners() {
		return Collections.emptyList();
	}
}