From 5cb454f0100c3f5f0f6020ec61b84da9f463e5cb Mon Sep 17 00:00:00 2001 From: "Bernhard J. Berger" <bernhard.berger@uni-bremen.de> Date: Tue, 27 Dec 2022 08:28:17 +0100 Subject: [PATCH] Re-implemented EvoAl core (except for constraint handling). --- .../ea/chromosomes/BoundedOperations.java | 46 -- .../core/main/ea/gene/DynamicChromosome.java | 41 - .../core/main/ea/gene/DynamicDoubleGene.java | 36 - .../core/main/ea/gene/DynamicEnumGene.java | 35 - .../evoal/core/main/ea/gene/DynamicGene.java | 57 -- .../core/main/ea/gene/DynamicIntegerGene.java | 32 - .../core/main/ea/gene/StringUniverse.java | 46 -- src/core/de.evoal.core/pom.xml | 4 + .../evoal/core/api/board/BlackboardEntry.java | 30 +- .../de/evoal/core/api/cdi/BeanFactory.java | 28 +- .../evoal/core/api/ea/codec/CustomCodec.java | 1 + .../ea/fitness/comparator/FitnessValue.java | 4 + .../api/ea/initial/InitialPopulation.java | 3 +- .../evoal/core/api/properties/Properties.java | 44 +- .../properties/PropertiesSpecification.java | 4 + .../api/properties/io/PropertiesWriter.java | 12 +- ...opertiesBasedPropertiesStreamSupplier.java | 4 + .../evoal/core/api/utils/LanguageHelper.java | 40 +- .../de/evoal/core/api/utils/Requirements.java | 18 + .../core/main/ea/alterer/AltererFactory.java | 62 +- .../crossover/CorrelationCrossover.java | 4 +- .../CorrelationCrossoverMemento.java | 2 +- .../crossover/LineCorrelationCrossover.java | 2 +- .../LineCorrelationCrossoverMemento.java | 2 +- .../MultiPointCorrelationCrossover.java | 2 +- ...MultiPointCorrelationCrossoverMemento.java | 2 +- .../PartiallyMatchedCorrelationCrossover.java | 2 +- ...llyMatchedCorrelationCrossoverMemento.java | 5 +- .../SinglePointCorrelationCrossover.java | 2 +- ...inglePointCorrelationCrossoverMemento.java | 3 +- .../UniformCorrelationCrossover.java | 2 +- .../UniformCorrelationCrossoverMemento.java | 2 +- .../internal/AbstractCorrelationAlterer.java | 0 .../internal/CorrelationCombineAlterer.java | 4 +- .../internal/CorrelationRecombinator.java | 0 .../internal/MeanCorrelationAlterer.java | 2 +- .../alterer/mutator/CorrelationMutator.java | 4 +- .../mutator/CorrelationMutatorFactory.java | 2 +- .../mutator/CorrelationMutatorMemento.java | 2 +- .../mutator/GaussianCorrelationMutator.java | 2 +- .../GaussianCorrelationMutatorMemento.java | 2 +- .../SingleBitFlipCorrelationMutator.java | 2 +- ...ingleBitFlipCorrelationMutatorMemento.java | 2 +- .../alterer/mutator/SingleBitFlipMutator.java | 2 - .../mutator/SwapCorrelationMutator.java | 2 +- .../SwapCorrelationMutatorMemento.java | 3 +- .../core/main/ea/codec/DynamicCodec.java | 107 +++ .../main/ea/codec/DynamicCodecProducer.java | 21 + .../chromosome/DynamicBitChromosome.java | 50 ++ .../chromosome/DynamicBoundedChromosome.java | 26 + .../codec/chromosome/DynamicChromosome.java | 46 ++ .../chromosome/DynamicChromosomeFactory.java | 18 + .../chromosome/DynamicDoubleChromosome.java | 58 ++ .../chromosome/DynamicGrayChromosome.java | 47 ++ .../chromosome/DynamicScaledChromosome.java | 34 + .../ea/comparator/ParetoFitnessValue.java | 11 + .../comparator/WeightedSumFitnessValue.java | 11 + .../core/main/ea/fitness/DistanceFitness.java | 47 +- .../ea/initial/InitialPopulationFactory.java | 15 +- .../ea/initial/RandomInitialPopulation.java | 4 +- .../core/main/ea/initial/RandomProducer.java | 30 + .../evoal/core/main/ea/model/Correlation.java | 2 +- .../core/main/ea/model/Correlations.java | 8 +- .../de/evoal/core/main/ea/model/Range.java | 2 +- .../core/main/ea/model/RangedCorrelation.java | 2 +- .../main/ea/producer}/SelectorFactory.java | 2 +- .../jenetics/AbstractBoundedChromosome.java | 93 +++ .../core/main/jenetics/BitChromosome.java | 700 ++++++++++++++++++ .../evoal/core/main/jenetics}/BitHelper.java | 2 +- .../main/jenetics}/BoundedBitChromosome.java | 3 +- .../jenetics/BoundedDoubleChromosome.java | 285 +++++++ .../core/main/jenetics/BoundedDoubleGene.java | 239 ++++++ .../core/main/jenetics/BoundedOperations.java | 25 + .../core/main/jenetics}/DecimalFactory.java | 2 +- .../jenetics}/GrayBoundedBitChromosome.java | 8 +- .../evoal/core/main/jenetics}/GrayHelper.java | 2 +- .../jenetics}/NaiveBoundedBitChromosome.java | 7 +- .../main/jenetics/VariableChromosome.java | 100 +++ .../producer/ConfigurationValueProducer.java | 8 + .../core/main/producer/MockupProducer.java | 15 + .../main/producer/SpecificationProducer.java | 43 ++ .../core/main/search/HeuristicSearch.java | 47 +- .../search/HeuristicSearchEvaluation.java | 22 +- .../core/main/search/HeuristicSearchMain.java | 6 +- .../statistics/fitness/FitnessStatistics.java | 23 +- .../individuals/IndividualStatistics.java | 16 +- .../main/statistics/nop/NopStatistics.java | 5 +- .../statistics/writer/csv/CsvStrategy.java | 0 .../main/statistics/writer/csv/CsvWriter.java | 0 .../src/main/java/module-info.java | 20 +- .../generator/main/benchmarks/Ackley.java | 3 +- .../generator/main/benchmarks/Rastrigin.java | 2 +- .../generator/main/benchmarks/Rosenbrock.java | 4 +- .../main/benchmarks/WeightedSphere.java | 2 +- .../main/functions/NormalNoiseFunction.java | 2 +- .../api/SurrogateBlackboardEntry.java | 7 +- .../surrogate/main/cdi/SurrogateProducer.java | 18 +- .../surrogate/main/cdi/TargetPointLoader.java | 67 ++ .../main/ea/SurrogateFitnessFunction.java | 4 +- .../main/ea/TrainingDataProducer.java | 29 + .../main/ea/TrainingInitialPopulation.java | 12 +- .../surrogate/main/ea/TrainingProducer.java | 31 + .../gof/cross/CrossValidationCalculator.java | 2 +- .../main/gof/rsquare/RSquareCalculator.java | 7 +- .../GenerationStatisticsWriter.java | 8 +- .../src/main/java/module-info.java | 2 + src/core/de.evoal.surrogate.neural/pom.xml | 54 ++ .../neural/EvoalDataSetIterator.java | 21 + .../neural/NeuralNetworkConfigurator.java | 154 ++++ .../neural/NeuralNetworkHelper.java | 37 + .../neural/SimpleNeuralNetwork.java | 41 + .../neural/SimpleNeuralNetworkFactory.java | 78 ++ .../src/main/java/module-info.java | 13 + .../simple/identity/IdentityFunction.java | 2 +- .../simple/linear/LinearFunction.java | 2 +- .../simple/linear/LinearFunctionFactory.java | 2 +- .../quadratic/SimpleQuadraticFunction.java | 2 +- .../SimpleQuadraticFunctionFactory.java | 2 +- .../src/main/java/module-info.java | 1 + .../svr/GaussianKernelSVRFunctionFactory.java | 4 +- .../surrogate/svr/KernelBasedSVRFunction.java | 6 +- .../svr/KernelBasedSVRFunctionFactory.java | 13 +- .../de/evoal/surrogate/svr/KernelHelper.java | 13 +- 123 files changed, 2874 insertions(+), 589 deletions(-) delete mode 100644 src/core/attic/de/evoal/core/main/ea/chromosomes/BoundedOperations.java delete mode 100644 src/core/attic/de/evoal/core/main/ea/gene/DynamicChromosome.java delete mode 100644 src/core/attic/de/evoal/core/main/ea/gene/DynamicDoubleGene.java delete mode 100644 src/core/attic/de/evoal/core/main/ea/gene/DynamicEnumGene.java delete mode 100644 src/core/attic/de/evoal/core/main/ea/gene/DynamicGene.java delete mode 100644 src/core/attic/de/evoal/core/main/ea/gene/DynamicIntegerGene.java delete mode 100644 src/core/attic/de/evoal/core/main/ea/gene/StringUniverse.java rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/AltererFactory.java (67%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossover.java (96%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossoverMemento.java (81%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossover.java (97%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossoverMemento.java (91%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossover.java (98%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossoverMemento.java (92%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossover.java (96%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossoverMemento.java (85%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossover.java (96%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossoverMemento.java (94%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossover.java (97%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossoverMemento.java (96%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/internal/AbstractCorrelationAlterer.java (100%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/internal/CorrelationCombineAlterer.java (97%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/internal/CorrelationRecombinator.java (100%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/internal/MeanCorrelationAlterer.java (92%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/mutator/CorrelationMutator.java (98%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorFactory.java (91%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorMemento.java (80%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutator.java (96%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutatorMemento.java (94%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutator.java (98%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutatorMemento.java (97%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipMutator.java (98%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutator.java (96%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutatorMemento.java (88%) create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/DynamicCodec.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/DynamicCodecProducer.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicBitChromosome.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicBoundedChromosome.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicChromosome.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicChromosomeFactory.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicDoubleChromosome.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicGrayChromosome.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicScaledChromosome.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/initial/RandomProducer.java rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/model/Correlation.java (93%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/model/Correlations.java (87%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/model/Range.java (85%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/ea/model/RangedCorrelation.java (93%) rename src/core/{attic/de/evoal/core/main/ea => de.evoal.core/src/main/java/de/evoal/core/main/ea/producer}/SelectorFactory.java (99%) create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/AbstractBoundedChromosome.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BitChromosome.java rename src/core/{attic/de/evoal/core/main/ea/chromosomes => de.evoal.core/src/main/java/de/evoal/core/main/jenetics}/BitHelper.java (96%) rename src/core/{attic/de/evoal/core/main/ea/chromosomes => de.evoal.core/src/main/java/de/evoal/core/main/jenetics}/BoundedBitChromosome.java (93%) create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedDoubleChromosome.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedDoubleGene.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedOperations.java rename src/core/{attic/de/evoal/core/main/ea/chromosomes => de.evoal.core/src/main/java/de/evoal/core/main/jenetics}/DecimalFactory.java (91%) rename src/core/{attic/de/evoal/core/main/ea/chromosomes => de.evoal.core/src/main/java/de/evoal/core/main/jenetics}/GrayBoundedBitChromosome.java (90%) rename src/core/{attic/de/evoal/core/main/ea/chromosomes => de.evoal.core/src/main/java/de/evoal/core/main/jenetics}/GrayHelper.java (96%) rename src/core/{attic/de/evoal/core/main/ea/chromosomes => de.evoal.core/src/main/java/de/evoal/core/main/jenetics}/NaiveBoundedBitChromosome.java (88%) create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/VariableChromosome.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/MockupProducer.java create mode 100644 src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/SpecificationProducer.java rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/search/HeuristicSearchEvaluation.java (84%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/statistics/fitness/FitnessStatistics.java (74%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/statistics/individuals/IndividualStatistics.java (87%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/statistics/nop/NopStatistics.java (78%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/statistics/writer/csv/CsvStrategy.java (100%) rename src/core/{attic => de.evoal.core/src/main/java}/de/evoal/core/main/statistics/writer/csv/CsvWriter.java (100%) create mode 100644 src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/TargetPointLoader.java create mode 100644 src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingDataProducer.java create mode 100644 src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingProducer.java create mode 100644 src/core/de.evoal.surrogate.neural/pom.xml create mode 100644 src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/EvoalDataSetIterator.java create mode 100644 src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/NeuralNetworkConfigurator.java create mode 100644 src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/NeuralNetworkHelper.java create mode 100644 src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/SimpleNeuralNetwork.java create mode 100644 src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/SimpleNeuralNetworkFactory.java create mode 100644 src/core/de.evoal.surrogate.neural/src/main/java/module-info.java diff --git a/src/core/attic/de/evoal/core/main/ea/chromosomes/BoundedOperations.java b/src/core/attic/de/evoal/core/main/ea/chromosomes/BoundedOperations.java deleted file mode 100644 index cd8cca01..00000000 --- a/src/core/attic/de/evoal/core/main/ea/chromosomes/BoundedOperations.java +++ /dev/null @@ -1,46 +0,0 @@ -package de.evoal.core.main.ea.chromosomes; - -import io.jenetics.util.RandomRegistry; - -import java.util.random.RandomGenerator; - -public final class BoundedOperations { - /** - * Use bounded operations. - */ - private static boolean useBoundedOperations = true; - - private BoundedOperations() { - } - - public static void setUseBoundedOperations(final boolean useBoundedOperations) { - BoundedOperations.useBoundedOperations = useBoundedOperations; - } - - public static double boundValue(final double value, final double min, final double max) { - if(useBoundedOperations) { - return Math.min(max, Math.max(min, value)); - } else { - return value; - } - } - - public static boolean isValid(final double value, final double min, final double max) { - if(useBoundedOperations) { - return Double.compare(value, min) >= 0 && - Double.compare(value, max) < 0; - - } else { - return true; - } - } - - public static double random(final double min, final double max) { - final RandomGenerator random = RandomRegistry.random(); - if(useBoundedOperations) { - return random.nextDouble(min, max); - } else { - return random.nextDouble(-100_000_000 , 100_000_000); - } - } -} diff --git a/src/core/attic/de/evoal/core/main/ea/gene/DynamicChromosome.java b/src/core/attic/de/evoal/core/main/ea/gene/DynamicChromosome.java deleted file mode 100644 index 6c506a4e..00000000 --- a/src/core/attic/de/evoal/core/main/ea/gene/DynamicChromosome.java +++ /dev/null @@ -1,41 +0,0 @@ -package de.evoal.core.main.ea.gene; - -import de.evoal.core.api.properties.PropertiesSpecification; -import de.evoal.core.api.properties.PropertySpecification; -import io.jenetics.AbstractChromosome; - -import io.jenetics.util.ISeq; - -public class DynamicChromosome<G extends DynamicGene<? extends Object>> extends AbstractChromosome<G> { - - protected DynamicChromosome(final ISeq<G> genes) { - super(genes); - } - - @Override - public DynamicChromosome newInstance(final ISeq<G> iSeq) { - return new DynamicChromosome(iSeq); - } - - @Override - public DynamicChromosome newInstance() { - return new DynamicChromosome(random(_genes)); - } - - private static <G extends DynamicGene<? extends Object>> ISeq<G> random(final ISeq<G> template) { - return template.stream() - .map(DynamicGene::newInstance) - .collect(ISeq.toISeq()); - } - - public static DynamicChromosome from(final PropertiesSpecification specification) { - return new DynamicChromosome(specification.getProperties() - .stream() - .map(DynamicChromosome::toGene) - .collect(ISeq.toISeq())); - } - - private static DynamicGene<? extends Object> toGene(final PropertySpecification spec) { - - } -} diff --git a/src/core/attic/de/evoal/core/main/ea/gene/DynamicDoubleGene.java b/src/core/attic/de/evoal/core/main/ea/gene/DynamicDoubleGene.java deleted file mode 100644 index ace1b582..00000000 --- a/src/core/attic/de/evoal/core/main/ea/gene/DynamicDoubleGene.java +++ /dev/null @@ -1,36 +0,0 @@ -package de.evoal.core.main.ea.gene; - -import io.jenetics.util.RandomRegistry; - -public class DynamicDoubleGene extends DynamicGene<Double> { - protected DynamicDoubleGene(final Double data) { - super(data); - } - - /** - * @param value The value to check. - * @return - */ - @Override - protected boolean isValidValue(final Double value) { - if(value == null) { - return false; - } - - return true; // TODO - } - - /** - * @return - */ - @Override - public DynamicGene newInstance() { - double value = RandomRegistry.random().nextDouble(); - - while(!isValidValue(value)) { - value = RandomRegistry.random().nextDouble(); - } - - return new DynamicDoubleGene(value); - } -} diff --git a/src/core/attic/de/evoal/core/main/ea/gene/DynamicEnumGene.java b/src/core/attic/de/evoal/core/main/ea/gene/DynamicEnumGene.java deleted file mode 100644 index 4378bff9..00000000 --- a/src/core/attic/de/evoal/core/main/ea/gene/DynamicEnumGene.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.evoal.core.main.ea.gene; - -import io.jenetics.util.RandomRegistry; - -public class DynamicEnumGene extends DynamicGene<Integer> { - private StringUniverse literalManager; - - protected DynamicEnumGene(final String data, final StringUniverse manager) { - super(manager.toID(data)); - this.literalManager = manager; - } - - @Override - protected boolean isValidValue(final Integer value) { - if(value == null) { - return false; - } - - return literalManager.isInRange(value); - } - - /** - * @return - */ - @Override - public DynamicGene newInstance() { - int value = RandomRegistry.random().nextInt(0, literalManager.lastId() + 1); - - while(!isValidValue(value)) { - value = RandomRegistry.random().nextInt(); - } - - return new DynamicEnumGene(literalManager.fetch(value), literalManager); - } -} diff --git a/src/core/attic/de/evoal/core/main/ea/gene/DynamicGene.java b/src/core/attic/de/evoal/core/main/ea/gene/DynamicGene.java deleted file mode 100644 index 57db2a91..00000000 --- a/src/core/attic/de/evoal/core/main/ea/gene/DynamicGene.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.evoal.core.main.ea.gene; - -import io.jenetics.Gene; -import lombok.extern.slf4j.Slf4j; - -import java.lang.reflect.InvocationTargetException; - -@Slf4j -public abstract class DynamicGene<T> implements Gene<Object, DynamicGene<T>> { - - private T data; - - protected DynamicGene(final T data) { - this.data =(T) data; - } - - /** - * @return - */ - @Override - public Object allele() { - return data; - } - - /** - * @param data - * @return - */ - @Override - public DynamicGene<T> newInstance(final Object data) { - try { - return this.getClass() - .getConstructor(Object.class) - .newInstance(data); - } catch (final Exception e) { - log.error("Failed to create new instance of gene: {}.", this, e); - throw new RuntimeException(e); - } - } - - /** - * @return - */ - @Override - public boolean isValid() { - return isValidValue(data); - } - - /** - * Checks if the given value is a valid one for this gene. - * - * @param value The value to check. - * @return iff the value is valid. - */ - protected abstract boolean isValidValue(final T value); -} - diff --git a/src/core/attic/de/evoal/core/main/ea/gene/DynamicIntegerGene.java b/src/core/attic/de/evoal/core/main/ea/gene/DynamicIntegerGene.java deleted file mode 100644 index c16e1458..00000000 --- a/src/core/attic/de/evoal/core/main/ea/gene/DynamicIntegerGene.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.evoal.core.main.ea.gene; - -import io.jenetics.util.RandomRegistry; - -public class DynamicIntegerGene extends DynamicGene<Integer> { - protected DynamicIntegerGene(final Integer data) { - super(data); - } - - @Override - protected boolean isValidValue(final Integer value) { - if(value == null) { - return false; - } - - return true; - } - - /** - * @return - */ - @Override - public DynamicGene newInstance() { - int value = RandomRegistry.random().nextInt(); - - while(!isValidValue(value)) { - value = RandomRegistry.random().nextInt(); - } - - return new DynamicIntegerGene(value); - } -} diff --git a/src/core/attic/de/evoal/core/main/ea/gene/StringUniverse.java b/src/core/attic/de/evoal/core/main/ea/gene/StringUniverse.java deleted file mode 100644 index b2ba822f..00000000 --- a/src/core/attic/de/evoal/core/main/ea/gene/StringUniverse.java +++ /dev/null @@ -1,46 +0,0 @@ -package de.evoal.core.main.ea.gene; - -import lombok.Getter; -import lombok.Setter; - -import java.util.HashMap; -import java.util.Map; - -public class StringUniverse { - - private final Map<String, Integer> literals = new HashMap<>(); - - @Getter - @Setter - private boolean sealed = false; - - public int toID(final String data) { - Integer id = literals.get(data); - - if(id == null && isSealed()) { - throw new IllegalStateException("The string '" + data + "' is an unknown literal."); - } else if(id == null) { - id = literals.size(); - literals.put(data, id); - } - - return id; - } - - public boolean isInRange(final int value) { - return value >= 0 && value < literals.size(); - } - - public int lastId() { - return literals.size() - 1; - } - - public String fetch(final int value) { - return literals.entrySet() - .stream() - .filter(e -> e.getValue().intValue() == value) - .findFirst() - .get() - .getKey(); - } -} diff --git a/src/core/de.evoal.core/pom.xml b/src/core/de.evoal.core/pom.xml index 4bc7b345..b2282d96 100644 --- a/src/core/de.evoal.core/pom.xml +++ b/src/core/de.evoal.core/pom.xml @@ -313,6 +313,10 @@ <compilerArgs> <arg>--add-exports</arg> <arg>io.jenetics.base/io.jenetics.internal.math=de.evoal.core</arg> + <arg>--add-exports</arg> + <arg>io.jenetics.base/io.jenetics.internal.util=de.evoal.core</arg> + <arg>--add-exports</arg> + <arg>io.jenetics.base/io.jenetics.internal.collection=de.evoal.core</arg> </compilerArgs> <forceJavacCompilerUse>true</forceJavacCompilerUse> </configuration> 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 678b5fd9..b3e466e6 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 @@ -5,7 +5,7 @@ public final class BlackboardEntry { /** * The target properties to search for. */ - public static final String TARGET_PROPERTIES = "TARGET_PROPERTIES"; + public static final String TARGET_PROPERTIES = "core:target-properties"; // public static final String TARGET_PROPERTIES_SOURCE = "TARGET_PROPERTIES_SOURCE"; @@ -14,15 +14,10 @@ public final class BlackboardEntry { */ // public static final String CONSTRAINT_VALIDATION_FOLDER = "CONSTRAINT_VALIDATION_FOLDER"; - /** - * Chooses the evaluation kind. - */ -// public static final String EVALUATION = "EVALUATION"; - /** * Number of evaluation runs. */ -// public static final String EVALUATION_ITERATIONS = "EVALUATION_ITERATIONS"; + public static final String EVALUATION_ITERATIONS = "core:evaluation-iterations"; /** * The evaluation run number. @@ -59,20 +54,6 @@ public final class BlackboardEntry { */ public static final String MAIN = "core:main"; - /** - * The trained 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"; - - /** - * File containing the predictive function file. - */ -// public static final String PREDICTIVE_FUNCTION_FILE = "PREDICTIVE_FUNCTION_FILE"; /** * Targets. @@ -82,12 +63,7 @@ public final class BlackboardEntry { /** * File containing targets for evaluation. */ -// 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 TARGET_POINTS_FILE = "core:target-points-file"; private final String label; diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/cdi/BeanFactory.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/cdi/BeanFactory.java index f7b90f12..61545d04 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/cdi/BeanFactory.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/cdi/BeanFactory.java @@ -1,5 +1,6 @@ package de.evoal.core.api.cdi; +import de.evoal.core.api.ea.initial.InitialPopulation; import de.evoal.core.api.utils.Requirements; import lombok.extern.slf4j.Slf4j; import org.apache.deltaspike.core.api.provider.BeanProvider; @@ -22,17 +23,20 @@ public final class BeanFactory { log.info("Creating bean of type {}.", type); try { return BeanProvider.getContextualReference(type); - } catch(final IllegalStateException e) { + } catch(final IllegalStateException | IllegalArgumentException e) { log.error("Failed to create contextual reference of type '{}'.", type); - final Set<Bean<T>> beans = BeanProvider.getBeanDefinitions(type, true, true); - - final String existingBeans = beans.stream().map(Bean::getName).collect(Collectors.joining(", ")); - log.error(" existing beans are: {}", existingBeans); - + logInstantiationError(type, e); throw e; } } + private static <T> void logInstantiationError(Class<T> type, RuntimeException e) { + final Set<Bean<T>> beans = BeanProvider.getBeanDefinitions(type, true, true); + + final String existingBeans = beans.stream().map(Bean::getName).collect(Collectors.joining(", ")); + log.error(" existing beans are: {}", existingBeans); + } + /** * Returns an instance of the given {@code type} and the given {@code name}. * If necessary, the instance is created. @@ -50,14 +54,14 @@ public final class BeanFactory { try { return BeanProvider.getContextualReference(name, false, type); - } catch(final IllegalStateException e) { + } catch(final IllegalStateException | IllegalArgumentException e) { log.error("Failed to create contextual reference of type '{}' with name '{}'.", type, name); - final Set<Bean<T>> beans = BeanProvider.getBeanDefinitions(type, true, true); - - final String existingBeans = beans.stream().map(Bean::getName).collect(Collectors.joining(", ")); - log.error(" existing beans are: {}", existingBeans); - + logInstantiationError(type, e); throw e; } } + + public static void injectFields(final Object instance) { + BeanProvider.injectFields(instance); + } } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/codec/CustomCodec.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/codec/CustomCodec.java index fac1ddb7..683b2d94 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/codec/CustomCodec.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/codec/CustomCodec.java @@ -11,6 +11,7 @@ import io.jenetics.engine.Codec; * @param <G> The gene type. */ public interface CustomCodec<G extends Gene<?, G>> extends Codec<Properties, G> { + /** * Encodes an individual according to the codes into a genotype. * 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 index fb8253ad..6b0e79e2 100644 --- 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 @@ -4,4 +4,8 @@ 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> { + /** + * @return A list of serializable information for fitness value statistics. + */ + public Object [] toStatistics(); } 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 index 445e3335..1d419270 100644 --- 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 @@ -8,8 +8,7 @@ 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); + InitialPopulation init(final 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/properties/Properties.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/Properties.java index ad55de2c..7b100609 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/Properties.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/Properties.java @@ -7,19 +7,27 @@ import java.util.Objects; public class Properties { private final PropertiesSpecification specification; - private final double[] values; + private final Object[] values; public Properties(final PropertiesSpecification specification) { this.specification = specification; - this.values = new double[specification.properties.size()]; + this.values = new Object[specification.properties.size()]; } - public Properties(final PropertiesSpecification specification, final double[] data) { + public Properties(final PropertiesSpecification specification, final Object[] data) { this(specification); System.arraycopy(data, 0, this.values, 0, data.length); } + public Properties(final PropertiesSpecification specification, final double[] data) { + this(specification); + + for(int i = 0; i < data.length; ++i) { + this.values[i] = data[i]; + } + } + public Properties(final Properties other) { this(other.specification, other.values); } @@ -34,23 +42,41 @@ public class Properties { return result; } - public double get(int i) { + public Object get(int i) { return values[i]; } - public double get(final PropertySpecification spec) { + public Double getAsDouble(int i) { + return (Double)values[i]; + } + + public Object get(final PropertySpecification spec) { return values[specification.indexOf(spec)]; } + public Double getAsDouble(final PropertySpecification spec) { + return (Double)values[specification.indexOf(spec)]; + } + public PropertiesSpecification getSpecification() { return specification; } - public double[] getValues() { + public Object[] getValues() { + return values; + } + + public double[] getValuesAsDouble() { + final double [] values = new double[this.values.length]; + + for(int i = 0; i < values.length; ++i) { + values[i] = (Double)this.values[i]; + } + return values; } - public final double put(final PropertySpecification property, double d) { + public final Object put(final PropertySpecification property, Object d) { final Integer index = specification.indices.get(property); if(index == null) { @@ -60,11 +86,11 @@ public class Properties { return put(index, d); } - public final double put(final int index, double d) { + public final Object put(final int index, Object d) { return values[index] = d; } - public void set(final int index, final double value) { + public void set(final int index, final Object value) { values[index] = value; } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/PropertiesSpecification.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/PropertiesSpecification.java index 3cd82ef4..c5b02923 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/PropertiesSpecification.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/PropertiesSpecification.java @@ -81,6 +81,10 @@ public class PropertiesSpecification { return this.indices.containsKey(spec); } + public PropertySpecification get(final int i) { + return properties.get(i); + } + public List<PropertySpecification> getProperties() { return Collections.unmodifiableList(properties); } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/io/PropertiesWriter.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/io/PropertiesWriter.java index ce615e5b..21b887eb 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/io/PropertiesWriter.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/io/PropertiesWriter.java @@ -28,7 +28,17 @@ public class PropertiesWriter implements AutoCloseable { for(final PropertySpecification spec : properties.getSpecification().getProperties()) { jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("name", spec.name()); - jsonGenerator.writeNumberField("value", properties.get(spec)); + + final Object value = properties.get(spec); + if(value instanceof Double || value instanceof Float) { + jsonGenerator.writeNumberField("value", ((Number)properties.get(spec)).doubleValue()); + } else if(value instanceof Integer) { + jsonGenerator.writeNumberField("value", ((Number)properties.get(spec)).longValue()); + } else if(value instanceof Boolean) { + jsonGenerator.writeBooleanField("value", (Boolean)properties.get(spec)); + } else if(value instanceof String) { + jsonGenerator.writeStringField("value", (String)properties.get(spec)); + } jsonGenerator.writeEndObject(); } jsonGenerator.writeEndArray(); diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/stream/PropertiesBasedPropertiesStreamSupplier.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/stream/PropertiesBasedPropertiesStreamSupplier.java index f69a76b9..2a037c5f 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/stream/PropertiesBasedPropertiesStreamSupplier.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/properties/stream/PropertiesBasedPropertiesStreamSupplier.java @@ -31,4 +31,8 @@ public class PropertiesBasedPropertiesStreamSupplier implements PropertiesStream public Stream<Properties> get() { return properties.stream(); } + + public int size() { + return properties.size(); + } } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/utils/LanguageHelper.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/utils/LanguageHelper.java index 513106d7..3bff0b7c 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/utils/LanguageHelper.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/utils/LanguageHelper.java @@ -30,32 +30,23 @@ public final class LanguageHelper { for(final String part : parts) { try { if(!(current instanceof Instance)) { - log.error("Failed to lookup part '{}' of path '{}'.", part, path); + log.error("Failed to lookup part '{}' of path '{}' in '{}'.", part, path, current); throw new IllegalStateException("EA configuration is not valid."); } - boolean foundAttribute = false; - for(final Attribute attr : ((Instance)current).getAttributes()) { - final NameOrMisc nom = attr.getName(); + final Attribute attribute = ((Instance)current).findAttribute(part); - if(nom instanceof Misc && ((Misc)nom).getName().equals(part)) { - current = attr.getValue(); - foundAttribute = true; - break; - } else if(nom instanceof Name && ((Name)nom).getName().getName().equals(part)) { - current = attr.getValue(); - foundAttribute = true; - break; - } - } - - if(!foundAttribute && "name".equals(part)) { + if(attribute != null) { + current = attribute.getValue(); + } else if("name".equals(part)) { current = ((Instance)current).getName().getName(); - foundAttribute = true; - } - - if(!foundAttribute) { - log.error("Failed to lookup part '{}' of path '{}'. Returning null.", part, path); + } else { + log.warn("Failed to lookup part '{}' of path '{}'. Returning null.", part, path); + log.warn("Current instance is: {}", ((Instance) current).getName().getName()); + log.warn("Available attributes:"); + for(final Attribute a : ((Instance) current).getAttributes()) { + log.warn(" {}", ((Name)a.getName()).getName().getName()); + } return null; } } catch(final NullPointerException e) { @@ -78,8 +69,11 @@ public final class LanguageHelper { } } - log.debug("Mapping " + path + " to " + current + " of type " + current.getClass()); - + if(current instanceof Instance) { + log.debug("Mapping '{}' to instance with name '{}'.", path, ((Instance)current).getName().getName()); + } else { + log.debug("Mapping '{}' to '{}'.", path, current); + } return (T) current; } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/utils/Requirements.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/utils/Requirements.java index b608b1e5..597a496b 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/utils/Requirements.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/utils/Requirements.java @@ -41,6 +41,24 @@ public final class Requirements { } } + /** + * Requires the arrays to be present and of same size. + * + * @param a The first array. + * @param b The second array. + * + * @throws NullPointerException iff either {@code a} or {@code b} is {@code null}. + * @throws IllegalArgumentException iff the size of {@code a} and {@code b} differ. + */ + public static <T>void requireSameSize(final double [] a, final T [] b) { + Objects.requireNonNull(a, "Array is not allowed to be null"); + Objects.requireNonNull(b, "Array is not allowed to be null"); + + if(a.length != b.length) { + throw new IllegalArgumentException("Arrays are expected to have the same size: " + a.length + " -- " + b.length); + } + } + /** * Requires the collections to be present and of same size. * diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/AltererFactory.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/AltererFactory.java similarity index 67% rename from src/core/attic/de/evoal/core/main/ea/alterer/AltererFactory.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/AltererFactory.java index 26927ebf..63fd72cc 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/AltererFactory.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/AltererFactory.java @@ -2,15 +2,15 @@ package de.evoal.core.main.ea.alterer; import java.util.function.BiFunction; -import de.evoal.core.main.ea.alterer.internal.MeanCorrelationAlterer; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; import de.evoal.core.main.ea.alterer.crossover.*; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; -import de.evoal.languages.model.instance.Instance; -import de.evoal.core.api.utils.LanguageHelper; +import de.evoal.core.main.ea.alterer.internal.MeanCorrelationAlterer; import de.evoal.core.main.ea.alterer.mutator.SingleBitFlipCorrelationMutator; import de.evoal.core.main.ea.alterer.mutator.SingleBitFlipMutator; import de.evoal.core.main.ea.alterer.mutator.SwapCorrelationMutator; -import de.evoal.core.api.ea.fitness.type.FitnessType; +import de.evoal.core.main.ea.model.Correlations; +import de.evoal.languages.model.instance.Instance; +import de.evoal.core.api.utils.LanguageHelper; import io.jenetics.*; import io.jenetics.util.Mean; import javax.enterprise.context.ApplicationScoped; @@ -36,7 +36,7 @@ public class AltererFactory { * <li>None</li> * </ul> */ - public <G extends Gene<?, G>> Alterer<G, FitnessType> create(final Instance config) { + public <G extends Gene<?, G>> Alterer<G, FitnessValue> create(final Instance config) { final String name = LanguageHelper.lookup(config, "name"); log.info("Creating alterer with name '{}'.", name); @@ -44,7 +44,7 @@ public class AltererFactory { switch(name) { //case "CompositeAlterer": return createCompositeAlterer(config); case "mean_alterer": return createMeanAlterer(config); - case "correlation_mean_alterer": return (Alterer<G, FitnessType>) createCorrelationMeanAlterer(config); + case "correlation_mean_alterer": return (Alterer<G, FitnessValue>) createCorrelationMeanAlterer(config); case "partial_matched_alterer": return createPartiallyMatchedAlterer(config); case "correlation_partial_matched_alterer": return createCorrelationPartiallyMatchedAlterer(config); @@ -68,128 +68,128 @@ public class AltererFactory { throw new IllegalStateException("Selector '" + name + "' is unknown."); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createUniformCrossover(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createUniformCrossover(final Instance config) { final Double crossoverProbability = LanguageHelper.lookup(config, "crossover_probability"); final Double swapProbability = LanguageHelper.lookup(config,"swap_probability"); return new UniformCrossover<>(crossoverProbability, swapProbability); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createCorrelationUniformCrossover(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createCorrelationUniformCrossover(final Instance config) { final Double crossoverProbability = LanguageHelper.lookup(config, "crossover_probability"); final Double swapProbability = LanguageHelper.lookup(config,"swap_probability"); return new UniformCorrelationCrossover(crossoverProbability, swapProbability, correlations); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createBitFlipMutator (final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createBitFlipMutator (final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); return new SingleBitFlipMutator(probability); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createCorrelationBitFlipMutator (final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createCorrelationBitFlipMutator (final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); final Double threshold = LanguageHelper.lookup(config, "threshold"); return new SingleBitFlipCorrelationMutator(probability, threshold, correlations); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createSwapMutator (final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createSwapMutator (final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); return new SwapMutator<>(probability); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createCorrelationSwapMutator (final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createCorrelationSwapMutator (final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); final Double threshold = LanguageHelper.lookup(config, "threshold"); return new SwapCorrelationMutator<>(probability, threshold, correlations); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createSinglePointCrossover(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createSinglePointCrossover(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); return new SinglePointCrossover<>(probability); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createCorrelationSinglePointCrossover(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createCorrelationSinglePointCrossover(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); return new SinglePointCorrelationCrossover(probability, correlations); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createPartiallyMatchedAlterer(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createPartiallyMatchedAlterer(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); - return (Alterer<G, FitnessType>) new PartiallyMatchedCrossover(probability); + return (Alterer<G, FitnessValue>) new PartiallyMatchedCrossover(probability); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createCorrelationPartiallyMatchedAlterer(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createCorrelationPartiallyMatchedAlterer(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); - return (Alterer<G, FitnessType>) new PartiallyMatchedCorrelationCrossover<G, FitnessType>(probability, correlations); + return (Alterer<G, FitnessValue>) new PartiallyMatchedCorrelationCrossover<G, FitnessValue>(probability, correlations); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createMultiPointCrossover(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createMultiPointCrossover(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); final Integer count = LanguageHelper.lookup(config, "count"); return new MultiPointCrossover<>(probability, count); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createCorrelationMultiPointCrossover(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createCorrelationMultiPointCrossover(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); final Integer count = LanguageHelper.lookup(config, "count"); return new MultiPointCorrelationCrossover<>(probability, count, correlations); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createMeanAlterer(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createMeanAlterer(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); - return (Alterer<G, FitnessType>) new MeanAlterer(probability); + return (Alterer<G, FitnessValue>) new MeanAlterer(probability); } - private <G extends NumericGene<?, G> & Mean<G>> Alterer<G, FitnessType> createCorrelationMeanAlterer(final Instance config) { + private <G extends NumericGene<?, G> & Mean<G>> Alterer<G, FitnessValue> createCorrelationMeanAlterer(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); - return (Alterer<G, FitnessType>) new MeanCorrelationAlterer<G, FitnessType>(probability, correlations); + return (Alterer<G, FitnessValue>) new MeanCorrelationAlterer<G, FitnessValue>(probability, correlations); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createLineCrossover(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createLineCrossover(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); final Double position = LanguageHelper.lookup(config, "position"); return new LineCrossover(probability, position); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createCorrelationLineCrossover(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createCorrelationLineCrossover(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); final Double position = LanguageHelper.lookup(config, "position"); return new LineCorrelationCrossover(probability, position, correlations); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createIntermediateCrossover(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createIntermediateCrossover(final Instance config) { throw new IllegalStateException("Unsupported alterer."); } - private <G extends Gene<?,G>> Alterer<G, FitnessType> createGaussianMutator(final Instance config) { + private <G extends Gene<?,G>> Alterer<G, FitnessValue> createGaussianMutator(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); return new GaussianMutator(probability); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createGaussianCorrelationMutator(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createGaussianCorrelationMutator(final Instance config) { final Double probability = LanguageHelper.lookup(config, "probability"); final Double threshold = LanguageHelper.lookup(config, "threshold"); return factory.apply(probability, threshold); } - private <G extends Gene<?, G>> Alterer<G, FitnessType> createCompositeAlterer(final Instance config) { + private <G extends Gene<?, G>> Alterer<G, FitnessValue> createCompositeAlterer(final Instance config) { throw new IllegalStateException("Unsupported alterer."); } } diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossover.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossover.java similarity index 96% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossover.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossover.java index c5748e3c..437f41af 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossover.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossover.java @@ -1,7 +1,7 @@ package de.evoal.core.main.ea.alterer.crossover; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlation; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.*; import io.jenetics.util.MSeq; import io.jenetics.util.RandomRegistry; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossoverMemento.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossoverMemento.java similarity index 81% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossoverMemento.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossoverMemento.java index 929b2210..ef0cfe21 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossoverMemento.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/CorrelationCrossoverMemento.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.crossover; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; +import de.evoal.core.main.ea.model.Correlation; public interface CorrelationCrossoverMemento<T extends CorrelationCrossoverMemento<T>> { diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossover.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossover.java similarity index 97% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossover.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossover.java index a044d677..f3ba1352 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossover.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossover.java @@ -1,7 +1,7 @@ package de.evoal.core.main.ea.alterer.crossover; import de.evoal.core.api.utils.Requirements; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.NumericGene; import io.jenetics.util.MSeq; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossoverMemento.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossoverMemento.java similarity index 91% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossoverMemento.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossoverMemento.java index 3ddd0104..aa2a2082 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossoverMemento.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/LineCorrelationCrossoverMemento.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.crossover; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; +import de.evoal.core.main.ea.model.Correlation; import io.jenetics.util.RandomRegistry; import lombok.Data; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossover.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossover.java similarity index 98% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossover.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossover.java index b829f6df..86edaa38 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossover.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossover.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.crossover; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.Gene; import io.jenetics.util.MSeq; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossoverMemento.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossoverMemento.java similarity index 92% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossoverMemento.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossoverMemento.java index 1bdf0e05..3c755d6c 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossoverMemento.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/MultiPointCorrelationCrossoverMemento.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.crossover; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; +import de.evoal.core.main.ea.model.Correlation; import io.jenetics.internal.math.Subset; import io.jenetics.util.RandomRegistry; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossover.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossover.java similarity index 96% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossover.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossover.java index 66977b3b..dfeb518c 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossover.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossover.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.crossover; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.EnumGene; import io.jenetics.util.MSeq; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossoverMemento.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossoverMemento.java similarity index 85% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossoverMemento.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossoverMemento.java index 84615c0a..12066ed2 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossoverMemento.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/PartiallyMatchedCorrelationCrossoverMemento.java @@ -1,14 +1,11 @@ package de.evoal.core.main.ea.alterer.crossover; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; +import de.evoal.core.main.ea.model.Correlation; import io.jenetics.internal.math.Subset; import io.jenetics.util.RandomRegistry; -import java.util.Random; import java.util.random.RandomGenerator; -import static java.lang.Math.min; - public class PartiallyMatchedCorrelationCrossoverMemento implements CorrelationCrossoverMemento<PartiallyMatchedCorrelationCrossoverMemento> { private int[] points = null; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossover.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossover.java similarity index 96% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossover.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossover.java index 42957f14..42d2e08a 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossover.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossover.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.crossover; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.Gene; import io.jenetics.util.MSeq; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossoverMemento.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossoverMemento.java similarity index 94% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossoverMemento.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossoverMemento.java index 53ee1d9a..df3bb82e 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossoverMemento.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/SinglePointCorrelationCrossoverMemento.java @@ -1,11 +1,10 @@ package de.evoal.core.main.ea.alterer.crossover; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; +import de.evoal.core.main.ea.model.Correlation; import io.jenetics.util.RandomRegistry; import lombok.Getter; import lombok.Setter; -import java.util.Random; import java.util.random.RandomGenerator; import static java.lang.Math.min; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossover.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossover.java similarity index 97% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossover.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossover.java index 18a6ddd8..5f611d67 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossover.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossover.java @@ -1,7 +1,7 @@ package de.evoal.core.main.ea.alterer.crossover; import de.evoal.core.api.utils.Requirements; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.Gene; import io.jenetics.util.MSeq; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossoverMemento.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossoverMemento.java similarity index 96% rename from src/core/attic/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossoverMemento.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossoverMemento.java index 4fe2316e..c87c0a30 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossoverMemento.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/crossover/UniformCorrelationCrossoverMemento.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.crossover; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; +import de.evoal.core.main.ea.model.Correlation; import io.jenetics.util.RandomRegistry; import lombok.Getter; import lombok.Setter; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/internal/AbstractCorrelationAlterer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/internal/AbstractCorrelationAlterer.java similarity index 100% rename from src/core/attic/de/evoal/core/main/ea/alterer/internal/AbstractCorrelationAlterer.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/internal/AbstractCorrelationAlterer.java diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/internal/CorrelationCombineAlterer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/internal/CorrelationCombineAlterer.java similarity index 97% rename from src/core/attic/de/evoal/core/main/ea/alterer/internal/CorrelationCombineAlterer.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/internal/CorrelationCombineAlterer.java index 0ce3b1c2..4e93aaf3 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/internal/CorrelationCombineAlterer.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/internal/CorrelationCombineAlterer.java @@ -1,7 +1,7 @@ package de.evoal.core.main.ea.alterer.internal; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlation; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.*; import io.jenetics.util.BaseSeq; import io.jenetics.util.MSeq; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/internal/CorrelationRecombinator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/internal/CorrelationRecombinator.java similarity index 100% rename from src/core/attic/de/evoal/core/main/ea/alterer/internal/CorrelationRecombinator.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/internal/CorrelationRecombinator.java diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/internal/MeanCorrelationAlterer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/internal/MeanCorrelationAlterer.java similarity index 92% rename from src/core/attic/de/evoal/core/main/ea/alterer/internal/MeanCorrelationAlterer.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/internal/MeanCorrelationAlterer.java index d8f44559..d2b8604f 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/internal/MeanCorrelationAlterer.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/internal/MeanCorrelationAlterer.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.internal; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.*; import io.jenetics.util.Mean; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/CorrelationMutator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/CorrelationMutator.java similarity index 98% rename from src/core/attic/de/evoal/core/main/ea/alterer/mutator/CorrelationMutator.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/CorrelationMutator.java index 186e7b94..b68141c8 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/CorrelationMutator.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/CorrelationMutator.java @@ -1,8 +1,8 @@ package de.evoal.core.main.ea.alterer.mutator; import de.evoal.core.main.ea.alterer.internal.AbstractCorrelationAlterer; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlation; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.*; import io.jenetics.internal.math.Probabilities; import io.jenetics.util.ISeq; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorFactory.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorFactory.java similarity index 91% rename from src/core/attic/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorFactory.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorFactory.java index 25b3c926..2c38a4f8 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorFactory.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorFactory.java @@ -1,7 +1,7 @@ package de.evoal.core.main.ea.alterer.mutator; import de.evoal.core.api.board.Blackboard; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.Alterer; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Produces; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorMemento.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorMemento.java similarity index 80% rename from src/core/attic/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorMemento.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorMemento.java index e7a7eee4..ad5e1b67 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorMemento.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/CorrelationMutatorMemento.java @@ -1,7 +1,7 @@ package de.evoal.core.main.ea.alterer.mutator; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; +import de.evoal.core.main.ea.model.Correlation; /** * Memento to preserve the state of correlation-aware mutator. diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutator.java similarity index 96% rename from src/core/attic/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutator.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutator.java index 66c1b305..e8165bed 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutator.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutator.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.mutator; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.NumericGene; import java.util.random.RandomGenerator; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutatorMemento.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutatorMemento.java similarity index 94% rename from src/core/attic/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutatorMemento.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutatorMemento.java index 15a4c49c..07e625b3 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutatorMemento.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/GaussianCorrelationMutatorMemento.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.mutator; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; +import de.evoal.core.main.ea.model.Correlation; import lombok.Data; import java.util.Random; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutator.java similarity index 98% rename from src/core/attic/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutator.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutator.java index 5eddb9e0..efb3b762 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutator.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutator.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.mutator; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.*; import io.jenetics.util.MSeq; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutatorMemento.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutatorMemento.java similarity index 97% rename from src/core/attic/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutatorMemento.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutatorMemento.java index a1fa9d38..c2ea8f05 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutatorMemento.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipCorrelationMutatorMemento.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.mutator; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; +import de.evoal.core.main.ea.model.Correlation; import lombok.Getter; import lombok.Setter; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipMutator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipMutator.java similarity index 98% rename from src/core/attic/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipMutator.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipMutator.java index aa03b14f..2aab3ccf 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipMutator.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SingleBitFlipMutator.java @@ -3,10 +3,8 @@ package de.evoal.core.main.ea.alterer.mutator; import io.jenetics.*; import io.jenetics.util.MSeq; -import java.util.Random; import java.util.random.RandomGenerator; - public class SingleBitFlipMutator< C extends Comparable<? super C> > diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutator.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutator.java similarity index 96% rename from src/core/attic/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutator.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutator.java index 7f3dfc11..beecd5fe 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutator.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutator.java @@ -1,6 +1,6 @@ package de.evoal.core.main.ea.alterer.mutator; -import de.evoal.core.main.ea.functions.correlation.model.Correlations; +import de.evoal.core.main.ea.model.Correlations; import io.jenetics.Chromosome; import io.jenetics.Gene; import io.jenetics.MutatorResult; diff --git a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutatorMemento.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutatorMemento.java similarity index 88% rename from src/core/attic/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutatorMemento.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutatorMemento.java index b8e71b71..ca6a0543 100644 --- a/src/core/attic/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutatorMemento.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/alterer/mutator/SwapCorrelationMutatorMemento.java @@ -1,8 +1,7 @@ package de.evoal.core.main.ea.alterer.mutator; -import de.evoal.core.main.ea.functions.correlation.model.Correlation; +import de.evoal.core.main.ea.model.Correlation; -import java.util.Random; import java.util.random.RandomGenerator; import static io.jenetics.internal.math.Randoms.indexes; diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/DynamicCodec.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/DynamicCodec.java new file mode 100644 index 00000000..e986cd9a --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/DynamicCodec.java @@ -0,0 +1,107 @@ +package de.evoal.core.main.ea.codec; + +import de.evoal.core.api.cdi.BeanFactory; +import de.evoal.core.api.ea.codec.CustomCodec; +import de.evoal.core.api.properties.Properties; +import de.evoal.core.api.properties.PropertiesSpecification; +import de.evoal.core.main.ea.codec.chromosome.DynamicChromosome; +import de.evoal.core.main.ea.codec.chromosome.DynamicChromosomeFactory; +import de.evoal.languages.model.ddl.DataDescription; +import de.evoal.languages.model.instance.Array; +import de.evoal.languages.model.instance.Attribute; +import de.evoal.languages.model.instance.DataReference; +import de.evoal.languages.model.instance.Instance; +import io.jenetics.Chromosome; +import io.jenetics.Gene; +import io.jenetics.Genotype; +import io.jenetics.util.Factory; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Slf4j +public class DynamicCodec<G extends Gene<?, G>> implements CustomCodec<G> { + + private final List<DynamicChromosome> dynamicTemplates; + + private final PropertiesSpecification specification; + + public DynamicCodec(final PropertiesSpecification specification, final List<DynamicChromosome> dynamicTemplates, final List<Chromosome<G>> jeneticsTemplates) { + this.specification = specification; + this.dynamicTemplates = dynamicTemplates; + } + + static DynamicCodec from(final Array config) { + final DynamicChromosomeFactory factory = BeanFactory.create(DynamicChromosomeFactory.class); + final List<DynamicChromosome> chromosomes = config.getValues() + .stream() + .map(Instance.class::cast) + .map(factory::create) + .collect(Collectors.toList()); + + final List<Chromosome> templates = chromosomes.stream() + .map(DynamicChromosome::toJenetics) + .collect(Collectors.toList()); + + final PropertiesSpecification specification = PropertiesSpecification.builder() + .add(config.getValues() + .stream() + .map(Instance.class::cast) + .map(i -> i.findAttribute("genes")) + .map(Attribute::getValue) + .map(Array.class::cast) + .map(Array::getValues) + .flatMap(vs -> vs.stream() + .map(Instance.class::cast) + .map(i -> i.findAttribute("content")) + .map(Attribute::getValue) + .map(DataReference.class::cast) + .map(DataReference::getDefinition) + .map(DataDescription::getName) + ) + .distinct()) + .build(); + + log.info("Created dynamic codec for properties specification {}.", specification); + + return new DynamicCodec(specification, chromosomes, templates); + } + + @Override + public Factory<Genotype<G>> encoding() { + final List<Chromosome<G>> chromosomes = dynamicTemplates.stream() + .map(c -> (Chromosome<G>)c.toJenetics()) + .collect(Collectors.toList()); + + return Genotype.of(chromosomes); + } + + @Override + public Function<Genotype<G>, Properties> decoder() { + return this::toProperties; + } + + private Properties toProperties(final Genotype<G> genotype) { + Properties result = new Properties(specification); + + for(int i = 0; i < dynamicTemplates.size(); ++i) { + final Chromosome<G> chromosome = genotype.get(i); + final DynamicChromosome dynamic = dynamicTemplates.get(i); + + result = dynamic.toProperties(chromosome, result); + } + + return result; + } + + @Override + public Genotype<G> encode(final Properties p) { + final List<Chromosome<G>> chromosomes = dynamicTemplates.stream() + .map(c -> (Chromosome<G>)c.toJenetics(p)) + .collect(Collectors.toList()); + + return Genotype.of(chromosomes); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/DynamicCodecProducer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/DynamicCodecProducer.java new file mode 100644 index 00000000..17376a08 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/DynamicCodecProducer.java @@ -0,0 +1,21 @@ +package de.evoal.core.main.ea.codec; + +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.cdi.ConfigurationValue; +import de.evoal.languages.model.instance.Array; +import lombok.extern.slf4j.Slf4j; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Dependent; +import javax.enterprise.inject.Produces; + +@ApplicationScoped +@Slf4j +public class DynamicCodecProducer { + @Produces @Dependent + public DynamicCodec create(@ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.genotype") Array config) { + log.info("Creating encoding for EA problem."); + + return DynamicCodec.from(config); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicBitChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicBitChromosome.java new file mode 100644 index 00000000..c050bb51 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicBitChromosome.java @@ -0,0 +1,50 @@ +package de.evoal.core.main.ea.codec.chromosome; + +import de.evoal.core.api.properties.Properties; +import de.evoal.core.api.properties.PropertySpecification; +import de.evoal.core.api.utils.Requirements; +import de.evoal.core.main.jenetics.BitHelper; +import de.evoal.core.main.jenetics.GrayBoundedBitChromosome; +import de.evoal.core.main.jenetics.NaiveBoundedBitChromosome; +import de.evoal.languages.model.el.IntegerLiteral; +import de.evoal.languages.model.instance.Instance; +import de.evoal.languages.model.instance.LiteralValue; +import io.jenetics.Chromosome; +import io.jenetics.util.DoubleRange; + +import javax.enterprise.context.Dependent; +import javax.inject.Named; + +@Dependent +@Named("bit-chromosome") +public class DynamicBitChromosome extends DynamicScaledChromosome { + + + @Override + public Chromosome toJenetics() { + final DoubleRange range = ranges.get(0); + + return NaiveBoundedBitChromosome.of(range.min(), range.max(), scale); + } + + @Override + public Chromosome toJenetics(final Properties values) { + final DoubleRange range = ranges.get(0); + final PropertySpecification spec = specification.get(0); + + return NaiveBoundedBitChromosome.of(values.getAsDouble(spec), range.min(), range.max(), scale); + } + + @Override + public Properties toProperties(final Chromosome chromosome, final Properties properties) { + final PropertySpecification spec = specification.get(0); + final NaiveBoundedBitChromosome actual = (NaiveBoundedBitChromosome)chromosome; + + final byte [] bytes = actual.toByteArray(); + final double value = BitHelper.toDouble(bytes, scale); + + properties.put(spec, value); + + return properties; + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicBoundedChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicBoundedChromosome.java new file mode 100644 index 00000000..def8f445 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicBoundedChromosome.java @@ -0,0 +1,26 @@ +package de.evoal.core.main.ea.codec.chromosome; + +import de.evoal.languages.model.ddl.DataDescription; +import de.evoal.languages.model.instance.Instance; +import io.jenetics.util.DoubleRange; + +import java.util.List; +import java.util.stream.Collectors; + +public abstract class DynamicBoundedChromosome extends DynamicChromosome { + protected List<DoubleRange> ranges; + + @Override + public void init(final Instance specification) { + super.init(specification); + + ranges = dataRepresented.stream() + .map(this::toRange) + .collect(Collectors.toList()); + } + + protected DoubleRange toRange(final DataDescription dataDescription) { + // TODO Find actual ranges from DDL + return DoubleRange.of(-(Double.MAX_VALUE/2), (Double.MAX_VALUE/2)); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicChromosome.java new file mode 100644 index 00000000..94b33169 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicChromosome.java @@ -0,0 +1,46 @@ +package de.evoal.core.main.ea.codec.chromosome; + +import de.evoal.core.api.properties.Properties; +import de.evoal.core.api.properties.PropertiesSpecification; +import de.evoal.core.api.properties.PropertySpecification; +import de.evoal.languages.model.ddl.DataDescription; +import de.evoal.languages.model.instance.Array; +import de.evoal.languages.model.instance.Attribute; +import de.evoal.languages.model.instance.DataReference; +import de.evoal.languages.model.instance.Instance; +import io.jenetics.Chromosome; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public abstract class DynamicChromosome { + protected List<DataDescription> dataRepresented; + protected PropertiesSpecification specification; + + public void init(final Instance specification) { + final Array genes = (Array)specification.findAttribute("genes") + .getValue(); + + this.dataRepresented = genes.getValues() + .stream() + .map(Instance.class::cast) + .map(i -> i.findAttribute("content")) + .map(Attribute::getValue) + .map(DataReference.class::cast) + .map(DataReference::getDefinition) + .collect(Collectors.toList()); + + this.dataRepresented = Collections.unmodifiableList(dataRepresented); + this.specification = PropertiesSpecification.builder() + .add(dataRepresented.stream() + .map(DataDescription::getName) + ) + .build(); + } + + public abstract Chromosome toJenetics(); + public abstract Chromosome toJenetics(final Properties values); + + public abstract Properties toProperties(final Chromosome chromosome, final Properties properties); +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicChromosomeFactory.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicChromosomeFactory.java new file mode 100644 index 00000000..721d9388 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicChromosomeFactory.java @@ -0,0 +1,18 @@ +package de.evoal.core.main.ea.codec.chromosome; + +import de.evoal.core.api.cdi.BeanFactory; +import de.evoal.languages.model.instance.Instance; + +import javax.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class DynamicChromosomeFactory { + public DynamicChromosome create(final Instance specification) { + final String chromosomeName = specification.getName().getName(); + + final DynamicChromosome chromosome = BeanFactory.create(chromosomeName, DynamicChromosome.class); + chromosome.init(specification); + + return chromosome; + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicDoubleChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicDoubleChromosome.java new file mode 100644 index 00000000..7711394b --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicDoubleChromosome.java @@ -0,0 +1,58 @@ +package de.evoal.core.main.ea.codec.chromosome; + +import de.evoal.core.api.properties.Properties; +import de.evoal.core.api.properties.PropertySpecification; +import de.evoal.core.main.jenetics.BoundedDoubleChromosome; +import de.evoal.core.main.jenetics.BoundedDoubleGene; +import de.evoal.languages.model.ddl.DataDescription; +import de.evoal.languages.model.instance.Instance; +import io.jenetics.Chromosome; +import io.jenetics.util.DoubleRange; + +import javax.enterprise.context.Dependent; +import javax.inject.Named; +import java.util.ArrayList; +import java.util.List; + +import java.util.stream.Collectors; + +@Dependent +@Named("double-chromosome") +public class DynamicDoubleChromosome extends DynamicBoundedChromosome { + @Override + public Chromosome toJenetics() { + final List<BoundedDoubleGene> genes = ranges.stream() + .map(BoundedDoubleGene::of) + .collect(Collectors.toList()); + + return BoundedDoubleChromosome.of(genes); + } + + @Override + public Chromosome toJenetics(final Properties values) { + final List<BoundedDoubleGene> genes = new ArrayList<>(ranges.size()); + + for(int i = 0; i < ranges.size(); ++i) { + final DoubleRange range = ranges.get(i); + final double value = values.getAsDouble(specification.get(i)); + + genes.add(BoundedDoubleGene.of(value, range)); + } + + return BoundedDoubleChromosome.of(genes); + } + + @Override + public Properties toProperties(final Chromosome chromosome, final Properties properties) { + final BoundedDoubleChromosome doubleChromosome = (BoundedDoubleChromosome) chromosome; + + for(int i = 0; i < specification.size(); ++i) { + final double value = doubleChromosome.get(i).doubleValue(); + final PropertySpecification spec = specification.get(i); + + properties.put(spec, value); + } + + return properties; + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicGrayChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicGrayChromosome.java new file mode 100644 index 00000000..1c18683b --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicGrayChromosome.java @@ -0,0 +1,47 @@ +package de.evoal.core.main.ea.codec.chromosome; + +import de.evoal.core.api.properties.Properties; +import de.evoal.core.api.properties.PropertySpecification; +import de.evoal.core.api.utils.Requirements; +import de.evoal.core.main.jenetics.GrayBoundedBitChromosome; +import de.evoal.core.main.jenetics.GrayHelper; +import de.evoal.languages.model.el.IntegerLiteral; +import de.evoal.languages.model.instance.Instance; +import de.evoal.languages.model.instance.LiteralValue; +import io.jenetics.Chromosome; +import io.jenetics.util.DoubleRange; + +import javax.enterprise.context.Dependent; +import javax.inject.Named; +import java.util.List; +import java.util.stream.Collectors; + +@Dependent +@Named("gray-chromosome") +public class DynamicGrayChromosome extends DynamicScaledChromosome { + @Override + public Chromosome toJenetics() { + final DoubleRange range = ranges.get(0); + + return GrayBoundedBitChromosome.of(range.min(), range.max(), scale); + } + @Override + public Chromosome toJenetics(final Properties values) { + final DoubleRange range = ranges.get(0); + final PropertySpecification spec = specification.get(0); + + return GrayBoundedBitChromosome.of(values.getAsDouble(spec), range.min(), range.max(), scale); + } + @Override + public Properties toProperties(final Chromosome chromosome, final Properties properties) { + final PropertySpecification spec = specification.get(0); + final GrayBoundedBitChromosome actual = (GrayBoundedBitChromosome)chromosome; + + final byte [] bytes = actual.toByteArray(); + final double value = GrayHelper.fromGray(bytes, scale); + + properties.put(spec, value); + + return properties; + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicScaledChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicScaledChromosome.java new file mode 100644 index 00000000..0af13e48 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/codec/chromosome/DynamicScaledChromosome.java @@ -0,0 +1,34 @@ +package de.evoal.core.main.ea.codec.chromosome; + +import de.evoal.core.api.utils.Requirements; +import de.evoal.languages.model.ddl.DataDescription; +import de.evoal.languages.model.el.IntegerLiteral; +import de.evoal.languages.model.instance.Instance; +import de.evoal.languages.model.instance.LiteralValue; +import io.jenetics.util.DoubleRange; + +public abstract class DynamicScaledChromosome extends DynamicBoundedChromosome { + protected int scale; + + @Override + public void init(final Instance specification) { + super.init(specification); + Requirements.requireSize(dataRepresented, 1); + Requirements.requireSize(ranges, 1); + + scale = ((IntegerLiteral)((LiteralValue)specification.findAttribute("scale").getValue()).getLiteral()).getValue(); + } + + protected DoubleRange toRange(final DataDescription dataDescription) { + double min = -Double.MAX_VALUE / 2; + double max = Double.MAX_VALUE / 2; + + final double scaleMax = Math.pow(2.0, scale); + + max = Math.min(max, scaleMax); + min = Math.max(min, -scaleMax); + + // TODO Find actual ranges from DDL + return DoubleRange.of(min, max); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/ParetoFitnessValue.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/ParetoFitnessValue.java index e4bf15cd..4a975682 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/ParetoFitnessValue.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/comparator/ParetoFitnessValue.java @@ -39,4 +39,15 @@ public class ParetoFitnessValue implements FitnessValue { public String toString() { return "ParetoComparatorType [values=" + fitnessValues + "]"; } + + @Override + public Object[] toStatistics() { + final Object [] result = new Object[fitnessValues.length()]; + + for(int i = 0; i < result.length; ++i) { + result[i] = fitnessValues.data()[i]; + } + + return result; + } } 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 index b8180614..6d77df73 100644 --- 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 @@ -52,4 +52,15 @@ public class WeightedSumFitnessValue implements FitnessValue { public String toString() { return "WeightedSum [fit=" + Arrays.toString(fitnessValues) + ", w" + Arrays.toString(normalizedWeights) + "]"; } + + @Override + public Object[] toStatistics() { + final Object [] result = new Object[fitnessValues.length]; + + for(int i = 0; i < result.length; ++i) { + result[i] = fitnessValues[i]; + } + + return result; + } } 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 index 7b971da3..39166471 100644 --- 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 @@ -4,10 +4,11 @@ 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.properties.PropertiesSpecification; +import de.evoal.core.api.properties.PropertySpecification; 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 de.evoal.languages.model.ddl.DataDescription; +import de.evoal.languages.model.instance.*; import org.apache.commons.math3.util.Pair; import javax.enterprise.context.Dependent; @@ -29,20 +30,23 @@ public class DistanceFitness extends FitnessDecorator { @Override public double[] evaluate(final Properties properties) { - final double [] target = this.target.getValues(); + final Object [] target = this.target.getValues(); final double [] current = decoratedFunction.evaluate(properties); - Requirements.requireSameSize(current, target); - + Requirements.<Object>requireSameSize(current, target); final double result[] = new double[target.length]; for(int i = 0; i < target.length; ++i) { - result[i] = target[i] - current[i]; + result[i] = difference(target[i], current[i]); } return result; } + private double difference(final Object o, final double v) { + return ((Number)o).doubleValue() - v; + } + @Override public FitnessFunction init(final Instance config) { super.init(config); @@ -53,13 +57,36 @@ public class DistanceFitness extends FitnessDecorator { this.target = board.get(BlackboardEntry.TARGET_PROPERTIES); } else { this.target = toProperties((Array)target.getValue()); + board.bind(BlackboardEntry.TARGET_PROPERTIES, this.target); } return this; } - private static Properties toProperties(final Array value) { - - return null; + private static Properties toProperties(final Array array) { + PropertiesSpecification specification = PropertiesSpecification.builder() + .add(array.getValues() + .stream() + .map(Instance.class::cast) + .map(i -> i.findAttribute("name")) + .map(Attribute::getValue) + .map(DataReference.class::cast) + .map(DataReference::getDefinition) + .map(DataDescription::getName) + ) + .build(); + + final Properties properties = new Properties(specification); + array.getValues() + .stream() + .map(Instance.class::cast) + .forEach(i -> { + final String name = ((DataReference)i.findAttribute("name").getValue()).getDefinition().getName(); + final Object value = ((LiteralValue)i.findAttribute("val").getValue()).getLiteral().getValue(); + + properties.put(new PropertySpecification(name), value); + }); + + return properties; } } 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 index ac8f7f1d..2f69f838 100644 --- 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 @@ -8,19 +8,26 @@ import de.evoal.languages.model.instance.Instance; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.Dependent; import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import javax.inject.Named; -@ApplicationScoped +@Dependent public class InitialPopulationFactory { + + @Inject + @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.initialization") + private Instance initialization; + /** - * Creates a initial generation based on the heuristic configuration. + * Creates an 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) { + @Produces @Dependent @Named("initial") + public InitialPopulation create() { 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 index 5f0c9482..9ea64a72 100644 --- 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 @@ -6,12 +6,12 @@ import io.jenetics.Gene; import io.jenetics.engine.Engine; import io.jenetics.engine.EvolutionStream; +import javax.enterprise.context.Dependent; 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) { + public InitialPopulation init(final Instance initialization) { // this is not the function you are looking for. return this; } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/initial/RandomProducer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/initial/RandomProducer.java new file mode 100644 index 00000000..113efb49 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/initial/RandomProducer.java @@ -0,0 +1,30 @@ +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; +import javax.inject.Named; + +/** + * TODO For some reasons I am not able to create the training instance directly ... + */ +@ApplicationScoped +public class RandomProducer { + + @Produces + @Dependent + @Named("random") + public InitialPopulation create(@ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.initialization") Instance initialization) { + final InitialPopulation population = new RandomInitialPopulation(); + BeanFactory.injectFields(population); + population.init(initialization); + + return population; + } +} diff --git a/src/core/attic/de/evoal/core/main/ea/model/Correlation.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/Correlation.java similarity index 93% rename from src/core/attic/de/evoal/core/main/ea/model/Correlation.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/Correlation.java index 450f8555..29df4674 100644 --- a/src/core/attic/de/evoal/core/main/ea/model/Correlation.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/Correlation.java @@ -1,4 +1,4 @@ -package de.evoal.core.main.ea.functions.correlation.model; +package de.evoal.core.main.ea.model; import de.evoal.core.api.ea.codec.CustomCodec; import lombok.Data; diff --git a/src/core/attic/de/evoal/core/main/ea/model/Correlations.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/Correlations.java similarity index 87% rename from src/core/attic/de/evoal/core/main/ea/model/Correlations.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/Correlations.java index bd199bba..949d0ab1 100644 --- a/src/core/attic/de/evoal/core/main/ea/model/Correlations.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/Correlations.java @@ -1,4 +1,4 @@ -package de.evoal.core.main.ea.functions.correlation.model; +package de.evoal.core.main.ea.model; import de.evoal.core.api.ea.codec.CustomCodec; import de.evoal.core.api.properties.Properties; @@ -33,14 +33,14 @@ public class Correlations<G extends Gene<?, G>> { final Properties properties = codec.decode(genotype); return correlations.stream() - .filter(c -> c.matchesSource(chromosomeIndex, properties.get(chromosomeIndex))) + .filter(c -> c.matchesSource(chromosomeIndex, properties.getAsDouble(chromosomeIndex))) .collect(Collectors.toList()); } public int findCorrelationRoot(final Genotype<G> genotype, final int chromosomeIndex) { final Properties properties = codec.decode(genotype); - final double chromosomeValue = properties.get(chromosomeIndex); + final double chromosomeValue = properties.getAsDouble(chromosomeIndex); for(final Correlation correlation : correlations) { if(!correlation.matchesTarget(chromosomeIndex, chromosomeValue)) { @@ -48,7 +48,7 @@ public class Correlations<G extends Gene<?, G>> { } final int sourceIndex = correlation.getChromosomeOne(); - final double sourceValue = properties.get(sourceIndex); + final double sourceValue = properties.getAsDouble(sourceIndex); if(!correlation.matchesSource(sourceIndex, sourceValue)) { continue; diff --git a/src/core/attic/de/evoal/core/main/ea/model/Range.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/Range.java similarity index 85% rename from src/core/attic/de/evoal/core/main/ea/model/Range.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/Range.java index 6b71bad7..5110014b 100644 --- a/src/core/attic/de/evoal/core/main/ea/model/Range.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/Range.java @@ -1,4 +1,4 @@ -package de.evoal.core.main.ea.functions.correlation.model; +package de.evoal.core.main.ea.model; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/src/core/attic/de/evoal/core/main/ea/model/RangedCorrelation.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/RangedCorrelation.java similarity index 93% rename from src/core/attic/de/evoal/core/main/ea/model/RangedCorrelation.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/RangedCorrelation.java index e4dc2468..cadbb0fc 100644 --- a/src/core/attic/de/evoal/core/main/ea/model/RangedCorrelation.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/model/RangedCorrelation.java @@ -1,4 +1,4 @@ -package de.evoal.core.main.ea.functions.correlation.model; +package de.evoal.core.main.ea.model; import lombok.Data; diff --git a/src/core/attic/de/evoal/core/main/ea/SelectorFactory.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/producer/SelectorFactory.java similarity index 99% rename from src/core/attic/de/evoal/core/main/ea/SelectorFactory.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/producer/SelectorFactory.java index 856ae299..7df1ae1b 100644 --- a/src/core/attic/de/evoal/core/main/ea/SelectorFactory.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/producer/SelectorFactory.java @@ -1,4 +1,4 @@ -package de.evoal.core.main.ea; +package de.evoal.core.main.ea.producer; import de.evoal.core.api.board.BlackboardEntry; import de.evoal.core.api.cdi.ConfigurationValue; diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/AbstractBoundedChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/AbstractBoundedChromosome.java new file mode 100644 index 00000000..4b56a149 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/AbstractBoundedChromosome.java @@ -0,0 +1,93 @@ +package de.evoal.core.main.jenetics; +import static io.jenetics.internal.util.Hashes.hash; + +import java.util.Objects; +import java.util.stream.Stream; + +import io.jenetics.BoundedChromosome; +import io.jenetics.BoundedGene; +import io.jenetics.util.ISeq; +import io.jenetics.util.IntRange; + +/** + * Abstract chromosome for {@code BoundedGene}s. + * + * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> + * @version 5.2 + * @since 1.6 + */ +abstract class AbstractBoundedChromosome< + A extends Comparable<? super A>, + G extends BoundedGene<A, G> + > + extends VariableChromosome<G> + implements BoundedChromosome<A, G> +{ + + /** + * The minimum value of this {@code BoundedChromosome}. + */ + final A _min; + + /** + * The maximum value of this {@code BoundedChromosome}. + */ + final A _max; + + /** + * Create a new chromosome from the given genes array. + * + * @param genes the genes of the new chromosome. + * @throws IllegalArgumentException if the length of the gene sequence is + * empty or doesn't match with the allowed length range. + * @throws IllegalArgumentException if the minimum or maximum of the range + * is smaller or equal zero + * @throws IllegalArgumentException if the given range size is zero + * @throws NullPointerException if the {@code genes} are {@code null}. + */ + AbstractBoundedChromosome( + final ISeq<? extends G> genes, + final IntRange lengthRange + ) { + super(genes, lengthRange); + _min = genes.get(0).min(); + _max = genes.get(0).max(); + } + + @Override + public A min() { + return _min; + } + + @Override + public A max() { + return _max; + } + + @Override + public int hashCode() { + return + hash(super.hashCode(), + hash(_min, + hash(_max))); + } + + @Override + public boolean equals(final Object obj) { + return obj == this || + obj != null && + getClass() == obj.getClass() && + Objects.equals(_min, ((AbstractBoundedChromosome<?, ?>)obj)._min) && + Objects.equals(_max, ((AbstractBoundedChromosome<?, ?>)obj)._max) && + super.equals(obj); + } + + static void checkGeneRange(final Stream<?> ranges) { + if (ranges.distinct().count() > 1) { + throw new IllegalArgumentException( + "All genes must have the same range." + ); + } + } + +} \ No newline at end of file diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BitChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BitChromosome.java new file mode 100644 index 00000000..f3d7eec0 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BitChromosome.java @@ -0,0 +1,700 @@ +package de.evoal.core.main.jenetics; + +import static java.lang.Math.min; +import static java.util.Objects.requireNonNull; +import static io.jenetics.internal.util.Requires.probability; +import static io.jenetics.internal.util.SerialIO.readBytes; +import static io.jenetics.internal.util.SerialIO.readInt; +import static io.jenetics.internal.util.SerialIO.writeBytes; +import static io.jenetics.internal.util.SerialIO.writeInt; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.Serial; +import java.io.Serializable; +import java.math.BigInteger; +import java.util.BitSet; +import java.util.function.Function; +import java.util.stream.IntStream; + +import io.jenetics.BitGene; +import io.jenetics.Chromosome; +import io.jenetics.internal.collection.BitArray; +import io.jenetics.util.ISeq; + +/** + * Implementation of the <i>classical</i> BitChromosome. + * + * @see BitGene + * + * @implNote + * This class is immutable and thread-safe. The bits of the bit chromosome are + * backed by a {@code byte[]} array with the following layout: + * <pre> {@code + * Byte: 3 2 1 0 + * | | | | + * Array: |11110011|10011101|01000000|00101010| + * | | | | + * Bit: 23 15 7 0 + * }</pre> + * + * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> + * @since 1.0 + * @version 7.0 + */ +public class BitChromosome extends Number + implements + Chromosome<BitGene>, + Comparable<BitChromosome>, + Serializable +{ + @Serial + private static final long serialVersionUID = 2L; + + + private static final double DEFAULT_PROBABILITY = 0.5; + + /** + * The boolean array which holds the {@link BitGene}s. + */ + private final BitArray _genes; + + /** + * The ones probability of the randomly generated Chromosome. + */ + private final double _p; + + // Private primary constructor. + private BitChromosome(final BitArray genes, final double p) { + _genes = requireNonNull(genes); + _p = probability(p); + } + + /** + * Create a new bit chromosome from the given bit (byte) array. + * + * @since 7.0 + * + * @param bits the bit values of the new chromosome gene. + * @param start the initial (bit) index of the range to be copied, inclusive + * @param end the final (bit) index of the range to be copied, exclusive. + * (This index may lie outside the array.) + * @param p the ones probability + * @throws java.lang.ArrayIndexOutOfBoundsException if {@code start < 0} or + * {@code start > bits.length*8} + * @throws java.lang.IllegalArgumentException if {@code start > end} + * @throws java.lang.NullPointerException if the {@code bits} array is + * {@code null}. + */ + public BitChromosome( + final byte[] bits, + final int start, + final int end, + final double p + ) { + this(BitArray.of(bits, start, min(end, bits.length*Byte.SIZE)), p); + } + + /** + * Create a new bit chromosome from the given bit (byte) array. + * + * @param bits the bit values of the new chromosome gene. + * @param start the initial (bit) index of the range to be copied, inclusive + * @param end the final (bit) index of the range to be copied, exclusive. + * (This index may lie outside the array.) + * @throws java.lang.ArrayIndexOutOfBoundsException if {@code start < 0} or + * {@code start > bits.length*8} + * @throws java.lang.IllegalArgumentException if {@code start > end} + * @throws java.lang.NullPointerException if the {@code bits} array is + * {@code null}. + */ + public BitChromosome(final byte[] bits, final int start, final int end) { + this(bits, start, end, DEFAULT_PROBABILITY); + } + + /** + * Create a new {@code BitChromosome} from the given {@code byte} array. + * This is a shortcut for {@code new BitChromosome(bits, 0, bits.length*8)}. + * + * @param bits the {@code byte} array. + */ + public BitChromosome(final byte[] bits) { + this(bits, 0, bits.length*Byte.SIZE); + } + + /** + * Return the one <em>nominal</em> probability of this chromosome. It's not + * the actual one-probability of {@code this} chromosome. + * + * @since 5.2 + * + * @return the one probability of this chromosome. + */ + public double oneProbability() { + return _p; + } + + @Override + public BitGene gene() { + return BitGene.of(_genes.get(0)); + } + + /** + * Return the value of the first gene of this chromosome. + * + * @since 4.2 + * + * @return the first value of this chromosome. + */ + public boolean booleanValue() { + return _genes.get(0); + } + + @Override + public BitGene get(final int index) { + return BitGene.of(_genes.get(index)); + } + + @Override + public int length() { + return _genes.length(); + } + + /** + * Return the value on the specified index. + * + * @since 4.2 + * + * @param index the gene index + * @return the wanted gene value + * @throws IndexOutOfBoundsException if the index is out of range + * (index < 1 || index >= length()). + */ + public boolean booleanValue(final int index) { + return _genes.get(index); + } + + /** + * Returns the number of bits set to true in this {@code BitChromosome}. + * + * @return the number of bits set to true in this {@code BitChromosome} + */ + public int bitCount() { + return _genes.bitCount(); + } + + /** + * Return the long value this BitChromosome represents. + * + * @return long value this BitChromosome represents. + */ + @Override + public int intValue() { + return (int)longValue(); + } + + /** + * Return the long value this BitChromosome represents. + * + * @return long value this BitChromosome represents. + */ + @Override + public long longValue() { + return toBigInteger().longValue(); + } + + /** + * Return the float value this BitChromosome represents. + * + * @return float value this BitChromosome represents. + */ + @Override + public float floatValue() { + return (float)longValue(); + } + + /** + * Return the double value this BitChromosome represents. + * + * @return double value this BitChromosome represents. + */ + @Override + public double doubleValue() { + return longValue(); + } + + /** + * Return always {@code true}. + * + * @return {@code true}, always + */ + @Override + public boolean isValid() { + return true; + } + + /** + * Return the {@code BigInteger} value this {@code BitChromosome} represents. + * + * @return {@code BigInteger} value this {@code BitChromosome} represents. + */ + public BigInteger toBigInteger() { + return _genes.toBigInteger(); + } + + /** + * Returns the byte array, which represents the bit values of {@code this} + * chromosome. + * + * @return a byte array which represents this {@code BitChromosome}. The + * length of the array is {@code (int)Math.ceil(length()/8.0)}. + */ + public byte[] toByteArray() { + return _genes.toByteArray(); + } + + /** + * Return the corresponding BitSet of this BitChromosome. + * + * @return The corresponding BitSet of this BitChromosome. + */ + public BitSet toBitSet() { + final BitSet set = new BitSet(length()); + for (int i = 0, n = length(); i < n; ++i) { + set.set(i, get(i).bit()); + } + return set; + } + + /** + * Return the indexes of the <i>ones</i> of this bit-chromosome as stream. + * + * @since 3.0 + * + * @return the indexes of the <i>ones</i> of this bit-chromosome + */ + public IntStream ones() { + return IntStream.range(0, length()) + .filter(_genes::get); + } + + /** + * Return the indexes of the <i>zeros</i> of this bit-chromosome as stream. + * + * @since 3.0 + * + * @return the indexes of the <i>zeros</i> of this bit-chromosome + */ + public IntStream zeros() { + return IntStream.range(0, length()) + .filter(index -> !_genes.get(index)); + } + + @Override + public BitChromosome newInstance(final ISeq<BitGene> genes) { + if (genes.isEmpty()) { + throw new IllegalArgumentException( + "The genes sequence must contain at least one gene." + ); + } + + final var array = BitArray.ofLength(genes.length()); + for (int i = 0; i < genes.length(); ++i) { + array.set(i, genes.get(i).booleanValue()); + } + + return new BitChromosome(array, _p); + } + + @Override + public BitChromosome newInstance() { + return of(length(), _p); + } + + /** + * Maps the gene alleles of this chromosome, given as {@link BitSet}, by + * applying the given mapper function {@code f}. The mapped gene values + * are then wrapped into a newly created chromosome. + * + * @since 6.1 + * + * @param f the mapper function + * @return a newly created chromosome with the mapped gene values + * @throws NullPointerException if the mapper function is {@code null}. + */ + public BitChromosome map(final Function<? super BitSet, ? extends BitSet> f) { + return of(f.apply(toBitSet()), length(), oneProbability()); + } + + /** + * Return the BitChromosome as String. A TRUE is represented by a 1 and + * a FALSE by a 0. The returned string can be used to create a new + * chromosome with the {@link #of(CharSequence)} constructor. + * + * @return String representation (containing only '1' and '0') of the + * BitChromosome. + */ + public String toCanonicalString() { + return _genes.toString(); + } + + @Override + public int compareTo(final BitChromosome that) { + return toBigInteger().compareTo(that.toBigInteger()); + } + + /** + * Returns a {@code BitChromosome} whose value is ({@code this & other}). + * + * @since 7.1 + * + * @param other value to be AND'ed with this {@code BitChromosome}. + * @return {@code this & other} + */ + public BitChromosome and(final BitChromosome other) { + final var array = _genes.copy(); + for (int i = 0; i < Math.min(length(), other.length()); ++i) { + array.set(i, array.get(i) && other._genes.get(i)); + } + + return new BitChromosome(array, _p); + } + + /** + * Returns a {@code BitChromosome} whose value is ({@code this | other}). + * + * @since 7.1 + * + * @param other value to be OR'ed with this {@code BitChromosome}. + * @return {@code this | other} + */ + public BitChromosome or(final BitChromosome other) { + final var array = _genes.copy(); + for (int i = 0; i < Math.min(length(), other.length()); ++i) { + array.set(i, array.get(i) || other._genes.get(i)); + } + + return new BitChromosome(array, _p); + } + + /** + * Returns a {@code BitChromosome} whose value is ({@code this ^ other}). + * + * @since 7.1 + * + * @param other value to be XOR'ed with this {@code BitChromosome}. + * @return {@code this ^ other} + */ + public BitChromosome xor(final BitChromosome other) { + final var array = _genes.copy(); + for (int i = 0; i < Math.min(length(), other.length()); ++i) { + array.set(i, array.get(i) ^ other._genes.get(i)); + } + + return new BitChromosome(array, _p); + } + + /** + * Invert the ones and zeros of this bit chromosome. + * + * @return a new BitChromosome with inverted ones and zeros. + */ + public BitChromosome invert() { + final var array = _genes.copy(); + array.invert(); + return new BitChromosome(array, 1.0 - _p); + } + + /** + * Returns a new {@code BitChromosome} whose value is ({@code this << n}). + * The shift distance, n, may be negative, in which case this method performs + * a right shift. + * + * @param n shift distance, in bits + * @return {@code this << n} + */ + public BitChromosome shiftLeft(final int n) { + final var genes = _genes.copy(); + if (n >= 0) { + genes.shiftLeft(n); + } else { + genes.shiftRight(Math.abs(n)); + } + return new BitChromosome(genes, _p); + } + + /** + * Returns a new {@code BitChromosome} whose value is ({@code this >> n}). The shift + * distance, n, may be negative, in which case this method performs a left + * shift. + * + * @param n shift distance, in bits + * @return {@code this >> n} + */ + public BitChromosome shiftRight(final int n) { + final var genes = _genes.copy(); + if (n >= 0) { + genes.shiftRight(n); + } else { + genes.shiftLeft(Math.abs(n)); + } + return new BitChromosome(genes, _p); + } + + @Override + public int hashCode() { + return _genes.hashCode(); + } + + @Override + public boolean equals(final Object obj) { + return obj == this || + obj instanceof BitChromosome other && + _genes.equals(other._genes); + } + + @Override + public String toString() { + return _genes.toByteString(); + } + + + /* ************************************************************************* + * Static factory methods. + **************************************************************************/ + + /** + * Constructing a new BitChromosome with the given {@code length} and + * randomly set bits. The TRUEs and FALSE in the {@code Chromosome} are + * equally distributed with one-probability of {@code p}. + * + * @param length Length of the BitChromosome, number of bits. + * @param p Probability of the TRUEs in the BitChromosome. + * @return a new {@code BitChromosome} with the given parameter + * @throws NegativeArraySizeException if the {@code length} is smaller + * than one. + * @throws IllegalArgumentException if {@code p} is not a valid probability. + */ + public static BitChromosome of(final int length, final double p) { + return new BitChromosome(BitArray.ofLength(length, p), p); + } + + /** + * Constructing a new BitChromosome with the given {@code length} and + * randomly set bits. The TRUEs and FALSE in the {@code Chromosome} are + * equally distributed with one-probability of 0.5. + * + * @param length Length of the BitChromosome. + * @return a new {@code BitChromosome} with the given parameter + * @throws NegativeArraySizeException if the {@code length} is smaller + * than one. + */ + public static BitChromosome of(final int length) { + return of(length, DEFAULT_PROBABILITY); + } + + /** + * Create a new {@code BitChromosome} with the given parameters. + * + * @param length length of the BitChromosome. + * @param bits the bit-set which initializes the chromosome + * @param p Probability of the TRUEs in the BitChromosome. + * @return a new {@code BitChromosome} with the given parameter + * @throws NegativeArraySizeException if the {@code length} is smaller than + * one. + * @throws NullPointerException if the {@code bitSet} is {@code null}. + * @throws IllegalArgumentException if {@code p} is not a valid probability. + */ + public static BitChromosome of( + final BitSet bits, + final int length, + final double p + ) { + final var array = BitArray.ofLength(length); + for (int i = 0; i < length; ++i) { + if (bits.get(i)) { + array.set(i, true); + } + } + + return new BitChromosome(array, probability(p)); + } + + /** + * Create a new {@code BitChromosome} with the given parameters. The + * {@link #oneProbability()} of the chromosome is set to {@code 0.5}. + * + * @param length length of the BitChromosome. + * @param bits the bit-set which initializes the chromosome + * @return a new {@code BitChromosome} with the given parameter + * @throws NegativeArraySizeException if the {@code length} is smaller + * than one. + * @throws NullPointerException if the {@code bitSet} is + * {@code null}. + */ + public static BitChromosome of(final BitSet bits, final int length) { + return of(bits, length, DEFAULT_PROBABILITY); + } + + /** + * Constructing a new BitChromosome from a given BitSet. The length of the + * constructed {@code BitChromosome} will be ({@link BitSet#length}). + * + * @see #of(BitSet, int, double) + * @see #of(BitSet, int) + * + * @param bits the bit-set which initializes the chromosome + * @return a new {@code BitChromosome} with the given parameter + * @throws NullPointerException if the {@code bitSet} is + * {@code null}. + */ + public static BitChromosome of(final BitSet bits) { + return of(bits, bits.length()); + } + + /** + * Create a new {@code BitChromosome} from the given big integer value and + * ones probability. + * + * @param value the value of the created {@code BitChromosome} + * @param length length of the BitChromosome + * @param p Probability of the TRUEs in the BitChromosome. + * @return a new {@code BitChromosome} with the given parameter + * @throws NullPointerException if the given {@code value} is {@code null}. + * @throws IllegalArgumentException if {@code p} is not a valid probability. + */ + public static BitChromosome of( + final BigInteger value, + final int length, + final double p + ) { + final var array = BitArray.of(value, length); + return new BitChromosome(array, probability(p)); + } + + /** + * Create a new {@code BitChromosome} from the given big integer value and + * ones probability. The {@link #oneProbability()} of the chromosome is set + * to {@code 0.5}. + * + * @since 7.0 + * + * @param value the value of the created {@code BitChromosome} + * @param length length of the BitChromosome + * @return a new {@code BitChromosome} with the given parameter + * @throws NullPointerException if the given {@code value} is {@code null}. + * @throws IllegalArgumentException if {@code p} is not a valid probability. + */ + public static BitChromosome of( + final BigInteger value, + final int length + ) { + return of(value, length, DEFAULT_PROBABILITY); + } + + + /** + * Create a new {@code BitChromosome} from the given big integer value. The + * {@link #oneProbability()} of the chromosome is set to {@code 0.5}. + * + * @param value the value of the created {@code BitChromosome} + * @return a new {@code BitChromosome} with the given parameter + * @throws NullPointerException if the given {@code value} is {@code null}. + */ + public static BitChromosome of(final BigInteger value) { + final var array = BitArray.of(value); + return new BitChromosome(array, DEFAULT_PROBABILITY); + } + + /** + * Create a new {@code BitChromosome} from the given character sequence + * containing '0' and '1'; as created with the {@link #toCanonicalString()} + * method. + * + * @param value the input string. + * @param length length of the BitChromosome + * @param p Probability of the TRUEs in the BitChromosome. + * @return a new {@code BitChromosome} with the given parameter + * @throws NullPointerException if the {@code value} is {@code null}. + * @throws IllegalArgumentException if the length of the character sequence + * is zero or contains other characters than '0' or '1'. + * @throws IllegalArgumentException if {@code p} is not a valid probability. + */ + public static BitChromosome of( + final CharSequence value, + final int length, + final double p + ) { + final var array = BitArray.of(value, length); + return new BitChromosome(array, probability(p)); + } + + /** + * Create a new {@code BitChromosome} from the given character sequence + * containing '0' and '1'; as created with the {@link #toCanonicalString()} + * method. + * + * @param value the input string. + * @param p Probability of the TRUEs in the BitChromosome. + * @return a new {@code BitChromosome} with the given parameter + * @throws NullPointerException if the {@code value} is {@code null}. + * @throws IllegalArgumentException if the length of the character sequence + * is zero or contains other characters than '0' or '1'. + * @throws IllegalArgumentException if {@code p} is not a valid probability. + */ + public static BitChromosome of(final CharSequence value, final double p) { + return of(value, value.length(), p); + } + + /** + * Create a new {@code BitChromosome} from the given character sequence + * containing '0' and '1'; as created with the {@link #toCanonicalString()} + * method. The {@link #oneProbability()} of the chromosome is set to + * {@code 0.5}. + * + * @param value the input string. + * @return a new {@code BitChromosome} with the given parameter + * @throws NullPointerException if the {@code value} is {@code null}. + * @throws IllegalArgumentException if the length of the character sequence + * is zero or contains other characters than '0' or '1'. + */ + public static BitChromosome of(final CharSequence value) { + return of(value, value.length(), DEFAULT_PROBABILITY); + } + + + /* ************************************************************************* + * Java object serialization + * ************************************************************************/ + + @Serial + private Object writeReplace() { + throw new IllegalStateException();//new SerialProxy(SerialProxy.BIT_CHROMOSOME, this); + } + + @Serial + private void readObject(final ObjectInputStream stream) + throws InvalidObjectException + { + throw new InvalidObjectException("Serialization proxy required."); + } + + void write(final DataOutput out) throws IOException { + writeBytes(toByteArray(), out); + writeInt(length(), out); + out.writeDouble(oneProbability()); + } + + static BitChromosome read(final DataInput in) throws IOException { + final var bytes = readBytes(in); + final var length = readInt(in); + final var p = in.readDouble(); + final var genes = BitArray.of(bytes,0, length); + + return new BitChromosome(genes, p); + } +} + diff --git a/src/core/attic/de/evoal/core/main/ea/chromosomes/BitHelper.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BitHelper.java similarity index 96% rename from src/core/attic/de/evoal/core/main/ea/chromosomes/BitHelper.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BitHelper.java index 495cf619..5b476c49 100644 --- a/src/core/attic/de/evoal/core/main/ea/chromosomes/BitHelper.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BitHelper.java @@ -1,4 +1,4 @@ -package de.evoal.core.main.ea.chromosomes; +package de.evoal.core.main.jenetics; import org.decimal4j.api.ImmutableDecimal; import org.decimal4j.factory.Factories; diff --git a/src/core/attic/de/evoal/core/main/ea/chromosomes/BoundedBitChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedBitChromosome.java similarity index 93% rename from src/core/attic/de/evoal/core/main/ea/chromosomes/BoundedBitChromosome.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedBitChromosome.java index 05edb2a5..b2ea8a64 100644 --- a/src/core/attic/de/evoal/core/main/ea/chromosomes/BoundedBitChromosome.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedBitChromosome.java @@ -1,6 +1,5 @@ -package de.evoal.core.main.ea.chromosomes; +package de.evoal.core.main.jenetics; -import io.jenetics.BitChromosome; import io.jenetics.BitGene; import io.jenetics.util.ISeq; diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedDoubleChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedDoubleChromosome.java new file mode 100644 index 00000000..d0999989 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedDoubleChromosome.java @@ -0,0 +1,285 @@ +package de.evoal.core.main.jenetics; + +import io.jenetics.*; +import io.jenetics.util.DoubleRange; +import io.jenetics.util.ISeq; +import io.jenetics.util.IntRange; + +import java.io.*; +import java.util.function.Function; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static java.util.Objects.requireNonNull; + +public class BoundedDoubleChromosome + extends + AbstractBoundedChromosome<Double, BoundedDoubleGene> + implements + NumericChromosome<Double, BoundedDoubleGene>, + Serializable +{ + private static final long serialVersionUID = 3L; + + /** + * Create a new chromosome from the given {@code genes} and the allowed + * length range of the chromosome. + * + * @since 4.0 + * + * @param genes the genes that form the chromosome. + * @param lengthRange the allowed length range of the chromosome + * @throws NullPointerException if one of the arguments is {@code null}. + * @throws IllegalArgumentException if the length of the gene sequence is + * empty, doesn't match with the allowed length range, the minimum + * or maximum of the range is smaller or equal zero or the given + * range size is zero. + */ + protected BoundedDoubleChromosome( + final ISeq<BoundedDoubleGene> genes, + final IntRange lengthRange + ) { + super(genes, lengthRange); + } + + @Override + public BoundedDoubleChromosome newInstance(final ISeq<BoundedDoubleGene> genes) { + return new BoundedDoubleChromosome(genes, lengthRange()); + } + + @Override + public BoundedDoubleChromosome newInstance() { + return of(_min, _max, lengthRange()); + } + + /** + * Maps the gene alleles of this chromosome, given as {@code double[]} array, + * by applying the given mapper function {@code f}. The mapped gene values + * are then wrapped into a newly created chromosome. + * + * <pre>{@code + * final DoubleChromosome chromosome = ...; + * final DoubleChromosome normalized = chromosome.map(Main::normalize); + * + * static double[] normalize(final double[] values) { + * final double sum = sum(values); + * for (int i = 0; i < values.length; ++i) { + * values[i] /= sum; + * } + * return values; + * } + * }</pre> + * + * @since 6.1 + * + * @param f the mapper function + * @return a newly created chromosome with the mapped gene values + * @throws NullPointerException if the mapper function is {@code null}. + * @throws IllegalArgumentException if the length of the mapped + * {@code double[]} array is empty or doesn't match with the allowed + * length range + */ + public BoundedDoubleChromosome map(final Function<? super double[], double[]> f) { + requireNonNull(f); + + final var range = DoubleRange.of(_min, _max); + final var genes = DoubleStream.of(f.apply(toArray())) + .mapToObj(v -> BoundedDoubleGene.of(v, range)) + .collect(ISeq.toISeq()); + + return newInstance(genes); + } + + /** + * Returns a sequential stream of the alleles with this chromosome as its + * source. + * + * @since 4.3 + * + * @return a sequential stream of alleles + */ + public DoubleStream doubleStream() { + return IntStream.range(0, length()).mapToDouble(this::doubleValue); + } + + /** + * Returns an double array containing all of the elements in this chromosome + * in proper sequence. If the chromosome fits in the specified array, it is + * returned therein. Otherwise, a new array is allocated with the length of + * this chromosome. + * + * @since 3.0 + * + * @param array the array into which the elements of this chromosomes are to + * be stored, if it is big enough; otherwise, a new array is + * allocated for this purpose. + * @return an array containing the elements of this chromosome + * @throws NullPointerException if the given {@code array} is {@code null} + */ + public double[] toArray(final double[] array) { + final double[] a = array.length >= length() + ? array + : new double[length()]; + + for (int i = length(); --i >= 0;) { + a[i] = doubleValue(i); + } + + return a; + } + + /** + * Returns an double array containing all of the elements in this chromosome + * in proper sequence. + * + * @since 3.0 + * + * @return an array containing the elements of this chromosome + */ + public double[] toArray() { + return toArray(new double[length()]); + } + + + /* ************************************************************************* + * Static factory methods. + * ************************************************************************/ + + /** + * Create a new {@code DoubleChromosome} with the given genes. + * + * @param genes the genes of the chromosome. + * @return a new chromosome with the given genes. + * @throws IllegalArgumentException if the length of the genes array is + * empty or the given {@code genes} doesn't have the same range. + * @throws NullPointerException if the given {@code genes} array is + * {@code null} + */ + public static BoundedDoubleChromosome of(final BoundedDoubleGene... genes) { + checkGeneRange(Stream.of(genes).map(BoundedDoubleGene::range)); + return new BoundedDoubleChromosome(ISeq.of(genes), IntRange.of(genes.length)); + } + + /** + * Create a new {@code DoubleChromosome} with the given genes. + * + * @since 4.3 + * + * @param genes the genes of the chromosome. + * @return a new chromosome with the given genes. + * @throws NullPointerException if the given {@code genes} are {@code null} + * @throws IllegalArgumentException if the of the genes iterable is empty or + * the given {@code genes} doesn't have the same range. + */ + public static BoundedDoubleChromosome of(final Iterable<BoundedDoubleGene> genes) { + final ISeq<BoundedDoubleGene> values = ISeq.of(genes); + checkGeneRange(values.stream().map(BoundedDoubleGene::range)); + return new BoundedDoubleChromosome(values, IntRange.of(values.length())); + } + + /** + * Create a new random chromosome. + * + * @since 4.0 + * + * @param min the min value of the {@link DoubleGene}s (inclusively). + * @param max the max value of the {@link DoubleGene}s (exclusively). + * @param lengthRange the allowed length range of the chromosome. + * @return a new {@code DoubleChromosome} with the given parameter + * @throws IllegalArgumentException if the length of the gene sequence is + * empty, doesn't match with the allowed length range, the minimum + * or maximum of the range is smaller or equal zero or the given + * range size is zero. + * @throws NullPointerException if the given {@code lengthRange} is + * {@code null} + */ + public static BoundedDoubleChromosome of( + final double min, + final double max, + final IntRange lengthRange + ) { + final ISeq<BoundedDoubleGene> genes = BoundedDoubleGene.seq(min, max, lengthRange); + return new BoundedDoubleChromosome(genes, lengthRange); + } + + /** + * Create a new random {@code DoubleChromosome}. + * + * @param min the min value of the {@link DoubleGene}s (inclusively). + * @param max the max value of the {@link DoubleGene}s (exclusively). + * @param length the length of the chromosome. + * @return a new {@code DoubleChromosome} with the given parameter + * @throws IllegalArgumentException if the {@code length} is smaller than + * one. + */ + public static BoundedDoubleChromosome of( + final double min, + final double max, + final int length + ) { + return of(min, max, IntRange.of(length)); + } + + /** + * Create a new random chromosome. + * + * @since 4.0 + * + * @param range the integer range of the chromosome. + * @param lengthRange the allowed length range of the chromosome. + * @return a new {@code DoubleChromosome} with the given parameter + * @throws IllegalArgumentException if the length of the gene sequence is + * empty, doesn't match with the allowed length range, the minimum + * or maximum of the range is smaller or equal zero or the given + * range size is zero. + * @throws NullPointerException if the given {@code lengthRange} is + * {@code null} + */ + public static BoundedDoubleChromosome of( + final DoubleRange range, + final IntRange lengthRange + ) { + return of(range.min(), range.max(), lengthRange); + } + + /** + * Create a new random {@code DoubleChromosome}. + * + * @since 3.2 + * + * @param range the integer range of the chromosome. + * @param length the length of the chromosome. + * @return a new random {@code DoubleChromosome} + * @throws NullPointerException if the given {@code range} is {@code null} + * @throws IllegalArgumentException if the {@code length} is smaller than + * one. + */ + public static BoundedDoubleChromosome of(final DoubleRange range, final int length) { + return of(range.min(), range.max(), length); + } + + /** + * Create a new random {@code DoubleChromosome} of length one. + * + * @param min the minimal value of this chromosome (inclusively). + * @param max the maximal value of this chromosome (exclusively). + * @return a new {@code DoubleChromosome} with the given parameter + */ + public static BoundedDoubleChromosome of(final double min, final double max) { + return of(min, max, 1); + } + + /** + * Create a new random {@code DoubleChromosome} of length one. + * + * @since 3.2 + * + * @param range the double range of the chromosome. + * @return a new random {@code DoubleChromosome} of length one + * @throws NullPointerException if the given {@code range} is {@code null} + */ + public static BoundedDoubleChromosome of(final DoubleRange range) { + return of(range.min(), range.max()); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedDoubleGene.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedDoubleGene.java new file mode 100644 index 00000000..e5bce3eb --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedDoubleGene.java @@ -0,0 +1,239 @@ +package de.evoal.core.main.jenetics; + +import io.jenetics.DoubleGene; +import io.jenetics.NumericGene; +import io.jenetics.util.*; + +import java.io.*; +import java.util.random.RandomGenerator; + +import static io.jenetics.internal.util.Hashes.hash; + +public class BoundedDoubleGene implements + NumericGene<Double, BoundedDoubleGene>, + Mean<BoundedDoubleGene>, + Comparable<BoundedDoubleGene>, + Serializable +{ + + private static final long serialVersionUID = 2L; + + private final double _allele; + private final double _min; + private final double _max; + + /** + * Create a new random {@code DoubleGene} with the given value and the + * given range. If the {@code value} isn't within the interval [min, max), + * no exception is thrown. In this case the method + * {@link DoubleGene#isValid()} returns {@code false}. + * + * @param allele the value of the gene. + * @param min the minimal valid value of this gene (inclusively). + * @param max the maximal valid value of this gene (exclusively). + */ + private BoundedDoubleGene(final double allele, final double min, final double max) { + _allele = BoundedOperations.boundValue(allele, min, max); + _min = min; + _max = max; + } + + @Override + public Double allele() { + return _allele; + } + + @Override + public Double min() { + return _min; + } + + @Override + public Double max() { + return _max; + } + + /** + * Return the range of {@code this} gene. + * + * @since 4.4 + * + * @return the range of {@code this} gene + */ + public DoubleRange range() { + return DoubleRange.of(_min, _max); + } + + @Override + public byte byteValue() { + return (byte) _allele; + } + + @Override + public short shortValue() { + return (short) _allele; + } + + @Override + public int intValue() { + return (int) _allele; + } + + @Override + public long longValue() { + return (long) _allele; + } + + @Override + public float floatValue() { + return (float) _allele; + } + + @Override + public double doubleValue() { + return _allele; + } + + @Override + public boolean isValid() { + return + Double.isFinite(_allele) && + Double.isFinite(_min) && + Double.isFinite(_max) && + BoundedOperations.isValid(_allele, _min, _max); + } + + @Override + public int compareTo(final BoundedDoubleGene other) { + return Double.compare(_allele, other._allele); + } + + @Override + public BoundedDoubleGene mean(final BoundedDoubleGene that) { + return of(_allele + (that._allele - _allele)/2.0, _min, _max); + } + + /** + * Create a new gene from the given {@code value} and the gene context. + * + * @since 5.0 + * @param allele the value of the new gene. + * @return a new gene with the given value. + */ + public DoubleGene newInstance(final double allele) { + return DoubleGene.of(allele, _min, _max); + } + + @Override + public BoundedDoubleGene newInstance(final Double allele) { + return of(allele, _min, _max); + } + + @Override + public BoundedDoubleGene newInstance(final Number allele) { + return of(allele.doubleValue(), _min, _max); + } + + @Override + public BoundedDoubleGene newInstance() { + return of(BoundedOperations.random(_min, _max), _min, _max); + } + + @Override + public int hashCode() { + return hash(_allele, hash(_min, hash(_max))); + } + + @Override + public boolean equals(final Object obj) { + return obj == this || + obj instanceof BoundedDoubleGene && + Double.compare(((BoundedDoubleGene)obj)._allele, _allele) == 0 && + Double.compare(((BoundedDoubleGene)obj)._min, _min) == 0 && + Double.compare(((BoundedDoubleGene)obj)._max, _max) == 0; + } + + @Override + public String toString() { + return String.format("[%s]", _allele); + } + + + /* ************************************************************************* + * Static factory methods. + * ************************************************************************/ + + /** + * Create a new random {@code DoubleGene} with the given value and the + * given range. If the {@code value} isn't within the interval [min, max), + * no exception is thrown. In this case the method + * {@link DoubleGene#isValid()} returns {@code false}. + * + * @param allele the value of the gene. + * @param min the minimal valid value of this gene (inclusively). + * @param max the maximal valid value of this gene (exclusively). + * @return a new {@code DoubleGene} with the given parameter + */ + public static BoundedDoubleGene of( + final double allele, + final double min, + final double max + ) { + return new BoundedDoubleGene(allele, min, max); + } + + /** + * Create a new random {@code DoubleGene} with the given value and the + * given range. If the {@code value} isn't within the interval [min, max), + * no exception is thrown. In this case the method + * {@link DoubleGene#isValid()} returns {@code false}. + * + * @since 3.2 + * + * @param allele the value of the gene. + * @param range the double range to use + * @return a new random {@code DoubleGene} + * @throws NullPointerException if the given {@code range} is {@code null}. + */ + public static BoundedDoubleGene of(final double allele, final DoubleRange range) { + return of(allele, range.min(), range.max()); + } + + /** + * Create a new random {@code DoubleGene}. It is guaranteed that the value + * of the {@code DoubleGene} lies in the interval [min, max). + * + * @param min the minimal valid value of this gene (inclusively). + * @param max the maximal valid value of this gene (exclusively). + * @return a new {@code DoubleGene} with the given parameter + */ + public static BoundedDoubleGene of(final double min, final double max) { + return of(BoundedOperations.random(min, max), min, max); + } + + /** + * Create a new random {@code DoubleGene}. It is guaranteed that the value + * of the {@code DoubleGene} lies in the interval [min, max). + * + * @since 3.2 + * + * @param range the double range to use + * @return a new {@code DoubleGene} with the given parameter + * @throws NullPointerException if the given {@code range} is {@code null}. + */ + public static BoundedDoubleGene of(final DoubleRange range) { + return of(BoundedOperations.random(range.min(), range.max()), range); + } + static ISeq<BoundedDoubleGene> seq( + final double min, + final double max, + final IntRange lengthRange + ) { + final RandomGenerator random = RandomRegistry.random(); + final int length = random.nextInt(lengthRange.min(), lengthRange.max()); + + return MSeq.<BoundedDoubleGene>ofLength(length) + .fill(() -> new BoundedDoubleGene(BoundedOperations.random(min, max), min, max)) + .toISeq(); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedOperations.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedOperations.java new file mode 100644 index 00000000..8d6ac70f --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/BoundedOperations.java @@ -0,0 +1,25 @@ +package de.evoal.core.main.jenetics; + +import io.jenetics.util.RandomRegistry; + +import java.util.random.RandomGenerator; + +public final class BoundedOperations { + + private BoundedOperations() { + } + + public static double boundValue(final double value, final double min, final double max) { + return Math.min(max, Math.max(min, value)); + } + + public static boolean isValid(final double value, final double min, final double max) { + return Double.compare(value, min) >= 0 && + Double.compare(value, max) < 0; + } + + public static double random(final double min, final double max) { + return RandomRegistry.random() + .nextDouble(min, max); + } +} diff --git a/src/core/attic/de/evoal/core/main/ea/chromosomes/DecimalFactory.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/DecimalFactory.java similarity index 91% rename from src/core/attic/de/evoal/core/main/ea/chromosomes/DecimalFactory.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/DecimalFactory.java index 24af5678..fd9e1160 100644 --- a/src/core/attic/de/evoal/core/main/ea/chromosomes/DecimalFactory.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/DecimalFactory.java @@ -1,4 +1,4 @@ -package de.evoal.core.main.ea.chromosomes; +package de.evoal.core.main.jenetics; import org.decimal4j.api.ImmutableDecimal; import org.decimal4j.factory.Factories; diff --git a/src/core/attic/de/evoal/core/main/ea/chromosomes/GrayBoundedBitChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/GrayBoundedBitChromosome.java similarity index 90% rename from src/core/attic/de/evoal/core/main/ea/chromosomes/GrayBoundedBitChromosome.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/GrayBoundedBitChromosome.java index 52f42efb..bf1398b8 100644 --- a/src/core/attic/de/evoal/core/main/ea/chromosomes/GrayBoundedBitChromosome.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/GrayBoundedBitChromosome.java @@ -1,8 +1,6 @@ -package de.evoal.core.main.ea.chromosomes; +package de.evoal.core.main.jenetics; -import static io.jenetics.internal.math.Randoms.nextDouble; - -import java.util.Random; +import io.jenetics.util.RandomRegistry; public class GrayBoundedBitChromosome extends BoundedBitChromosome<GrayBoundedBitChromosome> { /** @@ -23,7 +21,7 @@ public class GrayBoundedBitChromosome extends BoundedBitChromosome<GrayBoundedBi * Returns a random gray-encoded chromosome within the specified range. */ public static GrayBoundedBitChromosome of(final double min, final double max, final int scale) { - final double value = nextDouble(min, max, new Random()); + final double value = RandomRegistry.random().nextDouble(min, max); return GrayBoundedBitChromosome.of(value, min, max, scale); } diff --git a/src/core/attic/de/evoal/core/main/ea/chromosomes/GrayHelper.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/GrayHelper.java similarity index 96% rename from src/core/attic/de/evoal/core/main/ea/chromosomes/GrayHelper.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/GrayHelper.java index 5d30fbb6..65fe1161 100644 --- a/src/core/attic/de/evoal/core/main/ea/chromosomes/GrayHelper.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/GrayHelper.java @@ -1,4 +1,4 @@ -package de.evoal.core.main.ea.chromosomes; +package de.evoal.core.main.jenetics; /** * Helper class for the gray encoding diff --git a/src/core/attic/de/evoal/core/main/ea/chromosomes/NaiveBoundedBitChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/NaiveBoundedBitChromosome.java similarity index 88% rename from src/core/attic/de/evoal/core/main/ea/chromosomes/NaiveBoundedBitChromosome.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/NaiveBoundedBitChromosome.java index 1c478d81..20ae13a7 100644 --- a/src/core/attic/de/evoal/core/main/ea/chromosomes/NaiveBoundedBitChromosome.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/NaiveBoundedBitChromosome.java @@ -1,8 +1,7 @@ -package de.evoal.core.main.ea.chromosomes; +package de.evoal.core.main.jenetics; -import static io.jenetics.internal.math.Randoms.nextDouble; +import io.jenetics.util.RandomRegistry; -import java.util.Random; public class NaiveBoundedBitChromosome extends BoundedBitChromosome<NaiveBoundedBitChromosome> { @@ -16,7 +15,7 @@ public class NaiveBoundedBitChromosome extends BoundedBitChromosome<NaiveBounded } public static NaiveBoundedBitChromosome of(final double min, final double max, final int scale) { - double value = nextDouble(min, max, new Random()); + double value = RandomRegistry.random().nextDouble(min, max); return NaiveBoundedBitChromosome.of(value, min, max, scale); } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/VariableChromosome.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/VariableChromosome.java new file mode 100644 index 00000000..f180cfb8 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/jenetics/VariableChromosome.java @@ -0,0 +1,100 @@ +package de.evoal.core.main.jenetics; + +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; +import static io.jenetics.internal.util.Hashes.hash; + +import java.util.Objects; + +import io.jenetics.AbstractChromosome; +import io.jenetics.Gene; +import io.jenetics.util.ISeq; +import io.jenetics.util.IntRange; + +/** + * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> + * @version 4.0 + * @since 4.0 + */ +abstract class VariableChromosome<G extends Gene<?, G>> + extends AbstractChromosome<G> +{ + + private final IntRange _lengthRange; + + /** + * Create a new {@code VariableChromosome} from the given {@code genes} + * and the allowed length range of the chromosome. + * + * @param genes the genes that form the chromosome. + * @param lengthRange the allowed length range of the chromosome + * @throws NullPointerException if one of the arguments is {@code null}. + * @throws IllegalArgumentException if the length of the gene sequence is + * empty or doesn't match with the allowed length range. + * @throws IllegalArgumentException if the minimum or maximum of the range + * is smaller or equal zero + * @throws IllegalArgumentException if the given range size is zero + */ + VariableChromosome( + final ISeq<? extends G> genes, + final IntRange lengthRange + ) { + super(genes); + _lengthRange = checkLengthRange(lengthRange, genes.size()); + } + + static IntRange checkLengthRange(final IntRange lengthRange, final int length) { + requireNonNull(lengthRange); + if (lengthRange.min() <= 0) { + throw new IllegalArgumentException(format( + "Minimum length must be positive: %d", lengthRange.min() + )); + } + if (lengthRange.max() <= 0) { + throw new IllegalArgumentException(format( + "Maximum length must be positive: %d", lengthRange.max() + )); + } + if (lengthRange.size() <= 0) { + throw new IllegalArgumentException(format( + "Maximal length must be positive: %d", lengthRange.size() + )); + } + if (length < lengthRange.min() || + length >= lengthRange.max()) + { + throw new IllegalArgumentException(format( + "Number of genes (%d) not within the allowed range: %s", + length, + lengthRange + )); + } + + return lengthRange; + } + + /** + * Return the allowed length range of the chromosome. The minimum value of + * the range is included and the maximum value is excluded. + * + * @return the allowed length range of the chromosome + */ + public IntRange lengthRange() { + return _lengthRange; + } + + @Override + public int hashCode() { + return hash(super.hashCode(), hash(_lengthRange)); + } + + @Override + public boolean equals(final Object obj) { + return obj == this || + obj != null && + getClass() == obj.getClass() && + Objects.equals(_lengthRange, ((VariableChromosome<?>)obj)._lengthRange) && + super.equals(obj); + } + +} \ No newline at end of file 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 index 268f125f..4f341d3e 100644 --- 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 @@ -42,6 +42,14 @@ public class ConfigurationValueProducer { return lookup(board.get(value.entry()), value.access()); } + @Produces + @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "") + public final Array injectArrayValue(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) { diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/MockupProducer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/MockupProducer.java new file mode 100644 index 00000000..362abce4 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/MockupProducer.java @@ -0,0 +1,15 @@ +package de.evoal.core.main.producer; + +import de.evoal.core.main.ea.model.Correlations; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Dependent; +import javax.enterprise.inject.Produces; + +@ApplicationScoped +public class MockupProducer { + @Produces @Dependent + Correlations create() { + return new Correlations(null); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/SpecificationProducer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/SpecificationProducer.java new file mode 100644 index 00000000..e7ef652d --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/SpecificationProducer.java @@ -0,0 +1,43 @@ +package de.evoal.core.main.producer; + +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.cdi.ConfigurationValue; +import de.evoal.core.api.properties.PropertiesSpecification; +import de.evoal.languages.model.ddl.DataDescription; +import de.evoal.languages.model.instance.Array; +import de.evoal.languages.model.instance.Attribute; +import de.evoal.languages.model.instance.DataReference; +import de.evoal.languages.model.instance.Instance; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Dependent; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import javax.inject.Named; +import java.util.List; +import java.util.stream.Stream; + +@ApplicationScoped +public class SpecificationProducer { + @Produces + @Dependent + @Named("genotype-specification") + public PropertiesSpecification createSourceSpecification(final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.genotype") Array genotype) { + final Stream<String> names = genotype.getValues() + .stream() + .map(Instance.class::cast) + .map(i -> i.findAttribute("genes")) + .map(Attribute::getValue) + .map(Array.class::cast) + .map(Array::getValues) + .flatMap(List::stream) + .map(Instance.class::cast) + .map(i -> i.findAttribute("content")) + .map(Attribute::getValue) + .map(DataReference.class::cast) + .map(DataReference::getDefinition) + .map(DataDescription::getName); + + return PropertiesSpecification.builder().add(names).build(); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearch.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearch.java index 3ca2b025..75cfe96a 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearch.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearch.java @@ -10,13 +10,16 @@ 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.api.ea.initial.InitialPopulation; import de.evoal.core.api.utils.LanguageHelper; import de.evoal.core.api.ea.codec.CustomCodec; import de.evoal.core.api.ea.fitness.comparator.FitnessValue; import de.evoal.core.api.statistics.StatisticsWriter; +import de.evoal.core.main.ea.alterer.AltererFactory; +import de.evoal.core.main.ea.codec.DynamicCodec; import de.evoal.core.main.ea.fitness.JeneticsFitnessFunction; -import de.evoal.core.api.ea.initial.InitialPopulation; +import de.evoal.core.main.ea.initial.InitialPopulationFactory; import de.evoal.core.main.jenetics.ConstraintList; import de.evoal.languages.model.eal.EAModel; import de.evoal.languages.model.instance.Array; @@ -28,11 +31,13 @@ import io.jenetics.engine.*; import io.jenetics.stat.MinMax; import io.jenetics.util.Factory; import lombok.extern.slf4j.Slf4j; +import org.apache.deltaspike.core.api.provider.BeanProvider; import javax.enterprise.context.Dependent; import javax.enterprise.inject.Instance; import javax.inject.Inject; +import javax.inject.Named; @Slf4j @Dependent @@ -68,53 +73,53 @@ public class HeuristicSearch { private final Map<String, List<Alterer<?, FitnessValue>>> alterers = new HashMap<>(); - // TODO @Inject - private CustomCodec encoding; + @Inject + private DynamicCodec encoding; private final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); @Inject private JeneticsFitnessFunction fitnessFunction; - // TODO @Inject @Named("offspring") - // TODO private Selector offspringSelector; + @Inject @Named("offspring") + private Selector offspringSelector; - // TODO @Inject @Named("statistics") + @Inject @Named("statistics") private StatisticsWriter statistics; -// TODO @Inject @Named("survivor") -// TODO private Selector survivorSelector; + @Inject @Named("survivor") + private Selector survivorSelector; -// TODO @Inject -// TODO private AltererFactory factory; + @Inject + private AltererFactory factory; // TODO @Inject private Instance<List<Constraint>> constraints; - // TODO @Inject - private InitialPopulation initalStreamFactory; + @Inject @Named("initial") + private InitialPopulation initalStream; public void run() { setup(); final Factory<Genotype<?>> gtf = encoding.encoding(); - final Constraint<?, FitnessValue> constraint = new ConstraintList(constraints.get()); + //final Constraint<?, FitnessValue> constraint = new ConstraintList(constraints.get()); final Engine<?, FitnessValue> engine= Engine.builder(this.fitnessFunction, encoding) .alterers(flattenAltererMap()) - // TODO.offspringSelector(this.offspringSelector) - // TODO.survivorsSelector(this.survivorSelector) + .offspringSelector(this.offspringSelector) + .survivorsSelector(this.survivorSelector) .optimize(Optimize.MAXIMUM) .populationSize(sizeOfPopulation) - .constraint(constraint) +// TODO .constraint(constraint) .maximalPhenotypeAge(maximumAge) .executor(executor) .build(); EvolutionStatistics<FitnessValue, MinMax<FitnessValue>> statistics = EvolutionStatistics.ofComparable(); - EvolutionStream<?, FitnessValue> initialStream = initalStreamFactory.create(engine); + EvolutionStream<?, FitnessValue> initialStream = initalStream.create(engine); final EvolutionResult<?, FitnessValue> result = initialStream.limit(Limits.byFixedGeneration(numberOfGenerations)) @@ -142,13 +147,11 @@ public class HeuristicSearch { final Array array = (Array) category.getValue(); for(final Value alterer : array.getValues()) { -// TODO this.alterers -// TODO .computeIfAbsent(name, k -> new ArrayList<>()) -// TODO .add(factory.create((de.evoal.languages.model.instance.Instance)alterer)); + this.alterers + .computeIfAbsent(name, k -> new ArrayList<>()) + .add(factory.create((de.evoal.languages.model.instance.Instance)alterer)); } } - - } private <G extends Gene<?, G>> Alterer<?, FitnessValue> flattenAltererMap() { diff --git a/src/core/attic/de/evoal/core/main/search/HeuristicSearchEvaluation.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchEvaluation.java similarity index 84% rename from src/core/attic/de/evoal/core/main/search/HeuristicSearchEvaluation.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchEvaluation.java index ff621367..1aa0b95a 100644 --- a/src/core/attic/de/evoal/core/main/search/HeuristicSearchEvaluation.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchEvaluation.java @@ -1,6 +1,7 @@ package de.evoal.core.main.search; import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.cdi.BeanFactory; import de.evoal.core.api.cdi.BlackboardValue; import de.evoal.core.api.cdi.MainClass; import de.evoal.core.api.properties.Properties; @@ -13,7 +14,6 @@ import de.evoal.core.api.statistics.ColumnType; import de.evoal.core.api.statistics.WriterContext; import lombok.extern.slf4j.Slf4j; import org.apache.commons.math3.util.Pair; -import org.apache.deltaspike.core.api.provider.BeanProvider; import javax.inject.Inject; import javax.inject.Named; @@ -42,18 +42,10 @@ public class HeuristicSearchEvaluation implements MainClass { private File outputBaseDir; - @Inject - @BlackboardValue(BlackboardEntry.PREDICTIVE_FUNCTION_FILE) - private String predictiveFile; - - @Inject - @BlackboardValue(BlackboardEntry.TRAINING_POINT_FILE) - private String pointsFile; - private List<Pair<Properties, Properties>> targets; @Inject - @BlackboardValue(BlackboardEntry.TARGETS_FILE) + @BlackboardValue(BlackboardEntry.TARGET_POINTS_FILE) private String targetFile; @Inject @@ -65,8 +57,7 @@ public class HeuristicSearchEvaluation implements MainClass { @Override public void run() { - log.info("Running heuristic search evaluation with the following configuartion:"); - log.info(" predictive function loaded from ({}/{})", predictiveFile, pointsFile); + log.info("Running heuristic search evaluation with the following configuration:"); log.info(" target points loaded from ({})", targetFile); log.info(" heuristic configuration loaded from ({})", heuristicFile); log.info(" running {} iterations.", iterations); @@ -100,7 +91,7 @@ public class HeuristicSearchEvaluation implements MainClass { context.bindColumn(targetColumn, targetIndex); - board.bind(BlackboardEntry.TARGET_PROPERTIES_SOURCE, target.getFirst()); +// board.bind(BlackboardEntry.TARGET_PROPERTIES_SOURCE, target.getFirst()); board.bind(BlackboardEntry.TARGET_PROPERTIES, target.getSecond()); board.bind(BlackboardEntry.EVALUATION_OUTPUT_FOLDER, outputBaseDir); @@ -112,9 +103,8 @@ public class HeuristicSearchEvaluation implements MainClass { board.bind(BlackboardEntry.EVALUATION_RUN, run); context.bindColumn(runColumn, i); - final HeuristicSearch<?> search = new HeuristicSearch<>(); - BeanProvider.injectFields(search); - search.run(); + BeanFactory.create(HeuristicSearch.class) + .run(); } } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchMain.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchMain.java index ede13d74..cdedd099 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchMain.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/search/HeuristicSearchMain.java @@ -38,10 +38,7 @@ public class HeuristicSearchMain implements MainClass { 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 +48,6 @@ public class HeuristicSearchMain implements MainClass { targets.findFirst() .orElseThrow(() -> {throw new IllegalStateException("No target point found");}); -// 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/statistics/fitness/FitnessStatistics.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/fitness/FitnessStatistics.java similarity index 74% rename from src/core/attic/de/evoal/core/main/statistics/fitness/FitnessStatistics.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/fitness/FitnessStatistics.java index 1dd91a28..424be14f 100644 --- a/src/core/attic/de/evoal/core/main/statistics/fitness/FitnessStatistics.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/fitness/FitnessStatistics.java @@ -1,9 +1,12 @@ package de.evoal.core.main.statistics.fitness; +import de.evoal.core.api.board.Blackboard; +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.cdi.BlackboardValue; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; +import de.evoal.core.api.properties.Properties; import de.evoal.core.api.statistics.*; import de.evoal.languages.model.instance.Instance; -import de.evoal.core.api.ea.fitness.type.FitnessType; -import de.evoal.core.api.properties.PropertiesSpecification; import io.jenetics.Phenotype; import io.jenetics.engine.EvolutionResult; import io.jenetics.util.ISeq; @@ -24,8 +27,10 @@ import java.util.List; @Named("fitness-per-individual") @Dependent public class FitnessStatistics implements StatisticsWriter { - @Inject @Named("target-properties-specification") - private PropertiesSpecification targetSpecification; + + @Inject + @BlackboardValue(BlackboardEntry.TARGET_PROPERTIES) + private Properties targetSpecification; @Inject private WriterStrategy strategy; @@ -50,19 +55,19 @@ public class FitnessStatistics implements StatisticsWriter { columns.add(new Column("index", ColumnType.Integer)); for(int i = 0; i < targetSpecification.size(); ++i) { - columns.add(new Column("fitness-value-" + targetSpecification.getProperties().get(i).name(), ColumnType.Double)); + columns.add(new Column("fitness-value-" + targetSpecification.getSpecification().get(i).name(), ColumnType.Double)); } writer = strategy.create("fitness-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; data[1] = index; - final double [] fitnessValues = phenotype.fitness().getFitnessValues(); + final Object [] fitnessValues = phenotype.fitness().toStatistics(); for(int i = 0; i < fitnessValues.length; ++i) { data[2 + i] = fitnessValues[i]; @@ -72,8 +77,8 @@ public class FitnessStatistics 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/attic/de/evoal/core/main/statistics/individuals/IndividualStatistics.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/individuals/IndividualStatistics.java similarity index 87% rename from src/core/attic/de/evoal/core/main/statistics/individuals/IndividualStatistics.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/individuals/IndividualStatistics.java index 6179819c..910cba1f 100644 --- a/src/core/attic/de/evoal/core/main/statistics/individuals/IndividualStatistics.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/individuals/IndividualStatistics.java @@ -1,20 +1,22 @@ package de.evoal.core.main.statistics.individuals; +import de.evoal.core.api.ea.fitness.comparator.FitnessValue; import de.evoal.core.api.statistics.*; import de.evoal.languages.model.instance.Instance; import de.evoal.core.api.ea.codec.CustomCodec; -import de.evoal.core.api.ea.fitness.type.FitnessType; import de.evoal.core.api.properties.Properties; import de.evoal.core.api.properties.PropertiesSpecification; import io.jenetics.Genotype; +import javax.annotation.PostConstruct; +import javax.enterprise.context.Dependent; + import io.jenetics.Phenotype; import io.jenetics.engine.EvolutionResult; import io.jenetics.util.ISeq; -import javax.annotation.PostConstruct; -import javax.enterprise.context.Dependent; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import javax.enterprise.inject.Produces; import javax.inject.Inject; import javax.inject.Named; import java.util.ArrayList; @@ -33,7 +35,7 @@ public class IndividualStatistics implements StatisticsWriter { @Inject private CustomCodec encoding; - @Inject @Named("source-properties-specification") + @Inject @Named("surrogate-source-properties-specification") private PropertiesSpecification sourceSpecification; @Inject @@ -67,7 +69,7 @@ public class IndividualStatistics implements StatisticsWriter { writer = strategy.create("individuals", 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[4 + sourceSpecification.size()]; final Genotype<?> genotype = phenotype.genotype(); @@ -86,8 +88,8 @@ public class IndividualStatistics 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/attic/de/evoal/core/main/statistics/nop/NopStatistics.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/nop/NopStatistics.java similarity index 78% rename from src/core/attic/de/evoal/core/main/statistics/nop/NopStatistics.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/nop/NopStatistics.java index e0756ab8..195ae316 100644 --- a/src/core/attic/de/evoal/core/main/statistics/nop/NopStatistics.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/nop/NopStatistics.java @@ -1,9 +1,10 @@ package de.evoal.core.main.statistics.nop; +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 javax.enterprise.context.Dependent; import javax.inject.Named; @@ -12,7 +13,7 @@ import javax.inject.Named; @Dependent public class NopStatistics implements StatisticsWriter { @Override - public void add(final EvolutionResult<?, FitnessType> evolutionResult) { + public void add(final EvolutionResult<?, FitnessValue> evolutionResult) { } @Override diff --git a/src/core/attic/de/evoal/core/main/statistics/writer/csv/CsvStrategy.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/writer/csv/CsvStrategy.java similarity index 100% rename from src/core/attic/de/evoal/core/main/statistics/writer/csv/CsvStrategy.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/writer/csv/CsvStrategy.java diff --git a/src/core/attic/de/evoal/core/main/statistics/writer/csv/CsvWriter.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/writer/csv/CsvWriter.java similarity index 100% rename from src/core/attic/de/evoal/core/main/statistics/writer/csv/CsvWriter.java rename to src/core/de.evoal.core/src/main/java/de/evoal/core/main/statistics/writer/csv/CsvWriter.java 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 73bb87b6..bd75d437 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 @@ -55,11 +55,10 @@ module de.evoal.core { exports de.evoal.core.api.statistics; exports de.evoal.core.api.utils; -// opens de.evoal.core.api to weld.core.impl; + opens de.evoal.core.api.board to weld.core.impl; opens de.evoal.core.api.cdi to weld.core.impl; opens de.evoal.core.api.ea to weld.core.impl; - opens de.evoal.core.api.ea.codec to weld.core.impl; opens de.evoal.core.api.ea.constraints to weld.core.impl; opens de.evoal.core.api.ea.fitness to weld.core.impl; opens de.evoal.core.api.properties to weld.core.impl; @@ -68,12 +67,21 @@ module de.evoal.core { 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.alterer to weld.core.impl; + opens de.evoal.core.main.ea.alterer.mutator to weld.core.impl; + opens de.evoal.core.main.ea.codec to weld.core.impl; + opens de.evoal.core.main.ea.codec.chromosome to weld.core.impl; opens de.evoal.core.main.ea.comparator to weld.core.impl; + opens de.evoal.core.main.ea.fitness to weld.core.impl; opens de.evoal.core.main.ea.initial to weld.core.impl; + opens de.evoal.core.main.ea.producer 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.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.writer.csv to weld.core.impl; /* opens de.evoal.core.main.ddl.correlation to weld.core.impl; @@ -85,11 +93,5 @@ 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.statistics to weld.core.impl; - opens de.evoal.core.main.statistics.constraint 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; - opens de.evoal.core.main.statistics.writer.csv to weld.core.impl; */ } diff --git a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Ackley.java b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Ackley.java index 6cca3ee9..7b518dd4 100644 --- a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Ackley.java +++ b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Ackley.java @@ -2,6 +2,7 @@ package de.evoal.generator.main.benchmarks; import de.evoal.core.api.properties.Properties; import de.evoal.core.api.properties.PropertySpecification; +import de.evoal.core.api.utils.Requirements; import de.evoal.generator.api.AbstractGeneratorFunction; import de.evoal.generator.api.GeneratorFunction; import de.evoal.generator.main.utils.ELHelper; @@ -31,7 +32,7 @@ public class Ackley extends AbstractGeneratorFunction { double sum2 = 0.0; for(final PropertySpecification ps : readSpecification.getProperties()) { - double read_i = in.get(ps); + double read_i = in.getAsDouble(ps); sum1 += Math.pow(read_i, 2.0); sum2 += Math.cos(c * read_i); diff --git a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Rastrigin.java b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Rastrigin.java index c5538d06..46e7bfee 100644 --- a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Rastrigin.java +++ b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Rastrigin.java @@ -24,7 +24,7 @@ public class Rastrigin extends AbstractGeneratorFunction { double value = a * n; for(final PropertySpecification ps : readSpecification.getProperties()) { - double read_i = in.get(ps); + double read_i = in.getAsDouble(ps); value += (Math.pow(read_i, 2.0) - a * Math.cos(2 * Math.PI * read_i)); } diff --git a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Rosenbrock.java b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Rosenbrock.java index 9e1b291f..1e3e6647 100644 --- a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Rosenbrock.java +++ b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/Rosenbrock.java @@ -21,8 +21,8 @@ public class Rosenbrock extends AbstractGeneratorFunction { final PropertySpecification ps_i = readSpecification.getProperties().get(i); final PropertySpecification ps_n = readSpecification.getProperties().get(i+1); - double read_i = in.get(ps_i); - double read_n = in.get(ps_n); + double read_i = in.getAsDouble(ps_i); + double read_n = in.getAsDouble(ps_n); value += 100 * Math.pow((Math.pow(read_i, 2.0) - read_n), 2.0) + Math.pow(1 - read_i, 2.0); } diff --git a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/WeightedSphere.java b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/WeightedSphere.java index f59a1613..24cfc4d4 100644 --- a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/WeightedSphere.java +++ b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/benchmarks/WeightedSphere.java @@ -19,7 +19,7 @@ public class WeightedSphere extends AbstractGeneratorFunction { int counter = 0; for(final PropertySpecification ps : readSpecification.getProperties()) { - double read_i = in.get(ps); + double read_i = in.getAsDouble(ps); value += Math.pow(read_i, 2.0) * Math.pow(counter++, 2.0); } diff --git a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/functions/NormalNoiseFunction.java b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/functions/NormalNoiseFunction.java index f6e176c6..e52bd620 100644 --- a/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/functions/NormalNoiseFunction.java +++ b/src/core/de.evoal.generator.main/src/main/java/de/evoal/generator/main/functions/NormalNoiseFunction.java @@ -43,7 +43,7 @@ public class NormalNoiseFunction extends AbstractGeneratorFunction { for(int i = 0; i < dimension; ++i) { final PropertySpecification ps = writeSpecification.getProperties().get(i); - double value = result.get(ps) + distributions.get(i).sample(); + double value = result.getAsDouble(ps) + distributions.get(i).sample(); result.put(ps, value); } 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 940cb15c..e3673242 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 @@ -14,7 +14,12 @@ public final class SurrogateBlackboardEntry { /** * File containing a pre-trained surrogate. */ - public static final String PRETRAINED_SURROGATE_FILE = "surrogate:pre-trained"; + public static final String SURROGATE_PRETRAINED_FILE = "surrogate:pre-trained"; + + /** + * File containing the training data. + */ + public static final String SURROGATE_TRAINING_DATA_FILE = "surrogate:training-data"; private SurrogateBlackboardEntry() {} } 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 index c833689d..53adc4e5 100644 --- 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 @@ -3,10 +3,11 @@ 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.core.api.utils.Requirements; import de.evoal.surrogate.api.SurrogateBlackboardEntry; import de.evoal.surrogate.api.configuration.SurrogateConfiguration; import de.evoal.surrogate.api.function.SurrogateFunction; -import lombok.Getter; +import de.evoal.surrogate.main.internal.SurrogateFactory; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; @@ -14,7 +15,6 @@ 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; @@ -26,13 +26,14 @@ 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)) { + if(!event.isSame(SurrogateBlackboardEntry.SURROGATE_PRETRAINED_FILE)) { return; } - final String filename = board.get(SurrogateBlackboardEntry.PRETRAINED_SURROGATE_FILE); + final String filename = board.get(SurrogateBlackboardEntry.SURROGATE_PRETRAINED_FILE); final File file = new File(filename); + log.info("Using pre-trained surrogate model {}.", filename); if(!file.exists()) { log.error("Cannot find pre-trained surrogate model: {}", file); return; @@ -70,4 +71,13 @@ public class SurrogateProducer { .stream()) .build(); } + + @Produces @Dependent + public SurrogateFunction createSurrogateFunction() { + final SurrogateConfiguration configuration = this.configuration; + + Requirements.requireNotNull(configuration); + + return SurrogateFactory.create(configuration, null); + } } diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/TargetPointLoader.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/TargetPointLoader.java new file mode 100644 index 00000000..8b390572 --- /dev/null +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/cdi/TargetPointLoader.java @@ -0,0 +1,67 @@ +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.PropertiesPair; +import de.evoal.core.api.properties.PropertiesSpecification; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.Produces; + +import de.evoal.core.api.properties.stream.FileBasedPropertiesStreamSupplier; +import de.evoal.core.api.properties.stream.PropertiesBasedPropertiesPairStreamSupplier; +import de.evoal.core.api.properties.stream.PropertiesBasedPropertiesStreamSupplier; +import de.evoal.core.api.properties.stream.PropertiesStreamSupplier; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Inject; +import javax.inject.Named; +import java.io.File; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@ApplicationScoped +@Slf4j +public class TargetPointLoader { + + @Inject + private Blackboard board; + + /** + * For loading points from file. + */ + private PropertiesBasedPropertiesStreamSupplier loadedProperties; + + + private PropertiesStreamSupplier targetPoints; + + @SneakyThrows + public void load(final @Observes BlackboardEntry entry) { + if (!BlackboardEntry.TARGET_POINTS_FILE.equals(entry)) { + return; + } + + final String inputFileName = board.get(entry); + + log.info("Loading target points from '{}'", inputFileName); + final File inputFile = new File(inputFileName); + + if(!inputFile.exists() || ! inputFile.canRead()) { + log.error("Unable to read training points file '{}'", inputFile); + throw new IllegalArgumentException("Unable to read target points file: " + inputFile); + } + + loadedProperties = new PropertiesBasedPropertiesStreamSupplier(new FileBasedPropertiesStreamSupplier(inputFile).get().collect(Collectors.toList())); + log.info("Loaded {} target points from '{}'", loadedProperties.size(), inputFile); + } + + @Produces @Named("target-stream") + public Stream<PropertiesPair> getTargetStream( + @Named("surrogate-source-properties-specification") final PropertiesSpecification sourceSpecification, + @Named("surrogate-target-properties-specification") final PropertiesSpecification targetSpecification) { + log.info("Creating target stream using {} and {}.", sourceSpecification, targetSpecification); + + return new PropertiesBasedPropertiesPairStreamSupplier(targetPoints, /*sourceSpecification*/ PropertiesSpecification.builder().build(), targetSpecification).get(); + } +} 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 index 45d9a45c..fe102f28 100644 --- 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 @@ -6,17 +6,19 @@ import de.evoal.languages.model.instance.Instance; import de.evoal.surrogate.api.function.SurrogateFunction; import javax.enterprise.context.Dependent; +import javax.inject.Inject; import javax.inject.Named; @Dependent @Named("surrogate") public class SurrogateFitnessFunction implements FitnessFunction { + @Inject private SurrogateFunction function; @Override public double[] evaluate(final Properties properties) { - return function.apply(properties).getValues(); + return function.apply(properties).getValuesAsDouble(); } @Override diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingDataProducer.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingDataProducer.java new file mode 100644 index 00000000..4b5dfce6 --- /dev/null +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingDataProducer.java @@ -0,0 +1,29 @@ +package de.evoal.surrogate.main.ea; + +import de.evoal.core.api.board.Blackboard; +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.properties.stream.FileBasedPropertiesStreamSupplier; +import de.evoal.surrogate.api.SurrogateBlackboardEntry; +import de.evoal.surrogate.api.training.TrainingDataManager; +import lombok.extern.slf4j.Slf4j; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; +import java.io.File; + +@ApplicationScoped +@Slf4j +public class TrainingDataProducer { + public void setTrainingData(final @Observes BlackboardEntry event, final Blackboard board, final TrainingDataManager manager) { + if (!event.isSame(SurrogateBlackboardEntry.SURROGATE_TRAINING_DATA_FILE)) { + return; + } + + final String filename = board.get(SurrogateBlackboardEntry.SURROGATE_TRAINING_DATA_FILE); + final File trainingFile = new File(filename); + + log.info("Using training data from {}.", filename); + + manager.setTrainingStream(new FileBasedPropertiesStreamSupplier(trainingFile)); + } +} 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 index 6e747777..f9a82e89 100644 --- 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 @@ -15,12 +15,9 @@ 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 @@ -48,20 +45,19 @@ public class TrainingInitialPopulation<G extends Gene<?, G>, C extends Comparabl .build(); } - // TODO @Inject - private CustomCodec<G> encoding; + @Inject + private CustomCodec encoding; private EvolutionInit<G> createTargetBasedInitialPopulation() { return EvolutionInit.of(createInitialPopulation(), 1l); } private ISeq<Genotype<G>> createInitialPopulation() { - return - manager.getTrainingStream() + return manager.getTrainingStream() .apply(totalSpecification) .unordered() .limit(sizeOfPopulation) - .map(encoding::encode) + .map(((CustomCodec<G>)encoding)::encode) .collect(ISeq.toISeq()); } diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingProducer.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingProducer.java new file mode 100644 index 00000000..1e89c044 --- /dev/null +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/ea/TrainingProducer.java @@ -0,0 +1,31 @@ +package de.evoal.surrogate.main.ea; + +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; +import javax.inject.Named; + +/** + * TODO For some reasons I am not able to create the training instance directly ... + */ +@ApplicationScoped +public class TrainingProducer { + + @Produces + @Dependent + @Named("training") + public InitialPopulation create(@ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.initialization") Instance initialization) { + final TrainingInitialPopulation population = new TrainingInitialPopulation(); + BeanFactory.injectFields(population); + population.init(); + population.init(initialization); + + return population; + } +} diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/gof/cross/CrossValidationCalculator.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/gof/cross/CrossValidationCalculator.java index 32d660a5..47592b13 100644 --- a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/gof/cross/CrossValidationCalculator.java +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/gof/cross/CrossValidationCalculator.java @@ -120,7 +120,7 @@ public class CrossValidationCalculator implements SurrogateInformationCalculator for (int cvi = 0; cvi < calculated.size(); ++cvi) { //correctness[cvi] = correctness[cvi] + Math.abs((calculated.get(cvi) - predicted.get(cvi)) / calculated.get(cvi)); - correctness[cvi] = correctness[cvi] + Math.abs(calculated.get(cvi) - predicted.get(cvi)); + correctness[cvi] = correctness[cvi] + Math.abs(calculated.getAsDouble(cvi) - predicted.getAsDouble(cvi)); } }); diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/gof/rsquare/RSquareCalculator.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/gof/rsquare/RSquareCalculator.java index deda8dce..ac43b3b0 100644 --- a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/gof/rsquare/RSquareCalculator.java +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/gof/rsquare/RSquareCalculator.java @@ -50,7 +50,7 @@ public class RSquareCalculator implements SurrogateInformationCalculator { final double [][] yValues = pairStream.get() .map(Pair::getSecond) - .map(Properties::getValues) + .map(Properties::getValuesAsDouble) .toArray(size -> new double[size][]); final double [] means = new double [yValues[0].length]; @@ -75,11 +75,10 @@ public class RSquareCalculator implements SurrogateInformationCalculator { final Properties input = pair.getFirst(); final Properties calculated = function.apply(input); - double [] values = new double[calculated.size()]; - System.arraycopy(calculated.getValues(), 0, values, 0, values.length); + double [] values = calculated.getValuesAsDouble(); for(int i = 0; i < values.length; ++i) { - values[i] = Math.pow(pair.getSecond().get(i) - values[i], 2); + values[i] = Math.pow(pair.getSecond().getAsDouble(i) - values[i], 2); } return values; 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 8bbd56a4..458e6f22 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 @@ -142,14 +142,14 @@ public class GenerationStatisticsWriter implements StatisticsWriter { for(int d = 0; d < dimensions; ++d) { final double value = sourceTrainingPoints .get(t) - .get(d); + .getAsDouble(d); trainingsMatrix.set(d, t, value); onTheFlyMatrix.set(d, t, value); } } for(int d = 0; d < dimensions; ++d) { - onTheFlyMatrix.set(d, onTheFlySize - 1, candidate.get(d)); + onTheFlyMatrix.set(d, onTheFlySize - 1, candidate.getAsDouble(d)); } final Matrix trainingsCovarianceMatrix = calculateCovarianceMatrix(trainingsMatrix); @@ -178,10 +178,10 @@ public class GenerationStatisticsWriter implements StatisticsWriter { final Genotype<?> genotype = genotypes.get(i); final Properties individual = (Properties) encoding.decode(genotype); - final double [] data = individual.getValues(); + final Object [] data = individual.getValues(); for(int j = 0; j < data.length; ++j) { - result.set(i, j, data[j]); + result.set(i, j, (Double)data[j]); } } 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 db812053..3dcaafd9 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 @@ -35,6 +35,8 @@ module de.evoal.surrogate.api { // open packages for CDI opens de.evoal.surrogate.api.training to weld.core.impl; + opens de.evoal.surrogate.api.configuration to com.fasterxml.jackson.databind; + 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; diff --git a/src/core/de.evoal.surrogate.neural/pom.xml b/src/core/de.evoal.surrogate.neural/pom.xml new file mode 100644 index 00000000..7454dbb4 --- /dev/null +++ b/src/core/de.evoal.surrogate.neural/pom.xml @@ -0,0 +1,54 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>de.evoal</groupId> + <artifactId>releng.parent</artifactId> + <version>0.9.0-SNAPSHOT</version> + + <relativePath>../de.evoal.releng.parent</relativePath> + </parent> + + <artifactId>surrogate.neural</artifactId> + <name>EvoAl - Surrogate - Neural Network</name> + + <properties> + <deeplearning4j.version>1.0.0-M2.1</deeplearning4j.version> + </properties> + + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>core.plugin</artifactId> + <version>${project.version}</version> + </dependency> + + <!-- neural networks --> + <dependency> + <groupId>org.deeplearning4j</groupId> + <artifactId>deeplearning4j-nn</artifactId> + <version>${deeplearning4j.version}</version> + </dependency> + + <dependency> + <groupId>org.nd4j</groupId> + <artifactId>nd4j-native</artifactId> + <version>${deeplearning4j.version}</version> + </dependency> + + <dependency> + <groupId>org.nd4j</groupId> + <artifactId>nd4j-common</artifactId> + <version>${deeplearning4j.version}</version> + </dependency> + + <dependency> + <groupId>de.evoal</groupId> + <artifactId>surrogate.api</artifactId> + <version>0.9.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project> diff --git a/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/EvoalDataSetIterator.java b/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/EvoalDataSetIterator.java new file mode 100644 index 00000000..7cbaf7d1 --- /dev/null +++ b/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/EvoalDataSetIterator.java @@ -0,0 +1,21 @@ +package de.evoal.surrogates.neural; + +import de.evoal.core.api.properties.stream.PropertiesPairStreamSupplier; +import org.nd4j.common.primitives.Pair; + +import java.util.Iterator; + +public class EvoalDataSetIterator implements Iterable<Pair<double [], double []>> { + private final PropertiesPairStreamSupplier provider; + + public EvoalDataSetIterator(final PropertiesPairStreamSupplier provider) { + this.provider = provider; + } + + @Override + public Iterator<Pair<double[], double[]>> iterator() { + return provider.get() + .map(p -> new Pair<>(p.getFirst().getValues(), p.getSecond().getValues())) + .iterator(); + } +} diff --git a/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/NeuralNetworkConfigurator.java b/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/NeuralNetworkConfigurator.java new file mode 100644 index 00000000..d3da4e47 --- /dev/null +++ b/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/NeuralNetworkConfigurator.java @@ -0,0 +1,154 @@ +package de.evoal.surrogates.neural; + +import org.deeplearning4j.nn.api.OptimizationAlgorithm; +import org.deeplearning4j.nn.conf.NeuralNetConfiguration; +import org.deeplearning4j.nn.conf.inputs.InputType; +import org.deeplearning4j.nn.conf.layers.DenseLayer; +import org.deeplearning4j.nn.conf.layers.Layer; +import org.deeplearning4j.nn.conf.layers.OutputLayer; +import org.deeplearning4j.nn.multilayer.MultiLayerNetwork; +import org.deeplearning4j.nn.weights.WeightInit; +import org.nd4j.linalg.activations.Activation; +import org.nd4j.linalg.learning.config.AdaGrad; +import org.nd4j.linalg.learning.config.IUpdater; +import org.nd4j.linalg.lossfunctions.LossFunctions; + +import java.security.SecureRandom; +import java.util.List; +import java.util.Map; + +public final class NeuralNetworkConfigurator { + private final Map<String, Object> parameters; + + public NeuralNetworkConfigurator(final Map<String, Object> parameters) { + this.parameters = parameters; + } + + public MultiLayerNetwork create() { + final NeuralNetConfiguration.ListBuilder builder = + new NeuralNetConfiguration.Builder() + .seed(seed()) + .weightInit(weightInit()) + .updater(updater()) + .activation(activation()) + .optimizationAlgo(optimizationAlgorithm()) + .l2(regularizationCoefficient()) + .list(); + + final List<Map<String, Object>> layers = parameter("layers"); + for (int index = 0; index < layers.size(); ++index) { + final Map<String, Object> configuration = layers.get(index); + + builder.layer(index, createLayer(index, configuration, index == layers.size() - 1)); + } + + builder.setInputType(InputType.feedForward((int)layers.get(0).get("in"))); + final MultiLayerNetwork nn = new MultiLayerNetwork(builder.build()); + nn.init(); + + return nn; + } + + private Layer createLayer(final int index, final Map<String, Object> configuration, boolean isOutputLayer) { + if (isOutputLayer) { + final OutputLayer.Builder builder = new OutputLayer.Builder(); + builder.nIn(value(configuration, "in")); + builder.nOut(value(configuration, "out")); + + if (configuration.containsKey("weight-init")) { + builder.weightInit(weightInit(configuration)); + } + + if (configuration.containsKey("activation")) { + builder.activation(activation(configuration)); + } + + if (configuration.containsKey("loss-function")) { + builder.lossFunction(lossFunction(configuration)); + } + + return builder.build(); + } else { + final DenseLayer.Builder builder = new DenseLayer.Builder(); + builder.nIn(value(configuration, "in")); + builder.nOut(value(configuration, "out")); + + if (configuration.containsKey("weight-init")) { + builder.weightInit(weightInit(configuration)); + } + + if (configuration.containsKey("activation")) { + builder.activation(activation(configuration)); + } + + return builder.build(); + } + } + + private LossFunctions.LossFunction lossFunction(final Map<String, Object> configuration) { + return LossFunctions.LossFunction.valueOf(value(configuration, "loss-function")); + } + + private double regularizationCoefficient() { + return parameter("l2-regularization-coefficient"); + } + + private OptimizationAlgorithm optimizationAlgorithm() { + final String name = parameter("optimization-algorithm"); + + return OptimizationAlgorithm.valueOf(name); + } + + private Activation activation() { + return activation(parameters); + } + + private Activation activation(final Map<String, Object> configuration) { + final String name = value(configuration, "activation"); + + return Activation.valueOf(name); + } + + private IUpdater updater() { + final Map<String, Object> updaterConfig = parameter("updater"); + + switch (this.<String>value(updaterConfig, "name")) { + case "ada-grad": { + final double learningRate = value(updaterConfig, "learning-rate"); + + return new AdaGrad(learningRate); + } + + default: + throw new IllegalArgumentException("updater unknown: " + value(updaterConfig, "name")); + } + } + + private WeightInit weightInit() { + return weightInit(parameters); + } + + private WeightInit weightInit(final Map<String, Object> configuration) { + final String name = value(configuration, "weight-init"); + + return WeightInit.valueOf(name); + } + + private long seed() { + final Object seed = parameter("seed"); + + if (seed instanceof Number) { + return ((Number) seed).longValue(); + } else { + return new SecureRandom().nextLong(); + } + } + + private <T> T parameter(final String name) { + return value(parameters, name); + } + + private static <T> T value(final Map<String, Object> map, final String name) { + return (T) map.get(name); + } +} \ No newline at end of file diff --git a/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/NeuralNetworkHelper.java b/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/NeuralNetworkHelper.java new file mode 100644 index 00000000..83fa65cb --- /dev/null +++ b/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/NeuralNetworkHelper.java @@ -0,0 +1,37 @@ +package de.evoal.surrogates.neural; + +import de.evoal.surrogate.api.configuration.Parameter; +import lombok.NonNull; +import org.deeplearning4j.nn.multilayer.MultiLayerNetwork; +import org.deeplearning4j.util.ModelSerializer; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public final class NeuralNetworkHelper { + private NeuralNetworkHelper() { + } + + static List<Parameter> toParameters(final @NonNull MultiLayerNetwork nn) { + final List<Parameter> parameters = new ArrayList<>(); + parameters.add(toNetworkConfig(nn)); + + return parameters; + } + + private static Parameter toNetworkConfig(final MultiLayerNetwork nn) { + try (final ByteArrayOutputStream bos = new ByteArrayOutputStream()) { + ModelSerializer.writeModel(nn, bos, true); + + return Parameter.builder() + .name("model") + .value(bos.toString("UTF8")) + .build(); + } catch (final IOException e) { + e.printStackTrace(); + throw new RuntimeException("Failed"); + } + } +} diff --git a/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/SimpleNeuralNetwork.java b/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/SimpleNeuralNetwork.java new file mode 100644 index 00000000..ecde75ad --- /dev/null +++ b/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/SimpleNeuralNetwork.java @@ -0,0 +1,41 @@ +package de.evoal.surrogates.neural; + + +import de.evoal.core.api.properties.Properties; +import de.evoal.core.api.properties.PropertiesSpecification; +import de.evoal.surrogate.api.configuration.PartialFunctionConfiguration; +import de.evoal.surrogate.api.function.AbstractPartialSurrogateFunction; +import org.deeplearning4j.nn.multilayer.MultiLayerNetwork; +import org.nd4j.linalg.factory.Nd4j; + +public class SimpleNeuralNetwork extends AbstractPartialSurrogateFunction { + + /** + * Indices of input data + */ + private final int[] indices; + + /** + * Actual SVR + */ + private final MultiLayerNetwork nn; + + public SimpleNeuralNetwork(final PartialFunctionConfiguration configuration, final MultiLayerNetwork nn, final PropertiesSpecification input, final PropertiesSpecification actualInput, final PropertiesSpecification output) { + super(configuration, NeuralNetworkHelper.toParameters(nn), input, output); + + this.indices = input.getProperties().stream().mapToInt(p -> actualInput.indexOf(p)).toArray(); + + this.nn = nn; + } + + @Override + public double [] apply(final Properties input) { + final double [] data = new double[indices.length]; + + for(int i = 0; i < data.length; ++i) { + data[i] = input.get(indices[i]); + } + + return nn.output(Nd4j.create(new double[][]{data})).toDoubleVector(); + } +} diff --git a/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/SimpleNeuralNetworkFactory.java b/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/SimpleNeuralNetworkFactory.java new file mode 100644 index 00000000..b7752dc1 --- /dev/null +++ b/src/core/de.evoal.surrogate.neural/src/main/java/de/evoal/surrogates/neural/SimpleNeuralNetworkFactory.java @@ -0,0 +1,78 @@ +package de.evoal.surrogates.neural; + +import de.evoal.core.api.properties.PropertiesSpecification; +import de.evoal.core.api.properties.stream.PropertiesPairStreamSupplier; +import de.evoal.surrogate.api.configuration.Parameter; +import de.evoal.surrogate.api.configuration.PartialFunctionConfiguration; +import de.evoal.surrogate.api.function.AbstractPartialSurrogateFunctionFactory; +import de.evoal.surrogate.api.function.PartialSurrogateFunction; +import lombok.extern.slf4j.Slf4j; +import org.deeplearning4j.datasets.iterator.DoublesDataSetIterator; +import org.deeplearning4j.nn.multilayer.MultiLayerNetwork; +import org.nd4j.evaluation.classification.Evaluation; +import org.nd4j.evaluation.classification.ROCMultiClass; +import org.nd4j.linalg.dataset.api.iterator.DataSetIterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.enterprise.context.Dependent; +import javax.inject.Named; +import java.nio.channels.NotYetConnectedException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Dependent +@Named("neural-network") +@Slf4j +public class SimpleNeuralNetworkFactory extends AbstractPartialSurrogateFunctionFactory { + @Override + protected PartialSurrogateFunction calculateRegression(final PartialFunctionConfiguration configuration, final List<Parameter> parameters, final PropertiesSpecification actualInput, final PropertiesSpecification requiredInput, final PropertiesSpecification producedOutput, final PropertiesPairStreamSupplier provider) { + log.info("Calculate neural network from {} to {}.", requiredInput, producedOutput); + + final Map<String, Object> params = parameters.stream() + .collect(Collectors.toMap(Parameter::getName, Parameter::getValue)); + + final MultiLayerNetwork nn = createNeuralNetwork(params); + final DataSetIterator iterator = new DoublesDataSetIterator(new EvoalDataSetIterator(provider), 5); + + nn.fit(iterator, 1000); + + + Evaluation eval = nn.evaluate(iterator); + System.out.println("acc ->" + eval.accuracy()); + System.out.println(eval.precision()); + System.out.println(eval.recall()); + + // ROC for Area Under Curve on multi-class datasets (not binary classes) + ROCMultiClass [] roc = nn.doEvaluation(iterator, new ROCMultiClass()); + for(int i = 0; i < roc.length; ++i) { + System.out.println("[i] -> " + roc[i].calculateAverageAUC()); + System.out.println("[i] -> " + roc[i].calculateAverageAUCPR()); + } + + return new SimpleNeuralNetwork(configuration, nn, requiredInput, actualInput, producedOutput); + } + + private MultiLayerNetwork createNeuralNetwork(final Map<String, Object> parameters) { + return new NeuralNetworkConfigurator(parameters).create(); + } + + @Override + protected PartialSurrogateFunction restoreRegression(final PartialFunctionConfiguration configuration, final PropertiesSpecification actualInput, final PropertiesSpecification requiredInput, final PropertiesSpecification producedOutput) { + throw new NotYetConnectedException(); + /* + final KernelMachine<double []> regression = KernelHelper.fromParameters(configuration.getParameters(), configuration.getFunctionParameters()); + + final double margin = configuration.getParameters() + .stream() + .filter(p -> "soft-margin".equals(p.getName())) + .map(Parameter::getValue) + .map(Double.class::cast) + .findFirst() + .orElse(0.1); + + return new KernelBasedSVRFunction(configuration, regression, requiredInput, actualInput, producedOutput, margin); + */ + } +} diff --git a/src/core/de.evoal.surrogate.neural/src/main/java/module-info.java b/src/core/de.evoal.surrogate.neural/src/main/java/module-info.java new file mode 100644 index 00000000..cdc97724 --- /dev/null +++ b/src/core/de.evoal.surrogate.neural/src/main/java/module-info.java @@ -0,0 +1,13 @@ +module de.evoal.surrogate.neural { + requires commons.math3; + requires jakarta.enterprise.cdi.api; + requires lombok; + requires org.slf4j; + + requires de.evoal.core; + requires de.evoal.surrogate.api; + requires deeplearning4j.nn; + requires nd4j.api; + requires deeplearning4j.utility.iterators; + requires jakarta.inject.api; +} diff --git a/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/identity/IdentityFunction.java b/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/identity/IdentityFunction.java index b04cccc2..b1051d69 100644 --- a/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/identity/IdentityFunction.java +++ b/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/identity/IdentityFunction.java @@ -24,6 +24,6 @@ public class IdentityFunction extends AbstractPartialSurrogateFunction { } public double [] apply(final Properties input) { - return new double[] {input.get(propertyIndex)}; + return new double[] {input.getAsDouble(propertyIndex)}; } } diff --git a/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/linear/LinearFunction.java b/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/linear/LinearFunction.java index 0db00afc..8588235c 100644 --- a/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/linear/LinearFunction.java +++ b/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/linear/LinearFunction.java @@ -61,7 +61,7 @@ public class LinearFunction extends AbstractPartialSurrogateFunction { final PropertySpecification inputProperty = input.getProperties().get(0); final int propertyIndex = actualInput.indexOf(inputProperty); - this.regression = vector -> intercept + slope * vector.get(propertyIndex); + this.regression = vector -> intercept + slope * vector.getAsDouble(propertyIndex); } public double [] apply(final Properties input) { diff --git a/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/linear/LinearFunctionFactory.java b/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/linear/LinearFunctionFactory.java index 8e961f5b..086826dc 100644 --- a/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/linear/LinearFunctionFactory.java +++ b/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/linear/LinearFunctionFactory.java @@ -32,7 +32,7 @@ public class LinearFunctionFactory extends AbstractPartialSurrogateFunctionFacto provider.get() .forEach(coordinate -> { log.info("Mapping - ({}) to ({}).", coordinate.getFirst(), coordinate.getSecond()); - regression.addData(coordinate.getFirst().get(0), coordinate.getSecond().get(0)); + regression.addData(coordinate.getFirst().getAsDouble(0), coordinate.getSecond().getAsDouble(0)); }); return new LinearFunction(configuration, LinearFunction.toParameters(regression), requiredInput, actualInput, producedOutput); diff --git a/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/quadratic/SimpleQuadraticFunction.java b/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/quadratic/SimpleQuadraticFunction.java index 455e4598..195ed63b 100644 --- a/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/quadratic/SimpleQuadraticFunction.java +++ b/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/quadratic/SimpleQuadraticFunction.java @@ -60,7 +60,7 @@ public class SimpleQuadraticFunction extends AbstractPartialSurrogateFunction { final PropertySpecification inputProperty = input.getProperties().get(0); final int propertyIndex = actualInput.indexOf(inputProperty); - this.regression = vector -> intercept + slope * vector.get(propertyIndex); + this.regression = vector -> intercept + slope * vector.getAsDouble(propertyIndex); } public double [] apply(final Properties input) { diff --git a/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/quadratic/SimpleQuadraticFunctionFactory.java b/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/quadratic/SimpleQuadraticFunctionFactory.java index 63e673d0..acbdafff 100644 --- a/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/quadratic/SimpleQuadraticFunctionFactory.java +++ b/src/core/de.evoal.surrogate.simple/src/main/java/de/evoal/surrogate/simple/quadratic/SimpleQuadraticFunctionFactory.java @@ -33,7 +33,7 @@ public final class SimpleQuadraticFunctionFactory extends AbstractPartialSurroga provider.get() .forEach(coordinate -> { log.info("Mapping - ({}) to ({}).", coordinate.getFirst(), coordinate.getSecond()); - regression.addData(Math.pow(coordinate.getFirst().get(0), 2), coordinate.getSecond().get(0)); + regression.addData(Math.pow(coordinate.getFirst().getAsDouble(0), 2), coordinate.getSecond().getAsDouble(0)); }); return new SimpleQuadraticFunction(configuration, LinearFunction.toParameters(regression), requiredInput, actualInput, producedOutput); diff --git a/src/core/de.evoal.surrogate.simple/src/main/java/module-info.java b/src/core/de.evoal.surrogate.simple/src/main/java/module-info.java index 5d389895..8f69072b 100644 --- a/src/core/de.evoal.surrogate.simple/src/main/java/module-info.java +++ b/src/core/de.evoal.surrogate.simple/src/main/java/module-info.java @@ -6,4 +6,5 @@ module de.evoal.surrogate.simple { requires de.evoal.core; requires de.evoal.surrogate.api; + requires jakarta.inject.api; } diff --git a/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/GaussianKernelSVRFunctionFactory.java b/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/GaussianKernelSVRFunctionFactory.java index b58d9b6e..5cc2dcdd 100644 --- a/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/GaussianKernelSVRFunctionFactory.java +++ b/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/GaussianKernelSVRFunctionFactory.java @@ -26,7 +26,7 @@ import java.util.stream.Collectors; @Slf4j public class GaussianKernelSVRFunctionFactory extends KernelBasedSVRFunctionFactory { public GaussianKernelSVRFunctionFactory() { - super(KernelHelper::toGaussianKernel); + super(KernelHelper::toGaussianKernel, "gaussian"); } @Override @@ -41,6 +41,6 @@ public class GaussianKernelSVRFunctionFactory extends KernelBasedSVRFunctionFact .findFirst() .orElse(0.1); - return new KernelBasedSVRFunction(configuration, regression, requiredInput, actualInput, producedOutput, margin); + return new KernelBasedSVRFunction(configuration, regression, "gaussian", requiredInput, actualInput, producedOutput, margin); } } diff --git a/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelBasedSVRFunction.java b/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelBasedSVRFunction.java index 877a5391..4411b672 100644 --- a/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelBasedSVRFunction.java +++ b/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelBasedSVRFunction.java @@ -21,8 +21,8 @@ public class KernelBasedSVRFunction extends AbstractPartialSurrogateFunction { private final double gamma; - public KernelBasedSVRFunction(final PartialFunctionConfiguration configuration, final KernelMachine<double []> regression, final PropertiesSpecification input, final PropertiesSpecification actualInput, final PropertiesSpecification output, final double gamma) { - super(configuration, KernelHelper.toParameters(regression), input, output); + public KernelBasedSVRFunction(final PartialFunctionConfiguration configuration, final KernelMachine<double []> regression, final String kernelName, final PropertiesSpecification input, final PropertiesSpecification actualInput, final PropertiesSpecification output, final double gamma) { + super(configuration, KernelHelper.toParameters(regression, kernelName), input, output); this.indices = input.getProperties().stream().mapToInt(p -> actualInput.indexOf(p)).toArray(); @@ -35,7 +35,7 @@ public class KernelBasedSVRFunction extends AbstractPartialSurrogateFunction { final double [] data = new double[indices.length]; for(int i = 0; i < data.length; ++i) { - data[i] = input.get(indices[i]); + data[i] = input.getAsDouble(indices[i]); } return new double [] {regression.predict(data)}; diff --git a/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelBasedSVRFunctionFactory.java b/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelBasedSVRFunctionFactory.java index c0914223..5555805f 100644 --- a/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelBasedSVRFunctionFactory.java +++ b/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelBasedSVRFunctionFactory.java @@ -25,12 +25,15 @@ public abstract class KernelBasedSVRFunctionFactory extends AbstractPartialSurro */ private final Function<Map<String, Object>, MercerKernel<double[]>> toKernel; - public KernelBasedSVRFunctionFactory(final Function<Map<String, Object>, MercerKernel<double []>> toKernel) { + private final String nameOfKernel; + + public KernelBasedSVRFunctionFactory(final Function<Map<String, Object>, MercerKernel<double []>> toKernel, final String nameOfKernel) { this.toKernel = toKernel; + this.nameOfKernel = nameOfKernel; } @Override - protected PartialSurrogateFunction calculateRegression(final PartialFunctionConfiguration configuration, List<Parameter> parameters, PropertiesSpecification actualInput, PropertiesSpecification requiredInput, PropertiesSpecification producedOutput, PropertiesPairStreamSupplier provider) { + protected PartialSurrogateFunction calculateRegression(final PartialFunctionConfiguration configuration, final List<Parameter> parameters, PropertiesSpecification actualInput, PropertiesSpecification requiredInput, PropertiesSpecification producedOutput, PropertiesPairStreamSupplier provider) { log.info("Calculate SVR surrogate from {} to {}.", requiredInput, producedOutput); Requirements.requireSizeGreaterThean(requiredInput.getProperties(), 0); @@ -41,8 +44,8 @@ public abstract class KernelBasedSVRFunctionFactory extends AbstractPartialSurro provider.get() .forEach(p -> { - sources.add(p.getFirst().getValues()); - targets.add(p.getSecond().get(0)); + sources.add(p.getFirst().getValuesAsDouble()); + targets.add(p.getSecond().getAsDouble(0)); }); log.info("Using {} points for regression.", sources.size()); @@ -59,6 +62,6 @@ public abstract class KernelBasedSVRFunctionFactory extends AbstractPartialSurro final KernelMachine<double []> regression = SVR.fit(sourceArray, targetArray, toKernel.apply(params), epsilon, margin, tolerance); - return new KernelBasedSVRFunction(configuration, regression, requiredInput, actualInput, producedOutput, margin); + return new KernelBasedSVRFunction(configuration, regression, nameOfKernel, requiredInput, actualInput, producedOutput, margin); } } diff --git a/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelHelper.java b/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelHelper.java index fc82572f..63e0007f 100644 --- a/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelHelper.java +++ b/src/core/de.evoal.surrogate.svr/src/main/java/de/evoal/surrogate/svr/KernelHelper.java @@ -30,7 +30,7 @@ public final class KernelHelper { public static final String TOLERANCE_PARAMETER = "tolerance"; - private static final String KERNEL_PARAMETER = "kernel"; + public static final String KERNEL_PARAMETER = "kernel"; /** * Logger instance @@ -57,7 +57,7 @@ public final class KernelHelper { public static KernelMachine<double []> fromParameters(final List<Parameter> parameters, final List<Parameter> kernelParameters) { final Map<String, Object> kernelParameterMap = toMap(kernelParameters); - final MercerKernel<double []> kernel = toKernel(toMap(parameters)); + final MercerKernel<double []> kernel = toKernel(toMap(parameters), kernelParameterMap); final double[][] instances =(double[][]) kernelParameterMap.get("instances"); final double[] weight = (double[]) kernelParameterMap.get("weights"); final double b = (double)kernelParameterMap.get("intercept"); @@ -73,10 +73,10 @@ public final class KernelHelper { return new GaussianKernel(sigma); } - public static MercerKernel<double []> toKernel(final Map<String, Object> parameters) { - log.info(" Using kernel '{}'", parameters.get(KERNEL_PARAMETER)); + public static MercerKernel<double []> toKernel(final Map<String, Object> parameters, final Map<String, Object> state) { + log.info(" Using kernel '{}'", state.get(KERNEL_PARAMETER)); - switch((String)parameters.get(KERNEL_PARAMETER)) { + switch((String)state.get(KERNEL_PARAMETER)) { case "gaussian": { final double sigma = (double)parameters.get(SIGMA_PARAMETER); @@ -142,13 +142,14 @@ public final class KernelHelper { throw new IllegalArgumentException("The kernel " + parameters.get(KERNEL_PARAMETER) + " is not supported."); } - public static List<Parameter> toParameters(final Regression<double[]> regression) { + public static List<Parameter> toParameters(final Regression<double[]> regression, final String kernelName) { final KernelMachine<double []> machine = (KernelMachine<double[]>)regression; final List<Parameter> result = new LinkedList<>(); addParameter("weights", machine.weights(), result); addParameter("intercept", machine.intercept(), result); addParameter("instances", machine.instances(), result); + addParameter(KERNEL_PARAMETER, kernelName, result); return result; } -- GitLab