From a128e05f18a101983d331d0819008740b521d6df Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Thu, 7 Sep 2023 18:04:42 +0200 Subject: feat: declarative DSE rules and model refinement --- .../scope/internal/LowerTypeScopePropagator.java | 40 ++++++++++++++++++---- .../store/reasoning/scope/internal/MultiView.java | 23 ------------- .../scope/internal/ScopePropagatorAdapterImpl.java | 22 ++++++++---- .../scope/internal/ScopePropagatorBuilderImpl.java | 11 ++---- .../scope/internal/TypeScopePropagator.java | 12 +++++-- .../scope/internal/UpperTypeScopePropagator.java | 9 ++--- 6 files changed, 67 insertions(+), 50 deletions(-) delete mode 100644 subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/MultiView.java (limited to 'subprojects/store-reasoning-scope/src/main/java/tools') diff --git a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/LowerTypeScopePropagator.java b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/LowerTypeScopePropagator.java index b1c421b7..393c4b72 100644 --- a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/LowerTypeScopePropagator.java +++ b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/LowerTypeScopePropagator.java @@ -5,43 +5,55 @@ */ package tools.refinery.store.reasoning.scope.internal; +import tools.refinery.store.dse.transition.DesignSpaceExplorationBuilder; +import tools.refinery.store.dse.transition.objectives.Criteria; +import tools.refinery.store.dse.transition.objectives.Objectives; +import tools.refinery.store.model.ModelStoreBuilder; import tools.refinery.store.query.dnf.AnyQuery; import tools.refinery.store.query.dnf.Query; import tools.refinery.store.query.dnf.RelationalQuery; +import tools.refinery.store.query.term.Variable; +import tools.refinery.store.reasoning.ReasoningBuilder; +import tools.refinery.store.reasoning.literal.CountCandidateLowerBoundLiteral; import tools.refinery.store.reasoning.representation.PartialRelation; import java.util.Collection; import java.util.List; +import static tools.refinery.store.query.literal.Literals.check; +import static tools.refinery.store.query.term.int_.IntTerms.*; import static tools.refinery.store.reasoning.literal.PartialLiterals.may; +import static tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator.MULTI_VIEW; class LowerTypeScopePropagator extends TypeScopePropagator { private final int lowerBound; private LowerTypeScopePropagator(ScopePropagatorAdapterImpl adapter, int lowerBound, RelationalQuery allQuery, - RelationalQuery multiQuery) { + RelationalQuery multiQuery) { super(adapter, allQuery, multiQuery); this.lowerBound = lowerBound; } @Override public void updateBounds() { - constraint.setLb(lowerBound - getSingleCount()); + constraint.setLb((lowerBound - getSingleCount())); } - public static class Factory implements TypeScopePropagator.Factory { + public static class Factory extends TypeScopePropagator.Factory { + private final PartialRelation type; private final int lowerBound; private final RelationalQuery allMay; private final RelationalQuery multiMay; - public Factory(RelationalQuery multi, PartialRelation type, int lowerBound) { + public Factory(PartialRelation type, int lowerBound) { + this.type = type; this.lowerBound = lowerBound; allMay = Query.of(type.name() + "#may", (builder, instance) -> builder.clause( may(type.call(instance)) )); multiMay = Query.of(type.name() + "#multiMay", (builder, instance) -> builder.clause( may(type.call(instance)), - multi.call(instance) + MULTI_VIEW.call(instance) )); } @@ -51,8 +63,24 @@ class LowerTypeScopePropagator extends TypeScopePropagator { } @Override - public Collection getQueries() { + protected Collection getQueries() { return List.of(allMay, multiMay); } + + @Override + public void configure(ModelStoreBuilder storeBuilder) { + super.configure(storeBuilder); + + var requiredObjects = Query.of(type.name() + "#required", Integer.class, (builder, output) -> builder + .clause(Integer.class, currentCount -> List.of( + new CountCandidateLowerBoundLiteral(currentCount, type, List.of(Variable.of())), + output.assign(sub(currentCount, constant(lowerBound))), + check(greater(currentCount, constant(0))) + ))); + + storeBuilder.getAdapter(ReasoningBuilder.class).objective(Objectives.value(requiredObjects)); + storeBuilder.tryGetAdapter(DesignSpaceExplorationBuilder.class).ifPresent(dseBuilder -> + dseBuilder.accept(Criteria.whenNoMatch(requiredObjects))); + } } } diff --git a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/MultiView.java b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/MultiView.java deleted file mode 100644 index cea4e07d..00000000 --- a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/MultiView.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 The Refinery Authors - * - * SPDX-License-Identifier: EPL-2.0 - */ -package tools.refinery.store.reasoning.scope.internal; - -import tools.refinery.store.query.view.TuplePreservingView; -import tools.refinery.store.representation.Symbol; -import tools.refinery.store.representation.cardinality.CardinalityInterval; -import tools.refinery.store.representation.cardinality.CardinalityIntervals; -import tools.refinery.store.tuple.Tuple; - -class MultiView extends TuplePreservingView { - protected MultiView(Symbol symbol) { - super(symbol, "multi"); - } - - @Override - protected boolean doFilter(Tuple key, CardinalityInterval value) { - return !CardinalityIntervals.ONE.equals(value); - } -} diff --git a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/ScopePropagatorAdapterImpl.java b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/ScopePropagatorAdapterImpl.java index c257df6b..99c501ce 100644 --- a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/ScopePropagatorAdapterImpl.java +++ b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/ScopePropagatorAdapterImpl.java @@ -85,12 +85,7 @@ class ScopePropagatorAdapterImpl implements ScopePropagatorAdapter { int nodeId = key.get(0); if ((toValue == null || toValue.equals(CardinalityIntervals.ONE))) { if (fromValue != null && !fromValue.equals(CardinalityIntervals.ONE)) { - var variable = variables.get(nodeId); - if (variable == null || !activeVariables.remove(nodeId)) { - throw new AssertionError("Variable not active: " + nodeId); - } - variable.setBounds(0, 0); - markAsChanged(); + removeActiveVariable(toValue, nodeId); } return; } @@ -115,6 +110,21 @@ class ScopePropagatorAdapterImpl implements ScopePropagatorAdapter { } } + private void removeActiveVariable(CardinalityInterval toValue, int nodeId) { + var variable = variables.get(nodeId); + if (variable == null || !activeVariables.remove(nodeId)) { + throw new AssertionError("Variable not active: " + nodeId); + } + if (toValue == null) { + variable.setBounds(0, 0); + } else { + // Until queries are flushed and the constraints can be properly updated, + // the variable corresponding to the (previous) multi-object has to stand in for a single object. + variable.setBounds(1, 1); + } + markAsChanged(); + } + MPConstraint makeConstraint() { return solver.makeConstraint(); } diff --git a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/ScopePropagatorBuilderImpl.java b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/ScopePropagatorBuilderImpl.java index 11ca7381..531a7440 100644 --- a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/ScopePropagatorBuilderImpl.java +++ b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/ScopePropagatorBuilderImpl.java @@ -9,8 +9,6 @@ import com.google.ortools.Loader; import tools.refinery.store.adapter.AbstractModelAdapterBuilder; import tools.refinery.store.model.ModelStore; import tools.refinery.store.model.ModelStoreBuilder; -import tools.refinery.store.query.ModelQueryBuilder; -import tools.refinery.store.query.dnf.Query; import tools.refinery.store.reasoning.representation.PartialRelation; import tools.refinery.store.reasoning.scope.ScopePropagatorBuilder; import tools.refinery.store.reasoning.scope.ScopePropagatorStoreAdapter; @@ -60,25 +58,22 @@ public class ScopePropagatorBuilderImpl extends AbstractModelAdapterBuilder builder.clause( - new MultiView(countSymbol).call(instance))); typeScopePropagatorFactories = new ArrayList<>(scopes.size()); for (var entry : scopes.entrySet()) { var type = entry.getKey(); var bounds = entry.getValue(); if (bounds.lowerBound() > 0) { - var lowerFactory = new LowerTypeScopePropagator.Factory(multiQuery, type, bounds.lowerBound()); + var lowerFactory = new LowerTypeScopePropagator.Factory(type, bounds.lowerBound()); typeScopePropagatorFactories.add(lowerFactory); } if (bounds.upperBound() instanceof FiniteUpperCardinality finiteUpperCardinality) { - var upperFactory = new UpperTypeScopePropagator.Factory(multiQuery, type, + var upperFactory = new UpperTypeScopePropagator.Factory(type, finiteUpperCardinality.finiteUpperBound()); typeScopePropagatorFactories.add(upperFactory); } } - var queryBuilder = storeBuilder.getAdapter(ModelQueryBuilder.class); for (var factory : typeScopePropagatorFactories) { - queryBuilder.queries(factory.getQueries()); + factory.configure(storeBuilder); } } diff --git a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/TypeScopePropagator.java b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/TypeScopePropagator.java index 98f6ed8b..cfb95829 100644 --- a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/TypeScopePropagator.java +++ b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/TypeScopePropagator.java @@ -6,7 +6,9 @@ package tools.refinery.store.reasoning.scope.internal; import com.google.ortools.linearsolver.MPConstraint; +import tools.refinery.store.model.ModelStoreBuilder; import tools.refinery.store.query.ModelQueryAdapter; +import tools.refinery.store.query.ModelQueryBuilder; import tools.refinery.store.query.dnf.AnyQuery; import tools.refinery.store.query.dnf.RelationalQuery; import tools.refinery.store.query.resultset.ResultSet; @@ -53,9 +55,13 @@ abstract class TypeScopePropagator { adapter.markAsChanged(); } - interface Factory { - TypeScopePropagator createPropagator(ScopePropagatorAdapterImpl adapter); + public abstract static class Factory { + public abstract TypeScopePropagator createPropagator(ScopePropagatorAdapterImpl adapter); - Collection getQueries(); + protected abstract Collection getQueries(); + + public void configure(ModelStoreBuilder storeBuilder) { + storeBuilder.getAdapter(ModelQueryBuilder.class).queries(getQueries()); + } } } diff --git a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/UpperTypeScopePropagator.java b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/UpperTypeScopePropagator.java index 9f09ed56..a0be0fb4 100644 --- a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/UpperTypeScopePropagator.java +++ b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/internal/UpperTypeScopePropagator.java @@ -14,6 +14,7 @@ import java.util.Collection; import java.util.List; import static tools.refinery.store.reasoning.literal.PartialLiterals.must; +import static tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator.MULTI_VIEW; class UpperTypeScopePropagator extends TypeScopePropagator { private final int upperBound; @@ -29,19 +30,19 @@ class UpperTypeScopePropagator extends TypeScopePropagator { constraint.setUb(upperBound - getSingleCount()); } - public static class Factory implements TypeScopePropagator.Factory { + public static class Factory extends TypeScopePropagator.Factory { private final int upperBound; private final RelationalQuery allMust; private final RelationalQuery multiMust; - public Factory(RelationalQuery multi, PartialRelation type, int upperBound) { + public Factory(PartialRelation type, int upperBound) { this.upperBound = upperBound; allMust = Query.of(type.name() + "#must", (builder, instance) -> builder.clause( must(type.call(instance)) )); multiMust = Query.of(type.name() + "#multiMust", (builder, instance) -> builder.clause( must(type.call(instance)), - multi.call(instance) + MULTI_VIEW.call(instance) )); } @@ -51,7 +52,7 @@ class UpperTypeScopePropagator extends TypeScopePropagator { } @Override - public Collection getQueries() { + protected Collection getQueries() { return List.of(allMust, multiMust); } } -- cgit v1.2.3-70-g09d2