diff options
author | Kristóf Marussy <kristof@marussy.com> | 2023-09-07 18:04:42 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2023-09-07 18:04:42 +0200 |
commit | a128e05f18a101983d331d0819008740b521d6df (patch) | |
tree | cc23c330eea900ab7b513a6c21a241ebf0795785 /subprojects/store-reasoning-scope | |
parent | feat(dse): transformation rule builder (diff) | |
download | refinery-a128e05f18a101983d331d0819008740b521d6df.tar.gz refinery-a128e05f18a101983d331d0819008740b521d6df.tar.zst refinery-a128e05f18a101983d331d0819008740b521d6df.zip |
feat: declarative DSE rules and model refinement
Diffstat (limited to 'subprojects/store-reasoning-scope')
6 files changed, 67 insertions, 50 deletions
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 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.reasoning.scope.internal; | 6 | package tools.refinery.store.reasoning.scope.internal; |
7 | 7 | ||
8 | import tools.refinery.store.dse.transition.DesignSpaceExplorationBuilder; | ||
9 | import tools.refinery.store.dse.transition.objectives.Criteria; | ||
10 | import tools.refinery.store.dse.transition.objectives.Objectives; | ||
11 | import tools.refinery.store.model.ModelStoreBuilder; | ||
8 | import tools.refinery.store.query.dnf.AnyQuery; | 12 | import tools.refinery.store.query.dnf.AnyQuery; |
9 | import tools.refinery.store.query.dnf.Query; | 13 | import tools.refinery.store.query.dnf.Query; |
10 | import tools.refinery.store.query.dnf.RelationalQuery; | 14 | import tools.refinery.store.query.dnf.RelationalQuery; |
15 | import tools.refinery.store.query.term.Variable; | ||
16 | import tools.refinery.store.reasoning.ReasoningBuilder; | ||
17 | import tools.refinery.store.reasoning.literal.CountCandidateLowerBoundLiteral; | ||
11 | import tools.refinery.store.reasoning.representation.PartialRelation; | 18 | import tools.refinery.store.reasoning.representation.PartialRelation; |
12 | 19 | ||
13 | import java.util.Collection; | 20 | import java.util.Collection; |
14 | import java.util.List; | 21 | import java.util.List; |
15 | 22 | ||
23 | import static tools.refinery.store.query.literal.Literals.check; | ||
24 | import static tools.refinery.store.query.term.int_.IntTerms.*; | ||
16 | import static tools.refinery.store.reasoning.literal.PartialLiterals.may; | 25 | import static tools.refinery.store.reasoning.literal.PartialLiterals.may; |
26 | import static tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator.MULTI_VIEW; | ||
17 | 27 | ||
18 | class LowerTypeScopePropagator extends TypeScopePropagator { | 28 | class LowerTypeScopePropagator extends TypeScopePropagator { |
19 | private final int lowerBound; | 29 | private final int lowerBound; |
20 | 30 | ||
21 | private LowerTypeScopePropagator(ScopePropagatorAdapterImpl adapter, int lowerBound, RelationalQuery allQuery, | 31 | private LowerTypeScopePropagator(ScopePropagatorAdapterImpl adapter, int lowerBound, RelationalQuery allQuery, |
22 | RelationalQuery multiQuery) { | 32 | RelationalQuery multiQuery) { |
23 | super(adapter, allQuery, multiQuery); | 33 | super(adapter, allQuery, multiQuery); |
24 | this.lowerBound = lowerBound; | 34 | this.lowerBound = lowerBound; |
25 | } | 35 | } |
26 | 36 | ||
27 | @Override | 37 | @Override |
28 | public void updateBounds() { | 38 | public void updateBounds() { |
29 | constraint.setLb(lowerBound - getSingleCount()); | 39 | constraint.setLb((lowerBound - getSingleCount())); |
30 | } | 40 | } |
31 | 41 | ||
32 | public static class Factory implements TypeScopePropagator.Factory { | 42 | public static class Factory extends TypeScopePropagator.Factory { |
43 | private final PartialRelation type; | ||
33 | private final int lowerBound; | 44 | private final int lowerBound; |
34 | private final RelationalQuery allMay; | 45 | private final RelationalQuery allMay; |
35 | private final RelationalQuery multiMay; | 46 | private final RelationalQuery multiMay; |
36 | 47 | ||
37 | public Factory(RelationalQuery multi, PartialRelation type, int lowerBound) { | 48 | public Factory(PartialRelation type, int lowerBound) { |
49 | this.type = type; | ||
38 | this.lowerBound = lowerBound; | 50 | this.lowerBound = lowerBound; |
39 | allMay = Query.of(type.name() + "#may", (builder, instance) -> builder.clause( | 51 | allMay = Query.of(type.name() + "#may", (builder, instance) -> builder.clause( |
40 | may(type.call(instance)) | 52 | may(type.call(instance)) |
41 | )); | 53 | )); |
42 | multiMay = Query.of(type.name() + "#multiMay", (builder, instance) -> builder.clause( | 54 | multiMay = Query.of(type.name() + "#multiMay", (builder, instance) -> builder.clause( |
43 | may(type.call(instance)), | 55 | may(type.call(instance)), |
44 | multi.call(instance) | 56 | MULTI_VIEW.call(instance) |
45 | )); | 57 | )); |
46 | } | 58 | } |
47 | 59 | ||
@@ -51,8 +63,24 @@ class LowerTypeScopePropagator extends TypeScopePropagator { | |||
51 | } | 63 | } |
52 | 64 | ||
53 | @Override | 65 | @Override |
54 | public Collection<AnyQuery> getQueries() { | 66 | protected Collection<AnyQuery> getQueries() { |
55 | return List.of(allMay, multiMay); | 67 | return List.of(allMay, multiMay); |
56 | } | 68 | } |
69 | |||
70 | @Override | ||
71 | public void configure(ModelStoreBuilder storeBuilder) { | ||
72 | super.configure(storeBuilder); | ||
73 | |||
74 | var requiredObjects = Query.of(type.name() + "#required", Integer.class, (builder, output) -> builder | ||
75 | .clause(Integer.class, currentCount -> List.of( | ||
76 | new CountCandidateLowerBoundLiteral(currentCount, type, List.of(Variable.of())), | ||
77 | output.assign(sub(currentCount, constant(lowerBound))), | ||
78 | check(greater(currentCount, constant(0))) | ||
79 | ))); | ||
80 | |||
81 | storeBuilder.getAdapter(ReasoningBuilder.class).objective(Objectives.value(requiredObjects)); | ||
82 | storeBuilder.tryGetAdapter(DesignSpaceExplorationBuilder.class).ifPresent(dseBuilder -> | ||
83 | dseBuilder.accept(Criteria.whenNoMatch(requiredObjects))); | ||
84 | } | ||
57 | } | 85 | } |
58 | } | 86 | } |
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 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.reasoning.scope.internal; | ||
7 | |||
8 | import tools.refinery.store.query.view.TuplePreservingView; | ||
9 | import tools.refinery.store.representation.Symbol; | ||
10 | import tools.refinery.store.representation.cardinality.CardinalityInterval; | ||
11 | import tools.refinery.store.representation.cardinality.CardinalityIntervals; | ||
12 | import tools.refinery.store.tuple.Tuple; | ||
13 | |||
14 | class MultiView extends TuplePreservingView<CardinalityInterval> { | ||
15 | protected MultiView(Symbol<CardinalityInterval> symbol) { | ||
16 | super(symbol, "multi"); | ||
17 | } | ||
18 | |||
19 | @Override | ||
20 | protected boolean doFilter(Tuple key, CardinalityInterval value) { | ||
21 | return !CardinalityIntervals.ONE.equals(value); | ||
22 | } | ||
23 | } | ||
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 { | |||
85 | int nodeId = key.get(0); | 85 | int nodeId = key.get(0); |
86 | if ((toValue == null || toValue.equals(CardinalityIntervals.ONE))) { | 86 | if ((toValue == null || toValue.equals(CardinalityIntervals.ONE))) { |
87 | if (fromValue != null && !fromValue.equals(CardinalityIntervals.ONE)) { | 87 | if (fromValue != null && !fromValue.equals(CardinalityIntervals.ONE)) { |
88 | var variable = variables.get(nodeId); | 88 | removeActiveVariable(toValue, nodeId); |
89 | if (variable == null || !activeVariables.remove(nodeId)) { | ||
90 | throw new AssertionError("Variable not active: " + nodeId); | ||
91 | } | ||
92 | variable.setBounds(0, 0); | ||
93 | markAsChanged(); | ||
94 | } | 89 | } |
95 | return; | 90 | return; |
96 | } | 91 | } |
@@ -115,6 +110,21 @@ class ScopePropagatorAdapterImpl implements ScopePropagatorAdapter { | |||
115 | } | 110 | } |
116 | } | 111 | } |
117 | 112 | ||
113 | private void removeActiveVariable(CardinalityInterval toValue, int nodeId) { | ||
114 | var variable = variables.get(nodeId); | ||
115 | if (variable == null || !activeVariables.remove(nodeId)) { | ||
116 | throw new AssertionError("Variable not active: " + nodeId); | ||
117 | } | ||
118 | if (toValue == null) { | ||
119 | variable.setBounds(0, 0); | ||
120 | } else { | ||
121 | // Until queries are flushed and the constraints can be properly updated, | ||
122 | // the variable corresponding to the (previous) multi-object has to stand in for a single object. | ||
123 | variable.setBounds(1, 1); | ||
124 | } | ||
125 | markAsChanged(); | ||
126 | } | ||
127 | |||
118 | MPConstraint makeConstraint() { | 128 | MPConstraint makeConstraint() { |
119 | return solver.makeConstraint(); | 129 | return solver.makeConstraint(); |
120 | } | 130 | } |
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; | |||
9 | import tools.refinery.store.adapter.AbstractModelAdapterBuilder; | 9 | import tools.refinery.store.adapter.AbstractModelAdapterBuilder; |
10 | import tools.refinery.store.model.ModelStore; | 10 | import tools.refinery.store.model.ModelStore; |
11 | import tools.refinery.store.model.ModelStoreBuilder; | 11 | import tools.refinery.store.model.ModelStoreBuilder; |
12 | import tools.refinery.store.query.ModelQueryBuilder; | ||
13 | import tools.refinery.store.query.dnf.Query; | ||
14 | import tools.refinery.store.reasoning.representation.PartialRelation; | 12 | import tools.refinery.store.reasoning.representation.PartialRelation; |
15 | import tools.refinery.store.reasoning.scope.ScopePropagatorBuilder; | 13 | import tools.refinery.store.reasoning.scope.ScopePropagatorBuilder; |
16 | import tools.refinery.store.reasoning.scope.ScopePropagatorStoreAdapter; | 14 | import tools.refinery.store.reasoning.scope.ScopePropagatorStoreAdapter; |
@@ -60,25 +58,22 @@ public class ScopePropagatorBuilderImpl extends AbstractModelAdapterBuilder<Scop | |||
60 | 58 | ||
61 | @Override | 59 | @Override |
62 | protected void doConfigure(ModelStoreBuilder storeBuilder) { | 60 | protected void doConfigure(ModelStoreBuilder storeBuilder) { |
63 | var multiQuery = Query.of("MULTI", (builder, instance) -> builder.clause( | ||
64 | new MultiView(countSymbol).call(instance))); | ||
65 | typeScopePropagatorFactories = new ArrayList<>(scopes.size()); | 61 | typeScopePropagatorFactories = new ArrayList<>(scopes.size()); |
66 | for (var entry : scopes.entrySet()) { | 62 | for (var entry : scopes.entrySet()) { |
67 | var type = entry.getKey(); | 63 | var type = entry.getKey(); |
68 | var bounds = entry.getValue(); | 64 | var bounds = entry.getValue(); |
69 | if (bounds.lowerBound() > 0) { | 65 | if (bounds.lowerBound() > 0) { |
70 | var lowerFactory = new LowerTypeScopePropagator.Factory(multiQuery, type, bounds.lowerBound()); | 66 | var lowerFactory = new LowerTypeScopePropagator.Factory(type, bounds.lowerBound()); |
71 | typeScopePropagatorFactories.add(lowerFactory); | 67 | typeScopePropagatorFactories.add(lowerFactory); |
72 | } | 68 | } |
73 | if (bounds.upperBound() instanceof FiniteUpperCardinality finiteUpperCardinality) { | 69 | if (bounds.upperBound() instanceof FiniteUpperCardinality finiteUpperCardinality) { |
74 | var upperFactory = new UpperTypeScopePropagator.Factory(multiQuery, type, | 70 | var upperFactory = new UpperTypeScopePropagator.Factory(type, |
75 | finiteUpperCardinality.finiteUpperBound()); | 71 | finiteUpperCardinality.finiteUpperBound()); |
76 | typeScopePropagatorFactories.add(upperFactory); | 72 | typeScopePropagatorFactories.add(upperFactory); |
77 | } | 73 | } |
78 | } | 74 | } |
79 | var queryBuilder = storeBuilder.getAdapter(ModelQueryBuilder.class); | ||
80 | for (var factory : typeScopePropagatorFactories) { | 75 | for (var factory : typeScopePropagatorFactories) { |
81 | queryBuilder.queries(factory.getQueries()); | 76 | factory.configure(storeBuilder); |
82 | } | 77 | } |
83 | } | 78 | } |
84 | 79 | ||
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 @@ | |||
6 | package tools.refinery.store.reasoning.scope.internal; | 6 | package tools.refinery.store.reasoning.scope.internal; |
7 | 7 | ||
8 | import com.google.ortools.linearsolver.MPConstraint; | 8 | import com.google.ortools.linearsolver.MPConstraint; |
9 | import tools.refinery.store.model.ModelStoreBuilder; | ||
9 | import tools.refinery.store.query.ModelQueryAdapter; | 10 | import tools.refinery.store.query.ModelQueryAdapter; |
11 | import tools.refinery.store.query.ModelQueryBuilder; | ||
10 | import tools.refinery.store.query.dnf.AnyQuery; | 12 | import tools.refinery.store.query.dnf.AnyQuery; |
11 | import tools.refinery.store.query.dnf.RelationalQuery; | 13 | import tools.refinery.store.query.dnf.RelationalQuery; |
12 | import tools.refinery.store.query.resultset.ResultSet; | 14 | import tools.refinery.store.query.resultset.ResultSet; |
@@ -53,9 +55,13 @@ abstract class TypeScopePropagator { | |||
53 | adapter.markAsChanged(); | 55 | adapter.markAsChanged(); |
54 | } | 56 | } |
55 | 57 | ||
56 | interface Factory { | 58 | public abstract static class Factory { |
57 | TypeScopePropagator createPropagator(ScopePropagatorAdapterImpl adapter); | 59 | public abstract TypeScopePropagator createPropagator(ScopePropagatorAdapterImpl adapter); |
58 | 60 | ||
59 | Collection<AnyQuery> getQueries(); | 61 | protected abstract Collection<AnyQuery> getQueries(); |
62 | |||
63 | public void configure(ModelStoreBuilder storeBuilder) { | ||
64 | storeBuilder.getAdapter(ModelQueryBuilder.class).queries(getQueries()); | ||
65 | } | ||
60 | } | 66 | } |
61 | } | 67 | } |
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; | |||
14 | import java.util.List; | 14 | import java.util.List; |
15 | 15 | ||
16 | import static tools.refinery.store.reasoning.literal.PartialLiterals.must; | 16 | import static tools.refinery.store.reasoning.literal.PartialLiterals.must; |
17 | import static tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator.MULTI_VIEW; | ||
17 | 18 | ||
18 | class UpperTypeScopePropagator extends TypeScopePropagator { | 19 | class UpperTypeScopePropagator extends TypeScopePropagator { |
19 | private final int upperBound; | 20 | private final int upperBound; |
@@ -29,19 +30,19 @@ class UpperTypeScopePropagator extends TypeScopePropagator { | |||
29 | constraint.setUb(upperBound - getSingleCount()); | 30 | constraint.setUb(upperBound - getSingleCount()); |
30 | } | 31 | } |
31 | 32 | ||
32 | public static class Factory implements TypeScopePropagator.Factory { | 33 | public static class Factory extends TypeScopePropagator.Factory { |
33 | private final int upperBound; | 34 | private final int upperBound; |
34 | private final RelationalQuery allMust; | 35 | private final RelationalQuery allMust; |
35 | private final RelationalQuery multiMust; | 36 | private final RelationalQuery multiMust; |
36 | 37 | ||
37 | public Factory(RelationalQuery multi, PartialRelation type, int upperBound) { | 38 | public Factory(PartialRelation type, int upperBound) { |
38 | this.upperBound = upperBound; | 39 | this.upperBound = upperBound; |
39 | allMust = Query.of(type.name() + "#must", (builder, instance) -> builder.clause( | 40 | allMust = Query.of(type.name() + "#must", (builder, instance) -> builder.clause( |
40 | must(type.call(instance)) | 41 | must(type.call(instance)) |
41 | )); | 42 | )); |
42 | multiMust = Query.of(type.name() + "#multiMust", (builder, instance) -> builder.clause( | 43 | multiMust = Query.of(type.name() + "#multiMust", (builder, instance) -> builder.clause( |
43 | must(type.call(instance)), | 44 | must(type.call(instance)), |
44 | multi.call(instance) | 45 | MULTI_VIEW.call(instance) |
45 | )); | 46 | )); |
46 | } | 47 | } |
47 | 48 | ||
@@ -51,7 +52,7 @@ class UpperTypeScopePropagator extends TypeScopePropagator { | |||
51 | } | 52 | } |
52 | 53 | ||
53 | @Override | 54 | @Override |
54 | public Collection<AnyQuery> getQueries() { | 55 | protected Collection<AnyQuery> getQueries() { |
55 | return List.of(allMust, multiMust); | 56 | return List.of(allMust, multiMust); |
56 | } | 57 | } |
57 | } | 58 | } |