public class IndividualWrapper<IndividualType extends Individual, FitnessValueType extends FitnessValue>
        implements Comparable<IndividualWrapper<IndividualType, FitnessValueType>>, Cloneable {

    private IndividualType individual;
    private FitnessValueType fitnessValue;
    private Boolean terminationConditionSatisfied;

    /**
     * Constructs an empty wrapper.
     */
    public IndividualWrapper() {
        this.individual = null;
        this.fitnessValue = null;
        this.terminationConditionSatisfied = null;
    }

    /**
     * Composes the Avro schema of the individual wrapper.
     *
     * @param individualClass   the class of the individual
     * @param fitnessValueClass the class of the fitness value
     * @return the schema composed
     */
    public static final Schema getSchema(Class<?> individualClass, Class<?> fitnessValueClass) {
        // Makes the list of the fields.
        List<Field> fields = new ArrayList<Field>();

        // Retrieves the schemas of the classes with the reflect.
        Schema individualReflectSchema = ReflectData.AllowNull.get().getSchema(individualClass);
        Schema fitnessValueReflectSchema = ReflectData.AllowNull.get().getSchema(fitnessValueClass);

        // Composes the schemas with the possibility to set values to null.
        Schema individualSchema = Schema.createUnion(Arrays.asList(
                Schema.create(Schema.Type.NULL), individualReflectSchema));
        Schema fitnessValueSchema = Schema.createUnion(Arrays.asList(
                Schema.create(Schema.Type.NULL), fitnessValueReflectSchema));
        Schema terminationConditionSatisfiedSchema = Schema.createUnion(Arrays.asList(
                Schema.create(Schema.Type.NULL), Schema.create(Schema.Type.BOOLEAN)));

        // Adds the fields to the main schema.
        fields.add(new Field("individual", individualSchema, null, null));
        fields.add(new Field("fitnessValue", fitnessValueSchema, null, null));
        fields.add(new Field("terminationConditionSatisfied", terminationConditionSatisfiedSchema, null, null));

        // Creates the main schema and returns it.
        Schema schema = Schema.createRecord(IndividualWrapper.class.getName(), null,
                IndividualWrapper.class.getPackage().getName(), false);
        schema.setFields(fields);

        return schema;
    }

    /**
     * Empties the individual field.
     */
    public final void emptyIndividual() {
        this.individual = null;
    }

    /**
     * Checks if the individual is set.
     *
     * @return "true" if it is set
     */
    public final boolean isIndividualSet() {
        return (this.individual != null);
    }

    /**
     * Returns the individual inside the wrapper.
     *
     * @return the individual
     */
    public final IndividualType getIndividual() {
        return this.individual;
    }

    /**
     * Sets the individual.
     *
     * @param individual the individual ("null" to empty)
     */
    public final void setIndividual(IndividualType individual) {
        this.individual = individual;
    }

    /**
     * Empties the fitness value field.
     */
    public final void emptyFitnessValue() {
        this.fitnessValue = null;
    }

    /**
     * Checks if the fitness value is set.
     *
     * @return "true" if it is set
     */
    public final boolean isFitnessValueSet() {
        return (this.fitnessValue != null);
    }

    /**
     * Returns the fitness value of the individual.
     */
    public final FitnessValueType getFitnessValue() {
        return this.fitnessValue;
    }

    /**
     * Sets the fitness value of the individual.
     *
     * @param fitnessValue the fitness value ("null" to empty)
     */
    public final void setFitnessValue(FitnessValueType fitnessValue) {
        this.fitnessValue = fitnessValue;
    }

    /**
     * Sets if the individual satisfies the termination condition or not.
     *
     * @param value "true" if it satisfies the termination condition  ("null" to empty)
     */
    public final void setTerminationConditionSatisfied(Boolean value) {
        this.terminationConditionSatisfied = value;
    }

    /**
     * Empties the termination condition satisfied field. This means that the check has never been checked.
     */
    public final void emptyTerminationConditionSatisfied() {
        this.terminationConditionSatisfied = null;
    }

    /**
     * Checks if the individual satisfies the termination condition or not. If it returns the "null" value, it means
     * that is has not ever been checked.
     *
     * @return "true" if it satisfies the termination condition ("null" if never checked)
     */
    public final Boolean isTerminationConditionSatisfied() {
        return this.terminationConditionSatisfied;
    }

    /**
     * Checks if the termination condition satisfied flag is set.
     *
     * @return "true" if it is set
     */
    public final Boolean isTerminationConditionSatisfiedSet() {
        return (this.terminationConditionSatisfied != null);
    }

    /**
     * Returns the string representation of the wrapper.
     */
    @Override
    public final String toString() {
        return "{individual: " + this.individual + ", fitnessValue: " + this.fitnessValue +
                ", terminationConditionSatisfied: " + this.terminationConditionSatisfied + "}";
    }

    /**
     * Two individuals are equal only if all the fields are equal.
     */
    @SuppressWarnings("unchecked")
    @Override
    public final boolean equals(Object object) {
        if (!(object instanceof IndividualWrapper))
            return false;

        IndividualWrapper<IndividualType, FitnessValueType> other =
                (IndividualWrapper<IndividualType, FitnessValueType>) object;

        return this.individual.equals(other.individual);
    }

    @Override
    public final int hashCode() {
        final int prime = 31;

        int result = 1;

        result = prime * result + ((this.fitnessValue == null) ? 0 : this.fitnessValue.hashCode());
        result = prime * result + ((this.individual == null) ? 0 : this.individual.hashCode());
        result = prime * result + ((this.terminationConditionSatisfied == null) ? 0
                : this.terminationConditionSatisfied.hashCode());

        return result;
    }


    /**
     * Compares by the fitness value.
     *
     * @param other the other individual wrapper to compare
     * @return a negative integer, zero, or a positive integer as this object is less than,
     * equal to, or greater than the specified object
     */
    @Override
    public int compareTo(IndividualWrapper<IndividualType, FitnessValueType> other) {
        if (this.fitnessValue == null)
            return 0;

        return this.fitnessValue.compareTo(other.getFitnessValue());
    }

    @SuppressWarnings("unchecked")
    @Override
    public Object clone() throws CloneNotSupportedException {
        IndividualType individualClone = (IndividualType) this.individual.clone();
        FitnessValueType fitnessValueClone = (this.fitnessValue != null)
                ? (FitnessValueType) this.fitnessValue.clone() : null;

        IndividualWrapper<IndividualType, FitnessValueType> clone =
                new IndividualWrapper<IndividualType, FitnessValueType>();
        clone.setIndividual(individualClone);
        clone.setFitnessValue(fitnessValueClone);
        clone.setTerminationConditionSatisfied(this.terminationConditionSatisfied);

        return clone;
    }
}
 public class Properties {
    /**
     * Reads the properties from a file.
     *
     * @param inputFilePath the path where to read the properties
     * @param fileSystem    the filesystem
     * @return the read properties
     * @throws IOException
     */
    public static Properties readFromFile(Path inputFilePath, FileSystem fileSystem) throws IOException {
        FSDataInputStream fileInputStream = fileSystem.open(inputFilePath);

        Configuration configuration = new Configuration(false);
        configuration.readFields(fileInputStream);

        fileInputStream.close();

        Properties properties = new Properties(configuration);

        return properties;
    }

    private Configuration configuration;

    /**
     * Constructs the object.
     */
    public Properties() {
        this.configuration = new Configuration(false);
    }

    /**
     * Constructs the object specifying the configuration.
     *
     * @param configuration the configuration
     */
    public Properties(Configuration configuration) {
        this.configuration = configuration;
    }

    /**
     * Copies the properties into a Configuration object.
     *
     * @param configuration the destination
     */
    public void copyIntoConfiguration(Configuration configuration) {
        for (Map.Entry<String, String> entry : this.configuration)
            configuration.set(entry.getKey(), entry.getValue());
    }

    /**
     * Writes the properties into a file.
     *
     * @param outputFilePath the path where to write the properties
     * @param fileSystem     the filesystem
     * @throws java.io.IOException
     */
    public void writeToFile(Path outputFilePath, FileSystem fileSystem) throws IOException {
        FSDataOutputStream fileOutputStream = fileSystem.create(outputFilePath, true);
        this.configuration.write(fileOutputStream);
        fileOutputStream.close();
    }

    /**
     * Checks if a property is set or not.
     *
     * @param name the name of the property
     * @return "true" if yes, "false" otherwise
     */
    public boolean isSet(String name) {
        return (this.configuration.get(name) != null);
    }

    /**
     * Get the value of the the "name" property as a String.
     *
     * @param name         the name of the property
     * @param defaultValue the default value, if the property doesn't exist
     * @return the value of the property
     */
    public String getString(String name, String defaultValue) {
        return this.configuration.get(name, defaultValue);
    }

    /**
     * Get the value of the "name" property as a boolean.
     *
     * @param name         the name of the property
     * @param defaultValue the default value, if the property doesn't exist
     * @return the value of the property
     */
    public boolean getBoolean(String name, boolean defaultValue) {
        return this.configuration.getBoolean(name, defaultValue);
    }

    /**
     * Get the value of the "name" property as a Class.
     *
     * @param name         the name of the property
     * @param defaultValue the default value, if the property doesn't exist
     * @return the value of the property
     */
    public Class<?> getClass(String name, Class<?> defaultValue) {
        return this.configuration.getClass(name, defaultValue);
    }

    /**
     * Get the value of the "name" property as an Enum.
     *
     * @param name         the name of the property
     * @param defaultValue the default value, if the property doesn't exist
     * @return the value of the property
     */
    public <T extends Enum<T>> T getEnum(String name, T defaultValue) {
        return this.configuration.getEnum(name, defaultValue);
    }

    /**
     * Get the value of the "name" property as a float.
     *
     * @param name         the name of the property
     * @param defaultValue the default value, if the property doesn't exist
     * @return the value of the property
     */
    public float getFloat(String name, float defaultValue) {
        return this.configuration.getFloat(name, defaultValue);
    }

    /**
     * Get the value of the "name" property as an int.
     *
     * @param name         the name of the property
     * @param defaultValue the default value, if the property doesn't exist
     * @return the value of the property
     */
    public int getInt(String name, int defaultValue) {
        return this.configuration.getInt(name, defaultValue);
    }

    /**
     * Get the value of the "name" property as an array of int values.
     *
     * @param name the name of the property
     * @return the value of the property
     */
    public int[] getInts(String name) {
        Collection<String> strings = this.configuration.getStringCollection(name);

        int[] result = new int[strings.size()];

        int i = 0;

        for (String string : strings) {
            result[i] = Integer.parseInt(string);
            i++;
        }

        return result;
    }

    /**
     * Get the value of the "name" property as a long.
     *
     * @param name         the name of the property
     * @param defaultValue the default value, if the property doesn't exist
     * @return the value of the property
     */
    public long getLong(String name, long defaultValue) {
        return this.configuration.getLong(name, defaultValue);
    }

    /**
     * Get the value of the "name" property as a double.
     *
     * @param name         the name of the property
     * @param defaultValue the default value, if the property doesn't exist
     * @return the value of the property
     */
    public double getDouble(String name, double defaultValue) {
        String string = this.configuration.get(name);

        if (string == null)
            return defaultValue;

        return Double.parseDouble(string);
    }

    /**
     * Get the value of the "name" property as a collection of String.
     *
     * @param name the name of the property
     * @return the value of the property
     */
    public Collection<String> getStringCollection(String name) {
        return this.configuration.getStringCollection(name);
    }

    /**
     * Get the value of the "name" property as an array of String.
     *
     * @param name the name of the property
     * @return the value of the property
     */
    public String[] getStrings(String name) {
        return this.configuration.getStrings(name);
    }

    /**
     * Set the value of the the "name" property as a String.
     *
     * @param name  the name of the property
     * @param value the value to set
     */
    public void setString(String name, String value) {
        this.configuration.set(name, value);
    }

    /**
     * Set the value of the "name" property as a boolean.
     *
     * @param name  the name of the property
     * @param value the value to set
     */
    public void setBoolean(String name, boolean value) {
        this.configuration.setBoolean(name, value);
    }

    /**
     * Set the value of the "name" property as a Class.
     *
     * @param name  the name of the property
     * @param value the value to set
     */
    public void setClass(String name, Class<?> value) {
        this.configuration.setClass(name, value, Object.class);
    }

    /**
     * Set the value of the "name" property as an Enum.
     *
     * @param name  the name of the property
     * @param value the value to set
     */
    public <T extends Enum<T>> void setEnum(String name, T value) {
        this.configuration.setEnum(name, value);
    }

    /**
     * Set the value of the "name" property as a float.
     *
     * @param name  the name of the property
     * @param value the value to set
     */
    public void setFloat(String name, float value) {
        this.configuration.setFloat(name, value);
    }

    /**
     * Set the value of the "name" property as an int.
     *
     * @param name  the name of the property
     * @param value the value to set
     */
    public void setInt(String name, int value) {
        this.configuration.setInt(name, value);
    }

    /**
     * Set the value of the "name" property as an array of int values.
     *
     * @param name   the name of the property
     * @param values the values to set
     */
    public void setInts(String name, int... values) {
        String[] stringValues = new String[values.length];

        for (int i = 0; i < values.length; i++)
            stringValues[i] = Integer.toString(values[i]);

        this.configuration.setStrings(name, stringValues);
    }

    /**
     * Set the value of the "name" property as a long.
     *
     * @param name  the name of the property
     * @param value the value to set
     */
    public void setLong(String name, long value) {
        this.configuration.setLong(name, value);
    }

    /**
     * Set the value of the "name" property as a double.
     *
     * @param name  the name of the property
     * @param value the value to set
     */
    public void setDouble(String name, double value) {
        this.configuration.set(name, Double.toString(value));
    }

    /**
     * Set the value of the "name" property as an array of String.
     *
     * @param name   the name of the property
     * @param values the values to set
     */
    public void setStrings(String name, String... values) {
        this.configuration.setStrings(name, values);
    }
}
 public class IndividualReporter extends TimeReporter {
    /**
     * The header.
     */
    public static final String[] HEADER = {
            "island_number", "generations_block_number", "generation_number",
            "individual", "fitness_value", "termination_condition_satisfied"
    };

    public IndividualReporter(Path outputFilePath, FileSystem fileSystem) throws IOException {
        super(outputFilePath, fileSystem, HEADER);
    }

    public void writeIndividual(
            int islandNumber, long generationsBlockNumber, long generationNumber, Individual individual,
            FitnessValue fitnessValue, boolean terminationConditionSatisfied) {
        String[] line = {
                Integer.toString(islandNumber),
                Long.toString(generationsBlockNumber),
                Long.toString(generationNumber),
                individual.toString(),
                fitnessValue.toString(),
                Boolean.toString(terminationConditionSatisfied)
        };

        super.writeLine(line);
    }
}
 public class GeneticOperatorsTimeReporter extends TimeReporter {
    /**
     * The header.
     */
    public static final String[] HEADER = {
            "island_number", "generations_block_number", "generation_number", "phase_type",
            "start_time", "finish_time", "total_time", "human_total_time"
    };

    /**
     * The types of phases.
     */
    public static enum PhaseType {
        AVERAGE_INITIALISATION,
        TOTAL_INITIALISATION,
        MIN_FITNESS_EVALUATION,
        MAX_FITNESS_EVALUATION,
        AVERAGE_FITNESS_EVALUATION,
        TOTAL_FITNESS_EVALUATION,
        AVERAGE_INDIVIDUAL_TERMINATION_CONDITION_CHECK,
        TOTAL_INDIVIDUAL_TERMINATION_CONDITION_CHECK,
        TOTAL_ISLAND_TERMINATION_CONDITION_CHECK,
        TOTAL_GLOBAL_TERMINATION_CONDITION_CHECK,
        TOTAL_ELITISM,
        TOTAL_PARENTS_SELECTION,
        AVERAGE_CROSSOVER,
        TOTAL_CROSSOVER,
        AVERAGE_MUTATION,
        TOTAL_MUTATION,
        MIN_FITNESS_EVALUATION_DURING_SURVIVAL_SELECTION,
        MAX_FITNESS_EVALUATION_DURING_SURVIVAL_SELECTION,
        AVERAGE_FITNESS_EVALUATION_DURING_SURVIVAL_SELECTION,
        TOTAL_FITNESS_EVALUATION_DURING_SURVIVAL_SELECTION,
        TOTAL_SURVIVAL_SELECTION,
        TOTAL_MIGRATION
    }

    ;

    public GeneticOperatorsTimeReporter(Path outputFilePath, FileSystem fileSystem) throws IOException {
        super(outputFilePath, fileSystem, HEADER);
    }

    public void writeTime(
            int islandNumber, long generationsBlockNumber, long generationNumber, PhaseType phaseType, long startTime,
            long finishTime) {
        super.writeTime(islandNumber, generationsBlockNumber, generationNumber, phaseType.name(), startTime, finishTime);
    }
}
 public class GenerationsBlockTimeReporter extends TimeReporter {
    /**
     * The header.
     */
    public static final String[] HEADER = {
            "island_number", "generations_block_number", "generation_number", "phase_type",
            "start_time", "finish_time", "total_time", "human_total_time"
    };

    /**
     * The types of phases.
     */
    public static enum PhaseType {
        //TODO nuova
        INITIALISATION,
        GENERATION,
        GENERATIONS_BLOCK
    }

    ;

    public GenerationsBlockTimeReporter(Path outputFilePath, FileSystem fileSystem) throws IOException {
        super(outputFilePath, fileSystem, HEADER);
    }

    public void writeTime(
            int islandNumber, long generationsBlockNumber, long generationNumber, PhaseType phaseType, long startTime,
            long finishTime) {
        super.writeTime(islandNumber, generationsBlockNumber, generationNumber, phaseType.name(), startTime,
                finishTime);
    }
}
 public abstract class FitnessValue
        implements Comparable<FitnessValue> {

    public FitnessValue() {
    }

    /**
     * <p>
     * Compares the current fitness value with another. Pay attention to control
     * if the value is null.
     * </p>
     */
    @Override
    public abstract int compareTo(FitnessValue other);

    /**
     * <p>
     * Clones the fitness value.
     * </p>
     */
    @Override
    public abstract Object clone() throws CloneNotSupportedException;

    /**
     * <p>
     * Retrieves the unique hash code of the object.
     * </p>
     */
    @Override
    public abstract int hashCode();

} public abstract class Individual implements Cloneable {

    /**
     * <p>
     * Clones the fitness value.
     * </p>
     */
    @Override
    public abstract Object clone() throws CloneNotSupportedException;

    /**
     * <p>
     * Retrieves the unique hash code of the object.
     * </p>
     */
    @Override
    public abstract int hashCode();

} public class Initialisation<IndividualType extends Individual, FitnessValueType extends FitnessValue>
        extends GeneticOperator<IndividualType, FitnessValueType> {

    private int populationSize;

    /**
     * Constructs the instance of the class passing the properties.
     *
     * @param islandNumber         the island number
     * @param totalNumberOfIslands the total number of islands
     * @param userProperties       the properties defined by the user
     * @param configuration        the configuration
     * @param populationSize       the number of individuals to generate
     */
    public Initialisation(
            Integer islandNumber, Integer totalNumberOfIslands, Properties userProperties, Configuration configuration,
            Integer populationSize
    ) {
        super(islandNumber, totalNumberOfIslands, userProperties, configuration);

        this.populationSize = populationSize;
    }

    /**
     * Returns the number of individuals to generate.
     *
     * @return the number of individuals to generate
     */
    protected int getPopulationSize() {
        return this.populationSize;
    }

    /**
     * Generates the next individual.
     * <p>
     * If not overridden, it returns an empty individual.
     *
     * @param id the identify code of the individual to generate
     * @return the individual generated
     */
    public IndividualWrapper<IndividualType, FitnessValueType> generateNextIndividual(int id) {
        return new IndividualWrapper<>();
    }
}
 public class TerminationConditionCheck<IndividualType extends Individual, FitnessValueType extends FitnessValue>
        extends GeneticOperator<IndividualType, FitnessValueType> {

    /**
     * Constructs the instance of the class passing the user.
     *
     * @param islandNumber         the island number
     * @param totalNumberOfIslands the total number of islands
     * @param userProperties       the properties defined by the user
     * @param configuration        the configuration
     */
    public TerminationConditionCheck(
            Integer islandNumber, Integer totalNumberOfIslands, Properties userProperties, Configuration configuration
    ) {
        super(islandNumber, totalNumberOfIslands, userProperties, configuration);
    }

    /**
     * Checks if an individual satisfies the termination condition for the problem.
     * <p>
     * It acts just after the fitness phase.
     * <p>
     * If not overridden, it returns "false".
     *
     * @param individual the individual to check
     * @return "true" if it satisfies the termination condition
     */
    public boolean checkIndividualTerminationCondition(IndividualWrapper<IndividualType, FitnessValueType> individual) {
        return false;
    }

    /**
     * Checks if all island individuals satisfy the termination condition for the problem.
     * <p>
     * It acts just at the end of the generation phase.
     * <p>
     * If not overridden, it returns "false".
     *
     * @param individuals      the individual to check
     * @param islandProperties the island properties
     * @return "true" if they satisfy the termination condition
     */
    public boolean checkIslandTerminationCondition(
            List<IndividualWrapper<IndividualType, FitnessValueType>> individuals,
            Properties islandProperties
    ) {
        return false;
    }

    /**
     * It check the termination condition with the proprerties by all the islands for the same generation. A previous
     * property change could be stored in one of the island properties.
     * <p>
     * If not overridden, it returns "false".
     *
     * @param islandsProperties the properties, one for each island
     * @param generationNumber  the current number of generation
     * @return "true" if the termination condition is satisfied
     */
    public boolean checkGlobalTerminationCondition(List<Properties> islandsProperties, long generationNumber) {
        return false;
    }
}
 public class Pair<FirstElementType, SecondElementType> {

    private FirstElementType firstElement;
    private SecondElementType secondElement;

    /**
     * Constructs an empty pair.
     */
    public Pair() {
        this.firstElement = null;
        this.secondElement = null;
    }

    /**
     * Constructs a pair setting the elements too.
     *
     * @param firstElement  the first element
     * @param secondElement the second element
     */
    public Pair(FirstElementType firstElement, SecondElementType secondElement) {
        this.firstElement = firstElement;
        this.secondElement = secondElement;
    }

    /**
     * Sets the first element.
     *
     * @param firstElement the first element
     */
    public void setFirstElement(FirstElementType firstElement) {
        this.firstElement = firstElement;
    }

    /**
     * Sets the second element.
     *
     * @param secondElement the second element
     */
    public void setSecondElement(SecondElementType secondElement) {
        this.secondElement = secondElement;
    }

    /**
     * Returns the first element.
     *
     * @return the first element
     */
    public FirstElementType getFirstElement() {
        return this.firstElement;
    }

    /**
     * Returns the second element.
     *
     * @return the second element
     */
    public SecondElementType getSecondElement() {
        return this.secondElement;
    }

    @Override
    public String toString() {
        return "(" + this.firstElement + ", " + this.secondElement + ")";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((firstElement == null) ? 0 : firstElement.hashCode());
        result = prime * result + ((secondElement == null) ? 0 : secondElement.hashCode());
        return result;
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean equals(Object object) {
        Pair<FirstElementType, SecondElementType> other = (Pair<FirstElementType, SecondElementType>) object;
        return this.firstElement.equals(other.firstElement)
                && this.secondElement.equals(other.secondElement);
    }
}

import it.unisa.elephant56.core.common.IndividualWrapper;
import it.unisa.elephant56.core.common.Properties;
import it.unisa.elephant56.core.reporter.individual.IndividualReporter;
import it.unisa.elephant56.core.reporter.time.GeneticOperatorsTimeReporter;
import it.unisa.elephant56.core.reporter.time.GenerationsBlockTimeReporter;
import it.unisa.elephant56.user.common.FitnessValue;
import it.unisa.elephant56.user.common.Individual;
import it.unisa.elephant56.user.operators.*;
import it.unisa.elephant56.user.operators.Initialisation;
import it.unisa.elephant56.user.operators.TerminationConditionCheck;
import it.unisa.elephant56.util.common.Pair;
import org.apache.hadoop.conf.Configuration;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

package it.unisa.elephant56.core.generator;



public class GenerationsBlockExecutor {
    protected long generationsBlockNumber;

    protected int initialisationPopulationSize;

    protected long startGenerationNumber;
    protected long finishGenerationNumber;

    protected long currentGenerationNumber;
    protected long lastExecutedGenerationNumber;

    protected Class<? extends Initialisation> initiliasationClass;
    protected Class<? extends FitnessEvaluation> fitnessEvaluationClass;
    protected Class<? extends TerminationConditionCheck> terminationConditionCheckClass;
    protected Class<? extends Elitism> elitismClass;
    protected Class<? extends ParentsSelection> parentsSelectionClass;
    protected Class<? extends Crossover> crossoverClass;
    protected Class<? extends Mutation> mutationClass;
    protected Class<? extends SurvivalSelection> survivalSelectionClass;
    protected Class<? extends Migration> migrationClass;

    protected boolean isInitialisationActive;
    protected boolean isSurvivalSelectionActive;
    protected boolean isElitismActive;
    protected boolean isMigrationActive;

    protected int nodeNumber;
    protected int totalNumberOfNodes;

    protected Properties userProperties;
    protected Configuration configuration;

    protected boolean isTimeReporterActive;
    protected GeneticOperatorsTimeReporter geneticOperatorsTimeReporter;

    protected GenerationsBlockTimeReporter generationsBlockTimeReporter;
