aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/predicate/PredicateTranslator.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/predicate/PredicateTranslator.java')
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/predicate/PredicateTranslator.java93
1 files changed, 93 insertions, 0 deletions
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/predicate/PredicateTranslator.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/predicate/PredicateTranslator.java
new file mode 100644
index 00000000..b401118e
--- /dev/null
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/predicate/PredicateTranslator.java
@@ -0,0 +1,93 @@
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.predicate;
7
8import tools.refinery.store.model.ModelStoreBuilder;
9import tools.refinery.store.model.ModelStoreConfiguration;
10import tools.refinery.store.query.dnf.Query;
11import tools.refinery.store.query.dnf.RelationalQuery;
12import tools.refinery.store.query.literal.Literal;
13import tools.refinery.store.query.term.NodeVariable;
14import tools.refinery.store.query.term.Variable;
15import tools.refinery.store.query.view.ForbiddenView;
16import tools.refinery.store.query.view.MayView;
17import tools.refinery.store.query.view.MustView;
18import tools.refinery.store.reasoning.representation.PartialRelation;
19import tools.refinery.store.reasoning.translator.PartialRelationTranslator;
20import tools.refinery.store.reasoning.translator.TranslationException;
21import tools.refinery.store.representation.Symbol;
22import tools.refinery.store.representation.TruthValue;
23
24import static tools.refinery.store.query.literal.Literals.not;
25import static tools.refinery.store.reasoning.literal.PartialLiterals.may;
26import static tools.refinery.store.reasoning.literal.PartialLiterals.must;
27
28public class PredicateTranslator implements ModelStoreConfiguration {
29 private final PartialRelation relation;
30 private final RelationalQuery query;
31 private final boolean mutable;
32 private final TruthValue defaultValue;
33
34 public PredicateTranslator(PartialRelation relation, RelationalQuery query, boolean mutable,
35 TruthValue defaultValue) {
36 if (relation.arity() != query.arity()) {
37 throw new TranslationException(relation, "Expected arity %d query for partial relation %s, got %d instead"
38 .formatted(relation.arity(), relation, query.arity()));
39 }
40 if (defaultValue.must()) {
41 throw new TranslationException(relation, "Default value must be UNKNOWN or FALSE");
42 }
43 this.relation = relation;
44 this.query = query;
45 this.mutable = mutable;
46 this.defaultValue = defaultValue;
47 }
48
49 @Override
50 public void apply(ModelStoreBuilder storeBuilder) {
51 var translator = PartialRelationTranslator.of(relation)
52 .query(query);
53 if (mutable) {
54 var symbol = Symbol.of(relation.name(), relation.arity(), TruthValue.class, defaultValue);
55 translator.symbol(symbol);
56
57 var parameters = new NodeVariable[relation.arity()];
58 for (int i = 0; i < parameters.length; i++) {
59 parameters[i] = Variable.of("p" + i);
60 }
61
62 var must = Query.builder()
63 .parameters(parameters)
64 .clause(must(query.call(parameters)))
65 .clause(new MustView(symbol).call(parameters))
66 .build();
67 translator.must(must);
68
69 var mayLiterals = new Literal[2];
70 mayLiterals[0] = may(query.call(parameters));
71 if (defaultValue.may()) {
72 mayLiterals[1] = not(new ForbiddenView(symbol).call(parameters));
73 } else {
74 mayLiterals[1] = new MayView(symbol).call(parameters);
75 }
76 var may = Query.builder()
77 .parameters(parameters)
78 .clause(mayLiterals)
79 .build();
80 translator.may(may);
81 } else if (defaultValue.may()) {
82 // If all values are permitted, we don't need to check for any forbidden values in the model.
83 // If the result of this predicate of {@code ERROR}, some other partial relation (that we check for)
84 // will be {@code ERROR} as well.
85 translator.exclude(null);
86 translator.accept(null);
87 translator.objective(null);
88 } else {
89 translator.mayNever();
90 }
91 storeBuilder.with(translator);
92 }
93}