diff options
Diffstat (limited to 'subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningAdapterImpl.java')
-rw-r--r-- | subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningAdapterImpl.java | 186 |
1 files changed, 178 insertions, 8 deletions
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningAdapterImpl.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningAdapterImpl.java index 1bd3ad2e..bd16bdfa 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningAdapterImpl.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningAdapterImpl.java | |||
@@ -5,20 +5,114 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.store.reasoning.internal; | 6 | package tools.refinery.store.reasoning.internal; |
7 | 7 | ||
8 | import org.jetbrains.annotations.Nullable; | ||
9 | import tools.refinery.store.model.Interpretation; | ||
8 | import tools.refinery.store.model.Model; | 10 | import tools.refinery.store.model.Model; |
9 | import tools.refinery.store.reasoning.ReasoningAdapter; | 11 | import tools.refinery.store.reasoning.ReasoningAdapter; |
10 | import tools.refinery.store.reasoning.PartialInterpretation; | 12 | import tools.refinery.store.reasoning.interpretation.AnyPartialInterpretation; |
13 | import tools.refinery.store.reasoning.interpretation.PartialInterpretation; | ||
14 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
15 | import tools.refinery.store.reasoning.refinement.AnyPartialInterpretationRefiner; | ||
16 | import tools.refinery.store.reasoning.refinement.PartialInterpretationRefiner; | ||
17 | import tools.refinery.store.reasoning.refinement.StorageRefiner; | ||
18 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; | ||
11 | import tools.refinery.store.reasoning.representation.PartialSymbol; | 19 | import tools.refinery.store.reasoning.representation.PartialSymbol; |
12 | import tools.refinery.store.query.dnf.Dnf; | 20 | import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; |
13 | import tools.refinery.store.query.resultset.ResultSet; | 21 | import tools.refinery.store.representation.Symbol; |
22 | import tools.refinery.store.representation.cardinality.CardinalityInterval; | ||
23 | import tools.refinery.store.representation.cardinality.CardinalityIntervals; | ||
24 | import tools.refinery.store.tuple.Tuple; | ||
25 | import tools.refinery.store.tuple.Tuple1; | ||
14 | 26 | ||
15 | public class ReasoningAdapterImpl implements ReasoningAdapter { | 27 | import java.util.HashMap; |
28 | import java.util.Map; | ||
29 | |||
30 | class ReasoningAdapterImpl implements ReasoningAdapter { | ||
31 | static final Symbol<Integer> NODE_COUNT_SYMBOL = Symbol.of("MODEL_SIZE", 0, Integer.class, 0); | ||
16 | private final Model model; | 32 | private final Model model; |
17 | private final ReasoningStoreAdapterImpl storeAdapter; | 33 | private final ReasoningStoreAdapterImpl storeAdapter; |
34 | private final Map<AnyPartialSymbol, AnyPartialInterpretation>[] partialInterpretations; | ||
35 | private final Map<AnyPartialSymbol, AnyPartialInterpretationRefiner> refiners; | ||
36 | private final StorageRefiner[] storageRefiners; | ||
37 | private final Interpretation<Integer> nodeCountInterpretation; | ||
38 | private final Interpretation<CardinalityInterval> countInterpretation; | ||
18 | 39 | ||
19 | ReasoningAdapterImpl(Model model, ReasoningStoreAdapterImpl storeAdapter) { | 40 | ReasoningAdapterImpl(Model model, ReasoningStoreAdapterImpl storeAdapter) { |
20 | this.model = model; | 41 | this.model = model; |
21 | this.storeAdapter = storeAdapter; | 42 | this.storeAdapter = storeAdapter; |
43 | |||
44 | int concretenessLength = Concreteness.values().length; | ||
45 | // Creation of a generic array. | ||
46 | @SuppressWarnings({"unchecked", "squid:S1905"}) | ||
47 | var interpretationsArray = (Map<AnyPartialSymbol, AnyPartialInterpretation>[]) new Map[concretenessLength]; | ||
48 | partialInterpretations = interpretationsArray; | ||
49 | createPartialInterpretations(); | ||
50 | |||
51 | var refinerFactories = storeAdapter.getSymbolRefiners(); | ||
52 | refiners = new HashMap<>(refinerFactories.size()); | ||
53 | createRefiners(); | ||
54 | |||
55 | storageRefiners = storeAdapter.createStorageRefiner(model); | ||
56 | |||
57 | nodeCountInterpretation = model.getInterpretation(NODE_COUNT_SYMBOL); | ||
58 | if (model.getStore().getSymbols().contains(MultiObjectTranslator.COUNT_STORAGE)) { | ||
59 | countInterpretation = model.getInterpretation(MultiObjectTranslator.COUNT_STORAGE); | ||
60 | } else { | ||
61 | countInterpretation = null; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | private void createPartialInterpretations() { | ||
66 | var supportedInterpretations = storeAdapter.getSupportedInterpretations(); | ||
67 | int concretenessLength = Concreteness.values().length; | ||
68 | var interpretationFactories = storeAdapter.getSymbolInterpreters(); | ||
69 | for (int i = 0; i < concretenessLength; i++) { | ||
70 | var concreteness = Concreteness.values()[i]; | ||
71 | if (supportedInterpretations.contains(concreteness)) { | ||
72 | partialInterpretations[i] = new HashMap<>(interpretationFactories.size()); | ||
73 | } | ||
74 | } | ||
75 | // Create the partial interpretations in order so that factories may refer to interpretations of symbols | ||
76 | // preceding them in the ordered {@code interpretationFactories} map, e.g., for opposite interpretations. | ||
77 | for (var entry : interpretationFactories.entrySet()) { | ||
78 | var partialSymbol = entry.getKey(); | ||
79 | var factory = entry.getValue(); | ||
80 | for (int i = 0; i < concretenessLength; i++) { | ||
81 | if (partialInterpretations[i] != null) { | ||
82 | var concreteness = Concreteness.values()[i]; | ||
83 | var interpretation = createPartialInterpretation(concreteness, factory, partialSymbol); | ||
84 | partialInterpretations[i].put(partialSymbol, interpretation); | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
90 | private <A, C> PartialInterpretation<A, C> createPartialInterpretation( | ||
91 | Concreteness concreteness, PartialInterpretation.Factory<A, C> interpreter, AnyPartialSymbol symbol) { | ||
92 | // The builder only allows well-typed assignment of interpreters to symbols. | ||
93 | @SuppressWarnings("unchecked") | ||
94 | var typedSymbol = (PartialSymbol<A, C>) symbol; | ||
95 | return interpreter.create(this, concreteness, typedSymbol); | ||
96 | } | ||
97 | |||
98 | private void createRefiners() { | ||
99 | var refinerFactories = storeAdapter.getSymbolRefiners(); | ||
100 | // Create the partial interpretations refiners in order so that factories may refer to refiners of symbols | ||
101 | // preceding them in the ordered {@code interpretationFactories} map, e.g., for opposite interpretations. | ||
102 | for (var entry : refinerFactories.entrySet()) { | ||
103 | var partialSymbol = entry.getKey(); | ||
104 | var factory = entry.getValue(); | ||
105 | var refiner = createRefiner(factory, partialSymbol); | ||
106 | refiners.put(partialSymbol, refiner); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | private <A, C> PartialInterpretationRefiner<A, C> createRefiner( | ||
111 | PartialInterpretationRefiner.Factory<A, C> factory, AnyPartialSymbol symbol) { | ||
112 | // The builder only allows well-typed assignment of interpreters to symbols. | ||
113 | @SuppressWarnings("unchecked") | ||
114 | var typedSymbol = (PartialSymbol<A, C>) symbol; | ||
115 | return factory.create(this, typedSymbol); | ||
22 | } | 116 | } |
23 | 117 | ||
24 | @Override | 118 | @Override |
@@ -32,12 +126,88 @@ public class ReasoningAdapterImpl implements ReasoningAdapter { | |||
32 | } | 126 | } |
33 | 127 | ||
34 | @Override | 128 | @Override |
35 | public <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol) { | 129 | public <A, C> PartialInterpretation<A, C> getPartialInterpretation(Concreteness concreteness, |
36 | return null; | 130 | PartialSymbol<A, C> partialSymbol) { |
131 | var map = partialInterpretations[concreteness.ordinal()]; | ||
132 | if (map == null) { | ||
133 | throw new IllegalArgumentException("No interpretation for concreteness: " + concreteness); | ||
134 | } | ||
135 | var interpretation = map.get(partialSymbol); | ||
136 | if (interpretation == null) { | ||
137 | throw new IllegalArgumentException("No interpretation for partial symbol: " + partialSymbol); | ||
138 | } | ||
139 | // The builder only allows well-typed assignment of interpreters to symbols. | ||
140 | @SuppressWarnings("unchecked") | ||
141 | var typedInterpretation = (PartialInterpretation<A, C>) interpretation; | ||
142 | return typedInterpretation; | ||
143 | } | ||
144 | |||
145 | @Override | ||
146 | public <A, C> PartialInterpretationRefiner<A, C> getRefiner(PartialSymbol<A, C> partialSymbol) { | ||
147 | var refiner = refiners.get(partialSymbol); | ||
148 | if (refiner == null) { | ||
149 | throw new IllegalArgumentException("No refiner for partial symbol: " + partialSymbol); | ||
150 | } | ||
151 | // The builder only allows well-typed assignment of refiners to symbols. | ||
152 | @SuppressWarnings("unchecked") | ||
153 | var typedRefiner = (PartialInterpretationRefiner<A, C>) refiner; | ||
154 | return typedRefiner; | ||
155 | } | ||
156 | |||
157 | @Override | ||
158 | @Nullable | ||
159 | public Tuple1 split(int parentNode) { | ||
160 | int newNodeId = nodeCountInterpretation.get(Tuple.of()); | ||
161 | nodeCountInterpretation.put(Tuple.of(), newNodeId + 1); | ||
162 | // Avoid creating an iterator object. | ||
163 | //noinspection ForLoopReplaceableByForEach | ||
164 | for (int i = 0; i < storageRefiners.length; i++) { | ||
165 | if (!storageRefiners[i].split(parentNode, newNodeId)) { | ||
166 | return null; | ||
167 | } | ||
168 | } | ||
169 | return Tuple.of(newNodeId); | ||
170 | } | ||
171 | |||
172 | @Override | ||
173 | public @Nullable Tuple1 focus(int parentObject) { | ||
174 | if (countInterpretation == null) { | ||
175 | throw new IllegalStateException("Cannot focus without " + MultiObjectTranslator.class.getSimpleName()); | ||
176 | } | ||
177 | var tuple = Tuple.of(parentObject); | ||
178 | var count = countInterpretation.get(tuple); | ||
179 | if (CardinalityIntervals.ONE.equals(count)) { | ||
180 | return tuple; | ||
181 | } | ||
182 | if (CardinalityIntervals.LONE.equals(count)) { | ||
183 | countInterpretation.put(tuple, CardinalityIntervals.ONE); | ||
184 | return tuple; | ||
185 | } | ||
186 | if (CardinalityIntervals.NONE.equals(count)) { | ||
187 | return null; | ||
188 | } | ||
189 | return split(parentObject); | ||
190 | } | ||
191 | |||
192 | @Override | ||
193 | public boolean cleanup(int nodeToDelete) { | ||
194 | // Avoid creating an iterator object. | ||
195 | //noinspection ForLoopReplaceableByForEach | ||
196 | for (int i = 0; i < storageRefiners.length; i++) { | ||
197 | if (!storageRefiners[i].cleanup(nodeToDelete)) { | ||
198 | return false; | ||
199 | } | ||
200 | } | ||
201 | int currentModelSize = nodeCountInterpretation.get(Tuple.of()); | ||
202 | if (nodeToDelete == currentModelSize - 1) { | ||
203 | nodeCountInterpretation.put(Tuple.of(), nodeToDelete); | ||
204 | } | ||
205 | return true; | ||
37 | } | 206 | } |
38 | 207 | ||
39 | @Override | 208 | @Override |
40 | public ResultSet<Boolean> getLiftedResultSet(Dnf query) { | 209 | public int getNodeCount() { |
41 | return null; | 210 | Integer nodeCount = nodeCountInterpretation.get(Tuple.of()); |
211 | return nodeCount == null ? 0 : nodeCount; | ||
42 | } | 212 | } |
43 | } | 213 | } |