Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • evoal/source/evoal-core
1 result
Show changes
Showing
with 539 additions and 413 deletions
...@@ -33,28 +33,23 @@ module de.evoal.generator.main { ...@@ -33,28 +33,23 @@ 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;
} }
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