aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-reasoning-scope/src
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/store-reasoning-scope/src')
-rw-r--r--subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/LowerTypeScopePropagator.java17
-rw-r--r--subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/TypeScopePropagator.java2
-rw-r--r--subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/UpperTypeScopePropagator.java37
-rw-r--r--subprojects/store-reasoning-scope/src/test/java/tools/refinery/store/reasoning/scope/PredicateScopeTest.java157
4 files changed, 208 insertions, 5 deletions
diff --git a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/LowerTypeScopePropagator.java b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/LowerTypeScopePropagator.java
index 2be92464..702e570f 100644
--- a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/LowerTypeScopePropagator.java
+++ b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/LowerTypeScopePropagator.java
@@ -13,9 +13,12 @@ import tools.refinery.store.query.dnf.AnyQuery;
13import tools.refinery.store.query.dnf.Query; 13import tools.refinery.store.query.dnf.Query;
14import tools.refinery.store.query.dnf.RelationalQuery; 14import tools.refinery.store.query.dnf.RelationalQuery;
15import tools.refinery.store.query.term.Variable; 15import tools.refinery.store.query.term.Variable;
16import tools.refinery.store.query.term.uppercardinality.UpperCardinalityTerms;
16import tools.refinery.store.reasoning.ReasoningBuilder; 17import tools.refinery.store.reasoning.ReasoningBuilder;
17import tools.refinery.store.reasoning.literal.CountCandidateLowerBoundLiteral; 18import tools.refinery.store.reasoning.literal.CountCandidateLowerBoundLiteral;
19import tools.refinery.store.reasoning.literal.CountUpperBoundLiteral;
18import tools.refinery.store.reasoning.representation.PartialRelation; 20import tools.refinery.store.reasoning.representation.PartialRelation;
21import tools.refinery.store.representation.cardinality.UpperCardinality;
19 22
20import java.util.Collection; 23import java.util.Collection;
21import java.util.List; 24import java.util.List;
@@ -39,7 +42,7 @@ class LowerTypeScopePropagator extends TypeScopePropagator {
39 constraint.setLb((lowerBound - getSingleCount())); 42 constraint.setLb((lowerBound - getSingleCount()));
40 } 43 }
41 44
42 public static class Factory extends TypeScopePropagator.Factory { 45 static class Factory extends TypeScopePropagator.Factory {
43 private final PartialRelation type; 46 private final PartialRelation type;
44 private final int lowerBound; 47 private final int lowerBound;
45 private final RelationalQuery allMay; 48 private final RelationalQuery allMay;
@@ -77,10 +80,18 @@ class LowerTypeScopePropagator extends TypeScopePropagator {
77 output.assign(sub(constant(lowerBound), candidateLowerBound)), 80 output.assign(sub(constant(lowerBound), candidateLowerBound)),
78 check(greater(output, constant(0))) 81 check(greater(output, constant(0)))
79 ))); 82 )));
83 var tooFewObjects = Query.of(type.name() + "#tooFew", builder -> builder
84 .clause(UpperCardinality.class, upperBound -> List.of(
85 new CountUpperBoundLiteral(upperBound, type, List.of(Variable.of())),
86 check(UpperCardinalityTerms.less(upperBound,
87 UpperCardinalityTerms.constant(UpperCardinality.of(lowerBound))))
88 )));
80 89
81 storeBuilder.getAdapter(ReasoningBuilder.class).objective(Objectives.value(requiredObjects)); 90 storeBuilder.getAdapter(ReasoningBuilder.class).objective(Objectives.value(requiredObjects));
82 storeBuilder.tryGetAdapter(DesignSpaceExplorationBuilder.class).ifPresent(dseBuilder -> 91 storeBuilder.tryGetAdapter(DesignSpaceExplorationBuilder.class).ifPresent(dseBuilder -> {
83 dseBuilder.accept(Criteria.whenNoMatch(requiredObjects))); 92 dseBuilder.accept(Criteria.whenNoMatch(requiredObjects));
93 dseBuilder.exclude(Criteria.whenHasMatch(tooFewObjects));
94 });
84 } 95 }
85 } 96 }
86} 97}
diff --git a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/TypeScopePropagator.java b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/TypeScopePropagator.java
index bb50656b..193c132c 100644
--- a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/TypeScopePropagator.java
+++ b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/TypeScopePropagator.java
@@ -59,7 +59,7 @@ abstract class TypeScopePropagator {
59 adapter.markAsChanged(); 59 adapter.markAsChanged();
60 } 60 }
61 61
62 public abstract static class Factory { 62 abstract static class Factory {
63 public abstract TypeScopePropagator createPropagator(BoundScopePropagator adapter); 63 public abstract TypeScopePropagator createPropagator(BoundScopePropagator adapter);
64 64
65 protected abstract Collection<AnyQuery> getQueries(); 65 protected abstract Collection<AnyQuery> getQueries();
diff --git a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/UpperTypeScopePropagator.java b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/UpperTypeScopePropagator.java
index 4aba5aac..b2f8d39b 100644
--- a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/UpperTypeScopePropagator.java
+++ b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/UpperTypeScopePropagator.java
@@ -5,14 +5,24 @@
5 */ 5 */
6package tools.refinery.store.reasoning.scope; 6package tools.refinery.store.reasoning.scope;
7 7
8import tools.refinery.store.dse.transition.DesignSpaceExplorationBuilder;
9import tools.refinery.store.dse.transition.objectives.Criteria;
10import tools.refinery.store.dse.transition.objectives.Objectives;
11import tools.refinery.store.model.ModelStoreBuilder;
8import tools.refinery.store.query.dnf.AnyQuery; 12import tools.refinery.store.query.dnf.AnyQuery;
9import tools.refinery.store.query.dnf.Query; 13import tools.refinery.store.query.dnf.Query;
10import tools.refinery.store.query.dnf.RelationalQuery; 14import tools.refinery.store.query.dnf.RelationalQuery;
15import tools.refinery.store.query.term.Variable;
16import tools.refinery.store.reasoning.ReasoningBuilder;
17import tools.refinery.store.reasoning.literal.CountCandidateUpperBoundLiteral;
18import tools.refinery.store.reasoning.literal.CountLowerBoundLiteral;
11import tools.refinery.store.reasoning.representation.PartialRelation; 19import tools.refinery.store.reasoning.representation.PartialRelation;
12 20
13import java.util.Collection; 21import java.util.Collection;
14import java.util.List; 22import java.util.List;
15 23
24import static tools.refinery.store.query.literal.Literals.check;
25import static tools.refinery.store.query.term.int_.IntTerms.*;
16import static tools.refinery.store.reasoning.literal.PartialLiterals.must; 26import static tools.refinery.store.reasoning.literal.PartialLiterals.must;
17import static tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator.MULTI_VIEW; 27import static tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator.MULTI_VIEW;
18 28
@@ -30,12 +40,14 @@ class UpperTypeScopePropagator extends TypeScopePropagator {
30 constraint.setUb((upperBound - getSingleCount())); 40 constraint.setUb((upperBound - getSingleCount()));
31 } 41 }
32 42
33 public static class Factory extends TypeScopePropagator.Factory { 43 static class Factory extends TypeScopePropagator.Factory {
44 private final PartialRelation type;
34 private final int upperBound; 45 private final int upperBound;
35 private final RelationalQuery allMust; 46 private final RelationalQuery allMust;
36 private final RelationalQuery multiMust; 47 private final RelationalQuery multiMust;
37 48
38 public Factory(PartialRelation type, int upperBound) { 49 public Factory(PartialRelation type, int upperBound) {
50 this.type = type;
39 this.upperBound = upperBound; 51 this.upperBound = upperBound;
40 allMust = Query.of(type.name() + "#must", (builder, instance) -> builder.clause( 52 allMust = Query.of(type.name() + "#must", (builder, instance) -> builder.clause(
41 must(type.call(instance)) 53 must(type.call(instance))
@@ -55,5 +67,28 @@ class UpperTypeScopePropagator extends TypeScopePropagator {
55 protected Collection<AnyQuery> getQueries() { 67 protected Collection<AnyQuery> getQueries() {
56 return List.of(allMust, multiMust); 68 return List.of(allMust, multiMust);
57 } 69 }
70
71 @Override
72 public void configure(ModelStoreBuilder storeBuilder) {
73 super.configure(storeBuilder);
74
75 var excessObjects = Query.of(type.name() + "#excess", Integer.class, (builder, output) -> builder
76 .clause(Integer.class, candidateUpperBound -> List.of(
77 new CountCandidateUpperBoundLiteral(candidateUpperBound, type, List.of(Variable.of())),
78 output.assign(sub(candidateUpperBound, constant(upperBound))),
79 check(greater(output, constant(0)))
80 )));
81 var tooManyObjects = Query.of(type.name() + "#tooMany", builder -> builder
82 .clause(Integer.class, lowerBound -> List.of(
83 new CountLowerBoundLiteral(lowerBound, type, List.of(Variable.of())),
84 check(greater(lowerBound, constant(upperBound)))
85 )));
86
87 storeBuilder.getAdapter(ReasoningBuilder.class).objective(Objectives.value(excessObjects));
88 storeBuilder.tryGetAdapter(DesignSpaceExplorationBuilder.class).ifPresent(dseBuilder -> {
89 dseBuilder.accept(Criteria.whenNoMatch(excessObjects));
90 dseBuilder.exclude(Criteria.whenHasMatch(tooManyObjects));
91 });
92 }
58 } 93 }
59} 94}
diff --git a/subprojects/store-reasoning-scope/src/test/java/tools/refinery/store/reasoning/scope/PredicateScopeTest.java b/subprojects/store-reasoning-scope/src/test/java/tools/refinery/store/reasoning/scope/PredicateScopeTest.java
new file mode 100644
index 00000000..a2c56a6b
--- /dev/null
+++ b/subprojects/store-reasoning-scope/src/test/java/tools/refinery/store/reasoning/scope/PredicateScopeTest.java
@@ -0,0 +1,157 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.reasoning.scope;
7
8import org.junit.jupiter.api.Tag;
9import org.junit.jupiter.api.Test;
10import org.junit.jupiter.params.ParameterizedTest;
11import org.junit.jupiter.params.provider.ValueSource;
12import tools.refinery.store.dse.propagation.PropagationAdapter;
13import tools.refinery.store.dse.strategy.BestFirstStoreManager;
14import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
15import tools.refinery.store.model.ModelStore;
16import tools.refinery.store.query.dnf.Query;
17import tools.refinery.store.query.interpreter.QueryInterpreterAdapter;
18import tools.refinery.store.query.term.Variable;
19import tools.refinery.store.reasoning.ReasoningAdapter;
20import tools.refinery.store.reasoning.ReasoningStoreAdapter;
21import tools.refinery.store.reasoning.interpretation.PartialInterpretation;
22import tools.refinery.store.reasoning.literal.Concreteness;
23import tools.refinery.store.reasoning.representation.PartialRelation;
24import tools.refinery.store.reasoning.seed.ModelSeed;
25import tools.refinery.store.reasoning.translator.PartialRelationTranslator;
26import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator;
27import tools.refinery.store.reasoning.translator.metamodel.Metamodel;
28import tools.refinery.store.reasoning.translator.metamodel.MetamodelTranslator;
29import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator;
30import tools.refinery.store.reasoning.translator.multiplicity.ConstrainedMultiplicity;
31import tools.refinery.store.representation.TruthValue;
32import tools.refinery.store.representation.cardinality.CardinalityIntervals;
33import tools.refinery.store.statecoding.StateCoderAdapter;
34import tools.refinery.store.tuple.Tuple;
35
36import static org.hamcrest.MatcherAssert.assertThat;
37import static org.hamcrest.Matchers.is;
38import static tools.refinery.store.query.literal.Literals.not;
39
40class PredicateScopeTest {
41 private static final PartialRelation index = new PartialRelation("Index", 1);
42 private static final PartialRelation next = new PartialRelation("next", 2);
43 private static final PartialRelation nextInvalidMultiplicity = new PartialRelation("next::invalidMultiplicity", 1);
44 private static final PartialRelation prev = new PartialRelation("prev", 2);
45 private static final PartialRelation prevInvalidMultiplicity = new PartialRelation("prev::invalidMultiplicity", 1);
46 private static final PartialRelation loop = new PartialRelation("loop", 1);
47 private static final PartialRelation first = new PartialRelation("first", 1);
48 private static final PartialRelation last = new PartialRelation("last", 1);
49
50 @Tag("slow")
51 @ParameterizedTest
52 @ValueSource(ints = {1, 2, 3, 4, 5})
53 void generateTest(int randomSeed) {
54 var store = createStore();
55 var newIndex = Tuple.of(0);
56 var modelSeed = ModelSeed.builder(1)
57 .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder
58 .reducedValue(CardinalityIntervals.ONE)
59 .put(newIndex, CardinalityIntervals.SET))
60 .seed(ContainmentHierarchyTranslator.CONTAINED_SYMBOL,
61 builder -> builder.reducedValue(TruthValue.UNKNOWN))
62 .seed(index, builder -> builder
63 .reducedValue(TruthValue.UNKNOWN)
64 .put(newIndex, TruthValue.TRUE))
65 .seed(next, builder -> builder.reducedValue(TruthValue.UNKNOWN))
66 .seed(prev, builder -> builder.reducedValue(TruthValue.UNKNOWN))
67 .build();
68 var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed);
69 var initialVersion = model.commit();
70 var bestFistSearch = new BestFirstStoreManager(store, 1);
71 bestFistSearch.startExploration(initialVersion, randomSeed);
72 model.restore(bestFistSearch.getSolutionStore().getSolutions().get(0).version());
73 var reasoningAdapter = model.getAdapter(ReasoningAdapter.class);
74 var firstInterpretation = reasoningAdapter.getPartialInterpretation(Concreteness.CANDIDATE, first);
75 assertSize(firstInterpretation, 1);
76 var lastInterpretation = reasoningAdapter.getPartialInterpretation(Concreteness.CANDIDATE, last);
77 assertSize(lastInterpretation, 1);
78 }
79
80 @Test
81 void invalidResultTest() {
82 var store = createStore();
83 var modelSeed = ModelSeed.builder(8)
84 .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder.reducedValue(CardinalityIntervals.ONE))
85 .seed(ContainmentHierarchyTranslator.CONTAINED_SYMBOL,
86 builder -> builder.reducedValue(TruthValue.UNKNOWN))
87 .seed(ContainmentHierarchyTranslator.CONTAINS_SYMBOL,
88 builder -> builder.reducedValue(TruthValue.UNKNOWN))
89 .seed(index, builder -> builder.reducedValue(TruthValue.TRUE))
90 .seed(next, builder -> builder
91 .reducedValue(TruthValue.UNKNOWN)
92 .put(Tuple.of(1, 2), TruthValue.TRUE)
93 .put(Tuple.of(2, 3), TruthValue.TRUE)
94 .put(Tuple.of(3, 4), TruthValue.TRUE)
95 .put(Tuple.of(4, 5), TruthValue.TRUE)
96 .put(Tuple.of(6, 1), TruthValue.TRUE))
97 .seed(prev, builder -> builder.reducedValue(TruthValue.UNKNOWN))
98 .build();
99 var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed);
100 var reasoningAdapter = model.getAdapter(ReasoningAdapter.class);
101 var firstInterpretation = reasoningAdapter.getPartialInterpretation(Concreteness.CANDIDATE, first);
102 assertSize(firstInterpretation, 3);
103 var lastInterpretation = reasoningAdapter.getPartialInterpretation(Concreteness.CANDIDATE, last);
104 assertSize(lastInterpretation, 3);
105 var designSpaceAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
106 assertThat(designSpaceAdapter.checkAccept(), is(false));
107 }
108
109 private ModelStore createStore() {
110 var metamodel = Metamodel.builder()
111 .type(index)
112 .reference(next, index, false,
113 ConstrainedMultiplicity.of(CardinalityIntervals.LONE, nextInvalidMultiplicity), index, prev)
114 .reference(prev, index, false,
115 ConstrainedMultiplicity.of(CardinalityIntervals.LONE, prevInvalidMultiplicity), index, next)
116 .build();
117 return ModelStore.builder()
118 .with(QueryInterpreterAdapter.builder())
119 .with(StateCoderAdapter.builder())
120 .with(PropagationAdapter.builder())
121 .with(DesignSpaceExplorationAdapter.builder())
122 .with(ReasoningAdapter.builder())
123 .with(new MultiObjectTranslator())
124 .with(new MetamodelTranslator(metamodel))
125 .with(PartialRelationTranslator.of(loop)
126 .query(Query.of("loop", (builder, p1) -> builder.clause(
127 index.call(p1),
128 next.callTransitive(p1, p1)
129 )))
130 .mayNever())
131 .with(PartialRelationTranslator.of(first)
132 .query(Query.of("first", (builder, p1) -> builder.clause(
133 index.call(p1),
134 not(prev.call(p1, Variable.of()))
135 ))))
136 .with(PartialRelationTranslator.of(last)
137 .query(Query.of("last", (builder, p1) -> builder.clause(
138 index.call(p1),
139 not(next.call(p1, Variable.of()))
140 ))))
141 .with(new ScopePropagator()
142 .scope(index, CardinalityIntervals.exactly(8))
143 .scope(first, CardinalityIntervals.ONE)
144 .scope(last, CardinalityIntervals.ONE))
145 .build();
146 }
147
148 private void assertSize(PartialInterpretation<TruthValue, Boolean> partialInterpretation, int expected) {
149 int size = 0;
150 var cursor = partialInterpretation.getAll();
151 while (cursor.move()) {
152 assertThat(cursor.getValue(), is(TruthValue.TRUE));
153 size++;
154 }
155 assertThat(size, is(expected));
156 }
157}