aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Advice.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Advice.java')
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Advice.java159
1 files changed, 159 insertions, 0 deletions
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Advice.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Advice.java
new file mode 100644
index 00000000..7909a7e1
--- /dev/null
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Advice.java
@@ -0,0 +1,159 @@
1package tools.refinery.store.reasoning.translator;
2
3import tools.refinery.store.reasoning.representation.AnyPartialSymbol;
4import tools.refinery.store.reasoning.representation.PartialRelation;
5import tools.refinery.store.query.Variable;
6import tools.refinery.store.query.literal.Literal;
7import tools.refinery.store.query.substitution.Substitutions;
8
9import java.util.*;
10
11public final class Advice {
12 private final AnyPartialSymbol source;
13 private final PartialRelation target;
14 private final AdviceSlot slot;
15 private final boolean mandatory;
16 private final List<Variable> parameters;
17 private final List<Literal> literals;
18 private boolean processed;
19
20 public Advice(AnyPartialSymbol source, PartialRelation target, AdviceSlot slot, boolean mandatory, List<Variable> parameters, List<Literal> literals) {
21 if (mandatory && !slot.isMonotonic()) {
22 throw new IllegalArgumentException("Only monotonic advice can be mandatory");
23 }
24 this.source = source;
25 this.target = target;
26 this.slot = slot;
27 this.mandatory = mandatory;
28 checkArity(parameters);
29 this.parameters = parameters;
30 this.literals = literals;
31 }
32
33 public AnyPartialSymbol source() {
34 return source;
35 }
36
37 public PartialRelation target() {
38 return target;
39 }
40
41 public AdviceSlot slot() {
42 return slot;
43 }
44
45 public boolean mandatory() {
46 return mandatory;
47 }
48
49 public List<Variable> parameters() {
50 return parameters;
51 }
52
53 public List<Literal> literals() {
54 return literals;
55 }
56
57 public boolean processed() {
58 return processed;
59 }
60
61 public List<Literal> substitute(List<Variable> substituteParameters) {
62 checkArity(substituteParameters);
63 markProcessed();
64 int arity = parameters.size();
65 var variableMap = new HashMap<Variable, Variable>(arity);
66 for (int i = 0; i < arity; i++) {
67 variableMap.put(parameters.get(i), substituteParameters.get(i));
68 }
69 // Use a renewing substitution to remove any non-parameter variables and avoid clashed between variables
70 // coming from different advice in the same clause.
71 var substitution = Substitutions.renewing(variableMap);
72 return literals.stream().map(literal -> literal.substitute(substitution)).toList();
73 }
74
75 private void markProcessed() {
76 processed = true;
77 }
78
79 public void checkProcessed() {
80 if (mandatory && !processed) {
81 throw new IllegalStateException("Mandatory advice %s was not processed".formatted(this));
82 }
83 }
84
85 private void checkArity(List<Variable> toCheck) {
86 if (toCheck.size() != target.arity()) {
87 throw new IllegalArgumentException("%s needs %d parameters, but got %s".formatted(target.name(),
88 target.arity(), parameters.size()));
89 }
90 }
91
92 public static Builder builderFor(AnyPartialSymbol source, PartialRelation target, AdviceSlot slot) {
93 return new Builder(source, target, slot);
94 }
95
96
97 @Override
98 public String toString() {
99 return "Advice[source=%s, target=%s, slot=%s, mandatory=%s, parameters=%s, literals=%s]".formatted(source,
100 target, slot, mandatory, parameters, literals);
101 }
102
103 public static class Builder {
104 private final AnyPartialSymbol source;
105 private final PartialRelation target;
106 private final AdviceSlot slot;
107 private boolean mandatory;
108 private final List<Variable> parameters = new ArrayList<>();
109 private final List<Literal> literals = new ArrayList<>();
110
111 private Builder(AnyPartialSymbol source, PartialRelation target, AdviceSlot slot) {
112 this.source = source;
113 this.target = target;
114 this.slot = slot;
115 }
116
117 public Builder mandatory(boolean mandatory) {
118 this.mandatory = mandatory;
119 return this;
120 }
121
122 public Builder mandatory() {
123 return mandatory(false);
124 }
125
126 public Builder parameters(List<Variable> variables) {
127 parameters.addAll(variables);
128 return this;
129 }
130
131 public Builder parameters(Variable... variables) {
132 return parameters(List.of(variables));
133 }
134
135 public Builder parameter(Variable variable) {
136 parameters.add(variable);
137 return this;
138 }
139
140 public Builder literals(Collection<Literal> literals) {
141 this.literals.addAll(literals);
142 return this;
143 }
144
145 public Builder literals(Literal... literals) {
146 return literals(List.of(literals));
147 }
148
149 public Builder literal(Literal literal) {
150 literals.add(literal);
151 return this;
152 }
153
154 public Advice build() {
155 return new Advice(source, target, slot, mandatory, Collections.unmodifiableList(parameters),
156 Collections.unmodifiableList(literals));
157 }
158 }
159}