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