Skip to content
Snippets Groups Projects
Commit 8e3b7790 authored by Nils Leusmann's avatar Nils Leusmann
Browse files

Merge remote-tracking branch 'origin/develop' into 160-new-generator-type-sequencer

parents 11d18866 6c57172d
No related branches found
No related tags found
1 merge request!57Draft: Add sequence generators
Showing
with 539 additions and 413 deletions
...@@ -33,29 +33,24 @@ module de.evoal.generator.main { ...@@ -33,29 +33,24 @@ module de.evoal.generator.main {
requires de.evoal.optimisation.api; requires de.evoal.optimisation.api;
requires com.google.common; requires com.google.common;
opens de.evoal.generator;
opens de.evoal.pipeline;
opens de.evoal.generator.main;
opens de.evoal.generator.main.benchmarks;
opens de.evoal.generator.main.cdi;
opens de.evoal.generator.main.functions;
opens de.evoal.generator.main.generators;
exports de.evoal.generator.api;
opens de.evoal.generator.api to weld.core.impl;
opens de.evoal.generator.main.functions.distributions;
exports de.evoal.pipeline.api.board;
exports de.evoal.pipeline.api.cdi;
exports de.evoal.pipeline.api.distribution;
exports de.evoal.pipeline.api.executor;
exports de.evoal.pipeline.api.model;
exports de.evoal.pipeline.api.model.dynamic;
opens de.evoal.pipeline;
opens de.evoal.pipeline.api.board to weld.core.impl; opens de.evoal.pipeline.api.board to weld.core.impl;
opens de.evoal.pipeline.api.cdi to weld.core.impl; opens de.evoal.pipeline.api.cdi to weld.core.impl;
opens de.evoal.pipeline.api.distribution to weld.core.impl; opens de.evoal.pipeline.api.distribution to weld.core.impl;
opens de.evoal.pipeline.impl to weld.core.impl; opens de.evoal.pipeline.impl to weld.core.impl;
opens de.evoal.pipeline.impl.components.benchmarks to weld.core.impl; opens de.evoal.pipeline.impl.components.benchmarks to weld.core.impl;
opens de.evoal.pipeline.impl.components.io to weld.core.impl; opens de.evoal.pipeline.impl.components.io to weld.core.impl;
opens de.evoal.pipeline.impl.components.misc to weld.core.impl; opens de.evoal.pipeline.impl.components.misc to weld.core.impl;
opens de.evoal.pipeline.impl.components.distributions to weld.core.impl; opens de.evoal.pipeline.impl.components.distributions to weld.core.impl;
opens de.evoal.pipeline.impl.internal to weld.core.impl; opens de.evoal.pipeline.impl.internal to weld.core.impl;
opens de.evoal.pipeline.api.model.dynamic to weld.core.impl;
opens de.evoal.pipeline.components to weld.core.impl; opens de.evoal.pipeline.components to weld.core.impl;
} }
import "definitions" from de.evoal.core.math;
module de.evoal.generator.generator {
abstract type benchmark{}
/**
* In mathematical optimisation, the Ackley function is a non-convex function
* used as a performance test problem for optimisation algorithms. It was proposed
* by David Ackley in his 1987 PhD dissertation. ... <a href="https://en.wikipedia.org/wiki/Ackley_function">Wikipedia</a>.
*
* <math display="block">
* <mrow>
* <mi>f</mi>
* <mo form="prefix" stretchy="false">(</mo>
* <mi>w</mi>
* <mi>r</mi>
* <mi>i</mi>
* <mi>t</mi>
* <msub>
* <mi>e</mi>
* <mn>0</mn>
* </msub>
* <mo form="postfix" stretchy="false">)</mo>
* <mo>=</mo>
* <mo>−</mo>
* <mi>a</mi>
* <mo>⋅</mo>
* <mi>e</mi>
* <mi>x</mi>
* <mi>p</mi>
* <mo form="prefix" stretchy="false">(</mo>
* <mo>−</mo>
* <mi>b</mi>
* <msqrt>
* <mrow>
* <mfrac>
* <mn>1</mn>
* <mi>n</mi>
* </mfrac>
* <mrow>
* <munderover>
* <mo movablelimits="false">∑</mo>
* <mrow>
* <mi>i</mi>
* <mo>=</mo>
* <mn>1</mn>
* </mrow>
* <mi>n</mi>
* </munderover>
* </mrow>
* <mi>r</mi>
* <mi>e</mi>
* <mi>a</mi>
* <msub>
* <mi>d</mi>
* <mi>i</mi>
* </msub>
* </mrow>
* </msqrt>
* <mo form="postfix" stretchy="false">)</mo>
* <mo>−</mo>
* <mi>e</mi>
* <mi>x</mi>
* <mi>p</mi>
* <mo form="prefix" stretchy="false">(</mo>
* <mfrac>
* <mn>1</mn>
* <mi>n</mi>
* </mfrac>
* <mrow>
* <munderover>
* <mo movablelimits="false">∑</mo>
* <mrow>
* <mi>i</mi>
* <mo>=</mo>
* <mn>1</mn>
* </mrow>
* <mi>n</mi>
* </munderover>
* </mrow>
* <mi>c</mi>
* <mi>o</mi>
* <mi>s</mi>
* <mo form="prefix" stretchy="false">(</mo>
* <mi>c</mi>
* <mo>⋅</mo>
* <mi>r</mi>
* <mi>e</mi>
* <mi>a</mi>
* <msub>
* <mi>d</mi>
* <mi>i</mi>
* </msub>
* <mo form="postfix" stretchy="false">)</mo>
* <mo form="postfix" stretchy="false">)</mo>
* <mo>+</mo>
* <mi>a</mi>
* <mo>+</mo>
* <mi>e</mi>
* <mi>x</mi>
* <mi>p</mi>
* <mo form="prefix" stretchy="false">(</mo>
* <mn>1</mn>
* <mo form="postfix" stretchy="false">)</mo>
* </mrow>
* </math>
*
* According to this specification, the function only generates a single output
* variable out of a n input variables.
*/
type ackley extends benchmark {
/**
* The constant a is set to 20 in the original Ackley function.
*/
'a' : real := 20.0;
/**
* The constant b is set to 0.2 in the original Ackley function.
*/
b : real := 0.2;
/**
* The constant c is set to 2π in the original Ackley function.
*/
'c' : real := 2 * PI;
}
/**
* In mathematical optimisation, the Rastrigin function is a non-convex function
* used as a performance test problem for optimisation algorithms. ... <a href="https://en.wikipedia.org/wiki/Rastrigin_function">Wikipedia</a>
*
* <math display="block">
* <mrow>
* <mi>w</mi>
* <mi>r</mi>
* <mi>i</mi>
* <mi>t</mi>
* <msub>
* <mi>e</mi>
* <mn>0</mn>
* </msub>
* <mo>=</mo>
* <mi>a</mi>
* <mo>⋅</mo>
* <mi>n</mi>
* <mo>+</mo>
* <mrow>
* <munderover>
* <mo movablelimits="false">∑</mo>
* <mrow>
* <mi>i</mi>
* <mo>=</mo>
* <mn>1</mn>
* </mrow>
* <mi>n</mi>
* </munderover>
* </mrow>
* <mo form="prefix" stretchy="false">(</mo>
* <mi>r</mi>
* <mi>e</mi>
* <mi>a</mi>
* <msubsup>
* <mi>d</mi>
* <mi>i</mi>
* <mn>2</mn>
* </msubsup>
* <mo>−</mo>
* <mi>A</mi>
* <mo>⋅</mo>
* <mi>c</mi>
* <mi>o</mi>
* <mi>s</mi>
* <mo form="prefix" stretchy="false">(</mo>
* <mn>2</mn>
* <mi>π</mi>
* <mo>⋅</mo>
* <mi>r</mi>
* <mi>e</mi>
* <mi>a</mi>
* <msub>
* <mi>d</mi>
* <mi>i</mi>
* </msub>
* <mo form="postfix" stretchy="false">)</mo>
* <mo form="postfix" stretchy="false">)</mo>
* </mrow>
* </math>
*
*/
type rastrigin extends benchmark {
/**
* Constant a, which is typically 10.
*/
'a' : real := 10.0;
}
/**
* TODO Document me
*/
type 'weighted-sphere' extends benchmark {
}
/**
* TODO Document me
*/
type 'rosenbrock' extends benchmark {
}
/**
* Adds constant values for the specified data.
*/
type constants {
/**
* The constant values to append.
*/
constants : array real;
}
type distribution {}
type 'multivariate-normal-distribution' extends distribution {
means : array real;
covariance : array array real;
}
/**
* Adds noise to data. For each data to noise, you can specify a
* separate distribution.
*/
type 'noise-data' {
/**
* The different distributions to use. Make sure it matches the size of
* the data the function writes.
*/
distributions : array instance distribution;
}
/**
* A distribution specification.
*/
type 'normal-distribution' extends distribution {
/**
* The distribution's expected value.
*/
'μ' : real;
/**
* The distribution's standard deviation.
*/
'σ' : real;
}
/**
* Specification for uniform distribution.
*/
type 'uniform-distribution' extends distribution {
/**
* parameter for lower bound
*/
'lower' :real;
/**
* parameter for upper bound
*/
'upper' : real;
}
type 'constraint-validation' {
}
}
\ No newline at end of file
import "definitions" from de.evoal.optimisation.core;
import "definitions" from de.evoal.generator.generator;
module de.evoal.generator.optimisation {
/**
* A combination of kown optimisation functions for benchmarking purposes.
*/
type 'benchmark-function' extends 'optimisation-function' {
/**
* The binding of benchmark functions to the generated data.
*/
benchmarks : array instance 'benchmark-configuration';
}
/**
* States the benchmark function to use and which data it generates.
*/
type 'benchmark-configuration' {
/**
* Benchmark function to use during evaluation.
*/
function : instance benchmark;
/**
* The data the benchmark will read.
*/
reads : array data;
/**
* The data the benchmark will generate.
*/
writes : array data;
}
}
\ No newline at end of file
#!/bin/bash
if [ -z ${EVOAL_HOME+x} ]; then
EVOAL_HOME=$( cd -- "$(dirname $0)/../" >/dev/null 2>&1 ; pwd -P )
fi
source $EVOAL_HOME/bin/paths.env
if [ "$#" -lt 2 ]; then
echo "Usage: $0 <execution-folder> <generator-file> [EvoAl parameters]"
exit 1
fi
cd "$1" || exit 1
POSITIONAL_ARGUMENTS=( "$@" )
POSITIONAL_ARGUMENTS=("${POSITIONAL_ARGUMENTS[@]:2}")
declare -a LOCAL_JVM_ARGUMENTS=()
if [ ${EVOAL_VM+x} ]; then
LOCAL_JVM_ARGUMENTS+=( "${EVOAL_VM[@]}" )
fi
if [ ${EVOAL_DEBUG+x} ]; then
LOCAL_JVM_ARGUMENTS+=( "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=1044" )
fi
if [ ${EVOAL_LOGGING+x} ]; then
POSITIONAL_ARGUMENTS+=( "-Bcore:logging=$EVOAL_LOGGING" )
fi
set -x
java ${LOCAL_JVM_ARGUMENTS[@]} \
${EVOAL_JVM_ARGUMENTS[@]} \
${POSITIONAL_ARGUMENTS[@]} \
-Bcore:main=data-generator \
"-Bgenerator:configuration-file=$2"
package de.evoal.optimisation.api.model;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A stopping criterion determines if an optimisation algorithm should stop optimising.
* This abstract candidate-based version decides the stopping criterion based on
* single candidate and not on the entire iteration.
*/
public abstract class CandidateBasedStoppingCriterion implements StoppingCriterion {
/**
* @return {@code true} iff the algorithm should stop.
*/
public boolean isSatisfied(final Iteration iteration) {
final int iterationNumber = iteration.iteration();
final Candidate bestCandidate = iteration.bestCandidate();
final Optional<Integer> numberOfCandidates = iteration.candidateCount();
final AtomicInteger counter = new AtomicInteger(0);
return iteration.candidates()
.anyMatch(c -> isSatisfied(iterationNumber, counter.getAndIncrement(), numberOfCandidates.get(), bestCandidate, c));
}
/**
* Checks a stopping criterion for a specific {@code candidate}.
*
* @param iteration The current iteration number.
* @param candidateNumber The candidate number.
* @param candidateCount Number of individuals in the iteration.
* @param iterationBest The best candidate in the iteration.
* @param candidate The candidate to check.
* @return {@code true} iff the algorithm should stop.
*/
public abstract boolean isSatisfied(final int iteration, final int candidateNumber, final int candidateCount, final Candidate iterationBest, final Candidate candidate);
}
...@@ -2,6 +2,7 @@ package de.evoal.optimisation.api.model; ...@@ -2,6 +2,7 @@ package de.evoal.optimisation.api.model;
import de.evoal.core.api.cdi.BeanFactory; import de.evoal.core.api.cdi.BeanFactory;
import de.evoal.core.api.utils.AttributeHelper; import de.evoal.core.api.utils.AttributeHelper;
import de.evoal.languages.model.base.Attribute;
import de.evoal.languages.model.base.Instance; import de.evoal.languages.model.base.Instance;
import javax.inject.Inject; import javax.inject.Inject;
...@@ -20,4 +21,8 @@ public abstract class OptimisationFunctionDecorator implements OptimisationFunct ...@@ -20,4 +21,8 @@ public abstract class OptimisationFunctionDecorator implements OptimisationFunct
return this; return this;
} }
protected final boolean hasDecoratedFunction(final Instance config) {
return config.findAttribute("function") != null;
}
} }
...@@ -18,7 +18,7 @@ public abstract class AbstractCandidateStatisticsWriter implements StatisticsWri ...@@ -18,7 +18,7 @@ public abstract class AbstractCandidateStatisticsWriter implements StatisticsWri
@Inject @Inject
protected WriterStrategy strategy; protected WriterStrategy strategy;
private Writer writer; protected Writer writer;
@Override @Override
public void add(final Iteration result) { public void add(final Iteration result) {
......
package de.evoal.optimisation.main.statistics.stopping;
import de.evoal.core.api.cdi.BeanFactory;
import de.evoal.core.api.languages.AttributeEvaluator;
import de.evoal.languages.model.base.Instance;
import de.evoal.optimisation.api.model.Iteration;
import de.evoal.optimisation.api.model.StoppingCriterion;
import de.evoal.optimisation.api.statistics.io.Writer;
import de.evoal.optimisation.api.statistics.io.WriterException;
import de.evoal.optimisation.api.statistics.io.WriterStrategy;
import de.evoal.optimisation.api.statistics.writer.Column;
import de.evoal.optimisation.api.statistics.writer.ColumnType;
import de.evoal.optimisation.api.statistics.writer.StatisticsWriter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Logs stopping criteria information for an entire iteration.
*/
@Slf4j
@Named("de.evoal.optimisation.core.stopping-per-candidates-per-generation")
@Dependent
public class StoppingCritertionPerGeneration implements StatisticsWriter {
@Inject
private AttributeEvaluator evaluator;
private int numberOfColumns;
private StoppingCriterion[] stoppingCriteria;
@Inject
protected WriterStrategy strategy;
protected Writer writer;
@Override
@SneakyThrows(WriterException.class)
public StatisticsWriter init(final Instance configuration) {
final Instance [] configs = evaluator.attributeToInstanceArray(configuration, "criteria");
stoppingCriteria = Arrays.stream(configs)
.map(i -> BeanFactory.createComponent(StoppingCriterion.class, i))
.map(StoppingCriterion.class::cast)
.toArray(StoppingCriterion[]::new);
final List<Column> columns = new LinkedList<>();
columns.add(new Column("generation", ColumnType.Integer));
for(int i = 0; i < stoppingCriteria.length; i++) {
columns.add(new Column("criterion-" + i, ColumnType.Integer));
}
this.numberOfColumns = columns.size();
this.writer = strategy.create("stopping-criteria", columns);
return this;
}
@Override
public void add(final Iteration result) {
final int iterationNumber = result.iteration();
final Object [] record = toData(iterationNumber, result);
appendToWriter(record);
writer.flush();
}
protected Object [] toData(final int iterationNumber, final Iteration result) {
final Object [] data = new Object[numberOfColumns];
data[0] = iterationNumber;
for(int i = 0; i < stoppingCriteria.length; i++) {
final StoppingCriterion criterion = stoppingCriteria[i];
final boolean satisfied = criterion.isSatisfied(result);
data[i + 1] = satisfied ? 1 : 0;
}
return data;
}
private void appendToWriter(final Object [] record) {
try {
writer.addRecord(record);
} catch (final WriterException e) {
log.warn("Failed to writer statistics record.");
}
}
@Override
public void write() {
try {
strategy.close(writer);
} catch (final WriterException e) {
log.error("Failed to write statistics:", e);
}
}
}
package de.evoal.optimisation.main.statistics.stopping;
import de.evoal.core.api.cdi.BeanFactory;
import de.evoal.core.api.languages.AttributeEvaluator;
import de.evoal.languages.model.base.Instance;
import de.evoal.optimisation.api.model.*;
import de.evoal.optimisation.api.statistics.io.Writer;
import de.evoal.optimisation.api.statistics.io.WriterException;
import de.evoal.optimisation.api.statistics.io.WriterStrategy;
import de.evoal.optimisation.api.statistics.writer.Column;
import de.evoal.optimisation.api.statistics.writer.ColumnType;
import de.evoal.optimisation.api.statistics.writer.StatisticsWriter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Logs stopping criteria information for every individual of an iteration.
*/
@Slf4j
@Named("de.evoal.optimisation.core.stopping-per-candidates-per-iteration")
@Dependent
public class StoppingCritertionPerIndividual implements StatisticsWriter {
@Inject
private AttributeEvaluator evaluator;
private int numberOfColumns;
private CandidateBasedStoppingCriterion[] stoppingCriteria;
@Inject
protected WriterStrategy strategy;
protected Writer writer;
@Override
@SneakyThrows(WriterException.class)
public StatisticsWriter init(final Instance configuration) {
final Instance [] configs = evaluator.attributeToInstanceArray(configuration, "criteria");
stoppingCriteria = Arrays.stream(configs)
.map(i -> BeanFactory.createComponent(StoppingCriterion.class, i))
.peek(s -> {if (!(s instanceof CandidateBasedStoppingCriterion)) log.warn("One of the configured stopping criteria is not an individual-based one."); })
.filter(CandidateBasedStoppingCriterion.class::isInstance)
.map(CandidateBasedStoppingCriterion.class::cast)
.toArray(CandidateBasedStoppingCriterion[]::new);
final List<Column> columns = new LinkedList<>();
columns.add(new Column("generation", ColumnType.Integer));
columns.add(new Column("index", ColumnType.Integer));
for(int i = 0; i < stoppingCriteria.length; i++) {
columns.add(new Column("criterion-" + i, ColumnType.Integer));
}
this.numberOfColumns = columns.size();
this.writer = strategy.create("candidate-stopping-criteria", columns);
return this;
}
@Override
public void add(final Iteration result) {
final int iterationNumber = result.iteration();
final Candidate bestCandidate = result.bestCandidate();
final Optional<Integer> numberOfCandidates = result.candidateCount();
final AtomicInteger counter = new AtomicInteger(0);
result.candidates()
.map(c -> toData(iterationNumber, counter.getAndIncrement(), numberOfCandidates.get(), bestCandidate, c))
.forEach(this::appendToWriter);
writer.flush();
}
protected Object [] toData(final int iterationNumber, final int candidateNumber, final int numberOfCandidates, final Candidate bestCandidate, final Candidate candidate) {
final Object [] data = new Object[numberOfColumns];
data[0] = iterationNumber;
data[1] = candidateNumber;
for(int i = 0; i < stoppingCriteria.length; i++) {
final CandidateBasedStoppingCriterion criterion = stoppingCriteria[i];
final boolean satisfied = criterion.isSatisfied(
iterationNumber,
candidateNumber,
numberOfCandidates,
bestCandidate,
candidate);
data[i + 2] = satisfied ? 1 : 0;
}
return data;
}
private void appendToWriter(final Object [] record) {
try {
writer.addRecord(record);
} catch (final WriterException e) {
log.warn("Failed to writer statistics record.");
}
}
@Override
public void write() {
try {
strategy.close(writer);
} catch (final WriterException e) {
log.error("Failed to write statistics:", e);
}
}
}
...@@ -85,4 +85,5 @@ module de.evoal.optimisation.api { ...@@ -85,4 +85,5 @@ module de.evoal.optimisation.api {
opens de.evoal.optimisation.main.statistics.io.csv to weld.core.impl; opens de.evoal.optimisation.main.statistics.io.csv to weld.core.impl;
opens de.evoal.optimisation.main.statistics.nop to weld.core.impl; opens de.evoal.optimisation.main.statistics.nop to weld.core.impl;
opens de.evoal.optimisation.main.stopping to weld.core.impl; opens de.evoal.optimisation.main.stopping to weld.core.impl;
opens de.evoal.optimisation.main.statistics.stopping to weld.core.impl;
} }
...@@ -338,4 +338,12 @@ module de.evoal.optimisation.core { ...@@ -338,4 +338,12 @@ module de.evoal.optimisation.core {
*/ */
'maximum-iterations' : int := 10; 'maximum-iterations' : int := 10;
} }
type 'stopping-per-candidates-per-generation' extends 'statistics-writer' {
criteria : array instance 'stopping-criterion' := [];
}
type 'stopping-per-candidates-per-iteration' extends 'statistics-writer' {
criteria : array instance 'stopping-criterion' := [];
}
} }
package de.evoal.optimisation.ea.main.alterer; package de.evoal.optimisation.ea.main.alterer;
import java.util.Arrays; import java.util.List;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import de.evoal.core.api.cdi.BeanFactory; import de.evoal.core.api.cdi.BeanFactory;
...@@ -9,11 +9,8 @@ import de.evoal.optimisation.ea.api.codec.CustomCodec; ...@@ -9,11 +9,8 @@ import de.evoal.optimisation.ea.api.codec.CustomCodec;
import de.evoal.optimisation.ea.api.operators.AltererComponent; import de.evoal.optimisation.ea.api.operators.AltererComponent;
import de.evoal.optimisation.ea.api.operators.AltererComponentProvider; import de.evoal.optimisation.ea.api.operators.AltererComponentProvider;
import de.evoal.optimisation.ea.main.alterer.internal.MeanCorrelationAlterer; import de.evoal.optimisation.ea.main.alterer.internal.MeanCorrelationAlterer;
import de.evoal.optimisation.ea.main.alterer.mutator.SingleBitFlipMutator; import de.evoal.optimisation.ea.main.alterer.mutator.*;
import de.evoal.optimisation.ea.main.alterer.crossover.*; import de.evoal.optimisation.ea.main.alterer.crossover.*;
import de.evoal.optimisation.ea.main.alterer.mutator.SingleBitFlipCorrelationMutator;
import de.evoal.optimisation.ea.main.alterer.mutator.SingleChoiceMutator;
import de.evoal.optimisation.ea.main.alterer.mutator.SwapCorrelationMutator;
import de.evoal.optimisation.api.correlations.Correlations; import de.evoal.optimisation.api.correlations.Correlations;
import de.evoal.optimisation.ea.main.codec.program.rewriters.*; import de.evoal.optimisation.ea.main.codec.program.rewriters.*;
import de.evoal.languages.model.base.Instance; import de.evoal.languages.model.base.Instance;
...@@ -87,22 +84,32 @@ public class AltererFactory { ...@@ -87,22 +84,32 @@ public class AltererFactory {
case "single-node-crossover": return (Alterer<G, OptimisationValue>) createSingleNodeCrossover(config); case "single-node-crossover": return (Alterer<G, OptimisationValue>) createSingleNodeCrossover(config);
case "single-choice-mutator": return createSingleChoiceMutator(config); case "single-choice-mutator": return createSingleChoiceMutator(config);
case "single-choice-in-sequence-mutator": return createSingleChoiceInSequenceMutator(config);
} }
return BeanFactory.createComponent(AltererComponent.class, AltererComponentProvider.class, config); return BeanFactory.createComponent(AltererComponent.class, AltererComponentProvider.class, config);
} }
private <G extends Gene<?, G>> Alterer<G, OptimisationValue> createSingleChoiceMutator(final Instance config) { private <G extends Gene<?, G>> Alterer<G, OptimisationValue> createSingleChoiceMutator(final Instance config) {
final Object[] alterers = helper.lookup(config, "alterers"); final List<Instance> alterers = helper.lookup(config, "alterers");
final ISeq<Alterer> components = final ISeq<Alterer> components =
Arrays.stream(alterers) alterers.stream()
.map(Instance.class::cast)
.map(a -> create(a)) .map(a -> create(a))
.collect(ISeq.toISeq()); .collect(ISeq.toISeq());
return new SingleChoiceMutator(components); return new SingleChoiceMutator(components);
} }
private <G extends Gene<?, G>> Alterer<G, OptimisationValue> createSingleChoiceInSequenceMutator(final Instance config) {
final List<Instance> alterers = helper.lookup(config, "alterers");
final ISeq<Alterer> components =
alterers.stream()
.map(a -> create(a))
.collect(ISeq.toISeq());
return new SingleChoiceInSequenceMutator(components);
}
private <G extends TreeGene<?, G>> Alterer<G, OptimisationValue> createSingleNodeCrossover(Instance config) { private <G extends TreeGene<?, G>> Alterer<G, OptimisationValue> createSingleNodeCrossover(Instance config) {
final Double probability = helper.lookup(config, "probability"); final Double probability = helper.lookup(config, "probability");
......
/*
* Java Genetic Algorithm Library (jenetics-7.1.0).
* Copyright (c) 2007-2022 Franz Wilhelmstötter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author:
* Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
*/
package de.evoal.optimisation.ea.main.alterer.mutator;
import de.evoal.optimisation.ea.api.operators.AltererComponent;
import io.jenetics.Alterer;
import io.jenetics.AltererResult;
import io.jenetics.Gene;
import io.jenetics.Phenotype;
import io.jenetics.util.ISeq;
import io.jenetics.util.RandomRegistry;
import io.jenetics.util.Seq;
import lombok.extern.slf4j.Slf4j;
import java.util.random.RandomGenerator;
import java.util.stream.Collectors;
import static java.lang.String.format;
/**
* Combines several alterers to one.
*
* @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
* @since 1.0
* @version 5.0
*/
@Slf4j
public final class SingleChoiceInSequenceMutator<
G extends Gene<?, G>,
C extends Comparable<? super C>
>
implements AltererComponent
{
private final ISeq<Alterer<G, C>> _alterers;
private final RandomGenerator random = RandomRegistry.random();
/**
* Combine the given alterers.
*
* @param alterers the alterers to combine.
* @throws NullPointerException if one of the alterers is {@code null}.
*/
public SingleChoiceInSequenceMutator(final Seq<Alterer<G, C>> alterers) {
_alterers = ISeq.of(alterers);
}
@Override
public AltererResult alter(
final Seq population,
final long generation
) {
final ISeq<Phenotype> results =
(ISeq<Phenotype>) population.stream()
.map(Phenotype.class::cast)
.map(p -> {
final Phenotype ph = (Phenotype) p;
for(final Alterer alterer : _alterers) {
log.debug("Calling alterer {}", alterer.getClass().getSimpleName());
final AltererResult result = alterer.alter(ISeq.of((Phenotype)p), generation);
if(result.alterations() > 0) {
return result;
}
}
return new AltererResult<>(ISeq.of(ph),0);
})
.map(r -> ((AltererResult)r).population().get(0))
.map(Phenotype.class::cast)
.collect(ISeq.toISeq());
return new AltererResult(
results, (int)generation
);
}
@Override
public String toString() {
return format(
"%s:\n%s", getClass().getSimpleName(),
_alterers.stream()
.map(a -> " - " + a)
.collect(Collectors.joining("\n"))
);
}
}
...@@ -54,17 +54,17 @@ public class ModelGenotypeCodec implements CustomCodec<ModelGene> { ...@@ -54,17 +54,17 @@ public class ModelGenotypeCodec implements CustomCodec<ModelGene> {
@Override @Override
public ModelGenotypeCodec init(final Instance config) { public ModelGenotypeCodec init(final Instance config) {
log.info("Initialising model genotype codec"); log.info("Initialising model genotype codec");
final Object[] chromosomeConfigurations = helper.lookup(config, "chromosomes"); final List<Instance> chromosomeConfigurations = helper.lookup(config, "chromosomes");
final FQNProvider provider = new FQNProvider(); final FQNProvider provider = new FQNProvider();
Requirements.requireFalse(Arrays.stream(chromosomeConfigurations) Requirements.requireFalse(chromosomeConfigurations
.map(Instance.class::cast) .stream()
.anyMatch(i -> !CHROMOSOME_NAME.equals(provider.get(i))), .anyMatch(i -> !CHROMOSOME_NAME.equals(provider.get(i))),
"Non model-chromosome are not allowed."); "Non model-chromosome are not allowed.");
genotypeSpec = Arrays.stream(chromosomeConfigurations) genotypeSpec = chromosomeConfigurations
.map(Instance.class::cast) .stream()
.filter(i -> CHROMOSOME_NAME.equals(provider.get(i))) .filter(i -> CHROMOSOME_NAME.equals(provider.get(i)))
.map(i -> helper.<DataDescription>lookup(i, "root")) .map(i -> helper.<DataDescription>lookup(i, "root"))
.collect(Collectors.toList()); .collect(Collectors.toList());
...@@ -87,11 +87,11 @@ public class ModelGenotypeCodec implements CustomCodec<ModelGene> { ...@@ -87,11 +87,11 @@ public class ModelGenotypeCodec implements CustomCodec<ModelGene> {
.addDescriptions(genotypeSpec.stream()) .addDescriptions(genotypeSpec.stream())
.build(); .build();
Requirements.requireTrue(mapping.size() == chromosomeConfigurations.length, "Required to be of same size."); Requirements.requireTrue(mapping.size() == chromosomeConfigurations.size(), "Required to be of same size.");
information = IntStream.range(0, mapping.size()) information = IntStream.range(0, mapping.size())
.mapToObj(i -> { .mapToObj(i -> {
final Instance configuration = (Instance) chromosomeConfigurations[i]; final Instance configuration = (Instance) chromosomeConfigurations.get(i);
return toChromosome(configuration, i); return toChromosome(configuration, i);
}) })
...@@ -149,11 +149,12 @@ public class ModelGenotypeCodec implements CustomCodec<ModelGene> { ...@@ -149,11 +149,12 @@ public class ModelGenotypeCodec implements CustomCodec<ModelGene> {
while(!working.isEmpty()) { while(!working.isEmpty()) {
final TypeDefinition currentType = working.iterator().next(); final TypeDefinition currentType = working.iterator().next();
working.remove(currentType);
if(visited.contains(currentType)) { if(visited.contains(currentType)) {
continue; continue;
} }
working.remove(currentType);
visited.add(currentType); visited.add(currentType);
for(final AttributeDefinition attr : currentType.getAttributes()) { for(final AttributeDefinition attr : currentType.getAttributes()) {
...@@ -182,11 +183,12 @@ public class ModelGenotypeCodec implements CustomCodec<ModelGene> { ...@@ -182,11 +183,12 @@ public class ModelGenotypeCodec implements CustomCodec<ModelGene> {
while(!working.isEmpty()) { while(!working.isEmpty()) {
final TypeDefinition currentType = working.iterator().next(); final TypeDefinition currentType = working.iterator().next();
working.remove(currentType);
if(visited.contains(currentType)) { if(visited.contains(currentType)) {
continue; continue;
} }
working.remove(currentType);
visited.add(currentType); visited.add(currentType);
for(final AttributeDefinition attr : currentType.getAttributes()) { for(final AttributeDefinition attr : currentType.getAttributes()) {
......
...@@ -2,6 +2,7 @@ package de.evoal.optimisation.ea.main.codec.model; ...@@ -2,6 +2,7 @@ package de.evoal.optimisation.ea.main.codec.model;
import de.evoal.core.api.utils.AttributeHelper; import de.evoal.core.api.utils.AttributeHelper;
import de.evoal.core.api.utils.InitializationException; import de.evoal.core.api.utils.InitializationException;
import de.evoal.languages.model.ddl.StructuredDataDescription;
import de.evoal.optimisation.ea.api.codec.CustomCodecDescriber; import de.evoal.optimisation.ea.api.codec.CustomCodecDescriber;
import de.evoal.languages.model.base.Definition; import de.evoal.languages.model.base.Definition;
import de.evoal.languages.model.base.Instance; import de.evoal.languages.model.base.Instance;
...@@ -35,12 +36,12 @@ public class ModelGenotypeDescriber implements CustomCodecDescriber { ...@@ -35,12 +36,12 @@ public class ModelGenotypeDescriber implements CustomCodecDescriber {
@Override @Override
public List<Definition> describe() { public List<Definition> describe() {
log.info("Describing Genotype."); log.info("Describing Genotype.");
final Object [] genes = helper.lookup(configuration, "chromosomes"); final List<Instance> genes = helper.lookup(configuration, "chromosomes");
return Arrays.stream(genes) return genes
.map(Instance.class::cast) .stream()
.map(i -> helper.lookup(i, "root")) .map(i -> helper.<StructuredDataDescription>lookup(i, "root"))
.map(Definition.class::cast) .map(StructuredDataDescription::getType)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
} }
...@@ -52,6 +52,6 @@ module de.evoal.optimisation.ea.mdo { ...@@ -52,6 +52,6 @@ module de.evoal.optimisation.ea.mdo {
/** /**
* The root class name * The root class name
*/ */
root : instance model; root : data;
} }
} }
\ No newline at end of file
package de.evoal.surrogate.main.generator;
import de.evoal.core.api.properties.Properties;
import de.evoal.generator.api.AbstractGeneratorFunction;
import de.evoal.surrogate.api.function.SurrogateFunction;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.inject.Named;
@Dependent
@Named("de.evoal.surrogate.generator.surrogate")
public class SurrogateGeneratorFunction extends AbstractGeneratorFunction {
@Inject
private SurrogateFunction function;
@Override
public Properties apply(final Properties in) {
final Properties out = mergeAndCopy(in);
final Properties result = function.apply(in);
out.putAll(result);
return out;
}
}
package de.evoal.surrogate.main.pipeline;
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.InitializationException;
import de.evoal.languages.model.base.Instance;
import de.evoal.languages.model.ddl.DataDescription;
import de.evoal.pipeline.api.model.ComponentImpl;
import de.evoal.pipeline.api.model.TypedEObject;
import de.evoal.pipeline.api.model.dynamic.EAnnotationHelper;
import de.evoal.surrogate.api.function.SurrogateFunction;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EStructuralFeature;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
@Dependent
@Named("de.evoal.surrogate.pipeline.surrogate")
@Slf4j
public class SurrogateGenerator extends ComponentImpl {
@Inject
private EAnnotationHelper helper;
@Inject
private SurrogateFunction function;
private PropertiesSpecification inputSpecification;
private PropertiesSpecification outputSpecification;
private Map<PropertySpecification, EStructuralFeature> propertyToFeature = new HashMap<>();
private Map<EStructuralFeature, PropertySpecification> featureToProperty = new HashMap<>();
@Override
public ComponentImpl init(final Instance configuration) throws InitializationException {
this.inputSpecification = function.getInputSpecification();
this.outputSpecification = function.getOutputSpecification();
addToMappings(getReads());
addToMappings(getWrites());
return super.init(configuration);
}
private void addToMappings(final LinkedHashSet<EStructuralFeature> features) {
for(final EStructuralFeature feature : features) {
final PropertySpecification specification = toSpecification(feature);
propertyToFeature.put(specification, feature);
featureToProperty.put(feature, specification);
}
}
private PropertySpecification toSpecification(final EStructuralFeature feature) {
log.info("Converting {} to property specification.", feature.getName());
log.info(" Annotations are {}", feature.getEAnnotations());
EAnnotation ann = feature.getEAnnotations().get(0);
log.info(" source is {}", ann.getSource());
log.info(" contents is {}", ann.getContents());
final DataDescription description = helper.dataDescriptionOf(feature).get();
return new PropertySpecification(description.getName(), description);
}
@Override
public @NonNull TypedEObject apply(final @NonNull TypedEObject object) {
final Properties in = new Properties(inputSpecification);
copyInProperties(object, in);
final Properties out = function.apply(in);
copyOutProperties(out, object);
return object;
}
private void copyOutProperties(final Properties source, final TypedEObject target) {
for(final EStructuralFeature feature : getWrites()) {
final PropertySpecification property = featureToProperty.get(feature);
final Object data = source.get(property);
target.eSet(feature, data);
}
}
private void copyInProperties(final TypedEObject source, final Properties target) {
for(final EStructuralFeature feature : getReads()) {
final PropertySpecification property = featureToProperty.get(feature);
final Object data = source.eGet(feature);
target.put(property, data);
}
}
}
...@@ -47,12 +47,12 @@ module de.evoal.surrogate.api { ...@@ -47,12 +47,12 @@ module de.evoal.surrogate.api {
opens de.evoal.surrogate.main to weld.core.impl; opens de.evoal.surrogate.main to weld.core.impl;
opens de.evoal.surrogate.main.cdi to weld.core.impl; opens de.evoal.surrogate.main.cdi to weld.core.impl;
opens de.evoal.surrogate.main.ea to weld.core.impl; opens de.evoal.surrogate.main.ea to weld.core.impl;
opens de.evoal.surrogate.main.generator to weld.core.impl;
opens de.evoal.surrogate.main.internal to weld.core.impl; opens de.evoal.surrogate.main.internal to weld.core.impl;
opens de.evoal.surrogate.main.jackson to weld.core.impl, com.fasterxml.jackson.databind; opens de.evoal.surrogate.main.jackson to weld.core.impl, com.fasterxml.jackson.databind;
opens de.evoal.surrogate.main.gof.cross to weld.core.impl; opens de.evoal.surrogate.main.gof.cross to weld.core.impl;
opens de.evoal.surrogate.main.gof.rmse to weld.core.impl; opens de.evoal.surrogate.main.gof.rmse to weld.core.impl;
opens de.evoal.surrogate.main.gof.rsquare to weld.core.impl; opens de.evoal.surrogate.main.gof.rsquare to weld.core.impl;
opens de.evoal.surrogate.main.pipeline to weld.core.impl;
opens de.evoal.surrogate.main.statistics.constraint to weld.core.impl; opens de.evoal.surrogate.main.statistics.constraint to weld.core.impl;
opens de.evoal.surrogate.main.statistics.correlated to weld.core.impl; opens de.evoal.surrogate.main.statistics.correlated to weld.core.impl;
opens de.evoal.surrogate.main.statistics.ranged to weld.core.impl; opens de.evoal.surrogate.main.statistics.ranged to weld.core.impl;
......
import "definitions" from de.evoal.generator.generator; import "definitions" from de.evoal.pipeline.base;
/** /**
* Generator extensions based on surrogate models. * Generator extensions based on surrogate models.
*/ */
module de.evoal.surrogate.generator { module de.evoal.surrogate.pipeline {
/** /**
* Uses a pre-trained surrogate model as function. * Uses a pre-trained surrogate model as function.
*/ */
type surrogate extends 'benchmark' { type surrogate extends 'Processor' {
} }
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment