From 895b26df7a806a2136c2f7a46d56b542326e561f Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Wed, 6 Sep 2023 19:05:10 +0200 Subject: feat(dse): transformation rule builder --- .../tools/refinery/store/dse/ActionFactory.java | 15 --- .../store/dse/modification/DanglingEdges.java | 12 ++ .../dse/modification/ModificationAdapter.java | 2 +- .../modification/actions/CreateActionLiteral.java | 43 +++++++ .../modification/actions/DeleteActionLiteral.java | 51 ++++++++ .../actions/ModificationActionLiterals.java | 23 ++++ .../internal/ModificationAdapterImpl.java | 55 ++++++++- .../transition/DesignSpaceExplorationBuilder.java | 8 +- .../DesignSpaceExplorationStoreAdapter.java | 2 +- .../tools/refinery/store/dse/transition/Rule.java | 99 ++++++++++++++++ .../refinery/store/dse/transition/RuleBuilder.java | 71 +++++++++++ .../store/dse/transition/Transformation.java | 25 ++-- .../store/dse/transition/TransformationRule.java | 63 ---------- .../transition/actions/AbstractActionLiteral.java | 9 ++ .../store/dse/transition/actions/Action.java | 132 +++++++++++++++++++++ .../dse/transition/actions/ActionLiteral.java | 19 +++ .../dse/transition/actions/ActionLiterals.java | 33 ++++++ .../store/dse/transition/actions/BoundAction.java | 109 +++++++++++++++++ .../dse/transition/actions/BoundActionLiteral.java | 16 +++ .../dse/transition/actions/PutActionLiteral.java | 64 ++++++++++ .../dse/transition/callback/ActionCallback0.java | 15 +++ .../dse/transition/callback/ActionCallback1.java | 16 +++ .../dse/transition/callback/ActionCallback2.java | 16 +++ .../dse/transition/callback/ActionCallback3.java | 16 +++ .../dse/transition/callback/ActionCallback4.java | 16 +++ .../dse/transition/callback/RuleCallback0.java | 13 ++ .../dse/transition/callback/RuleCallback1.java | 14 +++ .../dse/transition/callback/RuleCallback2.java | 14 +++ .../dse/transition/callback/RuleCallback3.java | 14 +++ .../dse/transition/callback/RuleCallback4.java | 14 +++ .../DesignSpaceExplorationBuilderImpl.java | 30 ++--- .../DesignSpaceExplorationStoreAdapterImpl.java | 32 ++--- .../store/dse/transition/objectives/Criterion.java | 2 +- .../store/dse/transition/objectives/Objective.java | 2 +- .../dse/transition/objectives/QueryCriteria.java | 4 +- .../dse/transition/objectives/QueryObjective.java | 4 +- 36 files changed, 937 insertions(+), 136 deletions(-) delete mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/DanglingEdges.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/CreateActionLiteral.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/DeleteActionLiteral.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/ModificationActionLiterals.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Rule.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/RuleBuilder.java delete mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/TransformationRule.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/AbstractActionLiteral.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/Action.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiteral.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiterals.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundAction.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundActionLiteral.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/PutActionLiteral.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback0.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback1.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback2.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback3.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback4.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback0.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback1.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback2.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback3.java create mode 100644 subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback4.java (limited to 'subprojects/store-dse/src/main/java') diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java deleted file mode 100644 index 48a508b4..00000000 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/ActionFactory.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ -package tools.refinery.store.dse; - -import tools.refinery.store.model.Model; -import tools.refinery.store.tuple.Tuple; - -import java.util.function.Consumer; - -public interface ActionFactory { - Consumer prepare(Model model); -} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/DanglingEdges.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/DanglingEdges.java new file mode 100644 index 00000000..ac9d125b --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/DanglingEdges.java @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.modification; + +public enum DanglingEdges { + IGNORE, + DELETE, + FAIL +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java index f15c16e0..58b60499 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/ModificationAdapter.java @@ -16,7 +16,7 @@ public interface ModificationAdapter extends ModelAdapter { Tuple1 createObject(); - Tuple deleteObject(Tuple tuple); + boolean deleteObject(Tuple tuple, DanglingEdges danglingEdges); static ModificationBuilder builder() { return new ModificationBuilderImpl(); diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/CreateActionLiteral.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/CreateActionLiteral.java new file mode 100644 index 00000000..5b86a5e1 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/CreateActionLiteral.java @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.modification.actions; + +import tools.refinery.store.dse.modification.ModificationAdapter; +import tools.refinery.store.dse.transition.actions.AbstractActionLiteral; +import tools.refinery.store.dse.transition.actions.BoundActionLiteral; +import tools.refinery.store.model.Model; +import tools.refinery.store.query.term.NodeVariable; + +import java.util.List; + +public class CreateActionLiteral extends AbstractActionLiteral { + private final NodeVariable variable; + + public CreateActionLiteral(NodeVariable variable) { + + this.variable = variable; + } + + public NodeVariable getVariable() { + return variable; + } + + @Override + public List getInputVariables() { + return List.of(); + } + + @Override + public List getOutputVariables() { + return List.of(variable); + } + + @Override + public BoundActionLiteral bindToModel(Model model) { + var adapter = model.getAdapter(ModificationAdapter.class); + return ignoredTuple -> adapter.createObject(); + } +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/DeleteActionLiteral.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/DeleteActionLiteral.java new file mode 100644 index 00000000..18ad2b9d --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/DeleteActionLiteral.java @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.modification.actions; + +import tools.refinery.store.dse.modification.DanglingEdges; +import tools.refinery.store.dse.modification.ModificationAdapter; +import tools.refinery.store.dse.transition.actions.AbstractActionLiteral; +import tools.refinery.store.dse.transition.actions.BoundActionLiteral; +import tools.refinery.store.model.Model; +import tools.refinery.store.query.term.NodeVariable; +import tools.refinery.store.tuple.Tuple; + +import java.util.List; + +public class DeleteActionLiteral extends AbstractActionLiteral { + private final NodeVariable variable; + private final DanglingEdges danglingEdges; + + public DeleteActionLiteral(NodeVariable variable, DanglingEdges danglingEdges) { + + this.variable = variable; + this.danglingEdges = danglingEdges; + } + + public NodeVariable getVariable() { + return variable; + } + + public DanglingEdges getDanglingEdges() { + return danglingEdges; + } + + @Override + public List getInputVariables() { + return List.of(variable); + } + + @Override + public List getOutputVariables() { + return List.of(); + } + + @Override + public BoundActionLiteral bindToModel(Model model) { + var adapter = model.getAdapter(ModificationAdapter.class); + return tuple -> adapter.deleteObject(tuple, danglingEdges) ? Tuple.of() : null; + } +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/ModificationActionLiterals.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/ModificationActionLiterals.java new file mode 100644 index 00000000..31f50ac7 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/actions/ModificationActionLiterals.java @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.modification.actions; + +import tools.refinery.store.dse.modification.DanglingEdges; +import tools.refinery.store.query.term.NodeVariable; + +public class ModificationActionLiterals { + private ModificationActionLiterals() { + throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); + } + + public static CreateActionLiteral create(NodeVariable variable) { + return new CreateActionLiteral(variable); + } + + public static DeleteActionLiteral delete(NodeVariable variable, DanglingEdges danglingEdges) { + return new DeleteActionLiteral(variable, danglingEdges); + } +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java index b2a80d71..4e77c462 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/modification/internal/ModificationAdapterImpl.java @@ -6,6 +6,7 @@ package tools.refinery.store.dse.modification.internal; import tools.refinery.store.adapter.ModelStoreAdapter; +import tools.refinery.store.dse.modification.DanglingEdges; import tools.refinery.store.dse.modification.ModificationAdapter; import tools.refinery.store.model.Interpretation; import tools.refinery.store.model.Model; @@ -13,6 +14,8 @@ import tools.refinery.store.representation.Symbol; import tools.refinery.store.tuple.Tuple; import tools.refinery.store.tuple.Tuple1; +import java.util.HashSet; + public class ModificationAdapterImpl implements ModificationAdapter { static final Symbol NEXT_ID = Symbol.of("NEXT_ID", 0, Integer.class, 0); @@ -49,14 +52,56 @@ public class ModificationAdapterImpl implements ModificationAdapter { } @Override - public Tuple deleteObject(Tuple tuple) { + public boolean deleteObject(Tuple tuple, DanglingEdges danglingEdges) { if (tuple.getSize() != 1) { throw new IllegalArgumentException("Tuple size must be 1"); } -// TODO: implement more efficient deletion - if (tuple.get(0) == getModelSize() - 1) { - nodeCountInterpretation.put(Tuple.of(), getModelSize() - 1); + int objectId = tuple.get(0); + if (danglingEdges == DanglingEdges.DELETE) { + deleteDanglingEdges(objectId); + } else if (danglingEdges == DanglingEdges.FAIL && hasDanglingEdges(objectId)) { + return false; + + } + int modelSize = getModelSize(); + if (objectId == modelSize - 1) { + nodeCountInterpretation.put(Tuple.of(), modelSize - 1); + } + return true; + } + + private void deleteDanglingEdges(int objectId) { + for (var symbol : model.getStore().getSymbols()) { + deleteDanglingEdges(objectId, (Symbol) symbol); + } + } + + private void deleteDanglingEdges(int objectId, Symbol symbol) { + var interpretation = model.getInterpretation(symbol); + var toDelete = new HashSet(); + int arity = symbol.arity(); + for (int i = 0; i < arity; i++) { + var cursor = interpretation.getAdjacent(i, objectId); + while (cursor.move()) { + toDelete.add(cursor.getKey()); + } + } + var defaultValue = symbol.defaultValue(); + for (var tuple : toDelete) { + interpretation.put(tuple, defaultValue); + } + } + + private boolean hasDanglingEdges(int objectId) { + for (var symbol : model.getStore().getSymbols()) { + var interpretation = model.getInterpretation(symbol); + int arity = symbol.arity(); + for (int i = 0; i < arity; i++) { + if (interpretation.getAdjacentSize(i, objectId) > 0) { + return true; + } + } } - return tuple; + return false; } } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationBuilder.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationBuilder.java index 3855a20a..800cf8f7 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationBuilder.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationBuilder.java @@ -12,14 +12,16 @@ import tools.refinery.store.dse.transition.objectives.Objective; import java.util.Collection; import java.util.List; +// Builder pattern with methods returning {@code this} for convenience. +@SuppressWarnings("UnusedReturnValue") public interface DesignSpaceExplorationBuilder extends ModelAdapterBuilder { + DesignSpaceExplorationBuilder transformation(Rule transformationRuleDefinition); - DesignSpaceExplorationBuilder transformation(TransformationRule transformationRuleDefinition); - default DesignSpaceExplorationBuilder transformations(TransformationRule... transformationRuleDefinitions) { + default DesignSpaceExplorationBuilder transformations(Rule... transformationRuleDefinitions) { return transformations(List.of(transformationRuleDefinitions)); } - default DesignSpaceExplorationBuilder transformations(Collection transformationRules) { + default DesignSpaceExplorationBuilder transformations(Collection transformationRules) { transformationRules.forEach(this::transformation); return this; } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationStoreAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationStoreAdapter.java index 5c8c7a4d..fb082fae 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationStoreAdapter.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/DesignSpaceExplorationStoreAdapter.java @@ -17,7 +17,7 @@ public interface DesignSpaceExplorationStoreAdapter extends ModelStoreAdapter @Override DesignSpaceExplorationAdapter createModelAdapter(Model model); - List getTransformations(); + List getTransformations(); List getAccepts(); diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Rule.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Rule.java new file mode 100644 index 00000000..ff45ed3e --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Rule.java @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition; + +import tools.refinery.store.dse.transition.actions.Action; +import tools.refinery.store.dse.transition.actions.BoundAction; +import tools.refinery.store.dse.transition.callback.*; +import tools.refinery.store.model.Model; +import tools.refinery.store.query.dnf.RelationalQuery; + +public class Rule { + private final String name; + private final RelationalQuery precondition; + private final Action action; + + public Rule(String name, RelationalQuery precondition, Action action) { + if (precondition.arity() != action.getArity()) { + throw new IllegalArgumentException("Expected an action clause with %d parameters, got %d instead" + .formatted(precondition.arity(), action.getArity())); + } + this.name = name; + this.precondition = precondition; + this.action = action; + } + + public String getName() { + return name; + } + + public RelationalQuery getPrecondition() { + return precondition; + } + + public BoundAction createAction(Model model) { + return action.bindToModel(model); + } + + public static RuleBuilder builder(String name) { + return new RuleBuilder(name); + } + + public static RuleBuilder builder() { + return builder(null); + } + + public static Rule of(String name, RuleCallback0 callback) { + var builder = builder(name); + callback.accept(builder); + return builder.build(); + } + + public static Rule of(RuleCallback0 callback) { + return of(null, callback); + } + + public static Rule of(String name, RuleCallback1 callback) { + var builder = builder(name); + callback.accept(builder, builder.parameter("p1")); + return builder.build(); + } + + public static Rule of(RuleCallback1 callback) { + return of(null, callback); + } + + public static Rule of(String name, RuleCallback2 callback) { + var builder = builder(name); + callback.accept(builder, builder.parameter("p1"), builder.parameter("p2")); + return builder.build(); + } + + public static Rule of(RuleCallback2 callback) { + return of(null, callback); + } + + public static Rule of(String name, RuleCallback3 callback) { + var builder = builder(name); + callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), builder.parameter("p3")); + return builder.build(); + } + + public static Rule of(RuleCallback3 callback) { + return of(null, callback); + } + + public static Rule of(String name, RuleCallback4 callback) { + var builder = builder(name); + callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), builder.parameter("p3"), + builder.parameter("p4")); + return builder.build(); + } + + public static Rule of(RuleCallback4 callback) { + return of(null, callback); + } +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/RuleBuilder.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/RuleBuilder.java new file mode 100644 index 00000000..865ac369 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/RuleBuilder.java @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition; + +import tools.refinery.store.dse.transition.actions.Action; +import tools.refinery.store.dse.transition.actions.ActionLiteral; +import tools.refinery.store.dse.transition.callback.*; +import tools.refinery.store.query.dnf.AbstractQueryBuilder; +import tools.refinery.store.query.dnf.Dnf; +import tools.refinery.store.query.term.Variable; + +import java.util.List; + +public class RuleBuilder extends AbstractQueryBuilder { + private final String name; + private List action; + + RuleBuilder(String name) { + super(Dnf.builder(name == null ? null : name + "#precondition")); + this.name = name; + } + + @Override + protected RuleBuilder self() { + return this; + } + + public RuleBuilder action(ActionLiteral... literals) { + return action(List.of(literals)); + } + + public RuleBuilder action(List literals) { + if (this.action != null) { + throw new IllegalStateException("Actions have already been set"); + } + this.action = List.copyOf(literals); + return this; + } + + public RuleBuilder action(Action action) { + return action(action.getActionLiterals()); + } + + public RuleBuilder action(ActionCallback0 callback) { + return action(callback.toLiterals()); + } + + public RuleBuilder action(ActionCallback1 callback) { + return action(callback.toLiterals(Variable.of("v1"))); + } + + public RuleBuilder action(ActionCallback2 callback) { + return action(callback.toLiterals(Variable.of("v1"), Variable.of("v2"))); + } + + public RuleBuilder action(ActionCallback3 callback) { + return action(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("v3"))); + } + + public RuleBuilder action(ActionCallback4 callback) { + return action(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("v3"), Variable.of("v4"))); + } + + public Rule build() { + var precondition = dnfBuilder.build().asRelation(); + return new Rule(name, precondition, Action.ofPrecondition(precondition, action)); + } +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Transformation.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Transformation.java index ab9fda3e..0eeccbdf 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Transformation.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/Transformation.java @@ -5,26 +5,27 @@ */ package tools.refinery.store.dse.transition; +import tools.refinery.store.dse.transition.actions.BoundAction; +import tools.refinery.store.model.Model; +import tools.refinery.store.query.ModelQueryAdapter; import tools.refinery.store.query.resultset.OrderedResultSet; import tools.refinery.store.query.resultset.ResultSet; import tools.refinery.store.tuple.Tuple; -import java.util.function.Consumer; - public class Transformation { - private final TransformationRule definition; - + private final Rule definition; private final OrderedResultSet activations; + private final BoundAction action; - private final Consumer action; - - public Transformation(TransformationRule definition, OrderedResultSet activations, Consumer action) { + public Transformation(Model model, Rule definition) { this.definition = definition; - this.activations = activations; - this.action = action; + var precondition = definition.getPrecondition(); + var queryEngine = model.getAdapter(ModelQueryAdapter.class); + activations = new OrderedResultSet<>(queryEngine.getResultSet(precondition)); + action = definition.createAction(model); } - public TransformationRule getDefinition() { + public Rule getDefinition() { return definition; } @@ -37,8 +38,6 @@ public class Transformation { } public boolean fireActivation(Tuple activation) { - action.accept(activation); - //queryEngine.flushChanges(); - return true; + return action.fire(activation); } } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/TransformationRule.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/TransformationRule.java deleted file mode 100644 index d64a3db1..00000000 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/TransformationRule.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 The Refinery Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ -package tools.refinery.store.dse.transition; - -import tools.refinery.store.model.Model; -import tools.refinery.store.model.ModelStoreBuilder; -import tools.refinery.store.query.ModelQueryAdapter; -import tools.refinery.store.query.ModelQueryBuilder; -import tools.refinery.store.query.dnf.RelationalQuery; -import tools.refinery.store.dse.ActionFactory; -import tools.refinery.store.query.resultset.OrderedResultSet; -import tools.refinery.store.query.resultset.ResultSet; -import tools.refinery.store.tuple.Tuple; - -import java.util.*; - -public class TransformationRule { - - private final String name; - private final RelationalQuery precondition; - private final ActionFactory actionFactory; - - private Random random; - private ModelQueryAdapter queryEngine; - - public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory) { - this(name, precondition, actionFactory, new Random()); - } - - public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory, long seed) { - this(name, precondition, actionFactory, new Random(seed)); - } - - public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory, Random random) { - this.name = name; - this.precondition = precondition; - this.actionFactory = actionFactory; - this.random = random; - } - public void doConfigure(ModelStoreBuilder storeBuilder) { - var queryBuilder = storeBuilder.getAdapter(ModelQueryBuilder.class); - queryBuilder.query(this.precondition); - } - - public Transformation prepare(Model model) { - var queryEngine = model.getAdapter(ModelQueryAdapter.class); - var activations = new OrderedResultSet<>(queryEngine.getResultSet(precondition)); - var action = actionFactory.prepare(model); - return new Transformation(this,activations,action); - } - - public String getName() { - return name; - } - - public RelationalQuery getPrecondition() { - return precondition; - } - -} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/AbstractActionLiteral.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/AbstractActionLiteral.java new file mode 100644 index 00000000..e30f06bb --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/AbstractActionLiteral.java @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.actions; + +public abstract class AbstractActionLiteral implements ActionLiteral { +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/Action.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/Action.java new file mode 100644 index 00000000..d63ddfdd --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/Action.java @@ -0,0 +1,132 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.actions; + +import org.eclipse.collections.api.factory.primitive.ObjectIntMaps; +import org.eclipse.collections.api.map.primitive.MutableObjectIntMap; +import org.jetbrains.annotations.Nullable; +import tools.refinery.store.model.Model; +import tools.refinery.store.query.dnf.RelationalQuery; +import tools.refinery.store.query.dnf.SymbolicParameter; +import tools.refinery.store.query.term.NodeVariable; + +import java.util.*; + +public class Action { + private final List parameters; + private final Set localVariables; + private final List actionLiterals; + private final int[] @Nullable [] inputAllocations; + private final int[] @Nullable [] outputAllocations; + + public Action(List parameters, List actionLiterals) { + this.parameters = List.copyOf(parameters); + this.actionLiterals = List.copyOf(actionLiterals); + var allocation = ObjectIntMaps.mutable.empty(); + int arity = parameters.size(); + for (int i = 0; i < arity; i++) { + allocation.put(parameters.get(i), i); + } + var mutableLocalVariables = new LinkedHashSet(); + int size = actionLiterals.size(); + inputAllocations = new int[size][]; + outputAllocations = new int[size][]; + for (int i = 0; i < size; i++) { + computeInputAllocation(i, parameters, allocation); + computeOutputAllocation(i, mutableLocalVariables, allocation); + } + this.localVariables = Collections.unmodifiableSet(mutableLocalVariables); + } + + private void computeInputAllocation(int actionIndex, List parameters, + MutableObjectIntMap allocation) { + var actionLiteral = actionLiterals.get(actionIndex); + var inputVariables = actionLiteral.getInputVariables(); + if (inputVariables.equals(parameters)) { + // Identity mappings use a {@code null} allocation to pass the activation tuple unchanged. + return; + } + var inputs = new int[inputVariables.size()]; + for (int i = 0; i < inputs.length; i++) { + var variable = inputVariables.get(i); + if (!allocation.containsKey(variable)) { + throw new IllegalArgumentException("Unbound input variable %s of action literal %s" + .formatted(variable, actionLiteral)); + } + inputs[i] = allocation.get(variable); + } + inputAllocations[actionIndex] = inputs; + } + + private void computeOutputAllocation(int actionIndex, Set mutableLocalVariable, + MutableObjectIntMap allocation) { + var actionLiteral = actionLiterals.get(actionIndex); + var outputVariables = actionLiteral.getOutputVariables(); + int size = outputVariables.size(); + if (size == 0) { + // Identity mappings use a {@code null} allocation to avoid iterating over the output tuple. + return; + } + if (size >= 2 && new HashSet<>(outputVariables).size() != size) { + throw new IllegalArgumentException("Action literal %s has duplicate output variables %s" + .formatted(actionLiteral, outputVariables)); + } + int arity = parameters.size(); + var outputs = new int[size]; + for (int i = 0; i < size; i++) { + var variable = outputVariables.get(i); + if (allocation.containsKey(variable)) { + throw new IllegalArgumentException("Output variable %s of action literal %s was already assigned" + .formatted(variable, actionLiteral)); + } + int variableId = mutableLocalVariable.size(); + allocation.put(variable, arity + variableId); + outputs[i] = variableId; + mutableLocalVariable.add(variable); + } + outputAllocations[actionIndex] = outputs; + } + + public List getParameters() { + return parameters; + } + + public int getArity() { + return parameters.size(); + } + + public Set getLocalVariables() { + return localVariables; + } + + public List getActionLiterals() { + return actionLiterals; + } + + int @Nullable [] getInputAllocation(int actionIndex) { + return inputAllocations[actionIndex]; + } + + int @Nullable [] getOutputAllocation(int actionIndex) { + return outputAllocations[actionIndex]; + } + + public BoundAction bindToModel(Model model) { + return new BoundAction(this, model); + } + + public static Action ofSymbolicParameters(List symbolicParameters, + List actionLiterals) { + var nodeVariables = symbolicParameters.stream() + .map(symbolicParameter -> symbolicParameter.getVariable().asNodeVariable()) + .toList(); + return new Action(nodeVariables, actionLiterals); + } + + public static Action ofPrecondition(RelationalQuery precondition, List actionLiterals) { + return ofSymbolicParameters(precondition.getDnf().getSymbolicParameters(), actionLiterals); + } +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiteral.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiteral.java new file mode 100644 index 00000000..a721ef73 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiteral.java @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.actions; + +import tools.refinery.store.model.Model; +import tools.refinery.store.query.term.NodeVariable; + +import java.util.List; + +public interface ActionLiteral { + List getInputVariables(); + + List getOutputVariables(); + + BoundActionLiteral bindToModel(Model model); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiterals.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiterals.java new file mode 100644 index 00000000..275e1e25 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiterals.java @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.actions; + +import tools.refinery.store.query.term.NodeVariable; +import tools.refinery.store.representation.Symbol; + +import java.util.List; +import java.util.Objects; + +public final class ActionLiterals { + private ActionLiterals() { + throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); + } + + public static PutActionLiteral put(Symbol symbol, T value, NodeVariable... parameters) { + return new PutActionLiteral<>(symbol, value, List.of(parameters)); + } + + public static PutActionLiteral add(Symbol symbol, NodeVariable... parameters) { + if (!Objects.equals(symbol.defaultValue(), false)) { + throw new IllegalArgumentException("Use put to add a value to symbols other than two-valued logic"); + } + return put(symbol, true, parameters); + } + + public static PutActionLiteral remove(Symbol symbol, NodeVariable... parameters) { + return put(symbol, symbol.defaultValue(), parameters); + } +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundAction.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundAction.java new file mode 100644 index 00000000..55f43735 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundAction.java @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.actions; + +import org.jetbrains.annotations.Nullable; +import tools.refinery.store.model.Model; +import tools.refinery.store.tuple.Tuple; + +public class BoundAction { + private final Action action; + private final BoundActionLiteral[] boundLiterals; + private Tuple activation; + private final int[] localVariables; + + BoundAction(Action action, Model model) { + this.action = action; + var actionLiterals = action.getActionLiterals(); + int size = actionLiterals.size(); + boundLiterals = new BoundActionLiteral[size]; + for (int i = 0; i < size; i++) { + boundLiterals[i] = actionLiterals.get(i).bindToModel(model); + } + localVariables = new int[action.getLocalVariables().size()]; + } + + public boolean fire(Tuple activation) { + if (this.activation != null) { + throw new IllegalStateException("Reentrant firing is not allowed"); + } + this.activation = activation; + try { + int size = boundLiterals.length; + for (int i = 0; i < size; i++) { + var inputAllocation = action.getInputAllocation(i); + var boundLiteral = boundLiterals[i]; + var input = getInputTuple(inputAllocation); + var output = boundLiteral.fire(input); + if (output == null) { + return false; + } + var outputAllocation = this.action.getOutputAllocation(i); + setOutputTuple(outputAllocation, output); + } + } finally { + this.activation = null; + } + return true; + } + + private Tuple getInputTuple(int @Nullable [] inputAllocation) { + if (inputAllocation == null) { + // Identity allocation. + return activation; + } + return switch (inputAllocation.length) { + case 0 -> Tuple.of(); + case 1 -> Tuple.of(getInput(inputAllocation[0])); + case 2 -> Tuple.of(getInput(inputAllocation[0]), getInput(inputAllocation[1])); + case 3 -> Tuple.of(getInput(inputAllocation[0]), getInput(inputAllocation[1]), + getInput(inputAllocation[2])); + case 4 -> Tuple.of(getInput(inputAllocation[0]), getInput(inputAllocation[1]), + getInput(inputAllocation[2]), getInput(inputAllocation[3])); + default -> { + var elements = new int[inputAllocation.length]; + for (var i = 0; i < inputAllocation.length; i++) { + elements[i] = getInput(inputAllocation[i]); + } + yield Tuple.of(elements); + } + }; + } + + private int getInput(int index) { + int arity = action.getArity(); + return index < arity ? activation.get(index) : localVariables[index - arity]; + } + + private void setOutputTuple(int @Nullable [] outputAllocation, Tuple output) { + if (outputAllocation == null || outputAllocation.length == 0) { + return; + } + switch (outputAllocation.length) { + case 1 -> localVariables[outputAllocation[0]] = output.get(0); + case 2 -> { + localVariables[outputAllocation[0]] = output.get(0); + localVariables[outputAllocation[1]] = output.get(1); + } + case 3 -> { + localVariables[outputAllocation[0]] = output.get(0); + localVariables[outputAllocation[1]] = output.get(1); + localVariables[outputAllocation[2]] = output.get(2); + } + case 4 -> { + localVariables[outputAllocation[0]] = output.get(0); + localVariables[outputAllocation[1]] = output.get(1); + localVariables[outputAllocation[2]] = output.get(2); + localVariables[outputAllocation[3]] = output.get(3); + } + default -> { + for (int i = 0; i < outputAllocation.length; i++) { + localVariables[outputAllocation[i]] = output.get(i); + } + } + } + } +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundActionLiteral.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundActionLiteral.java new file mode 100644 index 00000000..09c3c58c --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundActionLiteral.java @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.actions; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import tools.refinery.store.tuple.Tuple; + +@FunctionalInterface +public interface BoundActionLiteral { + @Nullable + Tuple fire(@NotNull Tuple tuple); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/PutActionLiteral.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/PutActionLiteral.java new file mode 100644 index 00000000..86288921 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/PutActionLiteral.java @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.actions; + +import tools.refinery.store.model.Model; +import tools.refinery.store.query.term.NodeVariable; +import tools.refinery.store.representation.Symbol; +import tools.refinery.store.tuple.Tuple; + +import java.util.List; + +public class PutActionLiteral extends AbstractActionLiteral { + private final Symbol symbol; + private final List parameters; + private final T value; + + public PutActionLiteral(Symbol symbol, T value, List parameters) { + if (symbol.arity() != parameters.size()) { + throw new IllegalArgumentException("Expected %d parameters for symbol %s, got %d instead" + .formatted(symbol.arity(), symbol, parameters.size())); + } + if (value != null && !symbol.valueType().isInstance(value)) { + throw new IllegalArgumentException("Expected value of type %s for symbol %s, got %s of type %s instead" + .formatted(symbol.valueType().getName(), symbol, value, value.getClass().getName())); + } + this.symbol = symbol; + this.parameters = List.copyOf(parameters); + this.value = value; + } + + public Symbol getSymbol() { + return symbol; + } + + public List getParameters() { + return parameters; + } + + public T getValue() { + return value; + } + + @Override + public List getInputVariables() { + return getParameters(); + } + + @Override + public List getOutputVariables() { + return List.of(); + } + + @Override + public BoundActionLiteral bindToModel(Model model) { + var interpretation = model.getInterpretation(symbol); + return tuple -> { + interpretation.put(tuple, value); + return Tuple.of(); + }; + } +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback0.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback0.java new file mode 100644 index 00000000..1190fdeb --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback0.java @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.callback; + +import tools.refinery.store.dse.transition.actions.ActionLiteral; + +import java.util.List; + +@FunctionalInterface +public interface ActionCallback0 { + List toLiterals(); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback1.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback1.java new file mode 100644 index 00000000..869f1a96 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback1.java @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.callback; + +import tools.refinery.store.dse.transition.actions.ActionLiteral; +import tools.refinery.store.query.term.NodeVariable; + +import java.util.List; + +@FunctionalInterface +public interface ActionCallback1 { + List toLiterals(NodeVariable v1); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback2.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback2.java new file mode 100644 index 00000000..a648fc93 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback2.java @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.callback; + +import tools.refinery.store.dse.transition.actions.ActionLiteral; +import tools.refinery.store.query.term.NodeVariable; + +import java.util.List; + +@FunctionalInterface +public interface ActionCallback2 { + List toLiterals(NodeVariable v1, NodeVariable v2); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback3.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback3.java new file mode 100644 index 00000000..a9b1d334 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback3.java @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.callback; + +import tools.refinery.store.dse.transition.actions.ActionLiteral; +import tools.refinery.store.query.term.NodeVariable; + +import java.util.List; + +@FunctionalInterface +public interface ActionCallback3 { + List toLiterals(NodeVariable v1, NodeVariable v2, NodeVariable v3); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback4.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback4.java new file mode 100644 index 00000000..aef1351c --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/ActionCallback4.java @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.callback; + +import tools.refinery.store.dse.transition.actions.ActionLiteral; +import tools.refinery.store.query.term.NodeVariable; + +import java.util.List; + +@FunctionalInterface +public interface ActionCallback4 { + List toLiterals(NodeVariable v1, NodeVariable v2, NodeVariable v3, NodeVariable v4); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback0.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback0.java new file mode 100644 index 00000000..538c23ba --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback0.java @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.callback; + +import tools.refinery.store.dse.transition.RuleBuilder; + +@FunctionalInterface +public interface RuleCallback0 { + void accept(RuleBuilder builder); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback1.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback1.java new file mode 100644 index 00000000..bd7bf4f5 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback1.java @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.callback; + +import tools.refinery.store.dse.transition.RuleBuilder; +import tools.refinery.store.query.term.NodeVariable; + +@FunctionalInterface +public interface RuleCallback1 { + void accept(RuleBuilder builder, NodeVariable p1); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback2.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback2.java new file mode 100644 index 00000000..7b02b68a --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback2.java @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.callback; + +import tools.refinery.store.dse.transition.RuleBuilder; +import tools.refinery.store.query.term.NodeVariable; + +@FunctionalInterface +public interface RuleCallback2 { + void accept(RuleBuilder builder, NodeVariable p1, NodeVariable p2); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback3.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback3.java new file mode 100644 index 00000000..6f112d48 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback3.java @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.callback; + +import tools.refinery.store.dse.transition.RuleBuilder; +import tools.refinery.store.query.term.NodeVariable; + +@FunctionalInterface +public interface RuleCallback3 { + void accept(RuleBuilder builder, NodeVariable p1, NodeVariable p2, NodeVariable p3); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback4.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback4.java new file mode 100644 index 00000000..dbcf8567 --- /dev/null +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/callback/RuleCallback4.java @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.dse.transition.callback; + +import tools.refinery.store.dse.transition.RuleBuilder; +import tools.refinery.store.query.term.NodeVariable; + +@FunctionalInterface +public interface RuleCallback4 { + void accept(RuleBuilder builder, NodeVariable p1, NodeVariable p2, NodeVariable p3, NodeVariable p4); +} diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationBuilderImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationBuilderImpl.java index 4371cc03..a91f6870 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationBuilderImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationBuilderImpl.java @@ -7,13 +7,13 @@ package tools.refinery.store.dse.transition.internal; import tools.refinery.store.adapter.AbstractModelAdapterBuilder; import tools.refinery.store.dse.transition.DesignSpaceExplorationBuilder; -import tools.refinery.store.dse.transition.TransformationRule; +import tools.refinery.store.dse.transition.Rule; import tools.refinery.store.dse.transition.objectives.Criterion; import tools.refinery.store.dse.transition.objectives.Objective; import tools.refinery.store.model.ModelStore; import tools.refinery.store.model.ModelStoreBuilder; +import tools.refinery.store.query.ModelQueryBuilder; -import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; @@ -21,13 +21,13 @@ public class DesignSpaceExplorationBuilderImpl extends AbstractModelAdapterBuilder implements DesignSpaceExplorationBuilder { - LinkedHashSet transformationRuleDefinitions = new LinkedHashSet<>(); + LinkedHashSet transformationRuleDefinitions = new LinkedHashSet<>(); LinkedHashSet accepts = new LinkedHashSet<>(); LinkedHashSet excludes = new LinkedHashSet<>(); LinkedHashSet objectives = new LinkedHashSet<>(); @Override - public DesignSpaceExplorationBuilder transformation(TransformationRule transformationRuleDefinition) { + public DesignSpaceExplorationBuilder transformation(Rule transformationRuleDefinition) { transformationRuleDefinitions.add(transformationRuleDefinition); return this; } @@ -53,23 +53,23 @@ public class DesignSpaceExplorationBuilderImpl @Override protected void doConfigure(ModelStoreBuilder storeBuilder) { - transformationRuleDefinitions.forEach(x -> x.doConfigure(storeBuilder)); - accepts.forEach(x -> x.doConfigure(storeBuilder)); - excludes.forEach(x -> x.doConfigure(storeBuilder)); - objectives.forEach(x -> x.doConfigure(storeBuilder)); + var queryEngine = storeBuilder.getAdapter(ModelQueryBuilder.class); + transformationRuleDefinitions.forEach(x -> queryEngine.query(x.getPrecondition())); + accepts.forEach(x -> x.configure(storeBuilder)); + excludes.forEach(x -> x.configure(storeBuilder)); + objectives.forEach(x -> x.configure(storeBuilder)); super.doConfigure(storeBuilder); } @Override protected DesignSpaceExplorationStoreAdapterImpl doBuild(ModelStore store) { - List transformationRuleDefinitiions1 = new ArrayList<>(transformationRuleDefinitions); - List accepts1 = new ArrayList<>(accepts); - List excludes1 = new ArrayList<>(excludes); - List objectives1 = new ArrayList<>(objectives); + List transformationRuleDefinitionsList = List.copyOf(transformationRuleDefinitions); + List acceptsList = List.copyOf(accepts); + List excludesList = List.copyOf(excludes); + List objectivesList = List.copyOf(objectives); - return new DesignSpaceExplorationStoreAdapterImpl(store, - transformationRuleDefinitiions1, accepts1, - excludes1, objectives1); + return new DesignSpaceExplorationStoreAdapterImpl(store, transformationRuleDefinitionsList, acceptsList, + excludesList, objectivesList); } } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationStoreAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationStoreAdapterImpl.java index 3319e148..bd85e7a6 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationStoreAdapterImpl.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/internal/DesignSpaceExplorationStoreAdapterImpl.java @@ -7,7 +7,7 @@ package tools.refinery.store.dse.transition.internal; import tools.refinery.store.dse.transition.DesignSpaceExplorationStoreAdapter; import tools.refinery.store.dse.transition.Transformation; -import tools.refinery.store.dse.transition.TransformationRule; +import tools.refinery.store.dse.transition.Rule; import tools.refinery.store.dse.transition.objectives.Criterion; import tools.refinery.store.dse.transition.objectives.CriterionCalculator; import tools.refinery.store.dse.transition.objectives.Objective; @@ -20,18 +20,16 @@ import java.util.List; public class DesignSpaceExplorationStoreAdapterImpl implements DesignSpaceExplorationStoreAdapter { protected final ModelStore store; - protected final List transformationRuleDefinitions; + protected final List ruleDefinitions; protected final List accepts; protected final List excludes; protected final List objectives; - public DesignSpaceExplorationStoreAdapterImpl(ModelStore store, - List transformationRuleDefinitions, - List accepts, List excludes, - List objectives) { + public DesignSpaceExplorationStoreAdapterImpl( + ModelStore store, List ruleDefinitions, List accepts, List excludes, + List objectives) { this.store = store; - - this.transformationRuleDefinitions = transformationRuleDefinitions; + this.ruleDefinitions = ruleDefinitions; this.accepts = accepts; this.excludes = excludes; this.objectives = objectives; @@ -44,25 +42,31 @@ public class DesignSpaceExplorationStoreAdapterImpl implements DesignSpaceExplor @Override public DesignSpaceExplorationAdapterImpl createModelAdapter(Model model) { - final List t = this.transformationRuleDefinitions.stream().map(x->x.prepare(model)).toList(); - final List a = this.accepts.stream().map(x->x.createCalculator(model)).toList(); - final List e = this.excludes.stream().map(x->x.createCalculator(model)).toList(); - final List o = this.objectives.stream().map(x->x.createCalculator(model)).toList(); + final List t = this.ruleDefinitions.stream() + .map(x -> new Transformation(model, x)) + .toList(); + final List a = this.accepts.stream().map(x -> x.createCalculator(model)).toList(); + final List e = this.excludes.stream().map(x -> x.createCalculator(model)).toList(); + final List o = this.objectives.stream().map(x -> x.createCalculator(model)).toList(); return new DesignSpaceExplorationAdapterImpl(model, this, t, a, e, o); } + @Override - public List getTransformations() { - return transformationRuleDefinitions; + public List getTransformations() { + return ruleDefinitions; } + @Override public List getAccepts() { return accepts; } + @Override public List getExcludes() { return excludes; } + @Override public List getObjectives() { return objectives; diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Criterion.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Criterion.java index 66ca6f5e..4365cf9c 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Criterion.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Criterion.java @@ -9,7 +9,7 @@ import tools.refinery.store.model.Model; import tools.refinery.store.model.ModelStoreBuilder; public interface Criterion { - default void doConfigure(ModelStoreBuilder storeBuilder) { + default void configure(ModelStoreBuilder storeBuilder) { } CriterionCalculator createCalculator(Model model); } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Objective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Objective.java index b5924455..d2476a2e 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Objective.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/Objective.java @@ -9,7 +9,7 @@ import tools.refinery.store.model.Model; import tools.refinery.store.model.ModelStoreBuilder; public interface Objective { - default void doConfigure(ModelStoreBuilder storeBuilder) { + default void configure(ModelStoreBuilder storeBuilder) { } ObjectiveCalculator createCalculator(Model model); } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java index e2260cca..8d0a56cf 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryCriteria.java @@ -37,8 +37,8 @@ public class QueryCriteria implements Criterion { } @Override - public void doConfigure(ModelStoreBuilder storeBuilder) { - Criterion.super.doConfigure(storeBuilder); + public void configure(ModelStoreBuilder storeBuilder) { + Criterion.super.configure(storeBuilder); storeBuilder.getAdapter(ModelQueryBuilder.class).query(query); } } diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryObjective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryObjective.java index dfddccfc..9553e0e0 100644 --- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryObjective.java +++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/objectives/QueryObjective.java @@ -37,8 +37,8 @@ public class QueryObjective implements Objective { } @Override - public void doConfigure(ModelStoreBuilder storeBuilder) { - Objective.super.doConfigure(storeBuilder); + public void configure(ModelStoreBuilder storeBuilder) { + Objective.super.configure(storeBuilder); storeBuilder.getAdapter(ModelQueryBuilder.class).query(objectiveFunction); } } -- cgit v1.2.3-54-g00ecf