aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectTranslator.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectTranslator.java')
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectTranslator.java107
1 files changed, 107 insertions, 0 deletions
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
new file mode 100644
index 00000000..97fda9d5
--- /dev/null
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectTranslator.java
@@ -0,0 +1,107 @@
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.translator.multiobject;
7
8import tools.refinery.store.dse.propagation.PropagationBuilder;
9import tools.refinery.store.dse.transition.Rule;
10import tools.refinery.store.dse.transition.objectives.Criteria;
11import tools.refinery.store.dse.transition.objectives.Objectives;
12import tools.refinery.store.model.ModelStoreBuilder;
13import tools.refinery.store.model.ModelStoreConfiguration;
14import tools.refinery.store.query.dnf.Query;
15import tools.refinery.store.query.literal.Literals;
16import tools.refinery.store.query.term.Variable;
17import tools.refinery.store.query.term.int_.IntTerms;
18import tools.refinery.store.query.term.uppercardinality.UpperCardinalityTerms;
19import tools.refinery.store.query.view.AnySymbolView;
20import tools.refinery.store.reasoning.ReasoningAdapter;
21import tools.refinery.store.reasoning.ReasoningBuilder;
22import tools.refinery.store.reasoning.actions.PartialActionLiterals;
23import tools.refinery.store.reasoning.representation.PartialFunction;
24import tools.refinery.store.reasoning.translator.PartialRelationTranslator;
25import tools.refinery.store.reasoning.translator.RoundingMode;
26import tools.refinery.store.representation.Symbol;
27import tools.refinery.store.representation.cardinality.CardinalityDomain;
28import tools.refinery.store.representation.cardinality.CardinalityInterval;
29import tools.refinery.store.representation.cardinality.UpperCardinalities;
30import tools.refinery.store.representation.cardinality.UpperCardinality;
31
32import java.util.List;
33
34import static tools.refinery.store.query.literal.Literals.check;
35import static tools.refinery.store.query.term.int_.IntTerms.*;
36
37public class MultiObjectTranslator implements ModelStoreConfiguration {
38 public static final Symbol<CardinalityInterval> COUNT_STORAGE = Symbol.of("COUNT", 1, CardinalityInterval.class,
39 null);
40 public static final AnySymbolView LOWER_CARDINALITY_VIEW = new LowerCardinalityView(COUNT_STORAGE);
41 public static final AnySymbolView UPPER_CARDINALITY_VIEW = new UpperCardinalityView(COUNT_STORAGE);
42 public static final AnySymbolView MULTI_VIEW = new MultiView(COUNT_STORAGE);
43 public static final PartialFunction<CardinalityInterval, Integer> COUNT_SYMBOL = new PartialFunction<>("COUNT", 1,
44 CardinalityDomain.INSTANCE);
45
46 @Override
47 public void apply(ModelStoreBuilder storeBuilder) {
48 storeBuilder.symbol(COUNT_STORAGE);
49
50 var aboveLowerBound = Query.of("count#aboveLowerBound", Integer.class, (builder, node, output) -> builder
51 .clause(
52 MULTI_VIEW.call(node),
53 LOWER_CARDINALITY_VIEW.call(node, output),
54 check(greater(output, IntTerms.constant(0)))
55 ));
56 var missingCardinality = Query.of("count#missing", Integer.class, (builder, output) -> builder
57 .clause(
58 output.assign(aboveLowerBound.aggregate(INT_SUM, Variable.of()))
59 ));
60
61 storeBuilder.with(PartialRelationTranslator.of(ReasoningAdapter.EXISTS_SYMBOL)
62 .may(Query.of("exists#may", (builder, p1) -> builder
63 .clause(UpperCardinality.class, upper -> List.of(
64 UPPER_CARDINALITY_VIEW.call(p1, upper),
65 check(UpperCardinalityTerms.greaterEq(upper,
66 UpperCardinalityTerms.constant(UpperCardinalities.ONE)))
67 ))))
68 .must(Query.of("exists#must", (builder, p1) -> builder
69 .clause(Integer.class, lower -> List.of(
70 LOWER_CARDINALITY_VIEW.call(p1, lower),
71 check(greaterEq(lower, constant(1)))
72 ))))
73 .candidate(Query.of("exists#candidate", (builder, p1) -> builder
74 .clause(
75 LOWER_CARDINALITY_VIEW.call(p1, Variable.of(Integer.class)),
76 Literals.not(MULTI_VIEW.call(p1))
77 )))
78 .roundingMode(RoundingMode.PREFER_FALSE)
79 .refiner(ExistsRefiner.of(COUNT_STORAGE))
80 .exclude(null)
81 .accept(Criteria.whenNoMatch(aboveLowerBound))
82 .objective(Objectives.value(missingCardinality)));
83
84 storeBuilder.with(PartialRelationTranslator.of(ReasoningAdapter.EQUALS_SYMBOL)
85 .rewriter(EqualsRelationRewriter.of(UPPER_CARDINALITY_VIEW))
86 .refiner(EqualsRefiner.of(COUNT_STORAGE))
87 .exclude(null)
88 .accept(null)
89 .objective(null));
90
91 var reasoningBuilder = storeBuilder.getAdapter(ReasoningBuilder.class);
92 reasoningBuilder.initializer(new MultiObjectInitializer(COUNT_STORAGE));
93 reasoningBuilder.storageRefiner(COUNT_STORAGE, MultiObjectStorageRefiner::new);
94
95 storeBuilder.tryGetAdapter(PropagationBuilder.class)
96 .ifPresent(propagationBuilder -> propagationBuilder.rule(
97 Rule.of("exists#cleanup", (builder, node) -> builder
98 .clause(UpperCardinality.class, upper -> List.of(
99 UPPER_CARDINALITY_VIEW.call(node, upper),
100 check(UpperCardinalityTerms.less(upper,
101 UpperCardinalityTerms.constant(UpperCardinalities.ONE)))
102 ))
103 .action(
104 PartialActionLiterals.cleanup(node)
105 ))));
106 }
107}