diff --git a/src/core/attic/de/evoal/core/main/ea/InitialStreamFactory.java b/src/core/attic/de/evoal/core/main/ea/InitialStreamFactory.java deleted file mode 100644 index 10eb5d517a6f464fd1cdaa55dcf7c48fe0e6a4bf..0000000000000000000000000000000000000000 --- a/src/core/attic/de/evoal/core/main/ea/InitialStreamFactory.java +++ /dev/null @@ -1,86 +0,0 @@ -package de.evoal.core.main.ea; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.function.Function; -import java.util.random.RandomGenerator; -import java.util.stream.Collectors; - -import de.evoal.core.api.board.BlackboardEntry; -import de.evoal.core.api.cdi.ConfigurationValue; -import de.evoal.core.api.ea.surrogate.model.points.Point; -import de.evoal.core.api.ea.codec.CustomCodec; -import de.evoal.core.api.ea.surrogate.model.points.PointsFactory; -import de.evoal.core.api.properties.Properties; -import de.evoal.core.api.properties.PropertiesSpecification; -import io.jenetics.Gene; -import io.jenetics.Genotype; -import io.jenetics.engine.Engine; -import io.jenetics.engine.EvolutionInit; -import io.jenetics.engine.EvolutionStream; -import io.jenetics.util.ISeq; -import io.jenetics.util.RandomRegistry; -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.inject.Produces; -import javax.inject.Named; -import org.apache.deltaspike.core.api.provider.BeanProvider; - -@ApplicationScoped -public class InitialStreamFactory { - /** - * Creates a initial generation based on the heuristic configuration. - * - * Blackboard slots used: - * <ul> - * <li>{@link BlackboardEntry#EA_CONFIGURATION}.</li> - * </ul> - */ - @Produces - public Function<Engine, EvolutionStream> create( - @Named("source-properties-specification") final PropertiesSpecification sourceSpecification, - @Named("target-properties-specification") final PropertiesSpecification targetSpecification, - @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.size_of_population") final int sizeOfPopulation, - @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.initialization.name") final String initializationType, - final CustomCodec encoding) { - - final PropertiesSpecification totalSpecification = PropertiesSpecification.builder() - .add(sourceSpecification) - .add(targetSpecification) - .build(); - - switch (initializationType) { - case "random": return engine -> engine.stream(); - case "training": return engine -> engine.stream(createTargetBasedInitialPopulation(encoding, totalSpecification, sourceSpecification, sizeOfPopulation)); - } - - throw new IllegalArgumentException("Initialization type " + initializationType + " is unknown."); - } - - private static <G extends Gene<?, G>> EvolutionInit<G> createTargetBasedInitialPopulation(final CustomCodec<G> encoding, final PropertiesSpecification total, final PropertiesSpecification input, final int sizeOfPopulation) { - final ISeq<Genotype<G>> inital = createInitialPopulation(encoding, total, input, sizeOfPopulation); - - return EvolutionInit.of(inital, 1); - } - - private static <G extends Gene<?, G>> ISeq<Genotype<G>> createInitialPopulation(final CustomCodec<G> encoding, final PropertiesSpecification total, final PropertiesSpecification input, final int sizeOfPopulation) { - final List<Genotype<G>> initialPopulation = new ArrayList<>(sizeOfPopulation); - final PointsFactory factory = BeanProvider.getContextualReference("training-points", false, PointsFactory.class); - final RandomGenerator random = RandomRegistry.random(); - - final List<Point> trainingPoints = factory.apply(total).get().collect(Collectors.toList()); - - for(int i = 0; i < sizeOfPopulation; ++i) { - final int pointIndex = random.nextInt(trainingPoints.size()); - final Point point = trainingPoints.get(pointIndex); - - final Properties properties = Properties.create(input, point); - - final Genotype<G> genotype = encoding.encode(properties); - - ö .add(genotype); - } - - return initialPopulation.stream().collect(ISeq.toISeq()); - } -} diff --git a/src/core/attic/de/evoal/core/main/ea/comparator/ComparatorFactory.java b/src/core/attic/de/evoal/core/main/ea/comparator/ComparatorFactory.java deleted file mode 100644 index f67890f3fbb10d9749474499c621bd269eca8ccb..0000000000000000000000000000000000000000 --- a/src/core/attic/de/evoal/core/main/ea/comparator/ComparatorFactory.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.evoal.core.main.ea.comparator; - -import de.evoal.core.api.ea.fitness.type.FitnessConverter; -import de.evoal.core.api.board.BlackboardEntry; -import de.evoal.core.api.cdi.ConfigurationValue; -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.inject.Produces; -import org.apache.deltaspike.core.api.provider.BeanProvider; - -import javax.inject.Named; - -@ApplicationScoped -public class ComparatorFactory { - @Produces - @Named("depending") - public FitnessConverter create(@ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.comparator.name") String comparator) { - return (FitnessConverter) BeanProvider.getContextualReference(comparator, false, FitnessConverter.class); - } -} diff --git a/src/core/attic/de/evoal/core/main/ea/comparator/pareto/ParetoComparatorConverter.java b/src/core/attic/de/evoal/core/main/ea/comparator/pareto/ParetoComparatorConverter.java deleted file mode 100644 index 64b2cfc6bfae57570f857fa2d2c31fc5a57b8d18..0000000000000000000000000000000000000000 --- a/src/core/attic/de/evoal/core/main/ea/comparator/pareto/ParetoComparatorConverter.java +++ /dev/null @@ -1,16 +0,0 @@ -package de.evoal.core.main.ea.comparator.pareto; - -import de.evoal.core.api.ea.fitness.type.FitnessConverter; -import de.evoal.core.api.ea.fitness.type.FitnessType; -import javax.enterprise.context.ApplicationScoped; - -import javax.inject.Named; - -@ApplicationScoped -@Named("pareto") -public class ParetoComparatorConverter implements FitnessConverter { - @Override - public FitnessType convert(final double[] fitnessValues) { - return ParetoComparatorType.of(fitnessValues); - } -} diff --git a/src/core/attic/de/evoal/core/main/ea/comparator/weighted/WeightedSumComparatorConverter.java b/src/core/attic/de/evoal/core/main/ea/comparator/weighted/WeightedSumComparatorConverter.java deleted file mode 100644 index da2424292dcb70d3a2e9ea1addb3fe8e5f0cb744..0000000000000000000000000000000000000000 --- a/src/core/attic/de/evoal/core/main/ea/comparator/weighted/WeightedSumComparatorConverter.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.evoal.core.main.ea.comparator.weighted; - -import de.evoal.core.api.ea.fitness.type.FitnessConverter; -import de.evoal.core.api.ea.fitness.type.FitnessType; -import de.evoal.core.api.board.BlackboardEntry; -import de.evoal.core.api.cdi.ConfigurationValue; -import javax.enterprise.context.ApplicationScoped; - -import javax.inject.Inject; -import javax.inject.Named; - -@ApplicationScoped -@Named("weighted_sum") -public class WeightedSumComparatorConverter implements FitnessConverter { - @Inject - @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.comparator.weights") - private double [] weights; - - @Override - public FitnessType convert(final double[] fitnessValues) { - return WeightedSumComparatorType.of(weights, fitnessValues); - } -} diff --git a/src/core/attic/de/evoal/core/main/ea/comparator/weighted/WeightedSumComparatorType.java b/src/core/attic/de/evoal/core/main/ea/comparator/weighted/WeightedSumComparatorType.java deleted file mode 100644 index cc1aae5b0a0d66bf51713a7c913c9f23186bda53..0000000000000000000000000000000000000000 --- a/src/core/attic/de/evoal/core/main/ea/comparator/weighted/WeightedSumComparatorType.java +++ /dev/null @@ -1,79 +0,0 @@ -package de.evoal.core.main.ea.comparator.weighted; - -import de.evoal.core.api.ea.fitness.type.FitnessType; -import de.evoal.core.api.utils.Requirements; -import lombok.NonNull; - -import java.util.Arrays; - -import static de.evoal.core.api.utils.Requirements.requireSameSize; - -public class WeightedSumComparatorType extends Number implements FitnessType { - private final @NonNull double[] fitnessValues; - private final @NonNull double[] normalizedWeights; - - private WeightedSumComparatorType(final @NonNull double[] weights, final @NonNull double[] fitnessValues) { - Requirements.requireSameSize(weights, fitnessValues); - - this.normalizedWeights = new double[weights.length]; - System.arraycopy(weights, 0, normalizedWeights, 0, weights.length); - this.fitnessValues = fitnessValues; - - final double sumOfWeights = Arrays.stream(weights).sum(); - for(int i = 0; i < normalizedWeights.length; ++i) { - normalizedWeights[i] = normalizedWeights[i] / sumOfWeights; - } - } - - public static FitnessType of(final double [] weights, final double [] fitnessValues) { - return new WeightedSumComparatorType(weights, fitnessValues); - } - - @Override - public int compareTo(final FitnessType other) { - double ownFitness = 0.0; - double otherFitness = 0.0; - - for(int index = 0; index < fitnessValues.length; ++index) { - //ownFitness = ownFitness + this.normalizedWeights[index] * this.fitnessValues[index]; - //otherFitness = otherFitness + this.normalizedWeights[index] * other.getFitnessValues()[index]; - ownFitness = ownFitness - this.normalizedWeights[index] * Math.abs(this.fitnessValues[index]); - otherFitness = otherFitness - this.normalizedWeights[index] * Math.abs(other.getFitnessValues()[index]); - } - - return ownFitness == otherFitness ? 0 : (int)Math.signum(ownFitness - otherFitness); - } - - @Override - public double[] getFitnessValues() { - return fitnessValues; - } - - @Override - public String toString() { - return "WeightedSum [fit=" + Arrays.toString(fitnessValues) + ", w" + Arrays.toString(normalizedWeights) + "]"; - } - - @Override - public int intValue() { - throw new UnsupportedOperationException("Only allows conversion to a double value."); - } - - @Override - public long longValue() { - throw new UnsupportedOperationException("Only allows conversion to a double value."); - } - - @Override - public float floatValue() { - throw new UnsupportedOperationException("Only allows conversion to a double value."); - } - - @Override - public double doubleValue() { - if(fitnessValues.length != 1) { - throw new UnsupportedOperationException("Only allows conversion with a single double value."); - } - return fitnessValues[0]; - } -} diff --git a/src/core/attic/de/evoal/core/main/ea/fitness/FitnessFactory.java b/src/core/attic/de/evoal/core/main/ea/fitness/FitnessFactory.java deleted file mode 100644 index b95ba7c3b065a49a1cdd9050640f008d711ed681..0000000000000000000000000000000000000000 --- a/src/core/attic/de/evoal/core/main/ea/fitness/FitnessFactory.java +++ /dev/null @@ -1,60 +0,0 @@ -package de.evoal.core.main.ea.fitness; - -import java.util.*; -import java.util.stream.Collectors; - -import de.evoal.core.api.board.Blackboard; -import de.evoal.core.api.board.BlackboardEntry; -import de.evoal.core.api.ea.fitness.FitnessBase; -import de.evoal.core.api.cdi.ConfigurationValue; -import de.evoal.core.api.ea.fitness.FitnessEvaluator; - -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.context.Dependent; -import javax.enterprise.inject.Produces; -import lombok.extern.slf4j.Slf4j; -import org.apache.deltaspike.core.api.provider.BeanProvider; - -import javax.enterprise.inject.spi.Bean; -import javax.inject.Inject; -import javax.inject.Named; - -@ApplicationScoped -@Slf4j -public class FitnessFactory { - private final String NAME_SUFFIX = "-fitness"; - - @Inject - private Blackboard board; - - private FitnessFactory() { - } - - /** - * Creates a fitness function based on the heuristic configuration. - * - * Blackboard slots used: - * <ul> - * <li>{@link BlackboardEntry#EA_CONFIGURATION}.</li> - * <li>{@link BlackboardEntry#PREDICTIVE_FUNCTION}.</li> - * <li>{@link BlackboardEntry#TARGET_PROPERTIES}.</li> - * </ul> - */ - @Produces @Named("evaluator") @Dependent - public FitnessEvaluator create(final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.fitness.name") String name) { - log.info("Creating fitness evaluator {}.", name); - - return BeanProvider.getContextualReference(name + NAME_SUFFIX, false, FitnessEvaluator.class)::evaluate; - } - - @Produces @Named("function-names") @Dependent - public List<String> functionNames() { - return BeanProvider.getBeanDefinitions(FitnessBase.class, true, true) - .stream() - .map(Bean::getName) - .filter(Objects::nonNull) - .filter(name -> name.endsWith(NAME_SUFFIX)) - .map(s -> s.substring(0, s.length() - NAME_SUFFIX.length())) - .collect(Collectors.toList()); - } -} diff --git a/src/core/attic/de/evoal/core/main/search/ListConstraint.java b/src/core/attic/de/evoal/core/main/search/ListConstraint.java deleted file mode 100644 index dd0cded2efd4a62aa2963eae6a9d4516f8386110..0000000000000000000000000000000000000000 --- a/src/core/attic/de/evoal/core/main/search/ListConstraint.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.evoal.core.main.search; - -import de.evoal.core.api.ea.fitness.type.FitnessType; -import io.jenetics.Gene; -import io.jenetics.Phenotype; -import io.jenetics.engine.Constraint; - -import java.util.List; - -public class ListConstraint<G extends Gene<?, G>> implements Constraint<G, FitnessType> { - private final List<Constraint<G, FitnessType>> constraints; - - public ListConstraint(final List<Constraint<G, FitnessType>> constraints) { - this.constraints = constraints; - } - - @Override - public boolean test(final Phenotype<G, FitnessType> individual) { - return constraints.stream().allMatch(c -> c.test(individual)); - } - - @Override - public Phenotype<G, FitnessType> repair(Phenotype<G, FitnessType> individual, long generation) { - Phenotype<G, FitnessType> phenotype = individual; - - for(final Constraint<G, FitnessType> c : constraints) { - phenotype = c.repair(phenotype, generation); - } - - return phenotype; - } -} diff --git a/src/core/de.evoal.core/pom.xml b/src/core/de.evoal.core/pom.xml index e80c8343a6ff80455d5f98460cb312c32d2f05ea..4bc7b34552a37dc2393f8ee4c929832b44ce3981 100644 --- a/src/core/de.evoal.core/pom.xml +++ b/src/core/de.evoal.core/pom.xml @@ -174,7 +174,7 @@ <groupId>de.evoal.languages</groupId> <artifactId>de.evoal.languages.model.ddl.dsl</artifactId> <version>${evoal.languages.version}</version> - <scope>runtime</scope> + <scope>compile</scope> </dependency> <dependency> diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/board/BlackboardEntry.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/board/BlackboardEntry.java index fa81233b3d83a16ddd6bd55966f8803a601ab1a4..678b5fd9d4d2076444847dc4bf9176cf2e02a3b0 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/board/BlackboardEntry.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/board/BlackboardEntry.java @@ -2,53 +2,57 @@ package de.evoal.core.api.board; public final class BlackboardEntry { + /** + * The target properties to search for. + */ public static final String TARGET_PROPERTIES = "TARGET_PROPERTIES"; - public static final String TARGET_PROPERTIES_SOURCE = "TARGET_PROPERTIES_SOURCE"; + + // public static final String TARGET_PROPERTIES_SOURCE = "TARGET_PROPERTIES_SOURCE"; /** * Folder containing the constraint validation models. */ - public static final String CONSTRAINT_VALIDATION_FOLDER = "CONSTRAINT_VALIDATION_FOLDER"; +// public static final String CONSTRAINT_VALIDATION_FOLDER = "CONSTRAINT_VALIDATION_FOLDER"; /** * Chooses the evaluation kind. */ - public static final String EVALUATION = "EVALUATION"; +// public static final String EVALUATION = "EVALUATION"; /** * Number of evaluation runs. */ - public static final String EVALUATION_ITERATIONS = "EVALUATION_ITERATIONS"; +// public static final String EVALUATION_ITERATIONS = "EVALUATION_ITERATIONS"; /** * The evaluation run number. */ - public static final String EVALUATION_RUN = "EVALUATION_RUN"; + public static final String EVALUATION_RUN = "core:evaluation-run"; /** * The actual output folder for the evaluation. */ - public static final String EVALUATION_OUTPUT_FOLDER = "EVALUATION_OUTPUT_FOLDER"; + public static final String EVALUATION_OUTPUT_FOLDER = "core:evaluation-output-folder"; /** * Configuration file containing the configuration fot the standard fitness function. */ - public static final String FITNESS_STANDARD_FUNCTION_FILE = "FITNESS_STANDARD_FUNCTION_FILE"; +// public static final String FITNESS_STANDARD_FUNCTION_FILE = "FITNESS_STANDARD_FUNCTION_FILE"; /** * The heuristic configuration. */ - public static final String EA_CONFIGURATION = "EA_CONFIGURATION"; + public static final String EA_CONFIGURATION = "core:ea-configuration"; /** * The file containing the ea configuration. */ - public static final String EA_CONFIGURATION_FILE = "EA_CONFIGURATION_FILE"; + public static final String EA_CONFIGURATION_FILE = "core:ea-configuration-file"; /** * File containing the machine learning file. */ - public static final String MACHINE_LEARNING_FILE = "MACHINE_LEARNING_FILE"; +// public static final String MACHINE_LEARNING_FILE = "MACHINE_LEARNING_FILE"; /** * Name of the main to run. @@ -58,32 +62,33 @@ public final class BlackboardEntry { /** * The trained predictive function */ - public static final String PREDICTIVE_FUNCTION = "PREDICTIVE_FUNCTION"; +// public static final String PREDICTIVE_FUNCTION = "PREDICTIVE_FUNCTION"; /** * The predictive configuration to use */ - public static final String PREDICTIVE_FUNCTION_CONFIGURATION = "PREDICTIVE_FUNCTION_CONFIGURATION"; +// public static final String PREDICTIVE_FUNCTION_CONFIGURATION = "PREDICTIVE_FUNCTION_CONFIGURATION"; /** * File containing the predictive function file. */ - public static final String PREDICTIVE_FUNCTION_FILE = "PREDICTIVE_FUNCTION_FILE"; +// public static final String PREDICTIVE_FUNCTION_FILE = "PREDICTIVE_FUNCTION_FILE"; /** * Targets. */ - public static final String TARGET_POINTS = "TARGET_POINTS"; +// public static final String TARGET_POINTS = "TARGET_POINTS"; /** * File containing targets for evaluation. */ - public static final String TARGETS_FILE = "TARGETS_FILE"; +// public static final String TARGETS_FILE = "TARGETS_FILE"; /** * File containing the training points. */ - public static final String TRAINING_POINT_FILE = "TRAINING_POINT_FILE"; +// public static final String TRAINING_POINT_FILE = "TRAINING_POINT_FILE"; + private final String label; private BlackboardEntry(final String label) { @@ -94,6 +99,10 @@ public final class BlackboardEntry { return label; } + public boolean isSame(final String label) { + return this.label.equals(label); + } + public static BlackboardEntry of(final String label) { return new BlackboardEntry(label); } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/FitnessBase.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/FitnessBase.java deleted file mode 100644 index 1f562237f6bcd94889dfdecac12b538cb7b2fd8c..0000000000000000000000000000000000000000 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/FitnessBase.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.evoal.core.api.ea.fitness; - -import de.evoal.core.api.ea.constraints.strategies.fitness.MalusForFitnessStrategy; -import de.evoal.core.api.ea.fitness.type.FitnessConverter; -import de.evoal.core.api.board.BlackboardEntry; -import de.evoal.core.api.cdi.BlackboardValue; -import de.evoal.core.api.ea.fitness.type.FitnessType; -import de.evoal.core.api.properties.Properties; - -import javax.inject.Inject; -import javax.inject.Named; - -/** - * Base class for fitness functions that allows manipulating the calculated fitness - * values (in case of multi-optimization problems) based on, e.g., constraint - * violations. - */ -public abstract class FitnessBase implements FitnessEvaluator { - @Inject @Named("depending") - private FitnessConverter converter; - - @Inject - private MalusForFitnessStrategy malus; - - /** - * The surrogate function used. - */ - //@Inject - // TODO protected SurrogateFunction surrogate; - - /** - * The property values we are looking for. - */ - @Inject - @BlackboardValue(BlackboardEntry.TARGET_PROPERTIES) - protected Properties targetVector; - - /** - * The actual fitness function we are wrapping. - */ - protected abstract double [] _fitness(final Properties candidate); - - /** - * Calculates the fitness of the given candidate. - * - * @param candidate The possible candidate individual. - * @return The calculated fitness value. - */ - @Override - public final FitnessType evaluate(final Properties candidate) { - final double [] fitnessValues = _fitness(candidate); - - malus.apply(candidate, fitnessValues); - - return converter.convert(fitnessValues); - } -} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/FitnessEvaluator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/FitnessEvaluator.java deleted file mode 100644 index 1f234b10dd2204b70df24976048dada47290d95b..0000000000000000000000000000000000000000 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/FitnessEvaluator.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.evoal.core.api.ea.fitness; - -import de.evoal.core.api.ea.fitness.type.FitnessType; -import de.evoal.core.api.properties.Properties; - -import java.util.function.Function; - -/** - * A fitness evaluator calculates the fitness for a given individual. - */ -public interface FitnessEvaluator extends Function<Properties, FitnessType> { - /** - * Calculates the fitness value of the given individual. - */ - public FitnessType evaluate(final Properties individual); - - /** - * See {@link #evaluate(Properties)}. - */ - default FitnessType apply(final Properties individual) { - return evaluate(individual); - } -} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/FitnessFunction.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/FitnessFunction.java new file mode 100644 index 0000000000000000000000000000000000000000..fc2aa14d663a6fc3ee5e08d27053274f9ea64af3 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/FitnessFunction.java @@ -0,0 +1,20 @@ +package de.evoal.core.api.ea.fitness; + +import de.evoal.core.api.properties.Properties; +import de.evoal.languages.model.instance.Instance; + +import java.util.function.Function; + +/** + * A fitness function calculates a list of doubles for a given individual, + * expressing some kind of similarity measures. + */ +public interface FitnessFunction extends Function<Properties, double []> { + public default double [] apply(final Properties properties) { + return evaluate(properties); + } + + public double [] evaluate(final Properties properties); + + FitnessFunction init(final Instance config); +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/comparator/FitnessComparator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/comparator/FitnessComparator.java new file mode 100644 index 0000000000000000000000000000000000000000..ae502fa9608935e260b09111d90eac48299195f2 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/comparator/FitnessComparator.java @@ -0,0 +1,25 @@ +package de.evoal.core.api.ea.fitness.comparator; + +import de.evoal.languages.model.instance.Instance; + +import java.util.function.Function; + +/** + * Converts a given set of fitness values (result of {@link de.evoal.core.api.ea.fitness.FitnessFunction} + * into a {@link FitnessValue} for Jenetics. + */ +public interface FitnessComparator extends Function<double [], FitnessValue> { + /** + * Creates a fitness type instance for the given fitness values. + * + * @param fitnessValues The calculated fitness values to convert. + * @return The calculated FitnessType. + */ + public FitnessValue compare(final double [] fitnessValues); + + public default FitnessValue apply(final double [] fitnessValues) { + return compare(fitnessValues); + } + + FitnessComparator init(final Instance config); +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/comparator/FitnessValue.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/comparator/FitnessValue.java new file mode 100644 index 0000000000000000000000000000000000000000..fb8253ad7794b3ef9e9f380aa8ee3f1aab7c9cd9 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/comparator/FitnessValue.java @@ -0,0 +1,7 @@ +package de.evoal.core.api.ea.fitness.comparator; + +/** + * The fitness value is an abstract type that allows comparing them. + */ +public interface FitnessValue extends Comparable<FitnessValue> { +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/type/FitnessConverter.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/type/FitnessConverter.java deleted file mode 100644 index 2cd6d599bf462c1b7a5ae292eb0b84996ffd4b97..0000000000000000000000000000000000000000 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/type/FitnessConverter.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.evoal.core.api.ea.fitness.type; - -/** - * Converter base for creating FitnessType's from distance arrays. - */ -public interface FitnessConverter { - /** - * Creates a fitness type instance for the given fitness values. - * - * @param fitnessValues The calculated fitness values to convert. - * @return The calculated FitnessType. - */ - public FitnessType convert(final double [] fitnessValues); -} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/type/FitnessType.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/type/FitnessType.java deleted file mode 100644 index d3e894bfa7ca2b1b891fedb79845d2ac18b7e0f4..0000000000000000000000000000000000000000 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/fitness/type/FitnessType.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.evoal.core.api.ea.fitness.type; - -/** - * The fitness type of the heuristic search. - */ -public interface FitnessType extends Comparable<FitnessType> { - /** - * @return All fitness values - */ - public double[] getFitnessValues(); -} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/initial/InitialPopulation.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/initial/InitialPopulation.java new file mode 100644 index 0000000000000000000000000000000000000000..445e3335fddfd00af904abbff9ead197b8d81d4a --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/initial/InitialPopulation.java @@ -0,0 +1,15 @@ +package de.evoal.core.api.ea.initial; + +import de.evoal.languages.model.instance.Instance; +import io.jenetics.Gene; +import io.jenetics.engine.Engine; +import io.jenetics.engine.EvolutionStream; + +import java.util.function.Function; + +public interface InitialPopulation<G extends Gene<?, G>, C extends Comparable<C>> { + InitialPopulation init(Instance initialization); + + public EvolutionStream<G, C> create(final Engine<G, C> engine); + +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/statistics/StatisticsWriter.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/statistics/StatisticsWriter.java index 29586f7637b9fe8f22706e068461424bd725949b..501057998afce3a4385f4ec42000ef98ebb81d34 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/statistics/StatisticsWriter.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/statistics/StatisticsWriter.java @@ -1,6 +1,6 @@ package de.evoal.core.api.statistics; -import de.evoal.core.api.ea.fitness.type.FitnessType; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; import de.evoal.languages.model.instance.Instance; import io.jenetics.engine.EvolutionResult; @@ -19,7 +19,7 @@ public interface StatisticsWriter { /** * Adds a evaluation result to the statistics. */ - public void add(final EvolutionResult<?, FitnessType> result); + public void add(final EvolutionResult<?, FitnessValue> result); /** * Passes the writer configuration. diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/Evoal.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/Evoal.java index 36da25acf27caadb7298e88598495d96c9b488a4..07913ade960a3d03831e3fa30a5c9a8884718314 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/Evoal.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/Evoal.java @@ -60,6 +60,5 @@ public final class Evoal { for(final Bean<MainClass> bean : beans) { log.error(" {}", bean.getName()); } - } } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/ParetoComparator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/ParetoComparator.java new file mode 100644 index 0000000000000000000000000000000000000000..21baf96561ba22f36a0d9204f0454664acbca926 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/ParetoComparator.java @@ -0,0 +1,23 @@ +package de.evoal.core.main.ea.comparator; + +import de.evoal.core.api.ea.fitness.comparator.FitnessComparator; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; +import de.evoal.languages.model.instance.Instance; + +import javax.enterprise.context.ApplicationScoped; + +import javax.inject.Named; + +@ApplicationScoped +@Named("pareto") +public class ParetoComparator implements FitnessComparator { + @Override + public FitnessValue compare(final double[] fitnessValues) { + return ParetoFitnessValue.of(fitnessValues); + } + + @Override + public ParetoComparator init(Instance config) { + return this; + } +} diff --git a/src/core/attic/de/evoal/core/main/ea/comparator/pareto/ParetoComparatorType.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/ParetoFitnessValue.java similarity index 51% rename from src/core/attic/de/evoal/core/main/ea/comparator/pareto/ParetoComparatorType.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/ParetoFitnessValue.java index 0e012fcb2d2f9028a029dcffce135fc06174b029..e4bf15cd5bae1dac9b5f0c7f397df5c760b12909 100644 --- a/src/core/attic/de/evoal/core/main/ea/comparator/pareto/ParetoComparatorType.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/ParetoFitnessValue.java @@ -1,25 +1,29 @@ -package de.evoal.core.main.ea.comparator.pareto; +package de.evoal.core.main.ea.comparator; import java.util.Arrays; -import de.evoal.core.api.ea.fitness.type.FitnessType; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; import io.jenetics.ext.moea.Vec; import lombok.NonNull; -public class ParetoComparatorType implements FitnessType { +public class ParetoFitnessValue implements FitnessValue { private final Vec<double []> fitnessValues; - private ParetoComparatorType(final @NonNull double[] fitnessValues) { + private ParetoFitnessValue(final @NonNull double[] fitnessValues) { this.fitnessValues = Vec.of(fitnessValues); } - public static FitnessType of(final double [] fitnessValues) { - return new ParetoComparatorType(fitnessValues); + public static FitnessValue of(final double [] fitnessValues) { + return new ParetoFitnessValue(fitnessValues); } @Override - public int compareTo(final FitnessType other) { - return this.makeAbsolute().compareTo(((ParetoComparatorType)other).makeAbsolute()); + public int compareTo(final FitnessValue other) { + if(!(other instanceof ParetoFitnessValue)) { + throw new IllegalArgumentException("Only allowed to compare pareto fitness values"); + } + + return this.makeAbsolute().compareTo(((ParetoFitnessValue)other).makeAbsolute()); } private final Vec<double[]> makeAbsolute(){ @@ -31,11 +35,6 @@ public class ParetoComparatorType implements FitnessType { return Vec.of(negativeAbsoluteValues); } - @Override - public double[] getFitnessValues() { - return fitnessValues.data(); - } - @Override public String toString() { return "ParetoComparatorType [values=" + fitnessValues + "]"; diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/WeightedSumComparator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/WeightedSumComparator.java new file mode 100644 index 0000000000000000000000000000000000000000..90ac991abc22da1fa977d2f3164965117a27be58 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/WeightedSumComparator.java @@ -0,0 +1,39 @@ +package de.evoal.core.main.ea.comparator; + +import de.evoal.core.api.ea.fitness.comparator.FitnessComparator; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; +import de.evoal.languages.model.el.DoubleLiteral; +import de.evoal.languages.model.instance.Array; +import de.evoal.languages.model.instance.Instance; +import de.evoal.languages.model.instance.LiteralValue; +import de.evoal.languages.model.instance.Value; + +import javax.enterprise.context.Dependent; +import javax.inject.Named; + +@Dependent +@Named("weighted-sum") +public class WeightedSumComparator implements FitnessComparator { + private double [] weights; + + @Override + public FitnessValue compare(final double[] fitnessValues) { + return WeightedSumFitnessValue.of(weights, fitnessValues); + } + + @Override + public FitnessComparator init(final Instance config) { + final Array weights = (Array) config.findAttribute("weights") + .getValue(); + + this.weights = weights.getValues() + .stream() + .map(LiteralValue.class::cast) + .map(LiteralValue::getLiteral) + .map(DoubleLiteral.class::cast) + .mapToDouble(DoubleLiteral::getValue) + .toArray(); + + return this; + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/WeightedSumFitnessValue.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/WeightedSumFitnessValue.java new file mode 100644 index 0000000000000000000000000000000000000000..b81806142460964ae20db832c3b92b7ec683c292 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/WeightedSumFitnessValue.java @@ -0,0 +1,55 @@ +package de.evoal.core.main.ea.comparator; + +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; +import de.evoal.core.api.utils.Requirements; +import lombok.Getter; +import lombok.NonNull; + +import java.util.Arrays; + +import static de.evoal.core.api.utils.Requirements.requireSameSize; + +public class WeightedSumFitnessValue implements FitnessValue { + @Getter + private final @NonNull double[] fitnessValues; + private final @NonNull double[] normalizedWeights; + + private WeightedSumFitnessValue(final @NonNull double[] weights, final @NonNull double[] fitnessValues) { + Requirements.requireSameSize(weights, fitnessValues); + + this.normalizedWeights = new double[weights.length]; + System.arraycopy(weights, 0, normalizedWeights, 0, weights.length); + this.fitnessValues = fitnessValues; + + final double sumOfWeights = Arrays.stream(weights).sum(); + for(int i = 0; i < normalizedWeights.length; ++i) { + normalizedWeights[i] = normalizedWeights[i] / sumOfWeights; + } + } + + public static FitnessValue of(final double [] weights, final double [] fitnessValues) { + return new WeightedSumFitnessValue(weights, fitnessValues); + } + + @Override + public int compareTo(final FitnessValue other) { + if(!(other instanceof WeightedSumFitnessValue)) { + throw new IllegalArgumentException("Only allowed to compare WeightedSumFitnessValue"); + } + + double ownFitness = 0.0; + double otherFitness = 0.0; + + for(int index = 0; index < fitnessValues.length; ++index) { + ownFitness = ownFitness - this.normalizedWeights[index] * Math.abs(this.fitnessValues[index]); + otherFitness = otherFitness - this.normalizedWeights[index] * Math.abs(((WeightedSumFitnessValue)other).getFitnessValues()[index]); + } + + return ownFitness == otherFitness ? 0 : (int)Math.signum(ownFitness - otherFitness); + } + + @Override + public String toString() { + return "WeightedSum [fit=" + Arrays.toString(fitnessValues) + ", w" + Arrays.toString(normalizedWeights) + "]"; + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/DistanceFitness.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/DistanceFitness.java new file mode 100644 index 0000000000000000000000000000000000000000..7b971da36b55bdfa01ae2401a4f2dcabed2599b1 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/DistanceFitness.java @@ -0,0 +1,65 @@ +package de.evoal.core.main.ea.fitness; + +import de.evoal.core.api.board.Blackboard; +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.ea.fitness.FitnessFunction; +import de.evoal.core.api.properties.Properties; +import de.evoal.core.api.utils.Requirements; +import de.evoal.languages.model.instance.Array; +import de.evoal.languages.model.instance.Attribute; +import de.evoal.languages.model.instance.Instance; +import org.apache.commons.math3.util.Pair; + +import javax.enterprise.context.Dependent; +import javax.inject.Inject; +import javax.inject.Named; +import java.util.stream.Stream; + +@Dependent +@Named("distance") +public class DistanceFitness extends FitnessDecorator { + + @Inject + private Blackboard board; + + /** + * The target to search for. + */ + private Properties target; + + @Override + public double[] evaluate(final Properties properties) { + final double [] target = this.target.getValues(); + final double [] current = decoratedFunction.evaluate(properties); + + Requirements.requireSameSize(current, target); + + + final double result[] = new double[target.length]; + for(int i = 0; i < target.length; ++i) { + result[i] = target[i] - current[i]; + } + + return result; + } + + @Override + public FitnessFunction init(final Instance config) { + super.init(config); + + final Attribute target = config.findAttribute("target"); + + if(target == null) { + this.target = board.get(BlackboardEntry.TARGET_PROPERTIES); + } else { + this.target = toProperties((Array)target.getValue()); + } + + return this; + } + + private static Properties toProperties(final Array value) { + + return null; + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/FitnessDecorator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/FitnessDecorator.java new file mode 100644 index 0000000000000000000000000000000000000000..27d56829815e927e3cb7d7682c2e0c9330d86725 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/FitnessDecorator.java @@ -0,0 +1,18 @@ +package de.evoal.core.main.ea.fitness; + +import de.evoal.core.api.cdi.BeanFactory; +import de.evoal.core.api.ea.fitness.FitnessFunction; +import de.evoal.languages.model.instance.Instance; + +public abstract class FitnessDecorator implements FitnessFunction { + protected FitnessFunction decoratedFunction; + + @Override + public FitnessFunction init(final Instance config) { + final Instance decoratedConfig = (Instance) config.findAttribute("function").getValue(); + + decoratedFunction = BeanFactory.create(decoratedConfig.getName().getName(), FitnessFunction.class); + + return this; + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/FitnessFactory.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/FitnessFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..39712d10ec13fee8cfd1aa3428b8790f748ca2e2 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/FitnessFactory.java @@ -0,0 +1,54 @@ +package de.evoal.core.main.ea.fitness; + +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.cdi.ConfigurationValue; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Dependent; +import javax.enterprise.inject.Produces; + +import de.evoal.core.api.ea.fitness.FitnessFunction; +import de.evoal.core.api.ea.fitness.comparator.FitnessComparator; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; +import de.evoal.core.api.properties.Properties; +import de.evoal.languages.model.instance.Instance; +import lombok.extern.slf4j.Slf4j; +import org.apache.deltaspike.core.api.provider.BeanProvider; + +@ApplicationScoped +@Slf4j +public class FitnessFactory { + private final String NAME_SUFFIX = "-fitness"; + + private FitnessFactory() { + } + + /** + * Creates a fitness function based on the heuristic configuration.<br/> + * Blackboard slots used: + * <ul> + * <li>{@link BlackboardEntry#EA_CONFIGURATION}.</li> + * </ul> + */ + @Produces @Dependent + public JeneticsFitnessFunction create(final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.fitness") Instance fitnessConfig, + final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.comparator") Instance comparatorConfig) { + final String fitnessName = fitnessConfig.getName().getName(); + final String comparatorName = comparatorConfig.getName().getName(); + + log.info("Creating fitness function {} and using comparator {}.", fitnessName, comparatorName); + + final FitnessFunction ff = BeanProvider.getContextualReference(fitnessName, false, FitnessFunction.class) + .init(fitnessConfig); + final FitnessComparator cmp = BeanProvider.getContextualReference(comparatorName, false, FitnessComparator.class) + .init(comparatorConfig); + + return new JeneticsFitnessFunction() { + @Override + public FitnessValue apply(final Properties properties) { + double [] values = ff.evaluate(properties); + return cmp.compare(values); + } + }; + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/JeneticsFitnessFunction.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/JeneticsFitnessFunction.java new file mode 100644 index 0000000000000000000000000000000000000000..5da57327355a1db7f3914fe8ef6a74e4c9eefb5e --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/fitness/JeneticsFitnessFunction.java @@ -0,0 +1,9 @@ +package de.evoal.core.main.ea.fitness; + +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; +import de.evoal.core.api.properties.Properties; + +import java.util.function.Function; + +public interface JeneticsFitnessFunction extends Function<Properties, FitnessValue> { +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/initial/InitialPopulationFactory.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/initial/InitialPopulationFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..ac8f7f1d66babc6a727d5997d695a62165fe1d4d --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/initial/InitialPopulationFactory.java @@ -0,0 +1,27 @@ +package de.evoal.core.main.ea.initial; + +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.cdi.BeanFactory; +import de.evoal.core.api.cdi.ConfigurationValue; +import de.evoal.core.api.ea.initial.InitialPopulation; +import de.evoal.languages.model.instance.Instance; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Dependent; +import javax.enterprise.inject.Produces; + +@ApplicationScoped +public class InitialPopulationFactory { + /** + * Creates a initial generation based on the heuristic configuration. + * + * Blackboard slots used: + * <ul> + * <li>{@link BlackboardEntry#EA_CONFIGURATION}.</li> + * </ul> + */ + @Produces @Dependent + public InitialPopulation create(@ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.initialization") final Instance initialization) { + return BeanFactory.create(initialization.getName().getName(), InitialPopulation.class) + .init(initialization); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/initial/RandomInitialPopulation.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/initial/RandomInitialPopulation.java new file mode 100644 index 0000000000000000000000000000000000000000..5f0c948295cd3662aa9e625db2c15516877c70d1 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/initial/RandomInitialPopulation.java @@ -0,0 +1,23 @@ +package de.evoal.core.main.ea.initial; + +import de.evoal.core.api.ea.initial.InitialPopulation; +import de.evoal.languages.model.instance.Instance; +import io.jenetics.Gene; +import io.jenetics.engine.Engine; +import io.jenetics.engine.EvolutionStream; + +import javax.inject.Named; + +@Named("random") +public class RandomInitialPopulation<G extends Gene<?, G>, C extends Comparable<C>> implements InitialPopulation<G, C> { + @Override + public InitialPopulation init(Instance initialization) { + // this is not the function you are looking for. + return this; + } + + @Override + public EvolutionStream<G, C> create(final Engine<G, C> engine) { + return engine.stream(); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/ConstraintList.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/ConstraintList.java new file mode 100644 index 0000000000000000000000000000000000000000..1f3c7c540b9f3f17376f2195303cf4c4b89bf5e9 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/ConstraintList.java @@ -0,0 +1,32 @@ +package de.evoal.core.main.jenetics; + +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; +import io.jenetics.Gene; +import io.jenetics.Phenotype; +import io.jenetics.engine.Constraint; + +import java.util.List; + +public class ConstraintList<G extends Gene<?, G>> implements Constraint<G, FitnessValue> { + private final List<Constraint<G, FitnessValue>> constraints; + + public ConstraintList(final List<Constraint<G, FitnessValue>> constraints) { + this.constraints = constraints; + } + + @Override + public boolean test(final Phenotype<G, FitnessValue> individual) { + return constraints.stream().allMatch(c -> c.test(individual)); + } + + @Override + public Phenotype<G, FitnessValue> repair(Phenotype<G, FitnessValue> individual, long generation) { + Phenotype<G, FitnessValue> phenotype = individual; + + for(final Constraint<G, FitnessValue> c : constraints) { + phenotype = c.repair(phenotype, generation); + } + + return phenotype; + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/ConfigurationValueProducer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/ConfigurationValueProducer.java new file mode 100644 index 0000000000000000000000000000000000000000..268f125f140bbed31b76809a135a3758cc32f06d --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/ConfigurationValueProducer.java @@ -0,0 +1,76 @@ +package de.evoal.core.main.producer; + +import de.evoal.core.api.board.Blackboard; +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.cdi.ConfigurationValue; +import de.evoal.core.api.utils.LanguageHelper; +import de.evoal.languages.model.eal.EAModel; +import de.evoal.languages.model.el.DoubleLiteral; +import de.evoal.languages.model.instance.Array; +import de.evoal.languages.model.instance.Instance; +import de.evoal.languages.model.instance.LiteralValue; +import lombok.extern.slf4j.Slf4j; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.InjectionPoint; + +@ApplicationScoped +@Slf4j +public class ConfigurationValueProducer { + @Produces + @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "") + public Integer injectIntegerValue(final InjectionPoint ip, final Blackboard board) { + final ConfigurationValue value = ip.getAnnotated().getAnnotation(ConfigurationValue.class); + + return lookup(board.get(value.entry()), value.access()); + } + + @Produces + @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "") + public Double injectDoubleValue(final InjectionPoint ip, final Blackboard board) { + final ConfigurationValue value = ip.getAnnotated().getAnnotation(ConfigurationValue.class); + + return lookup(board.get(value.entry()), value.access()); + } + + @Produces + @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "") + public String injectStringValue(final InjectionPoint ip, final Blackboard board) { + final ConfigurationValue value = ip.getAnnotated().getAnnotation(ConfigurationValue.class); + + return lookup(board.get(value.entry()), value.access()); + } + + @Produces + @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "") + public final Instance injectInstanceValue(final InjectionPoint ip, final Blackboard board) { + final ConfigurationValue value = ip.getAnnotated().getAnnotation(ConfigurationValue.class); + + return lookup(board.get(value.entry()), value.access()); + } + + @Produces + @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "") + public Boolean injectBooleanValue(final InjectionPoint ip, final Blackboard board) { + final ConfigurationValue value = ip.getAnnotated().getAnnotation(ConfigurationValue.class); + + return lookup(board.get(value.entry()), value.access()); + } + + @Produces + @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "") + public double [] injectDoubleArrayValue(final InjectionPoint ip, final Blackboard board) { + final ConfigurationValue value = ip.getAnnotated().getAnnotation(ConfigurationValue.class); + + return (ConfigurationValueProducer.<Array>lookup(board.get(value.entry()), value.access())) + .getValues() + .stream() + .mapToDouble(x -> ((DoubleLiteral)(((LiteralValue)x).getLiteral())).getValue()) + .toArray(); + } + + private static <T> T lookup(final EAModel model, final String access) { + return LanguageHelper.lookup(model.getInstance(), access); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/EvolutionaryAlgorithmModelLoader.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/EvolutionaryAlgorithmModelLoader.java index 7b911646b182982f04a514ed6a65642c6fa1ad64..c91ec74c35bacdfd4f55b6684194141dab86e5a2 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/EvolutionaryAlgorithmModelLoader.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/EvolutionaryAlgorithmModelLoader.java @@ -8,12 +8,11 @@ import javax.enterprise.context.Dependent; import javax.enterprise.event.Observes; import javax.enterprise.inject.Produces; +import de.evoal.languages.model.ddl.dsl.DataDescriptionLanguageStandaloneSetup; import de.evoal.languages.model.dl.dsl.DefinitionLanguageStandaloneSetup; import de.evoal.languages.model.eal.EAModel; import de.evoal.languages.model.eal.dsl.EvolutionaryAlgorithmLanguageStandaloneSetup; -import de.evoal.languages.model.dl.impl.DlPackageImpl; import de.evoal.languages.model.eal.impl.EALPackageImpl; -import de.evoal.languages.model.el.dsl.ExpressionLanguageStandaloneSetup; import lombok.extern.slf4j.Slf4j; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; @@ -31,7 +30,7 @@ public class EvolutionaryAlgorithmModelLoader { private EAModel model; public void load(final @Observes BlackboardEntry entry) { - if(!BlackboardEntry.EA_CONFIGURATION_FILE.equals(entry)) { + if(!entry.isSame(BlackboardEntry.EA_CONFIGURATION_FILE)) { return; } @@ -44,7 +43,6 @@ public class EvolutionaryAlgorithmModelLoader { throw new IllegalArgumentException("Unable to read evolutionary algorithm configuration file: " + configurationFileName); } - initializeEMF(); final Injector ealInjector = new EvolutionaryAlgorithmLanguageStandaloneSetup().createInjectorAndDoEMFRegistration(); @@ -86,17 +84,9 @@ public class EvolutionaryAlgorithmModelLoader { */ private void initializeEMF() { EALPackageImpl.init(); - DlPackageImpl.init(); - EALPackageImpl.init(); - /* - if (!EPackage.Registry.INSTANCE.containsKey("https://www.evoal.de/languages/idl/1.0.0")) { - EPackage.Registry.INSTANCE.put("https://www.evoal.de/languages/idl/1.0.0", DlPackage.eINSTANCE); - } -*/ - ExpressionLanguageStandaloneSetup.doSetup(); - DefinitionLanguageStandaloneSetup.doSetup(); EvolutionaryAlgorithmLanguageStandaloneSetup.doSetup(); + DataDescriptionLanguageStandaloneSetup.doSetup(); } @Produces diff --git a/src/core/attic/de/evoal/core/main/search/HeuristicSearch.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearch.java similarity index 61% rename from src/core/attic/de/evoal/core/main/search/HeuristicSearch.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearch.java index 63e6718c42b8969ca83a8cb4f38d83476d285ed0..3ca2b0257b829b5f351e1e89baa8e450e63cc44e 100644 --- a/src/core/attic/de/evoal/core/main/search/HeuristicSearch.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearch.java @@ -5,19 +5,19 @@ import java.time.Duration; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.function.Function; import de.evoal.core.api.board.BlackboardEntry; import de.evoal.core.api.board.Blackboard; import de.evoal.core.api.cdi.BlackboardValue; import de.evoal.core.api.cdi.ConfigurationValue; -import de.evoal.core.main.ea.alterer.AltererFactory; import de.evoal.core.api.utils.LanguageHelper; import de.evoal.core.api.ea.codec.CustomCodec; -import de.evoal.core.api.ea.fitness.type.FitnessType; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; -import de.evoal.core.api.ea.fitness.FitnessEvaluator; import de.evoal.core.api.statistics.StatisticsWriter; +import de.evoal.core.main.ea.fitness.JeneticsFitnessFunction; +import de.evoal.core.api.ea.initial.InitialPopulation; +import de.evoal.core.main.jenetics.ConstraintList; import de.evoal.languages.model.eal.EAModel; import de.evoal.languages.model.instance.Array; import de.evoal.languages.model.instance.Attribute; @@ -29,13 +29,14 @@ import io.jenetics.stat.MinMax; import io.jenetics.util.Factory; import lombok.extern.slf4j.Slf4j; +import javax.enterprise.context.Dependent; import javax.enterprise.inject.Instance; import javax.inject.Inject; -import javax.inject.Named; @Slf4j -public class HeuristicSearch<G extends Gene<?, G>> { +@Dependent +public class HeuristicSearch { @Inject private Blackboard board; @@ -55,57 +56,56 @@ public class HeuristicSearch<G extends Gene<?, G>> { @Inject @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.number_of_generations") - private int numberOfGenerations = 100; + private int numberOfGenerations; @Inject @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.size_of_population") - private int sizeOfPopulation = 100; + private int sizeOfPopulation; @Inject @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.maximum_age") - private int maximumAge = 100; + private int maximumAge; - private final Map<String, List<Alterer<G, FitnessType>>> alterers = new HashMap<>(); + private final Map<String, List<Alterer<?, FitnessValue>>> alterers = new HashMap<>(); - @Inject + // TODO @Inject private CustomCodec encoding; private final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); @Inject - @Named("evaluator") - private FitnessEvaluator fitnessEvaluator; + private JeneticsFitnessFunction fitnessFunction; - @Inject @Named("offspring") - private Selector offspringSelector; + // TODO @Inject @Named("offspring") + // TODO private Selector offspringSelector; - @Inject @Named("statistics") + // TODO @Inject @Named("statistics") private StatisticsWriter statistics; - @Inject @Named("survivor") - private Selector survivorSelector; +// TODO @Inject @Named("survivor") +// TODO private Selector survivorSelector; - @Inject - private AltererFactory factory; +// TODO @Inject +// TODO private AltererFactory factory; - @Inject + // TODO @Inject private Instance<List<Constraint>> constraints; - @Inject - private Function<Engine, EvolutionStream> initalStreamFactory; + // TODO @Inject + private InitialPopulation initalStreamFactory; public void run() { setup(); - final Factory<Genotype<G>> gtf = encoding.encoding(); + final Factory<Genotype<?>> gtf = encoding.encoding(); - final Constraint<G, FitnessType> constraint = new ListConstraint(constraints.get()); + final Constraint<?, FitnessValue> constraint = new ConstraintList(constraints.get()); - final Engine<G, FitnessType> engine= Engine.builder(this.fitnessEvaluator, encoding) + final Engine<?, FitnessValue> engine= Engine.builder(this.fitnessFunction, encoding) .alterers(flattenAltererMap()) - .offspringSelector(this.offspringSelector) - .survivorsSelector(this.survivorSelector) + // TODO.offspringSelector(this.offspringSelector) + // TODO.survivorsSelector(this.survivorSelector) .optimize(Optimize.MAXIMUM) .populationSize(sizeOfPopulation) .constraint(constraint) @@ -113,10 +113,10 @@ public class HeuristicSearch<G extends Gene<?, G>> { .executor(executor) .build(); - EvolutionStatistics<FitnessType, MinMax<FitnessType>> statistics = EvolutionStatistics.ofComparable(); - EvolutionStream<G, FitnessType> initialStream = initalStreamFactory.apply(engine); + EvolutionStatistics<FitnessValue, MinMax<FitnessValue>> statistics = EvolutionStatistics.ofComparable(); + EvolutionStream<?, FitnessValue> initialStream = initalStreamFactory.create(engine); - final EvolutionResult<G, FitnessType> result + final EvolutionResult<?, FitnessValue> result = initialStream.limit(Limits.byFixedGeneration(numberOfGenerations)) .limit(Limits.byExecutionTime(Duration.ofMinutes(5))) // .parallel() @@ -142,24 +142,24 @@ public class HeuristicSearch<G extends Gene<?, G>> { final Array array = (Array) category.getValue(); for(final Value alterer : array.getValues()) { - this.alterers - .computeIfAbsent(name, k -> new ArrayList<>()) - .add(factory.create((de.evoal.languages.model.instance.Instance)alterer)); +// TODO this.alterers +// TODO .computeIfAbsent(name, k -> new ArrayList<>()) +// TODO .add(factory.create((de.evoal.languages.model.instance.Instance)alterer)); } } } - private Alterer<G, FitnessType> flattenAltererMap() { - Alterer<G, FitnessType> result = null; + private <G extends Gene<?, G>> Alterer<?, FitnessValue> flattenAltererMap() { + Alterer<G, FitnessValue> result = null; - for(final Map.Entry<String, List<Alterer<G, FitnessType>>> entry : alterers.entrySet()) { - for(final Alterer<G, FitnessType> e : entry.getValue()) { + for(final Map.Entry<String, List<Alterer<?, FitnessValue>>> entry : alterers.entrySet()) { + for(final Alterer<?, FitnessValue> e : entry.getValue()) { if(result == null) { - result = e; + result = (Alterer<G, FitnessValue>) e; } else { - result = Alterer.of(result, e); + result = Alterer.of(result, (Alterer<G, FitnessValue>) e); } } } diff --git a/src/core/attic/de/evoal/core/main/search/HeuristicSearchMain.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchMain.java similarity index 88% rename from src/core/attic/de/evoal/core/main/search/HeuristicSearchMain.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchMain.java index e1f1da1c3aecf39e621f9a12d3ce216872b974b8..ede13d749b01a54968683d96bb08485a145cd80b 100644 --- a/src/core/attic/de/evoal/core/main/search/HeuristicSearchMain.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchMain.java @@ -28,20 +28,20 @@ public class HeuristicSearchMain implements MainClass { @Override public void run() { - final String predictiveFileName = board.get(BlackboardEntry.PREDICTIVE_FUNCTION_FILE); + final String outputFolder = board.get(BlackboardEntry.EVALUATION_OUTPUT_FOLDER); final String heuristicFileName = board.get(BlackboardEntry.EA_CONFIGURATION_FILE); - final File outputBaseDir = HeuristicSearchUtils.calculateOutputBaseDir(new File(predictiveFileName), new File(heuristicFileName)); + final File outputBaseDir = HeuristicSearchUtils.calculateOutputBaseDir(new File(outputFolder), new File(heuristicFileName)); HeuristicSearchUtils.addColumn(context,"target", ColumnType.Integer, 0); HeuristicSearchUtils.addColumn(context,"run", ColumnType.Integer, 0); board.bind(BlackboardEntry.EVALUATION_OUTPUT_FOLDER, outputBaseDir); board.bind(BlackboardEntry.EVALUATION_RUN, "0"); - +/* final Stream<Pair<Properties, Properties>> targets = (Stream<Pair<Properties, Properties>>)BeanProvider.getContextualReference("target-stream"); setTarget(targets, board); - +*/ BeanFactory.create(HeuristicSearch.class) .run(); } @@ -51,7 +51,7 @@ public class HeuristicSearchMain implements MainClass { targets.findFirst() .orElseThrow(() -> {throw new IllegalStateException("No target point found");}); - board.bind(BlackboardEntry.TARGET_PROPERTIES_SOURCE, targetProperties.getFirst()); +// TODO board.bind(BlackboardEntry.TARGET_PROPERTIES_SOURCE, targetProperties.getFirst()); board.bind(BlackboardEntry.TARGET_PROPERTIES, targetProperties.getSecond()); } } diff --git a/src/core/attic/de/evoal/core/main/search/HeuristicSearchUtils.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchUtils.java similarity index 64% rename from src/core/attic/de/evoal/core/main/search/HeuristicSearchUtils.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchUtils.java index 1c996ea81cce78dec212a8a349d4d6abc40c44b1..4e1abf34f31e785565070087a7a8711cee671e2b 100644 --- a/src/core/attic/de/evoal/core/main/search/HeuristicSearchUtils.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchUtils.java @@ -25,12 +25,7 @@ public final class HeuristicSearchUtils { return col; } - public static File calculateOutputBaseDir(final File predictiveFile, final File heuristicFile) { - String outputDirname = predictiveFile.toString(); - outputDirname = outputDirname.split("\\.")[0]; - outputDirname = outputDirname.replace("input/", "output/"); - final File outputDir = new File(outputDirname); - - return new File(outputDir, heuristicFile.getName().split("\\.")[0]); + public static File calculateOutputBaseDir(final File outputFolder, final File heuristicFile) { + return new File(outputFolder, heuristicFile.getName().split("\\.")[0]); } } diff --git a/src/core/attic/de/evoal/core/main/statistics/StatisticsFactory.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/StatisticsFactory.java similarity index 96% rename from src/core/attic/de/evoal/core/main/statistics/StatisticsFactory.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/StatisticsFactory.java index 864d339020fd4ac3b5c65042162ebca1def89a89..98d228a6ca306b7bbff88ae912554b752ad6f9dc 100644 --- a/src/core/attic/de/evoal/core/main/statistics/StatisticsFactory.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/StatisticsFactory.java @@ -8,6 +8,7 @@ import de.evoal.languages.model.instance.Array; import de.evoal.languages.model.instance.Instance; import de.evoal.core.main.statistics.internal.MultipleStatisticsWriter; import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Dependent; import javax.enterprise.inject.Produces; import org.apache.commons.math3.util.Pair; @@ -18,6 +19,7 @@ import javax.inject.Named; @ApplicationScoped public class StatisticsFactory { @Produces + @Dependent @Named("statistics") public StatisticsWriter create(final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "statistics") Instance instance) { Requirements.requireSize(instance.getAttributes(), 1); diff --git a/src/core/attic/de/evoal/core/main/statistics/internal/MultipleStatisticsWriter.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/internal/MultipleStatisticsWriter.java similarity index 84% rename from src/core/attic/de/evoal/core/main/statistics/internal/MultipleStatisticsWriter.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/internal/MultipleStatisticsWriter.java index 0b08abaaccf281ae08ef6d846f0280110928257e..921a2ad4538268eaaea743abbffa9692dc0d2246 100644 --- a/src/core/attic/de/evoal/core/main/statistics/internal/MultipleStatisticsWriter.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/internal/MultipleStatisticsWriter.java @@ -1,8 +1,8 @@ package de.evoal.core.main.statistics.internal; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; import de.evoal.languages.model.instance.Instance; import de.evoal.core.api.statistics.StatisticsWriter; -import de.evoal.core.api.ea.fitness.type.FitnessType; import io.jenetics.engine.EvolutionResult; import java.util.Arrays; @@ -15,7 +15,7 @@ public class MultipleStatisticsWriter implements StatisticsWriter { } @Override - public void add(final EvolutionResult<?, FitnessType> evolutionResult) { + public void add(final EvolutionResult<?, FitnessValue> evolutionResult) { Arrays.stream(writers).forEach(w -> w.add(evolutionResult)); } diff --git a/src/core/de.evoal.core/src/main/java/module-info.java b/src/core/de.evoal.core/src/main/java/module-info.java index 5cab81e5fee1086185bbbba05f0a51a25848bb3e..73bb87b6cec5f0816a88ed92318828c4404e1862 100644 --- a/src/core/de.evoal.core/src/main/java/module-info.java +++ b/src/core/de.evoal.core/src/main/java/module-info.java @@ -31,8 +31,9 @@ module de.evoal.core { requires org.eclipse.xtext; requires de.evoal.languages.model.ddl; - requires de.evoal.languages.model.dl.dsl; + requires de.evoal.languages.model.ddl.dsl; requires de.evoal.languages.model.dl; + requires de.evoal.languages.model.dl.dsl; requires de.evoal.languages.model.eal; requires de.evoal.languages.model.eal.dsl; requires de.evoal.languages.model.el; @@ -46,7 +47,8 @@ module de.evoal.core { exports de.evoal.core.api.ea.constraints.strategies; exports de.evoal.core.api.ea.constraints.strategies.fitness; exports de.evoal.core.api.ea.fitness; - exports de.evoal.core.api.ea.fitness.type; + exports de.evoal.core.api.ea.fitness.comparator; + exports de.evoal.core.api.ea.initial; exports de.evoal.core.api.properties; exports de.evoal.core.api.properties.io; exports de.evoal.core.api.properties.stream; @@ -65,8 +67,15 @@ module de.evoal.core { opens de.evoal.core.api.properties.stream to weld.core.impl; opens de.evoal.core.api.statistics to weld.core.impl; opens de.evoal.core.api.utils to weld.core.impl; + + opens de.evoal.core.main.ea.fitness to weld.core.impl; + opens de.evoal.core.main.ea.comparator to weld.core.impl; + opens de.evoal.core.main.ea.initial to weld.core.impl; opens de.evoal.core.main.producer to weld.core.impl; -/* + opens de.evoal.core.main.search to weld.core.impl; + opens de.evoal.core.main.statistics to weld.core.impl; + + /* opens de.evoal.core.main.ddl.correlation to weld.core.impl; opens de.evoal.core.main.ddl.constraint to weld.core.impl; opens de.evoal.core.main.ddl.constraint.strategies to weld.core.impl; @@ -76,10 +85,8 @@ module de.evoal.core { opens de.evoal.core.main.ddl.deviation to weld.core.impl; opens de.evoal.core.main.ea.alterer to weld.core.impl; opens de.evoal.core.main.ea.alterer.mutator to weld.core.impl; - opens de.evoal.core.main.search to weld.core.impl; opens de.evoal.core.main.statistics to weld.core.impl; opens de.evoal.core.main.statistics.constraint to weld.core.impl; - opens de.evoal.core.main.statistics.fitness to weld.core.impl; opens de.evoal.core.main.statistics.individuals to weld.core.impl; opens de.evoal.core.main.statistics.nop to weld.core.impl; opens de.evoal.core.main.statistics.rangeCorrelated to weld.core.impl; diff --git a/src/core/de.evoal.core/src/main/resources/logback.xml b/src/core/de.evoal.core/src/main/resources/logback.xml index 94e55be2c26acd3500962d34eaa3d74732293502..b5396d366d9c8c72320ed1d590249cde72359835 100644 --- a/src/core/de.evoal.core/src/main/resources/logback.xml +++ b/src/core/de.evoal.core/src/main/resources/logback.xml @@ -6,8 +6,10 @@ </appender> <logger name="de.evoal" level="INFO" /> + <logger name="org.jboss.weld" level="DEBUG" /> + <logger name="org.jboss.weld.level" level="DEBUG" /> - <root level="WARN"> + <root level="INFO"> <appender-ref ref="STDOUT" /> </root> </configuration> \ No newline at end of file diff --git a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/cdi/GeneratorConfigurationProducer.java b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/cdi/GeneratorConfigurationProducer.java index db9f87b33fbcd8b753da26aa53d780b35c3e6ba5..e67d4dba8a49e964353c3d1231011bcdda8aa5fe 100644 --- a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/cdi/GeneratorConfigurationProducer.java +++ b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/cdi/GeneratorConfigurationProducer.java @@ -33,7 +33,7 @@ import org.eclipse.xtext.resource.XtextResourceSet; @Slf4j public class GeneratorConfigurationProducer { public void loadModel(final @Observes BlackboardEntry value, final Blackboard board) { - if(!GeneratorBlackboardEntry.GENERATOR_CONFIGURATION_FILE.equals(value.getLabel())) { + if(!value.isSame(GeneratorBlackboardEntry.GENERATOR_CONFIGURATION_FILE)) { return; } diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/SurrogateBlackboardEntry.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/SurrogateBlackboardEntry.java index eddfbc21cca16a15cd8123e14b525e4047be088f..940cb15c2c15841dc0f556b0d01750eae485c2ec 100644 --- a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/SurrogateBlackboardEntry.java +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/SurrogateBlackboardEntry.java @@ -11,5 +11,10 @@ public final class SurrogateBlackboardEntry { */ public static final String SURROGATE_CONFIGURATION_FILE = "surrogate:configuration-file"; + /** + * File containing a pre-trained surrogate. + */ + public static final String PRETRAINED_SURROGATE_FILE = "surrogate:pre-trained"; + private SurrogateBlackboardEntry() {} } diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/function/SurrogateFunction.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/function/SurrogateFunction.java index 13233e1bd622a0211a36e6aa2e4cec61036e2421..6f43da8756dd92bb9a6dbe1fe4203a069f16c984 100644 --- a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/function/SurrogateFunction.java +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/function/SurrogateFunction.java @@ -2,6 +2,7 @@ package de.evoal.surrogate.api.function; import de.evoal.core.api.properties.Properties; import de.evoal.core.api.properties.PropertiesSpecification; +import de.evoal.surrogate.api.configuration.SurrogateConfiguration; import lombok.Data; import lombok.NonNull; diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/training/TrainingDataManager.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/training/TrainingDataManager.java index 1e8507b3fbb2352be8a24897d3aeac2f8dced994..664e7aa193389eb3f4571fb239943406c5f2e2da 100644 --- a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/training/TrainingDataManager.java +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/api/training/TrainingDataManager.java @@ -9,7 +9,6 @@ import javax.enterprise.context.ApplicationScoped; @ApplicationScoped public class TrainingDataManager { - @Getter @Setter private PropertiesStreamSupplier trainingStream; diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/MLLConfigurationProducer.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/MLLConfigurationProducer.java index a17d773fd40e4b0abda5f09579efd44fc674abe2..6b03b28af48d1a17f5938d0d93f99350735fa2c0 100644 --- a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/MLLConfigurationProducer.java +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/MLLConfigurationProducer.java @@ -32,7 +32,7 @@ import java.util.Optional; @Slf4j public class MLLConfigurationProducer { public void loadModel(final @Observes BlackboardEntry value, final Blackboard board) { - if(!SurrogateBlackboardEntry.SURROGATE_CONFIGURATION_FILE.equals(value.getLabel())) { + if(!value.isSame(SurrogateBlackboardEntry.SURROGATE_CONFIGURATION_FILE)) { return; } diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/SurrogateProducer.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/SurrogateProducer.java new file mode 100644 index 0000000000000000000000000000000000000000..c833689dbec7571e51115e75c68ed2d18596880b --- /dev/null +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/SurrogateProducer.java @@ -0,0 +1,73 @@ +package de.evoal.surrogate.main.cdi; + +import de.evoal.core.api.board.Blackboard; +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.properties.PropertiesSpecification; +import de.evoal.surrogate.api.SurrogateBlackboardEntry; +import de.evoal.surrogate.api.configuration.SurrogateConfiguration; +import de.evoal.surrogate.api.function.SurrogateFunction; +import lombok.Getter; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Dependent; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import javax.inject.Named; +import java.io.File; +import java.util.function.Function; + +@ApplicationScoped +@Slf4j +public class SurrogateProducer { + + private SurrogateConfiguration configuration; + + public void setPreTrainedSurrogate(final @Observes BlackboardEntry event, final Blackboard board, final Function<@NonNull File, @NonNull SurrogateConfiguration> loader) { + if(!event.isSame(SurrogateBlackboardEntry.PRETRAINED_SURROGATE_FILE)) { + return; + } + + final String filename = board.get(SurrogateBlackboardEntry.PRETRAINED_SURROGATE_FILE); + final File file = new File(filename); + + if(!file.exists()) { + log.error("Cannot find pre-trained surrogate model: {}", file); + return; + } + + this.configuration = loader.apply(file); + } + + @Produces + @Dependent + public SurrogateConfiguration create() { + return configuration; + } + + @Produces + @Dependent + @Named("surrogate-source-properties-specification") + public PropertiesSpecification createSourceProperties(final SurrogateConfiguration config) { + return PropertiesSpecification.builder() + .add(config.getMappings() + .get(0) + .getInputDimensions() + .stream()) + .build(); + } + + @Produces + @Dependent + @Named("surrogate-target-properties-specification") + public PropertiesSpecification createTargetProperties(final SurrogateConfiguration config) { + return PropertiesSpecification.builder() + .add(config.getMappings() + .get(config.getMappings().size() - 1) + .getOutputDimensions() + .stream()) + .build(); + } +} diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/SurrogateFitnessFunction.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/SurrogateFitnessFunction.java new file mode 100644 index 0000000000000000000000000000000000000000..45d9a45c05aab9593711ae4cee564fbda75448e6 --- /dev/null +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/SurrogateFitnessFunction.java @@ -0,0 +1,26 @@ +package de.evoal.surrogate.main.ea; + +import de.evoal.core.api.ea.fitness.FitnessFunction; +import de.evoal.core.api.properties.Properties; +import de.evoal.languages.model.instance.Instance; +import de.evoal.surrogate.api.function.SurrogateFunction; + +import javax.enterprise.context.Dependent; +import javax.inject.Named; + +@Dependent +@Named("surrogate") +public class SurrogateFitnessFunction implements FitnessFunction { + + private SurrogateFunction function; + + @Override + public double[] evaluate(final Properties properties) { + return function.apply(properties).getValues(); + } + + @Override + public FitnessFunction init(final Instance config) { + return this; + } +} diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingInitialPopulation.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingInitialPopulation.java new file mode 100644 index 0000000000000000000000000000000000000000..6e747777fe9740b1e7521d5f89f3493df6238d70 --- /dev/null +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingInitialPopulation.java @@ -0,0 +1,77 @@ +package de.evoal.surrogate.main.ea; + +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.cdi.ConfigurationValue; +import de.evoal.core.api.ea.codec.CustomCodec; +import de.evoal.core.api.ea.initial.InitialPopulation; +import de.evoal.core.api.properties.PropertiesSpecification; +import de.evoal.languages.model.instance.Instance; +import de.evoal.surrogate.api.training.TrainingDataManager; +import io.jenetics.Gene; +import io.jenetics.Genotype; +import io.jenetics.engine.Engine; +import io.jenetics.engine.EvolutionInit; +import io.jenetics.engine.EvolutionStream; +import io.jenetics.util.ISeq; + +import javax.annotation.PostConstruct; +import javax.enterprise.context.Dependent; +import javax.inject.Inject; +import javax.inject.Named; + +@Dependent +@Named("training") +public class TrainingInitialPopulation<G extends Gene<?, G>, C extends Comparable<C>> implements InitialPopulation<G, C> { + + @Inject + @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.size_of_population") + private int sizeOfPopulation; + + @Inject + private TrainingDataManager manager; + + @Inject + @Named("surrogate-source-properties-specification") + private PropertiesSpecification sourceSpecification; + + @Inject + @Named("surrogate-target-properties-specification") + private PropertiesSpecification targetSpecification; + + private PropertiesSpecification totalSpecification; + + @PostConstruct + public void init() { + totalSpecification = PropertiesSpecification.builder() + .add(sourceSpecification) + .add(targetSpecification) + .build(); + } + + // TODO @Inject + private CustomCodec<G> encoding; + + private EvolutionInit<G> createTargetBasedInitialPopulation() { + return EvolutionInit.of(createInitialPopulation(), 1l); + } + + private ISeq<Genotype<G>> createInitialPopulation() { + return + manager.getTrainingStream() + .apply(totalSpecification) + .unordered() + .limit(sizeOfPopulation) + .map(encoding::encode) + .collect(ISeq.toISeq()); + } + + @Override + public InitialPopulation init(final Instance initialization) { + return this; + } + + @Override + public EvolutionStream<G, C> create(final Engine<G, C> engine) { + return engine.stream(createTargetBasedInitialPopulation()); + } +} diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/correlated/GenerationStatisticsWriter.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/correlated/GenerationStatisticsWriter.java index d5e783918ead484b0f08b7a79fdf9afc4047c947..8bbd56a43826b816f2735b673340b69317959b9d 100644 --- a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/correlated/GenerationStatisticsWriter.java +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/correlated/GenerationStatisticsWriter.java @@ -3,9 +3,7 @@ package de.evoal.surrogate.main.statistics.correlated; import de.evoal.core.api.statistics.*; import de.evoal.core.api.utils.LanguageHelper; import de.evoal.languages.model.instance.Instance; -import de.evoal.core.api.board.BlackboardEntry; -import de.evoal.core.api.cdi.ConfigurationValue; -import de.evoal.core.api.ea.fitness.type.FitnessType; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; import de.evoal.core.api.ea.codec.CustomCodec; import de.evoal.core.api.properties.Properties; import de.evoal.core.api.properties.PropertiesSpecification; @@ -38,38 +36,38 @@ public class GenerationStatisticsWriter implements StatisticsWriter { /** * List of all existing fitness functions. */ - private List<Function<Properties, FitnessType>> functions; + private List<Function<Properties, Properties>> functions; /** * List of all function names */ - @Inject @Named("function-names") + // TODO @Inject @Named("function-names") private List<String> functionNames; /** * Encoding for converting between ea and domain. */ - @Inject + // TODO @Inject private CustomCodec encoding; private long startTime; - private EvolutionResult<?, FitnessType> generationWithBestIndividual; + private EvolutionResult<?, FitnessValue> generationWithBestIndividual; private long endTime; @Inject - private Provider<Function<Properties, FitnessType>> fitnessFactory; + private Provider<Function<Properties, Properties>> fitnessFactory; - @Inject @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.fitness") + // TODO @Inject @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.fitness") private Instance config; @Inject private TrainingDataManager manager; - @Inject @Named("source-properties-specification") + // TODO @Inject @Named("source-properties-specification") private PropertiesSpecification sourceSpec; - @Inject @Named("target-properties-specification") + // TODO @Inject @Named("target-properties-specification") private PropertiesSpecification targetSpec; private List<Properties> sourceTrainingPoints; @@ -77,7 +75,7 @@ public class GenerationStatisticsWriter implements StatisticsWriter { * Creates a new GenerationStatistics instance. */ - @Inject + // TODO @Inject private WriterStrategy strategy; @PostConstruct @@ -255,8 +253,8 @@ public class GenerationStatisticsWriter implements StatisticsWriter { final Properties candidate = (Properties) encoding.decode(generationWithBestIndividual.bestPhenotype().genotype()); for(int i = 0; i < functions.size(); ++i) { - final FitnessType fitness = functions.get(i).apply(candidate); - data[3 + i] = fitness.getFitnessValues()[0]; + final FitnessValue fitness = (FitnessValue) functions.get(i).apply(candidate); + data[3 + i] = fitness; throw new IllegalArgumentException("fix me"); } @@ -286,11 +284,11 @@ public class GenerationStatisticsWriter implements StatisticsWriter { throw new IllegalStateException("We have to change the actual fitness type by looking up the correct definition."); } - public void add(final EvolutionResult<?, FitnessType> evolutionResult) { + public void add(final EvolutionResult<?, FitnessValue> evolutionResult) { updateBestGeneration(evolutionResult); } - private void updateBestGeneration(final EvolutionResult<?, FitnessType> generation) { + private void updateBestGeneration(final EvolutionResult<?, FitnessValue> generation) { if(generationWithBestIndividual == null) { generationWithBestIndividual = generation; } else if(generationWithBestIndividual.bestFitness().compareTo(generation.bestFitness()) <= 0) { diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/surrogate/SurrogateStatistics.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/surrogate/SurrogateStatistics.java index 0bfd4e0288ce050cfa39bc87b54fc8d421f4e861..259e151a290c512eb815b53a09470ad0d4c0777d 100644 --- a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/surrogate/SurrogateStatistics.java +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/surrogate/SurrogateStatistics.java @@ -5,12 +5,11 @@ import java.util.List; import javax.annotation.PostConstruct; import javax.enterprise.context.Dependent; -import javax.inject.Inject; import javax.inject.Named; import de.evoal.core.api.statistics.*; import de.evoal.core.api.ea.codec.CustomCodec; -import de.evoal.core.api.ea.fitness.type.FitnessType; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; import de.evoal.core.api.properties.Properties; import de.evoal.core.api.properties.PropertiesSpecification; import de.evoal.languages.model.instance.Instance; @@ -32,19 +31,19 @@ public class SurrogateStatistics implements StatisticsWriter { /** * The predictive function used. */ - @Inject + //@Inject protected SurrogateFunction predictive; /** * Encoding for converting between ea and domain. */ - @Inject + // TODO @Inject private CustomCodec encoding; - @Inject @Named("target-properties-specification") + //@Inject @Named("target-properties-specification") private PropertiesSpecification targetSpecification; - @Inject + // TODO @Inject private WriterStrategy strategy; private Writer writer; @@ -73,7 +72,7 @@ public class SurrogateStatistics implements StatisticsWriter { writer = strategy.create("prediction-by-individual", columns); } - private Object[] dataOfPhenotype(final int index, final long generation, Phenotype<?, FitnessType> phenotype) { + private Object[] dataOfPhenotype(final int index, final long generation, Phenotype<?, FitnessValue> phenotype) { final Object [] data = new Object[2 + targetSpecification.size()]; data[0] = generation; @@ -91,8 +90,8 @@ public class SurrogateStatistics implements StatisticsWriter { } @SneakyThrows(WriterException.class) - public void add(final EvolutionResult<?, FitnessType> evolutionResult) { - final ISeq<Phenotype<?, FitnessType>> population = (ISeq<Phenotype<?, FitnessType>>)(Object)evolutionResult.population(); + public void add(final EvolutionResult<?, FitnessValue> evolutionResult) { + final ISeq<Phenotype<?, FitnessValue>> population = (ISeq<Phenotype<?, FitnessValue>>)(Object)evolutionResult.population(); for(int i = 0; i < population.size(); ++i) { writer.addRecord(dataOfPhenotype(i, evolutionResult.generation(), population.get(i))); diff --git a/src/core/de.evoal.surrogate.api/src/main/java/module-info.java b/src/core/de.evoal.surrogate.api/src/main/java/module-info.java index 25fc6d511d8736e4b92aa44aedc3675829adec11..db812053849ec95a83c9dc2a03a843b886fc7dc7 100644 --- a/src/core/de.evoal.surrogate.api/src/main/java/module-info.java +++ b/src/core/de.evoal.surrogate.api/src/main/java/module-info.java @@ -37,10 +37,11 @@ module de.evoal.surrogate.api { opens de.evoal.surrogate.api.training to weld.core.impl; opens de.evoal.surrogate.main to weld.core.impl; opens de.evoal.surrogate.main.cdi to weld.core.impl; + opens de.evoal.surrogate.main.ea to weld.core.impl; opens de.evoal.surrogate.main.internal to weld.core.impl; - opens de.evoal.surrogate.main.jackson to weld.core.impl; + opens de.evoal.surrogate.main.jackson to weld.core.impl, com.fasterxml.jackson.databind; opens de.evoal.surrogate.main.gof.cross to weld.core.impl; opens de.evoal.surrogate.main.gof.rsquare to weld.core.impl; opens de.evoal.surrogate.main.statistics.correlated to weld.core.impl; opens de.evoal.surrogate.main.statistics.surrogate to weld.core.impl; -} +} \ No newline at end of file