summaryrefslogtreecommitdiffstats
path: root/subprojects/store-reasoning/src/main
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-07-25 16:06:36 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-07-25 16:06:36 +0200
commit6a25ba145844c79d3507f8eabdbed854be2b8097 (patch)
tree0ea9d4c7a9b5b94a0d4341eaa25eeb7e4d3f4f56 /subprojects/store-reasoning/src/main
parentfeat: custom connected component RETE node (diff)
downloadrefinery-6a25ba145844c79d3507f8eabdbed854be2b8097.tar.gz
refinery-6a25ba145844c79d3507f8eabdbed854be2b8097.tar.zst
refinery-6a25ba145844c79d3507f8eabdbed854be2b8097.zip
feat: concrete count in partial models
Diffstat (limited to 'subprojects/store-reasoning/src/main')
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/PartialClauseRewriter.java93
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/ClauseLifter.java4
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ConcreteCountLiteral.java47
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/CountLowerBoundLiteral.java48
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/CountUpperBoundLiteral.java50
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/ModelSeed.java4
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/EqualsRelationRewriter.java3
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectInitializer.java33
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectTranslator.java27
9 files changed, 289 insertions, 20 deletions
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/PartialClauseRewriter.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/PartialClauseRewriter.java
index bc379c64..c560162e 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/PartialClauseRewriter.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/PartialClauseRewriter.java
@@ -5,17 +5,25 @@
5 */ 5 */
6package tools.refinery.store.reasoning.internal; 6package tools.refinery.store.reasoning.internal;
7 7
8import tools.refinery.store.query.Constraint;
8import tools.refinery.store.query.dnf.Dnf; 9import tools.refinery.store.query.dnf.Dnf;
9import tools.refinery.store.query.dnf.DnfClause; 10import tools.refinery.store.query.dnf.DnfClause;
10import tools.refinery.store.query.literal.AbstractCallLiteral; 11import tools.refinery.store.query.literal.AbstractCallLiteral;
12import tools.refinery.store.query.literal.CallPolarity;
11import tools.refinery.store.query.literal.Literal; 13import tools.refinery.store.query.literal.Literal;
14import tools.refinery.store.query.term.Aggregator;
15import tools.refinery.store.query.term.ConstantTerm;
16import tools.refinery.store.query.term.Term;
12import tools.refinery.store.query.term.Variable; 17import tools.refinery.store.query.term.Variable;
13import tools.refinery.store.reasoning.literal.Concreteness; 18import tools.refinery.store.query.term.int_.IntTerms;
14import tools.refinery.store.reasoning.literal.ModalConstraint; 19import tools.refinery.store.query.term.uppercardinality.UpperCardinalityTerms;
15import tools.refinery.store.reasoning.literal.Modality; 20import tools.refinery.store.reasoning.literal.*;
16import tools.refinery.store.reasoning.representation.PartialRelation; 21import tools.refinery.store.reasoning.representation.PartialRelation;
22import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator;
23import tools.refinery.store.representation.cardinality.UpperCardinalities;
17 24
18import java.util.*; 25import java.util.*;
26import java.util.function.BinaryOperator;
19 27
20class PartialClauseRewriter { 28class PartialClauseRewriter {
21 private final PartialQueryRewriter rewriter; 29 private final PartialQueryRewriter rewriter;
@@ -42,6 +50,14 @@ class PartialClauseRewriter {
42 markAsDone(literal); 50 markAsDone(literal);
43 return; 51 return;
44 } 52 }
53 if (callLiteral instanceof CountLowerBoundLiteral countLowerBoundLiteral) {
54 rewriteCountLowerBound(countLowerBoundLiteral);
55 return;
56 }
57 if (callLiteral instanceof CountUpperBoundLiteral countUpperBoundLiteral) {
58 rewriteCountUpperBound(countUpperBoundLiteral);
59 return;
60 }
45 var target = callLiteral.getTarget(); 61 var target = callLiteral.getTarget();
46 if (target instanceof Dnf dnf) { 62 if (target instanceof Dnf dnf) {
47 rewriteRecursively(callLiteral, dnf); 63 rewriteRecursively(callLiteral, dnf);
@@ -61,6 +77,75 @@ class PartialClauseRewriter {
61 } 77 }
62 } 78 }
63 79
80 private void rewriteCountLowerBound(CountLowerBoundLiteral literal) {
81 rewriteCount(literal, "lower", Modality.MUST, MultiObjectTranslator.LOWER_CARDINALITY_VIEW, 1, IntTerms::mul,
82 IntTerms.INT_SUM);
83 }
84
85 private void rewriteCountUpperBound(CountUpperBoundLiteral literal) {
86 rewriteCount(literal, "upper", Modality.MAY, MultiObjectTranslator.UPPER_CARDINALITY_VIEW,
87 UpperCardinalities.ONE, UpperCardinalityTerms::mul, UpperCardinalityTerms.UPPER_CARDINALITY_SUM);
88 }
89
90 private <T> void rewriteCount(ConcreteCountLiteral<T> literal, String name, Modality modality, Constraint view,
91 T one, BinaryOperator<Term<T>> mul, Aggregator<T, T> sum) {
92 var type = literal.getResultType();
93 var target = literal.getTarget();
94 var concreteness = literal.getConcreteness();
95 int arity = target.arity();
96 var parameters = target.getParameters();
97 var literalArguments = literal.getArguments();
98 var privateVariables = literal.getPrivateVariables(positiveVariables);
99
100 var builder = Dnf.builder("%s#%s#%s".formatted(target.name(), concreteness, name));
101 var rewrittenArguments = new ArrayList<Variable>(parameters.size());
102 var variablesToCount = new ArrayList<Variable>();
103 var helperArguments = new ArrayList<Variable>();
104 var literalToRewrittenArgumentMap = new HashMap<Variable, Variable>();
105 for (int i = 0; i < arity; i++) {
106 var literalArgument = literalArguments.get(i);
107 var parameter = parameters.get(i);
108 var rewrittenArgument = literalToRewrittenArgumentMap.computeIfAbsent(literalArgument, key -> {
109 helperArguments.add(key);
110 var newArgument = builder.parameter(parameter);
111 if (privateVariables.contains(key)) {
112 variablesToCount.add(newArgument);
113 }
114 return newArgument;
115 });
116 rewrittenArguments.add(rewrittenArgument);
117 }
118 var outputVariable = builder.parameter(type);
119
120 var literals = new ArrayList<Literal>();
121 literals.add(new ModalConstraint(modality, literal.getConcreteness(), target)
122 .call(CallPolarity.POSITIVE, rewrittenArguments));
123 switch (variablesToCount.size()) {
124 case 0 -> literals.add(outputVariable.assign(new ConstantTerm<>(type, one)));
125 case 1 -> literals.add(view.call(variablesToCount.get(0),
126 outputVariable));
127 default -> {
128 var firstCount = Variable.of(type);
129 literals.add(view.call(variablesToCount.get(0), firstCount));
130 int length = variablesToCount.size();
131 Term<T> accumulator = firstCount;
132 for (int i = 1; i < length; i++) {
133 var countVariable = Variable.of(type);
134 literals.add(view.call(variablesToCount.get(i), countVariable));
135 accumulator = mul.apply(accumulator, countVariable);
136 }
137 literals.add(outputVariable.assign(accumulator));
138 }
139 }
140 builder.clause(literals);
141
142 var helperQuery = builder.build();
143 var aggregationVariable = Variable.of(type);
144 helperArguments.add(aggregationVariable);
145 workList.addFirst(literal.getResultVariable().assign(helperQuery.aggregateBy(aggregationVariable, sum,
146 helperArguments)));
147 }
148
64 private void markAsDone(Literal literal) { 149 private void markAsDone(Literal literal) {
65 completedLiterals.add(literal); 150 completedLiterals.add(literal);
66 positiveVariables.addAll(literal.getOutputVariables()); 151 positiveVariables.addAll(literal.getOutputVariables());
@@ -75,7 +160,7 @@ class PartialClauseRewriter {
75 private void rewriteRecursively(AbstractCallLiteral callLiteral, Dnf dnf) { 160 private void rewriteRecursively(AbstractCallLiteral callLiteral, Dnf dnf) {
76 var rewrittenDnf = rewriter.rewrite(dnf); 161 var rewrittenDnf = rewriter.rewrite(dnf);
77 var rewrittenLiteral = callLiteral.withTarget(rewrittenDnf); 162 var rewrittenLiteral = callLiteral.withTarget(rewrittenDnf);
78 completedLiterals.add(rewrittenLiteral); 163 markAsDone(rewrittenLiteral);
79 } 164 }
80 165
81 private void rewrite(AbstractCallLiteral callLiteral, Modality modality, Concreteness concreteness, 166 private void rewrite(AbstractCallLiteral callLiteral, Modality modality, Concreteness concreteness,
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/ClauseLifter.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/ClauseLifter.java
index 89e948dc..17916c02 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/ClauseLifter.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/ClauseLifter.java
@@ -70,9 +70,9 @@ class ClauseLifter {
70 literal instanceof AssignLiteral<?> || 70 literal instanceof AssignLiteral<?> ||
71 literal instanceof CheckLiteral) { 71 literal instanceof CheckLiteral) {
72 return literal; 72 return literal;
73 } else if (literal instanceof CountLiteral) { 73 } else if (literal instanceof AbstractCountLiteral<?>) {
74 throw new IllegalArgumentException("Count literal %s cannot be lifted".formatted(literal)); 74 throw new IllegalArgumentException("Count literal %s cannot be lifted".formatted(literal));
75 } else if (literal instanceof AggregationLiteral<?,?>) { 75 } else if (literal instanceof AggregationLiteral<?, ?>) {
76 throw new IllegalArgumentException("Aggregation literal %s cannot be lifted".formatted(literal)); 76 throw new IllegalArgumentException("Aggregation literal %s cannot be lifted".formatted(literal));
77 } else if (literal instanceof RepresentativeElectionLiteral) { 77 } else if (literal instanceof RepresentativeElectionLiteral) {
78 throw new IllegalArgumentException("SCC literal %s cannot be lifted".formatted(literal)); 78 throw new IllegalArgumentException("SCC literal %s cannot be lifted".formatted(literal));
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ConcreteCountLiteral.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ConcreteCountLiteral.java
new file mode 100644
index 00000000..91b30964
--- /dev/null
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ConcreteCountLiteral.java
@@ -0,0 +1,47 @@
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.literal;
7
8import tools.refinery.store.query.Constraint;
9import tools.refinery.store.query.equality.LiteralEqualityHelper;
10import tools.refinery.store.query.equality.LiteralHashCodeHelper;
11import tools.refinery.store.query.literal.AbstractCountLiteral;
12import tools.refinery.store.query.literal.Literal;
13import tools.refinery.store.query.term.DataVariable;
14import tools.refinery.store.query.term.Variable;
15
16import java.util.List;
17import java.util.Objects;
18
19// {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}.
20@SuppressWarnings("squid:S2160")
21public abstract class ConcreteCountLiteral<T> extends AbstractCountLiteral<T> {
22 private final Concreteness concreteness;
23
24 protected ConcreteCountLiteral(Class<T> resultType, DataVariable<T> resultVariable, Concreteness concreteness,
25 Constraint target, List<Variable> arguments) {
26 super(resultType, resultVariable, target, arguments);
27 this.concreteness = concreteness;
28 }
29
30 public Concreteness getConcreteness() {
31 return concreteness;
32 }
33
34 @Override
35 public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) {
36 if (!super.equalsWithSubstitution(helper, other)) {
37 return false;
38 }
39 var otherCountLiteral = (ConcreteCountLiteral<?>) other;
40 return Objects.equals(concreteness, otherCountLiteral.concreteness);
41 }
42
43 @Override
44 public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) {
45 return Objects.hash(super.hashCodeWithSubstitution(helper), concreteness);
46 }
47}
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/CountLowerBoundLiteral.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/CountLowerBoundLiteral.java
new file mode 100644
index 00000000..261088fc
--- /dev/null
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/CountLowerBoundLiteral.java
@@ -0,0 +1,48 @@
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.literal;
7
8import tools.refinery.store.query.Constraint;
9import tools.refinery.store.query.literal.AbstractCallLiteral;
10import tools.refinery.store.query.literal.Literal;
11import tools.refinery.store.query.substitution.Substitution;
12import tools.refinery.store.query.term.DataVariable;
13import tools.refinery.store.query.term.Variable;
14
15import java.util.List;
16
17public class CountLowerBoundLiteral extends ConcreteCountLiteral<Integer> {
18 public CountLowerBoundLiteral(DataVariable<Integer> resultVariable, Concreteness concreteness, Constraint target,
19 List<Variable> arguments) {
20 super(Integer.class, resultVariable, concreteness, target, arguments);
21 }
22
23 @Override
24 protected Integer zero() {
25 return 0;
26 }
27
28 @Override
29 protected Integer one() {
30 return 1;
31 }
32
33 @Override
34 protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) {
35 return new CountLowerBoundLiteral(substitution.getTypeSafeSubstitute(getResultVariable()), getConcreteness(),
36 getTarget(), substitutedArguments);
37 }
38
39 @Override
40 protected AbstractCallLiteral internalWithTarget(Constraint newTarget) {
41 return new CountLowerBoundLiteral(getResultVariable(), getConcreteness(), newTarget, getArguments());
42 }
43
44 @Override
45 protected String operatorName() {
46 return "@LowerBound(\"%s\") count".formatted(getConcreteness());
47 }
48}
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/CountUpperBoundLiteral.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/CountUpperBoundLiteral.java
new file mode 100644
index 00000000..960ded69
--- /dev/null
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/CountUpperBoundLiteral.java
@@ -0,0 +1,50 @@
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.literal;
7
8import tools.refinery.store.query.Constraint;
9import tools.refinery.store.query.literal.AbstractCallLiteral;
10import tools.refinery.store.query.literal.Literal;
11import tools.refinery.store.query.substitution.Substitution;
12import tools.refinery.store.query.term.DataVariable;
13import tools.refinery.store.query.term.Variable;
14import tools.refinery.store.representation.cardinality.UpperCardinalities;
15import tools.refinery.store.representation.cardinality.UpperCardinality;
16
17import java.util.List;
18
19public class CountUpperBoundLiteral extends ConcreteCountLiteral<UpperCardinality> {
20 public CountUpperBoundLiteral(DataVariable<UpperCardinality> resultVariable, Concreteness concreteness,
21 Constraint target, List<Variable> arguments) {
22 super(UpperCardinality.class, resultVariable, concreteness, target, arguments);
23 }
24
25 @Override
26 protected UpperCardinality zero() {
27 return UpperCardinalities.ZERO;
28 }
29
30 @Override
31 protected UpperCardinality one() {
32 return UpperCardinalities.UNBOUNDED;
33 }
34
35 @Override
36 protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) {
37 return new CountUpperBoundLiteral(substitution.getTypeSafeSubstitute(getResultVariable()), getConcreteness(),
38 getTarget(), substitutedArguments);
39 }
40
41 @Override
42 protected AbstractCallLiteral internalWithTarget(Constraint newTarget) {
43 return new CountUpperBoundLiteral(getResultVariable(), getConcreteness(), newTarget, getArguments());
44 }
45
46 @Override
47 protected String operatorName() {
48 return "@UpperBound(\"%s\") count".formatted(getConcreteness());
49 }
50}
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/ModelSeed.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/ModelSeed.java
index 3641730d..28e6258e 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/ModelSeed.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/ModelSeed.java
@@ -39,6 +39,10 @@ public class ModelSeed {
39 return typedSeed; 39 return typedSeed;
40 } 40 }
41 41
42 public boolean containsSeed(AnyPartialSymbol symbol) {
43 return seeds.containsKey(symbol);
44 }
45
42 public <A> Cursor<Tuple, A> getCursor(PartialSymbol<A, ?> partialSymbol, A defaultValue) { 46 public <A> Cursor<Tuple, A> getCursor(PartialSymbol<A, ?> partialSymbol, A defaultValue) {
43 return getSeed(partialSymbol).getCursor(defaultValue, nodeCount); 47 return getSeed(partialSymbol).getCursor(defaultValue, nodeCount);
44 } 48 }
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/EqualsRelationRewriter.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/EqualsRelationRewriter.java
index c7bc9fff..393a8769 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/EqualsRelationRewriter.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/EqualsRelationRewriter.java
@@ -11,6 +11,7 @@ import tools.refinery.store.query.literal.AbstractCallLiteral;
11import tools.refinery.store.query.literal.CallLiteral; 11import tools.refinery.store.query.literal.CallLiteral;
12import tools.refinery.store.query.literal.Literal; 12import tools.refinery.store.query.literal.Literal;
13import tools.refinery.store.query.term.Variable; 13import tools.refinery.store.query.term.Variable;
14import tools.refinery.store.query.view.AnySymbolView;
14import tools.refinery.store.reasoning.interpretation.QueryBasedRelationRewriter; 15import tools.refinery.store.reasoning.interpretation.QueryBasedRelationRewriter;
15import tools.refinery.store.reasoning.literal.Concreteness; 16import tools.refinery.store.reasoning.literal.Concreteness;
16import tools.refinery.store.reasoning.literal.Modality; 17import tools.refinery.store.reasoning.literal.Modality;
@@ -67,7 +68,7 @@ class EqualsRelationRewriter extends QueryBasedRelationRewriter {
67 }; 68 };
68 } 69 }
69 70
70 public static EqualsRelationRewriter of(UpperCardinalityView upperCardinalityView) { 71 public static EqualsRelationRewriter of(AnySymbolView upperCardinalityView) {
71 var may = Query.of("MAY_EQUALS", (builder, p1, p2) -> builder 72 var may = Query.of("MAY_EQUALS", (builder, p1, p2) -> builder
72 .clause( 73 .clause(
73 p1.isEquivalent(p2), 74 p1.isEquivalent(p2),
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectInitializer.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectInitializer.java
index 6917b8ed..084bf6f9 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectInitializer.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectInitializer.java
@@ -5,6 +5,7 @@
5 */ 5 */
6package tools.refinery.store.reasoning.translator.multiobject; 6package tools.refinery.store.reasoning.translator.multiobject;
7 7
8import org.jetbrains.annotations.NotNull;
8import tools.refinery.store.model.Model; 9import tools.refinery.store.model.Model;
9import tools.refinery.store.reasoning.ReasoningAdapter; 10import tools.refinery.store.reasoning.ReasoningAdapter;
10import tools.refinery.store.reasoning.refinement.PartialModelInitializer; 11import tools.refinery.store.reasoning.refinement.PartialModelInitializer;
@@ -26,8 +27,7 @@ class MultiObjectInitializer implements PartialModelInitializer {
26 27
27 @Override 28 @Override
28 public void initialize(Model model, ModelSeed modelSeed) { 29 public void initialize(Model model, ModelSeed modelSeed) {
29 var intervals = new CardinalityInterval[modelSeed.getNodeCount()]; 30 var intervals = initializeIntervals(modelSeed);
30 Arrays.fill(intervals, CardinalityIntervals.SET);
31 initializeExists(intervals, modelSeed); 31 initializeExists(intervals, modelSeed);
32 initializeEquals(intervals, modelSeed); 32 initializeEquals(intervals, modelSeed);
33 var countInterpretation = model.getInterpretation(countSymbol); 33 var countInterpretation = model.getInterpretation(countSymbol);
@@ -40,7 +40,33 @@ class MultiObjectInitializer implements PartialModelInitializer {
40 } 40 }
41 } 41 }
42 42
43 @NotNull
44 private CardinalityInterval[] initializeIntervals(ModelSeed modelSeed) {
45 var intervals = new CardinalityInterval[modelSeed.getNodeCount()];
46 if (modelSeed.containsSeed(MultiObjectTranslator.COUNT_SYMBOL)) {
47 Arrays.fill(intervals, CardinalityIntervals.ONE);
48 var cursor = modelSeed.getCursor(MultiObjectTranslator.COUNT_SYMBOL, CardinalityIntervals.ONE);
49 while (cursor.move()) {
50 int i = cursor.getKey().get(0);
51 checkNodeId(intervals, i);
52 intervals[i] = cursor.getValue();
53 }
54 } else {
55 Arrays.fill(intervals, CardinalityIntervals.SET);
56 if (!modelSeed.containsSeed(ReasoningAdapter.EXISTS_SYMBOL) ||
57 !modelSeed.containsSeed(ReasoningAdapter.EQUALS_SYMBOL)) {
58 throw new IllegalArgumentException("Seed for %s and %s is required if there is no seed for %s"
59 .formatted(ReasoningAdapter.EXISTS_SYMBOL, ReasoningAdapter.EQUALS_SYMBOL,
60 MultiObjectTranslator.COUNT_SYMBOL));
61 }
62 }
63 return intervals;
64 }
65
43 private void initializeExists(CardinalityInterval[] intervals, ModelSeed modelSeed) { 66 private void initializeExists(CardinalityInterval[] intervals, ModelSeed modelSeed) {
67 if (!modelSeed.containsSeed(ReasoningAdapter.EXISTS_SYMBOL)) {
68 return;
69 }
44 var cursor = modelSeed.getCursor(ReasoningAdapter.EXISTS_SYMBOL, TruthValue.UNKNOWN); 70 var cursor = modelSeed.getCursor(ReasoningAdapter.EXISTS_SYMBOL, TruthValue.UNKNOWN);
45 while (cursor.move()) { 71 while (cursor.move()) {
46 int i = cursor.getKey().get(0); 72 int i = cursor.getKey().get(0);
@@ -56,6 +82,9 @@ class MultiObjectInitializer implements PartialModelInitializer {
56 } 82 }
57 83
58 private void initializeEquals(CardinalityInterval[] intervals, ModelSeed modelSeed) { 84 private void initializeEquals(CardinalityInterval[] intervals, ModelSeed modelSeed) {
85 if (!modelSeed.containsSeed(ReasoningAdapter.EQUALS_SYMBOL)) {
86 return;
87 }
59 var seed = modelSeed.getSeed(ReasoningAdapter.EQUALS_SYMBOL); 88 var seed = modelSeed.getSeed(ReasoningAdapter.EQUALS_SYMBOL);
60 var cursor = seed.getCursor(TruthValue.FALSE, modelSeed.getNodeCount()); 89 var cursor = seed.getCursor(TruthValue.FALSE, modelSeed.getNodeCount());
61 while (cursor.move()) { 90 while (cursor.move()) {
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectTranslator.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectTranslator.java
index 0367214b..09993c80 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectTranslator.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectTranslator.java
@@ -8,11 +8,14 @@ package tools.refinery.store.reasoning.translator.multiobject;
8import tools.refinery.store.model.ModelStoreBuilder; 8import tools.refinery.store.model.ModelStoreBuilder;
9import tools.refinery.store.model.ModelStoreConfiguration; 9import tools.refinery.store.model.ModelStoreConfiguration;
10import tools.refinery.store.query.dnf.Query; 10import tools.refinery.store.query.dnf.Query;
11import tools.refinery.store.query.view.AnySymbolView;
11import tools.refinery.store.reasoning.ReasoningAdapter; 12import tools.refinery.store.reasoning.ReasoningAdapter;
12import tools.refinery.store.reasoning.ReasoningBuilder; 13import tools.refinery.store.reasoning.ReasoningBuilder;
14import tools.refinery.store.reasoning.representation.PartialFunction;
13import tools.refinery.store.reasoning.translator.PartialRelationTranslator; 15import tools.refinery.store.reasoning.translator.PartialRelationTranslator;
14import tools.refinery.store.reasoning.translator.RoundingMode; 16import tools.refinery.store.reasoning.translator.RoundingMode;
15import tools.refinery.store.representation.Symbol; 17import tools.refinery.store.representation.Symbol;
18import tools.refinery.store.representation.cardinality.CardinalityDomain;
16import tools.refinery.store.representation.cardinality.CardinalityInterval; 19import tools.refinery.store.representation.cardinality.CardinalityInterval;
17import tools.refinery.store.representation.cardinality.UpperCardinalities; 20import tools.refinery.store.representation.cardinality.UpperCardinalities;
18import tools.refinery.store.representation.cardinality.UpperCardinality; 21import tools.refinery.store.representation.cardinality.UpperCardinality;
@@ -26,35 +29,37 @@ import static tools.refinery.store.query.term.uppercardinality.UpperCardinalityT
26import static tools.refinery.store.query.term.uppercardinality.UpperCardinalityTerms.greaterEq; 29import static tools.refinery.store.query.term.uppercardinality.UpperCardinalityTerms.greaterEq;
27 30
28public class MultiObjectTranslator implements ModelStoreConfiguration { 31public class MultiObjectTranslator implements ModelStoreConfiguration {
29 private final Symbol<CardinalityInterval> countSymbol = Symbol.of("COUNT", 1, CardinalityInterval.class, 32 private static final Symbol<CardinalityInterval> COUNT_STORAGE = Symbol.of("COUNT", 1, CardinalityInterval.class,
30 null); 33 null);
31 private final LowerCardinalityView lowerCardinalityView = new LowerCardinalityView(countSymbol); 34 public static final AnySymbolView LOWER_CARDINALITY_VIEW = new LowerCardinalityView(COUNT_STORAGE);
32 private final UpperCardinalityView upperCardinalityView = new UpperCardinalityView(countSymbol); 35 public static final AnySymbolView UPPER_CARDINALITY_VIEW = new UpperCardinalityView(COUNT_STORAGE);
36 public static final PartialFunction<CardinalityInterval, Integer> COUNT_SYMBOL = new PartialFunction<>("COUNT", 1,
37 CardinalityDomain.INSTANCE);
33 38
34 @Override 39 @Override
35 public void apply(ModelStoreBuilder storeBuilder) { 40 public void apply(ModelStoreBuilder storeBuilder) {
36 storeBuilder.symbol(countSymbol); 41 storeBuilder.symbol(COUNT_STORAGE);
37 42
38 storeBuilder.with(PartialRelationTranslator.of(ReasoningAdapter.EXISTS_SYMBOL) 43 storeBuilder.with(PartialRelationTranslator.of(ReasoningAdapter.EXISTS_SYMBOL)
39 .may(Query.of("MAY_EXISTS", (builder, p1) -> builder 44 .may(Query.of("MAY_EXISTS", (builder, p1) -> builder
40 .clause(UpperCardinality.class, upper -> List.of( 45 .clause(UpperCardinality.class, upper -> List.of(
41 upperCardinalityView.call(p1, upper), 46 UPPER_CARDINALITY_VIEW.call(p1, upper),
42 check(greaterEq(upper, constant(UpperCardinalities.ONE))) 47 check(greaterEq(upper, constant(UpperCardinalities.ONE)))
43 )))) 48 ))))
44 .must(Query.of("MUST_EXISTS", (builder, p1) -> builder 49 .must(Query.of("MUST_EXISTS", (builder, p1) -> builder
45 .clause(Integer.class, lower -> List.of( 50 .clause(Integer.class, lower -> List.of(
46 lowerCardinalityView.call(p1, lower), 51 LOWER_CARDINALITY_VIEW.call(p1, lower),
47 check(greaterEq(lower, constant(1))) 52 check(greaterEq(lower, constant(1)))
48 )))) 53 ))))
49 .roundingMode(RoundingMode.PREFER_FALSE) 54 .roundingMode(RoundingMode.PREFER_FALSE)
50 .refiner(ExistsRefiner.of(countSymbol))); 55 .refiner(ExistsRefiner.of(COUNT_STORAGE)));
51 56
52 storeBuilder.with(PartialRelationTranslator.of(ReasoningAdapter.EQUALS_SYMBOL) 57 storeBuilder.with(PartialRelationTranslator.of(ReasoningAdapter.EQUALS_SYMBOL)
53 .rewriter(EqualsRelationRewriter.of(upperCardinalityView)) 58 .rewriter(EqualsRelationRewriter.of(UPPER_CARDINALITY_VIEW))
54 .refiner(EqualsRefiner.of(countSymbol))); 59 .refiner(EqualsRefiner.of(COUNT_STORAGE)));
55 60
56 var reasoningBuilder = storeBuilder.getAdapter(ReasoningBuilder.class); 61 var reasoningBuilder = storeBuilder.getAdapter(ReasoningBuilder.class);
57 reasoningBuilder.initializer(new MultiObjectInitializer(countSymbol)); 62 reasoningBuilder.initializer(new MultiObjectInitializer(COUNT_STORAGE));
58 reasoningBuilder.storageRefiner(countSymbol, MultiObjectStorageRefiner::new); 63 reasoningBuilder.storageRefiner(COUNT_STORAGE, MultiObjectStorageRefiner::new);
59 } 64 }
60} 65}