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 cd8cca012275bf660762a7ef93e4875ea40acd7c..0000000000000000000000000000000000000000 --- 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 6c506a4e9db323b6cb487f2b33a3a0210c177fb7..0000000000000000000000000000000000000000 --- 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 ace1b582fbf625b97ef5a14521f30683ba68ed11..0000000000000000000000000000000000000000 --- 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 4378bff9892f6a9c788cdc550dff2648f91495fa..0000000000000000000000000000000000000000 --- 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 57db2a9103f2f05a864c900917817e06d821daef..0000000000000000000000000000000000000000 --- 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 c16e14589d7dc4d7395f6029d6a2501bc7d2dac6..0000000000000000000000000000000000000000 --- 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 b2ba822fd4b9eb02177c2c22e8fb08fd3bf38584..0000000000000000000000000000000000000000 --- 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 4bc7b34552a37dc2393f8ee4c929832b44ce3981..b2282d964b9a91e70f3e595329963f9c6f73b343 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 678b5fd9d4d2076444847dc4bf9176cf2e02a3b0..b3e466e67b5c7f1907abdcad97cc323499dd9a59 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 f7b90f120d4dde3fbaa37e2c66aa561d22c9d80c..61545d04aa925c2b297eb7f08edf65dadeff25c5 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 fac1ddb75eb736abc32aaa157d3b98b5a5ce6491..683b2d94a773a641e924b8952739471b6ed17c2d 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 fb8253ad7794b3ef9e9f380aa8ee3f1aab7c9cd9..6b0e79e2d536d1c9416eccdfb9a15903cfd7a530 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 445e3335fddfd00af904abbff9ead197b8d81d4a..1d4192704c6a6cf104330aefc639726062c1b14a 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 ad55de2c2e3995b4136bc6e4917cd2bc8d700131..7b100609cac782cc10ded80453597c76cc5868a1 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 3cd82ef459206dda885e79bad403ea36d2ef5a7c..c5b02923dbce173bf999fc8319c129d6418a57b8 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 ce615e5be640652850f75d4455ddaf2c5f6c46e7..21b887eb713caf858d176e88bd96431350f0de84 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 f69a76b988e84834d5093bda9df4b6e400a0e8d7..2a037c5fc864fc96288aa8c4a36bcbac992100c1 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 513106d74eb9f2bce165271b1858d38048778d43..3bff0b7c93093be89bb1018318d89dc64d7ea337 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 b608b1e5aca7bf7532c8eef2c98a86c6c3c971b5..597a496bfa4b50f1e3ec884180554241fbf3fc1d 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 26927ebf0828c35d89b75bf8ec173f6635430291..63fd72cc5d4cbab28bc98dce8bae2e9fe93b5509 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 c5748e3c755ac5c2af2393cc03f3dff2f0ba8143..437f41af99d2709e8358b18da00e539bb255c2ae 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 929b221040152b4265d780b6016b9ce2b77f2995..ef0cfe2159213fde83e3abda475be6db5787025a 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 a044d67736bd3cea7c90ed15c8be74f51f504ab4..f3ba135260acb4201168f02b4bb19066dcd0725c 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 3ddd0104a2322b2b0a7ace35e6faccf74dd82b05..aa2a20825ee7efbf8c612a860672d751b255a3ae 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 b829f6dfab02fcd31a5fda7c26fd72aa88ba9beb..86edaa38c2d16a32c4c945dbaa3ab33fbcbb9948 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 1bdf0e05649590e1b82e6e4b5eb5b704cb28cffe..3c755d6c5dc71404321b2e548d0d13da633b4c4f 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 66977b3bdcc2b8a678711c9e6ffd607ab28c841e..dfeb518c4c9d2ebedd83ac008e0dce3f0da503c5 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 84615c0a4373c413a7956bc8fc0ba07c46aa7d9f..12066ed21cc5ac9a06eb8496ead941fc177fdbdb 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 42957f149aebabf7745ea41b361befadf82547a8..42d2e08aa27c9f7df6cb4c3c1c7ee9b3b1a06338 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 53ee1d9aff828f5a989d937594e441a1db9afb2a..df3bb82ec20bf8ebab6e6463b6e73a1408855564 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 18a6ddd84dca859e95ca58f1bfd3f17ecdf96a79..5f611d67b054b8d2675f80818375e57b217c42c8 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 4fe2316e26afa1ca7f113f21aa3e0663c3e626e8..c87c0a30e103c3f9c135d92f6b8e743b3d219af6 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 0ce3b1c205171223b18207effc725772c8de727c..4e93aaf3fbe83a30dca435ad70d7d042a9fd71ba 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 d8f44559188c7e4ffb59af2fd2d5be47c32c025b..d2b8604fe69279b3130cf85560705647b751bb99 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 186e7b94c4b413e55415bd43c0f8547cbc320ab0..b68141c83763d9cd94839d5b9ac69796d06de88d 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 25b3c926ecfca732df4661812c144d695a91d454..2c38a4f827bd6e643e419d6eedd1fca06f3c0fae 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 e7a7eee4a74fe817ed7dfdf126a2bbd4af3b4a1b..ad5e1b675f66cde6e353a253beeb07ee78ae0857 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 66c1b3050dbdcba41979249d73d56763b7412670..e8165bed1855de343ab1100b76d389ce5c8507d1 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 15a4c49cff89e42fd8ed9cbd425c32d296eec560..07e625b3a13290e63ede5be9aa7db58cf2ebe0cd 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 5eddb9e06a6a33e308b815e6df88f5d41b0a5d01..efb3b762b557c2fd1a0a7e213fce988d185d74b4 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 a1fa9d382f041b219e7646cf84b5f5ee60f35a1c..c2ea8f05c0d4c58ea3860fc0288c0983a65a03df 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 aa03b14f1477fce7f0ecab66e6d3ab56a12498a5..2aab3ccf4fdac70b79765e3721caa05d66848179 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 7f3dfc111edf9bafbd210db37b59cd303f1e739e..beecd5fe58851d6983c5fb1f82d45725bc19ee98 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 b8e71b71fe6489ee150adb7705651fdb0ed93436..ca6a0543f73925dfa94e800613aa0a18a21faab7 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 0000000000000000000000000000000000000000..e986cd9a3f623f2c11ab5715982f32e4367a26bf --- /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 0000000000000000000000000000000000000000..17376a08c791a5ab848e022627878f3cc0fc9c8c --- /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 0000000000000000000000000000000000000000..c050bb51a6b61fa159dd91a822ce9882fcae909b --- /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 0000000000000000000000000000000000000000..def8f4459c752783cc93a34914ae09d56c29241c --- /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 0000000000000000000000000000000000000000..94b33169e514f03499cee3820a0a3d51eaa515db --- /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 0000000000000000000000000000000000000000..721d938888fdfc08a420d062da14241bcd6d01a3 --- /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 0000000000000000000000000000000000000000..7711394b2390be281584b6467a8ab2cb63082de0 --- /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 0000000000000000000000000000000000000000..1c18683bf94e54e5b623e397c761b1c886b530c2 --- /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 0000000000000000000000000000000000000000..0af13e4897aea8bfe236ac519c57f9b2f48f907e --- /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 e4bf15cd5bae1dac9b5f0c7f397df5c760b12909..4a97568219d391d9a517109edd73479d84b8568e 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 b81806142460964ae20db832c3b92b7ec683c292..6d77df732e8719201dee96fc7a7039d9ee7a3c24 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 7b971da36b55bdfa01ae2401a4f2dcabed2599b1..391664710632312f830fd30733e61f6d15ea2358 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 ac8f7f1d66babc6a727d5997d695a62165fe1d4d..2f69f8388c3c801e778f361f84cb8dbae8008660 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 5f0c948295cd3662aa9e625db2c15516877c70d1..9ea64a72fa31208ced48e34eed27fbd527c00536 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 0000000000000000000000000000000000000000..113efb499c008419e93907d6ecef7d4db7cf25c4 --- /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 450f855557b82a12672fbd3b88429313ec2ea66a..29df4674b71e6b21d625a8c4b40a0bd1293b7064 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 bd199bba1b1d14c24efe7d3de0bdfd16fa56f127..949d0ab15c30df507592ae0754ed19b2b367aedd 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 6b71bad7b9cecd2d3f3bce17e50592877e86b959..5110014bd8c24c3800fe2db2abe105f7456e9684 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 e4dc2468f61454425e55cbfc5254bfa9856117a7..cadbb0fce3c12585231f81462b6d3a6f708da2a4 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 856ae2998c43f06e38fb67914b22a2eb174596cf..7df1ae1b70b0858188d00efe7461c59555d82bfa 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 0000000000000000000000000000000000000000..4b56a1493e18bf06993ecfb884aaa4fd3005f21f --- /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 0000000000000000000000000000000000000000..f3d7eec0c9f8f0e78f2118ab26aac80a8c121f64 --- /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 495cf61907b79983d4d088e3a7cf2bd3e5c8f811..5b476c49cf3f694d8eee98971c5642ae2c60138b 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 05edb2a55de7d009c599db6be0394af03dfeb2b1..b2ea8a64feaf43ce589c65cd5292ea44f7de5edb 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 0000000000000000000000000000000000000000..d0999989bee80b2ded4d58a3116a7f9e4b4b06c1 --- /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 0000000000000000000000000000000000000000..e5bce3ebd9acf91a480ed61291df6f6284dc49f0 --- /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 0000000000000000000000000000000000000000..8d6ac70f5b008a1fe81fcbca4616611b0639a4ab --- /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 24af567848876b58bfa6ab5593ef8b6e8c812519..fd9e1160bf38d0f72d0e06be6c379889b07303a5 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 52f42efbd93a9bbfd455dceb2c00021b1abccfa0..bf1398b8101ad170334d20c10979afc4ed2d1c94 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 5d30fbb6bef83d3574927c118763df9c6d1b0e25..65fe1161df8b12bf0178b16d75c3c48b6e28ab16 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 1c478d81743378473ee624263d5e5ffd5ecfb7b8..20ae13a7bff17c6395ea98b25bfaa8f372244d1b 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 0000000000000000000000000000000000000000..f180cfb880c53c519d3cc244ebd2d7eaef013039 --- /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 268f125f140bbed31b76809a135a3758cc32f06d..4f341d3eacd2b9118e2a27b93bd1bbb2336ed4b5 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 0000000000000000000000000000000000000000..362abce453ea7dff8bedd6820f3c37cffbc65627 --- /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 0000000000000000000000000000000000000000..e7ef652dfcf1342bcb309c5e2825ff134b64a3eb --- /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 3ca2b0257b829b5f351e1e89baa8e450e63cc44e..75cfe96a825df46cd6b037f0b622e8f86f57a023 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 ff621367b0d6c3dd245bc7db121c089d9eedee8a..1aa0b95acdcf8067343fef5817d4a10f2c75cb1a 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 ede13d749b01a54968683d96bb08485a145cd80b..cdedd0991bf7cfc9d049bc6b867d5784a54994e6 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 1dd91a28fa915a90531de9672e1d644f32da917d..424be14f007be1b497b3f11a661bb01ed173da79 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 6179819c72cb238a35f29c2ac1b7f1e48be2f156..910cba1f3d8b715842043b65214e8e012dc96b34 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 e0756ab82805db61dc82e657a27f3b80847ba2b7..195ae316e57a342ff0b062d271d774ee762d469d 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 73bb87b6cec5f0816a88ed92318828c4404e1862..bd75d43767a6f5de2be38efb655cbb6393ada2d3 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 6cca3ee9d8f15408bd3ce24089b7880848227ca5..7b518dd4a0adf9511c0807598eddc6821a7377c8 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 c5538d06ed427fe8a72fe0cc14f574337ca53e0e..46e7bfeede9efb81dcc1f0224da6c70c800c8c39 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 9e1b291fd2087d1a9ef485449537986b0ff2f0a9..1e3e6647a9e947ee72cf8988ee07a59673161283 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 f59a161383b96902909a6adc4f114984ca9be41f..24cfc4d410b3037fb58468734d15c57a3e9c2217 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 f6e176c61518ed49fddff8f2e32f6ea2643612b9..e52bd620a4a6b934690804548abdbd1d702e2b15 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 940cb15c2c15841dc0f556b0d01750eae485c2ec..e36732427af29100241ffb9c6603110b9c06ccae 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 c833689dbec7571e51115e75c68ed2d18596880b..53adc4e5460aa962382ff1f1fa9f93949a7cdc61 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 0000000000000000000000000000000000000000..8b390572ca10a59b35c6cd339c41919e4db131c2 --- /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 45d9a45c05aab9593711ae4cee564fbda75448e6..fe102f28b9e092da7f13e5df3b0339567c152bc4 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 0000000000000000000000000000000000000000..4b5dfce6af450d48aa3e930cfd75d5ed8b11aa85 --- /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 6e747777fe9740b1e7521d5f89f3493df6238d70..f9a82e89877a93e2ba193aa65e76f989350e2c2c 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 0000000000000000000000000000000000000000..1e89c04493fc80fcbe742c89cdcdcaa2d51b7a32 --- /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 32d660a553363b59496352831e2596dad2be388f..47592b1311ed407f00acbe4d05e28380c22eac29 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 deda8dce092b4664d93b68af481bc3a13b098e07..ac43b3b0f66d2ddadbe4c6387664ad3e571075f6 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 8bbd56a43826b816f2735b673340b69317959b9d..458e6f229b9e814c437eb01614c063ee17390ec8 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 db812053849ec95a83c9dc2a03a843b886fc7dc7..3dcaafd9265df6f75cfb0a7077db9382287aa51b 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 0000000000000000000000000000000000000000..7454dbb4aab59d39c8e3886a03206a84c0918827 --- /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 0000000000000000000000000000000000000000..7cbaf7d1a0001c7c4421bf6a4226510ec74cc1ad --- /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 0000000000000000000000000000000000000000..d3da4e47e1ddd4e0c13a2133021dd394e635c9e9 --- /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 0000000000000000000000000000000000000000..83fa65cbfc5532736d3ee6fc369bc4006b54028a --- /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 0000000000000000000000000000000000000000..ecde75ada70c952b8b5fef759b33b8cf5ca62e6d --- /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 0000000000000000000000000000000000000000..b7752dc1fe2d6d1243fdbcfaf96796c9663be04c --- /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 0000000000000000000000000000000000000000..cdc977244ba00668ad57c39ed9cca413e6cbd386 --- /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 b04cccc2407f8fcf5a7a3e9084020f91325baf2d..b1051d6973d4473f096fbe3e787d87be935f14c1 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 0db00afcc0587bf3090a077f030e02dd25557f56..8588235cefa91ac11713fcd95cbd47d39eb74e03 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 8e961f5b4023d26726851af25ff95fc745435c24..086826dcfc42b5f9d19f97bfc8b60349eb956f4d 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 455e4598398b28b05d56dfed8c074c8236769d96..195ed63b0baced0cefd9972e0a7df8d35e5a00e3 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 63e673d0b05e98b4964bd0cef592293fa570dbd7..acbdafff510dac3bb68d3a5e83745b19c2194d32 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 5d38989565e94575336f6f726df3defa12ca8671..8f69072b04cd0073bc0576b1076ff14888ec106c 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 b58d9b6e23d2cf0e4cd990b68308f78d3fa36dd4..5cc2dcdd5af3f9d23470e978de8495acbaf7f2d7 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 877a5391a63c4a2b30023c2a9016abf0e7fcaff8..4411b6728d7d20e46feec26cec88b080868be143 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 c091422329ffcf18bf23c1f3133d1e8f7cd09c44..5555805fe1fd7a75745d57549c1a19e2029652be 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 fc82572f771eeaf60da1a930c9be0a2bb9248e75..63e0007f4ecae28011ca7b5ce8800216ace56784 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; }