diff options
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.java | 93 |
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 | */ | ||
6 | package tools.refinery.store.reasoning.translator.predicate; | ||
7 | |||
8 | import tools.refinery.store.model.ModelStoreBuilder; | ||
9 | import tools.refinery.store.model.ModelStoreConfiguration; | ||
10 | import tools.refinery.store.query.dnf.Query; | ||
11 | import tools.refinery.store.query.dnf.RelationalQuery; | ||
12 | import tools.refinery.store.query.literal.Literal; | ||
13 | import tools.refinery.store.query.term.NodeVariable; | ||
14 | import tools.refinery.store.query.term.Variable; | ||
15 | import tools.refinery.store.query.view.ForbiddenView; | ||
16 | import tools.refinery.store.query.view.MayView; | ||
17 | import tools.refinery.store.query.view.MustView; | ||
18 | import tools.refinery.store.reasoning.representation.PartialRelation; | ||
19 | import tools.refinery.store.reasoning.translator.PartialRelationTranslator; | ||
20 | import tools.refinery.store.reasoning.translator.TranslationException; | ||
21 | import tools.refinery.store.representation.Symbol; | ||
22 | import tools.refinery.store.representation.TruthValue; | ||
23 | |||
24 | import static tools.refinery.store.query.literal.Literals.not; | ||
25 | import static tools.refinery.store.reasoning.literal.PartialLiterals.may; | ||
26 | import static tools.refinery.store.reasoning.literal.PartialLiterals.must; | ||
27 | |||
28 | public 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 | } | ||