diff --git a/src/core/de.evoal.core/pom.xml b/src/core/de.evoal.core/pom.xml index ad8f1328302b346833a30159ff2da3c4fef31501..2fec84e86d3f4a1283c80c6140f6b69b08e5b544 100644 --- a/src/core/de.evoal.core/pom.xml +++ b/src/core/de.evoal.core/pom.xml @@ -322,6 +322,8 @@ <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> + <arg>--add-exports</arg> + <arg>org.eclipse.xtext.util/org.eclipse.xtext.util=de.evoal.core</arg> </compilerArgs> <forceJavacCompilerUse>true</forceJavacCompilerUse> </configuration> diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/calculation/CalculationFactory.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/calculation/CalculationFactory.java index a4e07cef46ba910470819f63d70416f094c9b1dc..6a864175095c0ed84214089ef0ae1b2cde4ca3d1 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/calculation/CalculationFactory.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/calculation/CalculationFactory.java @@ -6,28 +6,39 @@ import de.evoal.core.api.cdi.ConfigurationValue; import javax.enterprise.context.ApplicationScoped; import de.evoal.core.api.utils.LanguageHelper; +import de.evoal.languages.model.instance.Array; import de.evoal.languages.model.instance.Instance; +import de.evoal.languages.model.instance.LiteralValue; import org.apache.deltaspike.core.api.provider.BeanProvider; import javax.inject.Inject; +import java.util.HashMap; +import java.util.Map; @ApplicationScoped public class CalculationFactory { - private final Instance handlerConfigurations; + private final Map<String, Instance> calculationConfigurationByCategory = new HashMap<>(); @Inject - public CalculationFactory(final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.constraint_handling") Instance handlerConfiguration) { - handlerConfigurations = handlerConfiguration; + public CalculationFactory(final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.handlers") Array handlerConfigurations) { + handlerConfigurations.getValues() + .stream() + .map(Instance.class::cast) + .filter(LanguageHelper.filterInstanceByType("constraint-handler")) + .forEach(i -> { + final String category = LanguageHelper.lookup(i, "category"); + final Instance config = LanguageHelper.lookup(i, "calculation"); + + calculationConfigurationByCategory.put(category, config); + }); } public CalculationStrategy create(final Constraint constraint) { - final Instance handlerConfig = LanguageHelper.lookup(handlerConfigurations, constraint.getGroup()); - final Instance calculationConfig = LanguageHelper.lookup(handlerConfigurations, "calculation"); - - final String calculationName = LanguageHelper.lookup(calculationConfig, "name"); + final Instance config = calculationConfigurationByCategory.get(constraint.getGroup()); + final String calculationName = LanguageHelper.lookup(config, "name"); final CalculationStrategy strategy = BeanProvider.getContextualReference(calculationName, false, CalculationStrategy.class); - strategy.init(constraint, calculationConfig); + strategy.init(constraint, config); return strategy; } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/calculation/CalculationStrategy.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/calculation/CalculationStrategy.java index c8f77254cb02ee9dd4a14cee58bbbd4ba6dd6daa..24a389e4df5ec84f6800aecc0263dfefefc68d19 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/calculation/CalculationStrategy.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/calculation/CalculationStrategy.java @@ -17,7 +17,7 @@ public interface CalculationStrategy { * @param properties Properties of an individual to check. * @return A non-null non-empty list of constraint handling results. */ - public @NonNull CalculationResult calculate(final Properties properties); + public @NonNull CalculationResult calculate(final Properties genotype, final Properties fitness); /** * Initialises the strategy with the constraint and the calculation configuration. diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/model/Constraint.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/model/Constraint.java index d30c0aaba5ad7e301de3d374e13c2c075d00e18e..c55abd06ba5ede6833bcf6623809477ff4c6d37e 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/model/Constraint.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/model/Constraint.java @@ -5,7 +5,7 @@ import de.evoal.core.api.properties.PropertySpecification; import lombok.Data; import java.util.List; -import java.util.function.Function; +import java.util.function.BiFunction; /** * A single evaluable constraint. A constraint ca be applied to an individual @@ -26,7 +26,7 @@ public class Constraint { /** * The applicable constraint function. */ - private Function<Properties, Object> function; + private BiFunction<Properties, Properties, Object> function; /** * List of used properties. @@ -39,11 +39,11 @@ public class Constraint { * @param properties The individual to check. * @return The result of the constraint's evaluation. */ - public ConstraintResult apply(final Properties properties) { + public ConstraintResult apply(final Properties genotypeProps, final Properties fitnessProps) { final ConstraintResult result = new ConstraintResult(); result.setConstraint(this); - result.setComparisonDifference(((Number)function.apply(properties)).doubleValue()); + result.setComparisonDifference(((Number)function.apply(genotypeProps, fitnessProps)).doubleValue()); result.getUsedProperties().addAll(usedProperties); result.setType(getConstraintType()); diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/model/Constraints.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/model/Constraints.java index 9f33b621be70f558e9bd539b1c43afcd9d472974..b34928c867e0e42f3b26c63de17738d416c3046a 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/model/Constraints.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/api/ea/constraints/model/Constraints.java @@ -25,9 +25,9 @@ public class Constraints { * @param properties Properties to use * @return A non-null list of constraint results. */ - public List<ConstraintResult> apply(final Properties properties) { + public List<ConstraintResult> apply(final Properties genotype, final Properties fitness) { return constraints.stream() - .map(c -> c.apply(properties)) + .map(c -> c.apply(genotype, fitness)) .collect(Collectors.toList()); } } 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 3bff0b7c93093be89bb1018318d89dc64d7ea337..cbb3117e80f2c8a3d6c45923a0e0bb4cf506352d 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 @@ -5,6 +5,8 @@ import de.evoal.languages.model.instance.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.function.Predicate; + /** * Helper class for processing eal files. */ @@ -77,4 +79,7 @@ public final class LanguageHelper { return (T) current; } + public static Predicate<? super Value> filterInstanceByType(final String instanceTypeName) { + return i -> instanceTypeName.equals(((Instance)i).getName().getName()); + } } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ConstraintProducer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ConstraintProducer.java index 20c48b94e6cdef9bb4bb386b75c75e590007ec22..768940a25c021a344c03f40a4a44d39d43976f34 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ConstraintProducer.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ConstraintProducer.java @@ -1,5 +1,7 @@ package de.evoal.core.main.ea.constraints.constraint; +import de.evoal.core.api.board.BlackboardEntry; +import de.evoal.core.api.cdi.ConfigurationValue; import de.evoal.core.api.ea.constraints.model.Constraint; import de.evoal.core.api.ea.constraints.model.Constraints; import de.evoal.core.api.ea.codec.CustomCodec; @@ -7,12 +9,18 @@ import de.evoal.core.api.ea.constraints.model.DataConstraints; import de.evoal.core.api.properties.PropertiesSpecification; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Produces; +import javax.inject.Named; import de.evoal.core.main.ea.constraints.el.ElHelper; +import de.evoal.core.main.ea.fitness.JeneticsFitnessFunction; import de.evoal.languages.model.ddl.DataDescription; import de.evoal.languages.model.ddl.FunctionName; import de.evoal.languages.model.el.Call; import de.evoal.core.main.ea.constraints.constraint.ast.ConditionConverter; +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 lombok.extern.slf4j.Slf4j; import java.util.Objects; @@ -21,13 +29,16 @@ import java.util.Optional; @ApplicationScoped @Slf4j public class ConstraintProducer { - private PropertiesSpecification specification; + private PropertiesSpecification fitnessSpec; + private PropertiesSpecification genoSpec; @Produces @ApplicationScoped public Constraints create(final DataConstraints constraints, - final CustomCodec codec) { - this.specification = specification; + @Named("genotype-specification") final PropertiesSpecification genoSpec, + @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.fitness") final Instance fitnessConfig) { + this.genoSpec = genoSpec; + this.fitnessSpec = toInnerSpecification(fitnessConfig); final Constraints result = new Constraints(); @@ -51,6 +62,25 @@ public class ConstraintProducer { return result; } + private PropertiesSpecification toInnerSpecification(final Instance fitnessConfig) { + final Attribute subFunction = fitnessConfig.findAttribute("function"); + + if(subFunction != null) { + return toInnerSpecification((Instance)subFunction.getValue()); + } + + final Attribute mapping = fitnessConfig.findAttribute("maps-to"); + + return PropertiesSpecification.builder() + .add(((Array)mapping.getValue()) + .getValues() + .stream() + .map(DataReference.class::cast) + .map(DataReference::getDefinition) + ) + .build(); + } + private Optional<Constraint> convert(final Call constraint, DataDescription context) { if(constraint.getParameters().size() != 2) { log.error("Constraint has more than two parameters. Skipping."); @@ -60,7 +90,7 @@ public class ConstraintProducer { final Constraint result = new Constraint(); result.setGroup(ElHelper.findString(constraint.getParameters().get(1))); - final ConditionConverter converter = new ConditionConverter(specification, context); + final ConditionConverter converter = new ConditionConverter(genoSpec, fitnessSpec, context); converter.doSwitch(constraint.getParameters().get(0)); result.setFunction(converter.getFunction()); diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/BoundaryIdentifier.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/BoundaryIdentifier.java index b24b5714342793a4531a2a894f1632a206945244..a33f957e680d0b4b52de48c2f79e8b7653f0967e 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/BoundaryIdentifier.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/BoundaryIdentifier.java @@ -15,13 +15,7 @@ import lombok.extern.slf4j.Slf4j; import java.util.*; @Slf4j -public class BoundaryIdentifier extends ELSwitch<Object> { - - private final DataDescription context; - - public BoundaryIdentifier(final DataDescription context) { - this.context = context; - } +public class BoundaryIdentifier { public static PropertiesBoundaries run(final DataConstraints constraints) { final Map<DataDescription, Number> lowerBounds = new HashMap<>(); @@ -41,7 +35,7 @@ public class BoundaryIdentifier extends ELSwitch<Object> { } private static void processConstraint(final Expression constraint, final DataDescription context, final Map<DataDescription, Number> lowerBounds, final Map<DataDescription, Number> upperBounds) { - final BoundaryIdentifier identifier = new BoundaryIdentifier(context); + final UnaryBoundaryIdentifier identifier = new UnaryBoundaryIdentifier(context); Object result = identifier.doSwitch(constraint); if(result == null) { @@ -89,170 +83,4 @@ public class BoundaryIdentifier extends ELSwitch<Object> { } } } - - - @Override - - public Object caseOrExpression(OrExpression object) { - Requirements.requireSize(object.getSubExpressions(), 1); - - return doSwitch(object.getSubExpressions().get(0)); - } - - @Override - public Object caseXorExpression(XorExpression object) { - Requirements.requireSize(object.getSubExpressions(), 1); - - return doSwitch(object.getSubExpressions().get(0)); - } - - @Override - public Object caseAndExpression(final AndExpression object) { - Requirements.requireSize(object.getSubExpressions(), 1); - - return doSwitch(object.getSubExpressions().get(0)); - } - - @Override - public Object caseNotExpression(NotExpression object) { - Requirements.requireFalse(object.isNegated()); - - return doSwitch(object.getOperand()); - } - - @Override - public Object caseComparisonExpression(final ComparisonExpression object) { - Requirements.requireSize(object.getComparison(), 1); - - final Object leftValue = doSwitch(object.getLeftOperand()); - final Object rightValue = doSwitch(object.getComparison().get(0).getSubExpression()); - - if(!((leftValue instanceof DataDescription && rightValue instanceof Number) || - (rightValue instanceof DataDescription && leftValue instanceof Number))) { - // not a supported relation - return null; - } - - switch (object.getComparison().get(0).getOperator()) { - case GREATER_EQUAL: - case GREATER_THAN: { - if(leftValue instanceof DataDescription) { - // lower - return new Object[] {rightValue, leftValue}; - } else { - // upper - return new Object[] {leftValue, rightValue}; - } - } - case LESS_EQUAL: - case LESS_THAN: - { - if(leftValue instanceof DataDescription) { - // upper - return new Object[] {leftValue, rightValue}; - } else { - // lower - return new Object[] {rightValue, leftValue}; - } - } - case EQUAL: - case UNEQUAL: { - throw new IllegalArgumentException("(Un)equal is not allowed"); - } - } - - return null; - } - - - @Override - public Object caseAddOrSubtractExpression(final AddOrSubtractExpression object) { - Requirements.requireEmpty(object.getOperators()); - return doSwitch(object.getLeftOperand()); - } - - @Override - public Object caseMultiplyDivideModuloExpression(final MultiplyDivideModuloExpression object) { - Requirements.requireEmpty(object.getOperators()); - return doSwitch(object.getLeftOperand()); - } - - @Override - public Object casePowerOfExpression(final PowerOfExpression object) { - Requirements.requireNull(object.getRightOperand()); - - return doSwitch(object.getLeftOperand()); - } - - @Override - public Object caseUnaryAddOrSubtractExpression(UnaryAddOrSubtractExpression object) { - Object value = doSwitch(object.getSubExpression()); - - for(final AddOrSubtractOperator operator : object.getOperators()) { - switch (operator) { - case ADD: { - value = value; - break; - } - - case SUBTRACT: { - if(value instanceof Double) { - value = -(Double)value; - } else if(value instanceof Integer) { - value = -(Integer)value; - } else { - throw new IllegalStateException("Unsupported"); - } - break; - } - } - } - - return value; - } - - @Override - public Object caseIntegerLiteral(final IntegerLiteral object) { - return object.getValue(); - } - - @Override - public Object caseDoubleLiteral(final DoubleLiteral object) { - return object.getValue(); - } - - @Override - public Object caseStringLiteral(final StringLiteral object) { - return null; - } - - @Override - public Object caseValueReference(final ValueReference object) { - if(object instanceof SelfReference) { - Requirements.requireNotNull(context); - return context; - } - - if(!(object instanceof DataReference)) { - throw new IllegalStateException("Value reference is not a data reference: " + object.eClass()); - } - - final DataReference reference = (DataReference)object; - return reference.getDefinition(); - } - - @Override - public Object caseBooleanLiteral(final BooleanLiteral object) { - return null; - } - - @Override - public Object caseCall(Call object) { - return null; - } - - @Override - public Object caseParantheses(final Parantheses object) { - return doSwitch(object.getSubExpression()); - } } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/ConditionConverter.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/ConditionConverter.java index de012a6a648e92e05527be9d1da4ff5d3ff0a731..d424bb6f9598b6ed985faef89efbc20dbb11ef91 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/ConditionConverter.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/ConditionConverter.java @@ -16,17 +16,19 @@ import de.evoal.languages.model.el.util.ELSwitch; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.function.Function; +import java.util.function.BiFunction; public class ConditionConverter extends ELSwitch<Object> { - private Function<Properties, Object> function; + private BiFunction<Properties, Properties, Object> function; private final List<PropertySpecification> usedProperties = new ArrayList<>(); - private final PropertiesSpecification specification; + private final PropertiesSpecification genoSpec; + private final PropertiesSpecification fitnessSpec; private final DataDescription context; private ConstraintType type; - public ConditionConverter(final PropertiesSpecification specification, final DataDescription context) { - this.specification = specification; + public ConditionConverter(final PropertiesSpecification genoSpec, final PropertiesSpecification fitnessSpec, final DataDescription context) { + this.genoSpec = genoSpec; + this.fitnessSpec = fitnessSpec; this.context = context; } @@ -70,20 +72,20 @@ public class ConditionConverter extends ELSwitch<Object> { public Object caseComparisonExpression(ComparisonExpression object) { Requirements.requireSize(object.getComparison(), 1); - final Function<Properties, Object> leftValue = (Function<Properties, Object>) doSwitch(object.getLeftOperand()); - final Function<Properties, Object> rightValue = (Function<Properties, Object>) doSwitch(object.getComparison().get(0).getSubExpression()); + final BiFunction<Properties, Properties, Object> leftValue = (BiFunction<Properties, Properties, Object>) doSwitch(object.getLeftOperand()); + final BiFunction<Properties, Properties, Object> rightValue = (BiFunction<Properties, Properties, Object>) doSwitch(object.getComparison().get(0).getSubExpression()); switch (object.getComparison().get(0).getOperator()) { case EQUAL: case GREATER_EQUAL: case GREATER_THAN: { - function = properties -> minus(leftValue.apply(properties), rightValue.apply(properties)); + function = (gen, fit) -> minus(leftValue.apply(gen, fit), rightValue.apply(gen, fit)); break; } case LESS_EQUAL: case LESS_THAN: { - function = properties -> minus(rightValue.apply(properties), leftValue.apply(properties)); + function = (gen, fit) -> minus(rightValue.apply(gen, fit), leftValue.apply(gen, fit)); break; } case UNEQUAL: { @@ -114,22 +116,22 @@ public class ConditionConverter extends ELSwitch<Object> { @Override public Object caseAddOrSubtractExpression(final AddOrSubtractExpression object) { - Function<Properties, Object> value = (Function<Properties, Object>) doSwitch(object.getLeftOperand()); + BiFunction<Properties, Properties, Object> value = (BiFunction<Properties, Properties, Object>) doSwitch(object.getLeftOperand()); for(int i = 0; i < object.getOperators().size(); ++i) { final AddOrSubtractOperator operator = object.getOperators().get(i); - final Function<Properties, Object> rOp = (Function<Properties, Object>) doSwitch(object.getOperands().get(i)); + final BiFunction<Properties, Properties, Object> rOp = (BiFunction<Properties, Properties, Object>) doSwitch(object.getOperands().get(i)); switch (operator) { case ADD: { - final Function<Properties, Object> lOp = value; - value = properties -> add(lOp.apply(properties), rOp.apply(properties)); + final BiFunction<Properties, Properties, Object> lOp = value; + value = (gen, fit) -> add(lOp.apply(gen, fit), rOp.apply(gen, fit)); break; } case SUBTRACT: { - final Function<Properties, Object> lOp = value; - value = properties -> minus(lOp.apply(properties), rOp.apply(properties)); + final BiFunction<Properties, Properties, Object> lOp = value; + value = (gen, fit) -> minus(lOp.apply(gen, fit), rOp.apply(gen, fit)); break; } } @@ -139,28 +141,28 @@ public class ConditionConverter extends ELSwitch<Object> { @Override public Object caseMultiplyDivideModuloExpression(MultiplyDivideModuloExpression object) { - Function<Properties, Object> value = (Function<Properties, Object>) doSwitch(object.getLeftOperand()); + BiFunction<Properties, Properties, Object> value = (BiFunction<Properties, Properties, Object>) doSwitch(object.getLeftOperand()); for(int i = 0; i < object.getOperators().size(); ++i) { final MultiplyDivideModuloOperator operator = object.getOperators().get(i); - final Function<Properties, Object> rOp = (Function<Properties, Object>) doSwitch(object.getOperands().get(i)); + final BiFunction<Properties, Properties, Object> rOp = (BiFunction<Properties, Properties, Object>) doSwitch(object.getOperands().get(i)); switch (operator) { case DIVIDE: { - final Function<Properties, Object> lOp = value; - value = properties -> divide(lOp.apply(properties), rOp.apply(properties)); + final BiFunction<Properties, Properties, Object> lOp = value; + value = (gen, fit) -> divide(lOp.apply(gen, fit), rOp.apply(gen, fit)); break; } case MODULO: { - final Function<Properties, Object> lOp = value; - value = properties -> modulo(lOp.apply(properties), rOp.apply(properties)); + final BiFunction<Properties, Properties, Object> lOp = value; + value = (gen, fit) -> modulo(lOp.apply(gen, fit), rOp.apply(gen, fit)); break; } case MULTIPLY: { - final Function<Properties, Object> lOp = value; - value = properties -> multiply(lOp.apply(properties), rOp.apply(properties)); + final BiFunction<Properties, Properties, Object> lOp = value; + value = (gen, fit) -> multiply(lOp.apply(gen, fit), rOp.apply(gen, fit)); break; } } @@ -170,20 +172,20 @@ public class ConditionConverter extends ELSwitch<Object> { @Override public Object casePowerOfExpression(PowerOfExpression object) { - Function<Properties, Object> value = (Function<Properties, Object>) doSwitch(object.getLeftOperand()); + BiFunction<Properties, Properties, Object> value = (BiFunction<Properties, Properties, Object>) doSwitch(object.getLeftOperand()); if(object.getRightOperand() != null) { - final Function<Properties, Object> lOp = value; - final Function<Properties, Object> rOp = (Function<Properties, Object>) doSwitch(object.getRightOperand()); + final BiFunction<Properties, Properties, Object> lOp = value; + final BiFunction<Properties, Properties, Object> rOp = (BiFunction<Properties, Properties, Object>) doSwitch(object.getRightOperand()); - value = properties -> pow(lOp.apply(properties), rOp.apply(properties)); + value = (gen, fit) -> pow(lOp.apply(gen, fit), rOp.apply(gen, fit)); } return value; } @Override public Object caseUnaryAddOrSubtractExpression(UnaryAddOrSubtractExpression object) { - Function<Properties, Object> value = (Function<Properties, Object>) doSwitch(object.getSubExpression()); + BiFunction<Properties, Properties, Object> value = (BiFunction<Properties, Properties, Object>) doSwitch(object.getSubExpression()); for(final AddOrSubtractOperator operator : object.getOperators()) { switch (operator) { @@ -193,8 +195,8 @@ public class ConditionConverter extends ELSwitch<Object> { } case SUBTRACT: { - final Function<Properties, Object> lOp = value; - value = properties -> minus(0, lOp.apply(properties)); + final BiFunction<Properties, Properties, Object> lOp = value; + value = (gen, fit) -> minus(0, lOp.apply(gen, fit)); break; } } @@ -203,17 +205,17 @@ public class ConditionConverter extends ELSwitch<Object> { @Override public Object caseIntegerLiteral(final IntegerLiteral object) { - return (Function<Properties, Object>) properties -> (double)object.getValue(); + return (BiFunction<Properties, Properties, Object>) (gen, fit) -> (double)object.getValue(); } @Override public Object caseDoubleLiteral(final DoubleLiteral object) { - return (Function<Properties, Object>) properties -> object.getValue(); + return (BiFunction<Properties, Properties, Object>) (gen, fit) -> object.getValue(); } @Override public Object caseStringLiteral(final StringLiteral object) { - return (Function<Properties, Object>) properties -> Double.parseDouble(object.getValue()); + return (BiFunction<Properties, Properties, Object>) (gen, fit) -> Double.parseDouble(object.getValue()); } @Override @@ -221,24 +223,45 @@ public class ConditionConverter extends ELSwitch<Object> { if(object instanceof SelfReference) { Requirements.requireNotNull(context); final String propertyName = context.getName(); - final int propertyIndex = specification.indexOf(propertyName); + if(fitnessSpec.contains(new PropertySpecification(context.getName(), context))) { + final int propertyIndex = fitnessSpec.indexOf(propertyName); - usedProperties.add(specification.getProperties().get(propertyIndex)); + usedProperties.add(fitnessSpec.getProperties().get(propertyIndex)); - return (Function<Properties, Object>) properties -> properties.get(propertyIndex); + return (BiFunction<Properties, Properties, Object>) (gen, fit) -> fit.get(propertyIndex); + + } else { + final int propertyIndex = genoSpec.indexOf(propertyName); + + usedProperties.add(genoSpec.getProperties().get(propertyIndex)); + + return (BiFunction<Properties, Properties, Object>) (gen, fit) -> gen.get(propertyIndex); + + } } if(!(object instanceof DataReference)) { throw new IllegalStateException("Value reference is not a data reference."); } - final DataReference reference = (DataReference)object; - final String propertyName = reference.getDefinition().getName(); - final int propertyIndex = specification.indexOf(propertyName); + final DataReference reference = (DataReference) object; + final DataDescription description = reference.getDefinition(); + if(fitnessSpec.contains(new PropertySpecification(description.getName(), description))) { + final String propertyName = description.getName(); + final int propertyIndex = fitnessSpec.indexOf(propertyName); - usedProperties.add(specification.getProperties().get(propertyIndex)); + usedProperties.add(fitnessSpec.getProperties().get(propertyIndex)); - return (Function<Properties, Object>) properties -> properties.get(propertyIndex); + return (BiFunction<Properties, Properties, Object>) (gen, fit) -> fit.get(propertyIndex); + } else { + final String propertyName = description.getName(); + final int propertyIndex = genoSpec.indexOf(propertyName); + + usedProperties.add(genoSpec.getProperties().get(propertyIndex)); + + return (BiFunction<Properties, Properties, Object>) (gen, fit) -> gen.get(propertyIndex); + + } } @Override @@ -256,7 +279,7 @@ public class ConditionConverter extends ELSwitch<Object> { return doSwitch(object.getSubExpression()); } - public Function<Properties, Object> getFunction() { + public BiFunction<Properties, Properties, Object> getFunction() { return function; } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/UnaryBoundaryIdentifier.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/UnaryBoundaryIdentifier.java new file mode 100644 index 0000000000000000000000000000000000000000..c73b01ce8b160e21310c34e72471f4dfdc376ca9 --- /dev/null +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/ast/UnaryBoundaryIdentifier.java @@ -0,0 +1,196 @@ +package de.evoal.core.main.ea.constraints.constraint.ast; + +import de.evoal.core.api.ea.constraints.model.DataConstraints; +import de.evoal.core.api.properties.PropertySpecification; +import de.evoal.core.api.properties.info.PropertiesBoundaries; +import de.evoal.core.api.utils.Requirements; +import de.evoal.languages.model.ddl.DataDescription; +import de.evoal.languages.model.ddl.DataReference; +import de.evoal.languages.model.ddl.RepresentationType; +import de.evoal.languages.model.ddl.SelfReference; +import de.evoal.languages.model.el.*; +import de.evoal.languages.model.el.util.ELSwitch; +import lombok.extern.slf4j.Slf4j; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class UnaryBoundaryIdentifier extends ELSwitch<Object> { + + private final DataDescription context; + + public UnaryBoundaryIdentifier(final DataDescription context) { + this.context = context; + } + + + @Override + public Object caseOrExpression(OrExpression object) { + Requirements.requireSize(object.getSubExpressions(), 1); + + return doSwitch(object.getSubExpressions().get(0)); + } + + @Override + public Object caseXorExpression(XorExpression object) { + Requirements.requireSize(object.getSubExpressions(), 1); + + return doSwitch(object.getSubExpressions().get(0)); + } + + @Override + public Object caseAndExpression(final AndExpression object) { + Requirements.requireSize(object.getSubExpressions(), 1); + + return doSwitch(object.getSubExpressions().get(0)); + } + + @Override + public Object caseNotExpression(NotExpression object) { + Requirements.requireFalse(object.isNegated()); + + return doSwitch(object.getOperand()); + } + + @Override + public Object caseComparisonExpression(final ComparisonExpression object) { + if(object.getComparison().isEmpty()) { + return null; + } + + Requirements.requireSize(object.getComparison(), 1); + + final Object leftValue = doSwitch(object.getLeftOperand()); + final Object rightValue = doSwitch(object.getComparison().get(0).getSubExpression()); + + if(!((leftValue instanceof DataDescription && rightValue instanceof Number) || + (rightValue instanceof DataDescription && leftValue instanceof Number))) { + // not a supported relation + return null; + } + + switch (object.getComparison().get(0).getOperator()) { + case GREATER_EQUAL: + case GREATER_THAN: { + if(leftValue instanceof DataDescription) { + // lower + return new Object[] {rightValue, leftValue}; + } else { + // upper + return new Object[] {leftValue, rightValue}; + } + } + case LESS_EQUAL: + case LESS_THAN: + { + if(leftValue instanceof DataDescription) { + // upper + return new Object[] {leftValue, rightValue}; + } else { + // lower + return new Object[] {rightValue, leftValue}; + } + } + case EQUAL: + case UNEQUAL: { + throw new IllegalArgumentException("(Un)equal is not allowed"); + } + } + + return null; + } + + + @Override + public Object caseAddOrSubtractExpression(final AddOrSubtractExpression object) { + Requirements.requireEmpty(object.getOperators()); + return doSwitch(object.getLeftOperand()); + } + + @Override + public Object caseMultiplyDivideModuloExpression(final MultiplyDivideModuloExpression object) { + Requirements.requireEmpty(object.getOperators()); + return doSwitch(object.getLeftOperand()); + } + + @Override + public Object casePowerOfExpression(final PowerOfExpression object) { + Requirements.requireNull(object.getRightOperand()); + + return doSwitch(object.getLeftOperand()); + } + + @Override + public Object caseUnaryAddOrSubtractExpression(UnaryAddOrSubtractExpression object) { + Object value = doSwitch(object.getSubExpression()); + + for(final AddOrSubtractOperator operator : object.getOperators()) { + switch (operator) { + case ADD: { + value = value; + break; + } + + case SUBTRACT: { + if(value instanceof Double) { + value = -(Double)value; + } else if(value instanceof Integer) { + value = -(Integer)value; + } else { + throw new IllegalStateException("Unsupported"); + } + break; + } + } + } + + return value; + } + + @Override + public Object caseIntegerLiteral(final IntegerLiteral object) { + return object.getValue(); + } + + @Override + public Object caseDoubleLiteral(final DoubleLiteral object) { + return object.getValue(); + } + + @Override + public Object caseStringLiteral(final StringLiteral object) { + return null; + } + + @Override + public Object caseValueReference(final ValueReference object) { + if(object instanceof SelfReference) { + Requirements.requireNotNull(context); + return context; + } + + if(!(object instanceof DataReference)) { + throw new IllegalStateException("Value reference is not a data reference: " + object.eClass()); + } + + final DataReference reference = (DataReference)object; + return reference.getDefinition(); + } + + @Override + public Object caseBooleanLiteral(final BooleanLiteral object) { + return null; + } + + @Override + public Object caseCall(Call object) { + return null; + } + + @Override + public Object caseParantheses(final Parantheses object) { + return doSwitch(object.getSubExpression()); + } +} diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/calculations/NormalCalculation.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/calculations/NormalCalculation.java index 78aab84a0b1291edc0501f504ba060c4da0d6863..a12ba46fce9ba845f9bf37d304859f1a8331afcc 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/calculations/NormalCalculation.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/calculations/NormalCalculation.java @@ -18,8 +18,8 @@ public class NormalCalculation implements CalculationStrategy { private Constraint constraint; @Override - public @NonNull CalculationResult calculate(final Properties properties) { - return new CalculationResult(constraint.apply(properties)); + public @NonNull CalculationResult calculate(final Properties genotype, final Properties fitness) { + return new CalculationResult(constraint.apply(genotype, fitness)); } @Override diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/calculations/StandardDeviationCalculation.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/calculations/StandardDeviationCalculation.java index 62c45212e9bfff9764e2538d50566b5a19dd3e22..0c8dd19ca36c87deead86a206bdb8b328ae595c8 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/calculations/StandardDeviationCalculation.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/calculations/StandardDeviationCalculation.java @@ -39,13 +39,14 @@ public class StandardDeviationCalculation implements CalculationStrategy { private List<Pair<Integer, Double>> allowedDeviations; @Override - public @NonNull CalculationResult calculate(final Properties properties) { - return new CalculationResult(calculateMinimalDifference(0, new HashMap<>(), properties)); + public @NonNull CalculationResult calculate(final Properties genotype, final Properties fitness) { + return new CalculationResult(calculateMinimalDifference(0, new HashMap<>(), genotype, fitness)); } - private ConstraintResult calculateMinimalDifference(final int index, final Map<Integer, Double> differences, final Properties properties) { + // TODO Adapt fitness + private ConstraintResult calculateMinimalDifference(final int index, final Map<Integer, Double> differences, final Properties genotype, final Properties fitness) { if(index == allowedDeviations.size()) { - final Properties adaptedProperties = new Properties(properties); + final Properties adaptedProperties = new Properties(genotype); for(final Map.Entry<Integer, Double> entry : differences.entrySet()) { final Integer propIndex = entry.getKey(); @@ -53,14 +54,14 @@ public class StandardDeviationCalculation implements CalculationStrategy { adaptedProperties.put(propIndex, value); } - return constraint.apply(adaptedProperties); + return constraint.apply(adaptedProperties, fitness); } final Pair<Integer, Double> deviation = allowedDeviations.get(index); // no deviation differences.put(deviation.getFirst(), 0.0); - ConstraintResult minimalResult = calculateMinimalDifference(index + 1, differences, properties); + ConstraintResult minimalResult = calculateMinimalDifference(index + 1, differences, genotype, fitness); if(CalculationResult.isSuccessful(minimalResult) || deviation.getSecond() == 0.0) { return minimalResult; @@ -69,7 +70,7 @@ public class StandardDeviationCalculation implements CalculationStrategy { // - deviation { differences.put(deviation.getFirst(), -deviation.getSecond() * factor); - ConstraintResult result = calculateMinimalDifference(index + 1, differences, properties); + ConstraintResult result = calculateMinimalDifference(index + 1, differences, genotype, fitness); if(CalculationResult.isSuccessful(result)) { return result; @@ -81,7 +82,7 @@ public class StandardDeviationCalculation implements CalculationStrategy { // + deviation { differences.put(deviation.getFirst(), deviation.getSecond() * factor); - ConstraintResult result = calculateMinimalDifference(index + 1, differences, properties); + ConstraintResult result = calculateMinimalDifference(index + 1, differences, genotype, fitness); if(CalculationResult.isSuccessful(result)) { return result; diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/constraint/JeneticsConstraintProducer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/constraint/JeneticsConstraintProducer.java index f8214273d1f8b88c4b654bdc5bf2c5fe1e10690b..e57067ec77fb2ef9ef2f48f1e0731337a6eac66a 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/constraint/JeneticsConstraintProducer.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/constraint/JeneticsConstraintProducer.java @@ -1,15 +1,17 @@ package de.evoal.core.main.ea.constraints.constraint.strategies.constraint; +import de.evoal.core.api.cdi.BeanFactory; import de.evoal.core.api.ea.constraints.model.Constraint; import de.evoal.core.api.ea.constraints.model.Constraints; import de.evoal.core.api.ea.constraints.calculation.CalculationFactory; import de.evoal.core.api.board.BlackboardEntry; import de.evoal.core.api.cdi.ConfigurationValue; import de.evoal.core.api.ea.codec.CustomCodec; +import de.evoal.core.api.ea.fitness.FitnessFunction; +import de.evoal.core.api.properties.PropertiesSpecification; import de.evoal.core.main.ea.constraints.constraint.utils.ConfigurationUtils; -import de.evoal.languages.model.instance.Attribute; -import de.evoal.languages.model.instance.Instance; -import de.evoal.languages.model.instance.Misc; +import de.evoal.languages.model.instance.*; +import org.apache.deltaspike.core.api.provider.BeanProvider; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Produces; @@ -21,22 +23,56 @@ import java.util.stream.Collectors; public class JeneticsConstraintProducer { @Produces public List<io.jenetics.engine.Constraint> create( - final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.handling") Instance handlerConfiguration, + final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.handlers") Array handlerConfigurations, + final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.fitness") Instance fitnessConfiguration, final Constraints constraints, final CustomCodec codec, final CalculationFactory factory) { // collect group information to handle - final List<Attribute> groups = ConfigurationUtils.findByHandlerName(handlerConfiguration, "killAtBirth"); - final Set<String> allGroups = groups.stream().map(e -> ((Misc)e.getName()).getName()).collect(Collectors.toSet()); + final List<Instance> groups = ConfigurationUtils.findConstraintHandlerByHandlingStrategy(handlerConfigurations, "kill-at-birth"); + final Set<String> allGroups = groups.stream().map(i -> (String)((LiteralValue)i.findAttribute("category").getValue()).getLiteral().getValue()).collect(Collectors.toSet()); final List<Constraint> listOfConstraints = constraints.getConstraints(); + final FitnessFunction function = create(fitnessConfiguration); + final PropertiesSpecification fitnessSpec = toSpecification(fitnessConfiguration); + final List<io.jenetics.engine.Constraint> result = listOfConstraints .stream() .filter(c -> allGroups.contains(c.getGroup())) .map(factory::create) - .map(s -> new JeneticsConstraintStrategy(s, codec, new RandomGenotypeStrategy())) + .map(s -> new JeneticsConstraintStrategy(s, codec, function, fitnessSpec, new RandomGenotypeStrategy())) .collect(Collectors.toList()); return result; } + + private PropertiesSpecification toSpecification(final Instance fitnessConfiguration) { + return PropertiesSpecification.builder() + .add(((Array)findInner(fitnessConfiguration).findAttribute("maps-to").getValue()) + .getValues() + .stream() + .map(DataReference.class::cast) + .map(DataReference::getDefinition) + ) + .build(); + } + + private FitnessFunction create(Instance fitnessConfig) { + fitnessConfig = findInner(fitnessConfig); + + final String fitnessName = fitnessConfig.getName().getName(); + + return BeanProvider.getContextualReference(fitnessName, false, FitnessFunction.class) + .init(fitnessConfig); + } + + private Instance findInner(final Instance fitnessConfig) { + final Attribute subFunction = fitnessConfig.findAttribute("function"); + + if(subFunction != null) { + return findInner((Instance)subFunction.getValue()); + } + + return fitnessConfig; + } } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/constraint/JeneticsConstraintStrategy.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/constraint/JeneticsConstraintStrategy.java index 69e82db68340582fe7870e26d05f33d92336ae82..85388f55e65d2da3c6d61f2f840ffb87c69914d5 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/constraint/JeneticsConstraintStrategy.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/constraint/JeneticsConstraintStrategy.java @@ -3,7 +3,9 @@ package de.evoal.core.main.ea.constraints.constraint.strategies.constraint; import de.evoal.core.api.ea.constraints.calculation.CalculationStrategy; import de.evoal.core.api.ea.constraints.strategies.HandlingStrategy; import de.evoal.core.api.ea.codec.CustomCodec; +import de.evoal.core.api.ea.fitness.FitnessFunction; import de.evoal.core.api.properties.Properties; +import de.evoal.core.api.properties.PropertiesSpecification; import io.jenetics.Gene; import io.jenetics.Phenotype; @@ -14,19 +16,25 @@ public class JeneticsConstraintStrategy< private final CalculationStrategy calculation; private final CustomCodec<G> codec; + private final FitnessFunction function; + private final PropertiesSpecification fitnessSpec; private final RepairStrategy repair; - public JeneticsConstraintStrategy(final CalculationStrategy calculation, final CustomCodec<G> codec, final RepairStrategy repair) { + public JeneticsConstraintStrategy(final CalculationStrategy calculation, final CustomCodec<G> codec, final FitnessFunction function, final PropertiesSpecification fitnessSpec, final RepairStrategy repair) { this.calculation = calculation; this.codec = codec; + this.function = function; + this.fitnessSpec = fitnessSpec; this.repair = repair; } @Override public boolean test(final Phenotype<G, C> individual) { - final Properties properties = codec.decode(individual.genotype()); + final Properties genotype = codec.decode(individual.genotype()); + final double [] calculated = function.evaluate(genotype); + final Properties fitness = new Properties(fitnessSpec, calculated); - return calculation.calculate(properties).isSuccessful(); + return calculation.calculate(genotype, fitness).isSuccessful(); } @Override diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/fitness/MalusFunctionProducer.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/fitness/MalusFunctionProducer.java index c2badcd9af0e305588f5c97704cf447df76e49fe..449b23a7ff20c72a42d7305efcb990765f6e55a4 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/fitness/MalusFunctionProducer.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/fitness/MalusFunctionProducer.java @@ -17,6 +17,7 @@ import javax.enterprise.inject.Produces; import de.evoal.core.main.ea.constraints.constraint.strategies.fitness.internal.MalusForFitnessFunction; import de.evoal.core.main.ea.constraints.constraint.utils.ConfigurationUtils; +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.instance.Misc; @@ -29,7 +30,7 @@ import java.util.*; public class MalusFunctionProducer { @ApplicationScoped @Produces public MalusForFitnessStrategy create( - final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.constraint_handling") Instance handlerConfiguration, + final @ConfigurationValue(entry = BlackboardEntry.EA_CONFIGURATION, access = "algorithm.handlers") Array handlers, final Constraints constraints, final @Named("genotype-specification") PropertiesSpecification source, final @Named("output-dependencies") PropertiesDependencies dependencies, @@ -38,10 +39,10 @@ public class MalusFunctionProducer { final MalusForFitnessStrategy resultingFunction = new MalusForFitnessStrategy(target.size()); // collect group information to handle - final List<Attribute> groups = ConfigurationUtils.findByHandlerName(handlerConfiguration, "malusForFitness"); + final List<Instance> groups = ConfigurationUtils.findConstraintHandlerByHandlingStrategy(handlers, "malus-for-fitness"); // collect all constraints for each index (of the appropriate groups) - final List<List<Pair<Constraint, Attribute>>> constraintsForIndex = new ArrayList<>(source.size()); + final List<List<Pair<Constraint, Instance>>> constraintsForIndex = new ArrayList<>(source.size()); for(int index = 0; index < source.size(); ++index) { constraintsForIndex.add(new ArrayList<>()); } @@ -49,7 +50,7 @@ public class MalusFunctionProducer { for(final Constraint constraint : constraints.getConstraints()) { final String group = constraint.getGroup(); - for(final Attribute info : groups) { + for(final Instance info : groups) { if(((Misc)info.getName()).getName().equals(group)) { for(final PropertySpecification ps : constraint.getUsedProperties()) { final int index = source.indexOf(ps); @@ -66,9 +67,9 @@ public class MalusFunctionProducer { for(final PropertySpecification ips : dependencies.get(target.getProperties().get(index))) { final int ipsIndex = source.indexOf(ips); - for(final Pair<Constraint, Attribute> pair : constraintsForIndex.get(ipsIndex)) { + for(final Pair<Constraint, Instance> pair : constraintsForIndex.get(ipsIndex)) { final Constraint constraint = pair.getFirst(); - final Attribute configuration = pair.getSecond(); + final Instance configuration = pair.getSecond(); // prevent constraints from being applied multiple times per fitness value if(applied.contains(constraint)) { @@ -78,9 +79,9 @@ public class MalusFunctionProducer { final CalculationStrategy calculation = factory.create(constraint); - final String handlerName = LanguageHelper.lookup((Instance) configuration.getValue(), "name"); + final String handlerName = LanguageHelper.lookup(configuration, "name"); - final MalusFunction strategy = new MalusForFitnessFunction(constraint, LanguageHelper.lookup((Instance)configuration.getValue(), "handling"), index) ; + final MalusFunction strategy = new MalusForFitnessFunction(constraint, LanguageHelper.lookup(configuration, "handling"), index) ; resultingFunction.add(index, strategy); } } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/fitness/internal/MalusForFitnessFunction.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/fitness/internal/MalusForFitnessFunction.java index b6789f6509660cc7ca357becd737f96ccc6468a8..9a2626e3f7e1da6d1f1de1721f36c71ae9881b0f 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/fitness/internal/MalusForFitnessFunction.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/strategies/fitness/internal/MalusForFitnessFunction.java @@ -18,8 +18,9 @@ public class MalusForFitnessFunction implements MalusFunction { @Override public double apply(final Properties properties, double fitnessValue) { - final ConstraintResult result = constraint.apply(properties); + // final ConstraintResult result = constraint.apply(properties); - return fitnessValue - smoothing * Math.abs(result.getComparisonDifference()); + throw new IllegalStateException("Not yet implemented"); +// return fitnessValue - smoothing * Math.abs(result.getComparisonDifference()); } } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/utils/ConfigurationUtils.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/utils/ConfigurationUtils.java index 292212db76149bf8f65b31efcddee6ae690cbd84..eda85164f80e863087cecbf4e9b06f3e0a2ce23d 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/utils/ConfigurationUtils.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/ea/constraints/constraint/utils/ConfigurationUtils.java @@ -1,28 +1,24 @@ package de.evoal.core.main.ea.constraints.constraint.utils; import de.evoal.core.api.utils.LanguageHelper; +import de.evoal.languages.model.instance.Array; import de.evoal.languages.model.instance.Attribute; import de.evoal.languages.model.instance.Instance; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public final class ConfigurationUtils { private ConfigurationUtils() { } - public static List<Attribute> findByHandlerName(final Instance configuration, final String name) { - final List<Attribute> result = new ArrayList<>(); - - for(final Attribute attribute : configuration.getAttributes()) { - final Instance handlerConfiguration = LanguageHelper.lookup((Instance)attribute.getValue(), "handling"); - final String handlerName = LanguageHelper.lookup(handlerConfiguration, "name"); - - if(name.equals(handlerName)) { - result.add(attribute); - } - } - - return result; + public static List<Instance> findConstraintHandlerByHandlingStrategy(final Array handlers, final String name) { + return handlers.getValues() + .stream() + .map(Instance.class::cast) + .filter(i -> "constraint-handler".equals(i.getName().getName())) + .filter(i -> name.equals(((Instance)i.findAttribute("constraint-handling").getValue()).getName().getName())) + .collect(Collectors.toList()); } } diff --git a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/EvolutionaryAlgorithmModelLoader.java b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/EvolutionaryAlgorithmModelLoader.java index c91ec74c35bacdfd4f55b6684194141dab86e5a2..675674449689193014f50acf95e86145e248a1e8 100644 --- a/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/EvolutionaryAlgorithmModelLoader.java +++ b/src/core/de.evoal.core/src/main/java/de/evoal/core/main/producer/EvolutionaryAlgorithmModelLoader.java @@ -16,6 +16,7 @@ import de.evoal.languages.model.eal.impl.EALPackageImpl; import lombok.extern.slf4j.Slf4j; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.xtext.resource.XtextResource; import org.eclipse.xtext.resource.XtextResourceSet; @@ -61,6 +62,9 @@ public class EvolutionaryAlgorithmModelLoader { final Resource resource = resourceSet.getResource(modelURI, true); resource.load(resourceSet.getLoadOptions()); + + resourceSet.getResources() + .forEach(EcoreUtil::resolveAll); if(!resource.getErrors().isEmpty()) { for(Resource.Diagnostic diagnostic : resource.getErrors()) { log.error("Error while processing rule '{}': {}", configurationFile, diagnostic); @@ -72,6 +76,10 @@ public class EvolutionaryAlgorithmModelLoader { } } + if(!resource.getErrors().isEmpty()) { + throw new IllegalArgumentException("EAL file contains errors. Please fix the file."); + } + model = (EAModel) resource.getContents().get(0); board.bind(BlackboardEntry.EA_CONFIGURATION, model); } catch (final Exception e) { diff --git a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/constraint/ConstraintStatistics.java b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/constraint/ConstraintStatistics.java index c2cc6358f7c2a9b42fd2af5b5c4fc97fd313350c..cc8621a000613311e7ca94f06f951c8973e04a9e 100644 --- a/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/constraint/ConstraintStatistics.java +++ b/src/core/de.evoal.surrogate.api/src/main/java/de/evoal/surrogate/main/statistics/constraint/ConstraintStatistics.java @@ -94,7 +94,8 @@ public class ConstraintStatistics implements StatisticsWriter { population.stream() .map(Phenotype::genotype) .map(g -> (Properties)codec.decode(g)) - .map(strategy::calculate) + // TODO .map(strategy::calculate) + .map(CalculationResult.class::cast) .collect(Collectors.toList()); final long invalid = calculationResults