diff options
Diffstat (limited to 'subprojects/language-semantics')
6 files changed, 368 insertions, 42 deletions
diff --git a/subprojects/language-semantics/build.gradle.kts b/subprojects/language-semantics/build.gradle.kts index 38cd9e0d..23668f30 100644 --- a/subprojects/language-semantics/build.gradle.kts +++ b/subprojects/language-semantics/build.gradle.kts | |||
@@ -13,5 +13,7 @@ dependencies { | |||
13 | implementation(libs.eclipseCollections.api) | 13 | implementation(libs.eclipseCollections.api) |
14 | api(project(":refinery-language")) | 14 | api(project(":refinery-language")) |
15 | api(project(":refinery-store")) | 15 | api(project(":refinery-store")) |
16 | api(project(":refinery-store-query")) | ||
17 | api(project(":refinery-store-reasoning")) | ||
16 | testImplementation(testFixtures(project(":refinery-language"))) | 18 | testImplementation(testFixtures(project(":refinery-language"))) |
17 | } | 19 | } |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java index fe67ed2c..93c7c8e5 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java | |||
@@ -9,66 +9,298 @@ import com.google.inject.Inject; | |||
9 | import org.eclipse.collections.api.factory.primitive.ObjectIntMaps; | 9 | import org.eclipse.collections.api.factory.primitive.ObjectIntMaps; |
10 | import org.eclipse.collections.api.map.primitive.MutableObjectIntMap; | 10 | import org.eclipse.collections.api.map.primitive.MutableObjectIntMap; |
11 | import tools.refinery.language.model.problem.*; | 11 | import tools.refinery.language.model.problem.*; |
12 | import tools.refinery.language.semantics.model.internal.DecisionTree; | ||
13 | import tools.refinery.language.utils.BuiltinSymbols; | ||
12 | import tools.refinery.language.utils.ProblemDesugarer; | 14 | import tools.refinery.language.utils.ProblemDesugarer; |
13 | import tools.refinery.store.representation.Symbol; | 15 | import tools.refinery.language.utils.ProblemUtil; |
16 | import tools.refinery.store.model.ModelStoreBuilder; | ||
17 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
18 | import tools.refinery.store.reasoning.representation.PartialRelation; | ||
19 | import tools.refinery.store.reasoning.seed.ModelSeed; | ||
20 | import tools.refinery.store.reasoning.seed.Seed; | ||
21 | import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator; | ||
22 | import tools.refinery.store.reasoning.translator.metamodel.Metamodel; | ||
23 | import tools.refinery.store.reasoning.translator.metamodel.MetamodelBuilder; | ||
24 | import tools.refinery.store.reasoning.translator.metamodel.MetamodelTranslator; | ||
25 | import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; | ||
26 | import tools.refinery.store.reasoning.translator.multiplicity.ConstrainedMultiplicity; | ||
27 | import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity; | ||
28 | import tools.refinery.store.reasoning.translator.multiplicity.UnconstrainedMultiplicity; | ||
14 | import tools.refinery.store.representation.TruthValue; | 29 | import tools.refinery.store.representation.TruthValue; |
30 | import tools.refinery.store.representation.cardinality.CardinalityInterval; | ||
31 | import tools.refinery.store.representation.cardinality.CardinalityIntervals; | ||
32 | import tools.refinery.store.representation.cardinality.UpperCardinalities; | ||
15 | import tools.refinery.store.tuple.Tuple; | 33 | import tools.refinery.store.tuple.Tuple; |
16 | 34 | ||
17 | import java.util.HashMap; | 35 | import java.util.ArrayList; |
36 | import java.util.LinkedHashMap; | ||
18 | import java.util.Map; | 37 | import java.util.Map; |
19 | 38 | ||
20 | public class ModelInitializer { | 39 | public class ModelInitializer { |
21 | @Inject | 40 | @Inject |
22 | private ProblemDesugarer desugarer; | 41 | private ProblemDesugarer desugarer; |
23 | 42 | ||
43 | @Inject | ||
44 | private SemanticsUtils semanticsUtils; | ||
45 | |||
46 | private Problem problem; | ||
47 | |||
48 | private BuiltinSymbols builtinSymbols; | ||
49 | |||
50 | private PartialRelation nodeRelation; | ||
51 | |||
24 | private final MutableObjectIntMap<Node> nodeTrace = ObjectIntMaps.mutable.empty(); | 52 | private final MutableObjectIntMap<Node> nodeTrace = ObjectIntMaps.mutable.empty(); |
25 | 53 | ||
26 | private final Map<tools.refinery.language.model.problem.Relation, Symbol<TruthValue>> relationTrace = | 54 | private final Map<Relation, RelationInfo> relationInfoMap = new LinkedHashMap<>(); |
27 | new HashMap<>(); | ||
28 | 55 | ||
29 | private int nodeCount = 0; | 56 | private Map<Relation, PartialRelation> relationTrace; |
57 | |||
58 | private final MetamodelBuilder metamodelBuilder = Metamodel.builder(); | ||
59 | |||
60 | public int getNodeCount() { | ||
61 | return nodeTrace.size(); | ||
62 | } | ||
63 | |||
64 | public MutableObjectIntMap<Node> getNodeTrace() { | ||
65 | return nodeTrace; | ||
66 | } | ||
30 | 67 | ||
31 | /*public void createModel(Problem problem) { | 68 | public Map<Relation, PartialRelation> getRelationTrace() { |
32 | var builtinSymbols = desugarer.getBuiltinSymbols(problem).orElseThrow(() -> new IllegalArgumentException( | 69 | return relationTrace; |
70 | } | ||
71 | |||
72 | public ModelSeed createModel(Problem problem, ModelStoreBuilder builder) { | ||
73 | this.problem = problem; | ||
74 | builtinSymbols = desugarer.getBuiltinSymbols(problem).orElseThrow(() -> new IllegalArgumentException( | ||
33 | "Problem has no builtin library")); | 75 | "Problem has no builtin library")); |
34 | var collectedSymbols = desugarer.collectSymbols(problem); | 76 | var nodeInfo = collectPartialRelation(builtinSymbols.node(), 1, TruthValue.TRUE, TruthValue.TRUE); |
35 | for (var node : collectedSymbols.nodes().keySet()) { | 77 | nodeRelation = nodeInfo.partialRelation(); |
36 | nodeTrace.put(node, nodeCount); | 78 | metamodelBuilder.type(nodeRelation, true); |
37 | nodeCount += 1; | 79 | relationInfoMap.put(builtinSymbols.exists(), new RelationInfo(ReasoningAdapter.EXISTS_SYMBOL, null, |
38 | } | 80 | TruthValue.TRUE)); |
39 | for (var pair : collectedSymbols.relations().entrySet()) { | 81 | relationInfoMap.put(builtinSymbols.equals(), new RelationInfo(ReasoningAdapter.EQUALS_SYMBOL, (TruthValue) null, |
40 | var relation = pair.getKey(); | 82 | null)); |
41 | var relationInfo = pair.getValue(); | 83 | relationInfoMap.put(builtinSymbols.contained(), new RelationInfo(ContainmentHierarchyTranslator.CONTAINED_SYMBOL, |
42 | var isEqualsRelation = relation == builtinSymbols.equals(); | 84 | null, TruthValue.UNKNOWN)); |
43 | var decisionTree = mergeAssertions(relationInfo, isEqualsRelation); | 85 | relationInfoMap.put(builtinSymbols.contains(), new RelationInfo(ContainmentHierarchyTranslator.CONTAINS_SYMBOL, |
44 | var defaultValue = isEqualsRelation ? TruthValue.FALSE : TruthValue.UNKNOWN; | 86 | null, TruthValue.UNKNOWN)); |
45 | relationTrace.put(relation, Symbol.of( | 87 | relationInfoMap.put(builtinSymbols.invalidNumberOfContainers(), |
46 | relationInfo.name(), relationInfo.arity(), TruthValue.class, defaultValue)); | 88 | new RelationInfo(ContainmentHierarchyTranslator.INVALID_NUMBER_OF_CONTAINERS, TruthValue.FALSE, |
47 | } | 89 | TruthValue.FALSE)); |
48 | } | 90 | collectNodes(); |
49 | 91 | collectPartialSymbols(); | |
50 | private DecisionTree mergeAssertions(RelationInfo relationInfo, boolean isEqualsRelation) { | 92 | collectAssertions(); |
51 | var arity = relationInfo.arity(); | 93 | var metamodel = metamodelBuilder.build(); |
52 | var defaultAssertions = new DecisionTree(arity, isEqualsRelation ? null : TruthValue.UNKNOWN); | 94 | builder.with(ReasoningAdapter.builder()); |
53 | var assertions = new DecisionTree(arity); | 95 | builder.with(new MultiObjectTranslator()); |
54 | for (var assertion : relationInfo.assertions()) { | 96 | builder.with(new MetamodelTranslator(metamodel)); |
55 | var tuple = getTuple(assertion); | 97 | relationTrace = new LinkedHashMap<>(relationInfoMap.size()); |
56 | var value = getTruthValue(assertion.getValue()); | 98 | int nodeCount = getNodeCount(); |
57 | if (assertion.isDefault()) { | 99 | var modelSeedBuilder = ModelSeed.builder(nodeCount); |
58 | defaultAssertions.mergeValue(tuple, value); | 100 | for (var entry : relationInfoMap.entrySet()) { |
101 | var relation = entry.getKey(); | ||
102 | var info = entry.getValue(); | ||
103 | var partialRelation = info.partialRelation(); | ||
104 | relationTrace.put(relation, partialRelation); | ||
105 | modelSeedBuilder.seed(partialRelation, info.toSeed(nodeCount)); | ||
106 | } | ||
107 | return modelSeedBuilder.build(); | ||
108 | } | ||
109 | |||
110 | private void collectNodes() { | ||
111 | for (var statement : problem.getStatements()) { | ||
112 | if (statement instanceof IndividualDeclaration individualDeclaration) { | ||
113 | for (var individual : individualDeclaration.getNodes()) { | ||
114 | collectNode(individual); | ||
115 | } | ||
116 | } else if (statement instanceof ClassDeclaration classDeclaration) { | ||
117 | var newNode = classDeclaration.getNewNode(); | ||
118 | if (newNode != null) { | ||
119 | collectNode(newNode); | ||
120 | } | ||
121 | } else if (statement instanceof EnumDeclaration enumDeclaration) { | ||
122 | for (var literal : enumDeclaration.getLiterals()) { | ||
123 | collectNode(literal); | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | for (var node : problem.getNodes()) { | ||
128 | collectNode(node); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | private void collectNode(Node node) { | ||
133 | nodeTrace.getIfAbsentPut(node, this::getNodeCount); | ||
134 | } | ||
135 | |||
136 | private void collectPartialSymbols() { | ||
137 | for (var statement : problem.getStatements()) { | ||
138 | if (statement instanceof ClassDeclaration classDeclaration) { | ||
139 | collectClassDeclaration(classDeclaration); | ||
140 | } else if (statement instanceof EnumDeclaration enumDeclaration) { | ||
141 | collectPartialRelation(enumDeclaration, 1, null, TruthValue.FALSE); | ||
142 | } else if (statement instanceof PredicateDefinition predicateDefinition) { | ||
143 | // TODO Implement predicate definitions | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | |||
148 | private void collectClassDeclaration(ClassDeclaration classDeclaration) { | ||
149 | collectPartialRelation(classDeclaration, 1, null, TruthValue.UNKNOWN); | ||
150 | for (var featureDeclaration : classDeclaration.getFeatureDeclarations()) { | ||
151 | if (featureDeclaration instanceof ReferenceDeclaration referenceDeclaration) { | ||
152 | collectPartialRelation(referenceDeclaration, 2, null, TruthValue.UNKNOWN); | ||
153 | var invalidMultiplicityConstraint = referenceDeclaration.getInvalidMultiplicity(); | ||
154 | if (invalidMultiplicityConstraint != null) { | ||
155 | collectPartialRelation(invalidMultiplicityConstraint, 1, TruthValue.FALSE, TruthValue.FALSE); | ||
156 | } | ||
59 | } else { | 157 | } else { |
60 | assertions.mergeValue(tuple, value); | 158 | throw new IllegalArgumentException("Unknown feature declaration: " + featureDeclaration); |
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | private RelationInfo collectPartialRelation(Relation relation, int arity, TruthValue value, | ||
164 | TruthValue defaultValue) { | ||
165 | return relationInfoMap.computeIfAbsent(relation, key -> { | ||
166 | var name = getName(relation); | ||
167 | return new RelationInfo(name, arity, value, defaultValue); | ||
168 | }); | ||
169 | } | ||
170 | |||
171 | private String getName(Relation relation) { | ||
172 | return semanticsUtils.getName(relation).orElseGet(() -> "#" + relationInfoMap.size()); | ||
173 | } | ||
174 | |||
175 | private void collectAssertions() { | ||
176 | for (var statement : problem.getStatements()) { | ||
177 | if (statement instanceof ClassDeclaration classDeclaration) { | ||
178 | collectClassDeclarationAssertions(classDeclaration); | ||
179 | } else if (statement instanceof EnumDeclaration enumDeclaration) { | ||
180 | collectEnumAssertions(enumDeclaration); | ||
181 | } else if (statement instanceof IndividualDeclaration individualDeclaration) { | ||
182 | for (var individual : individualDeclaration.getNodes()) { | ||
183 | collectIndividualAssertions(individual); | ||
184 | } | ||
185 | } else if (statement instanceof Assertion assertion) { | ||
186 | collectAssertion(assertion); | ||
61 | } | 187 | } |
62 | } | 188 | } |
63 | defaultAssertions.overwriteValues(assertions); | 189 | } |
64 | if (isEqualsRelation) { | 190 | |
65 | for (int i = 0; i < nodeCount; i++) { | 191 | private void collectClassDeclarationAssertions(ClassDeclaration classDeclaration) { |
66 | defaultAssertions.setIfMissing(Tuple.of(i, i), TruthValue.TRUE); | 192 | var superTypes = classDeclaration.getSuperTypes(); |
193 | var partialSuperTypes = new ArrayList<PartialRelation>(superTypes.size() + 1); | ||
194 | partialSuperTypes.add(nodeRelation); | ||
195 | for (var superType : superTypes) { | ||
196 | partialSuperTypes.add(getRelationInfo(superType).partialRelation()); | ||
197 | } | ||
198 | var info = getRelationInfo(classDeclaration); | ||
199 | metamodelBuilder.type(info.partialRelation(), classDeclaration.isAbstract(), | ||
200 | partialSuperTypes); | ||
201 | var newNode = classDeclaration.getNewNode(); | ||
202 | if (newNode != null) { | ||
203 | var newNodeId = getNodeId(newNode); | ||
204 | collectCardinalityAssertions(newNodeId, TruthValue.UNKNOWN); | ||
205 | mergeValue(classDeclaration, Tuple.of(newNodeId), TruthValue.TRUE); | ||
206 | } | ||
207 | for (var featureDeclaration : classDeclaration.getFeatureDeclarations()) { | ||
208 | if (featureDeclaration instanceof ReferenceDeclaration referenceDeclaration) { | ||
209 | collectReferenceDeclarationAssertions(classDeclaration, referenceDeclaration); | ||
210 | } else { | ||
211 | throw new IllegalArgumentException("Unknown feature declaration: " + featureDeclaration); | ||
67 | } | 212 | } |
68 | defaultAssertions.setAllMissing(TruthValue.FALSE); | ||
69 | } | 213 | } |
70 | return defaultAssertions; | 214 | } |
71 | }*/ | 215 | |
216 | private void collectReferenceDeclarationAssertions(ClassDeclaration classDeclaration, | ||
217 | ReferenceDeclaration referenceDeclaration) { | ||
218 | var relation = getRelationInfo(referenceDeclaration).partialRelation(); | ||
219 | var source = getRelationInfo(classDeclaration).partialRelation(); | ||
220 | var target = getRelationInfo(referenceDeclaration.getReferenceType()).partialRelation(); | ||
221 | boolean containment = referenceDeclaration.getKind() == ReferenceKind.CONTAINMENT; | ||
222 | var opposite = referenceDeclaration.getOpposite(); | ||
223 | PartialRelation oppositeRelation = null; | ||
224 | if (opposite != null) { | ||
225 | oppositeRelation = getRelationInfo(opposite).partialRelation(); | ||
226 | } | ||
227 | var multiplicity = getMultiplicityConstraint(referenceDeclaration); | ||
228 | metamodelBuilder.reference(relation, source, containment, multiplicity, target, oppositeRelation); | ||
229 | } | ||
230 | |||
231 | private Multiplicity getMultiplicityConstraint(ReferenceDeclaration referenceDeclaration) { | ||
232 | if (!ProblemUtil.hasMultiplicityConstraint(referenceDeclaration)) { | ||
233 | return UnconstrainedMultiplicity.INSTANCE; | ||
234 | } | ||
235 | var problemMultiplicity = referenceDeclaration.getMultiplicity(); | ||
236 | CardinalityInterval interval; | ||
237 | if (problemMultiplicity == null) { | ||
238 | interval = CardinalityIntervals.LONE; | ||
239 | } else if (problemMultiplicity instanceof ExactMultiplicity exactMultiplicity) { | ||
240 | interval = CardinalityIntervals.exactly(exactMultiplicity.getExactValue()); | ||
241 | } else if (problemMultiplicity instanceof RangeMultiplicity rangeMultiplicity) { | ||
242 | var upperBound = rangeMultiplicity.getUpperBound(); | ||
243 | interval = CardinalityIntervals.between(rangeMultiplicity.getLowerBound(), | ||
244 | upperBound < 0 ? UpperCardinalities.UNBOUNDED : UpperCardinalities.atMost(upperBound)); | ||
245 | } else { | ||
246 | throw new IllegalArgumentException("Unknown multiplicity: " + problemMultiplicity); | ||
247 | } | ||
248 | var constraint = getRelationInfo(referenceDeclaration.getInvalidMultiplicity()).partialRelation(); | ||
249 | return ConstrainedMultiplicity.of(interval, constraint); | ||
250 | } | ||
251 | |||
252 | private void collectEnumAssertions(EnumDeclaration enumDeclaration) { | ||
253 | var info = getRelationInfo(enumDeclaration); | ||
254 | metamodelBuilder.type(info.partialRelation(), nodeRelation); | ||
255 | var overlay = new DecisionTree(1, null); | ||
256 | for (var literal : enumDeclaration.getLiterals()) { | ||
257 | collectIndividualAssertions(literal); | ||
258 | var nodeId = getNodeId(literal); | ||
259 | overlay.mergeValue(Tuple.of(nodeId), TruthValue.TRUE); | ||
260 | } | ||
261 | info.assertions().overwriteValues(overlay); | ||
262 | } | ||
263 | |||
264 | private void collectIndividualAssertions(Node node) { | ||
265 | var nodeId = getNodeId(node); | ||
266 | collectCardinalityAssertions(nodeId, TruthValue.TRUE); | ||
267 | } | ||
268 | |||
269 | private void collectCardinalityAssertions(int nodeId, TruthValue value) { | ||
270 | mergeValue(builtinSymbols.exists(), Tuple.of(nodeId), value); | ||
271 | mergeValue(builtinSymbols.equals(), Tuple.of(nodeId, nodeId), value); | ||
272 | } | ||
273 | |||
274 | private void collectAssertion(Assertion assertion) { | ||
275 | var relation = assertion.getRelation(); | ||
276 | var tuple = getTuple(assertion); | ||
277 | var value = getTruthValue(assertion.getValue()); | ||
278 | if (assertion.isDefault()) { | ||
279 | mergeDefaultValue(relation, tuple, value); | ||
280 | } else { | ||
281 | mergeValue(relation, tuple, value); | ||
282 | } | ||
283 | } | ||
284 | |||
285 | private void mergeValue(Relation relation, Tuple key, TruthValue value) { | ||
286 | getRelationInfo(relation).assertions().mergeValue(key, value); | ||
287 | } | ||
288 | |||
289 | private void mergeDefaultValue(Relation relation, Tuple key, TruthValue value) { | ||
290 | getRelationInfo(relation).defaultAssertions().mergeValue(key, value); | ||
291 | } | ||
292 | |||
293 | private RelationInfo getRelationInfo(Relation relation) { | ||
294 | var info = relationInfoMap.get(relation); | ||
295 | if (info == null) { | ||
296 | throw new IllegalArgumentException("Unknown relation: " + relation); | ||
297 | } | ||
298 | return info; | ||
299 | } | ||
300 | |||
301 | private int getNodeId(Node node) { | ||
302 | return nodeTrace.getOrThrow(node); | ||
303 | } | ||
72 | 304 | ||
73 | private Tuple getTuple(Assertion assertion) { | 305 | private Tuple getTuple(Assertion assertion) { |
74 | var arguments = assertion.getArguments(); | 306 | var arguments = assertion.getArguments(); |
@@ -77,7 +309,7 @@ public class ModelInitializer { | |||
77 | for (int i = 0; i < arity; i++) { | 309 | for (int i = 0; i < arity; i++) { |
78 | var argument = arguments.get(i); | 310 | var argument = arguments.get(i); |
79 | if (argument instanceof NodeAssertionArgument nodeArgument) { | 311 | if (argument instanceof NodeAssertionArgument nodeArgument) { |
80 | nodes[i] = nodeTrace.getOrThrow(nodeArgument.getNode()); | 312 | nodes[i] = getNodeId(nodeArgument.getNode()); |
81 | } else if (argument instanceof WildcardAssertionArgument) { | 313 | } else if (argument instanceof WildcardAssertionArgument) { |
82 | nodes[i] = -1; | 314 | nodes[i] = -1; |
83 | } else { | 315 | } else { |
@@ -98,4 +330,27 @@ public class ModelInitializer { | |||
98 | case ERROR -> TruthValue.ERROR; | 330 | case ERROR -> TruthValue.ERROR; |
99 | }; | 331 | }; |
100 | } | 332 | } |
333 | |||
334 | private record RelationInfo(PartialRelation partialRelation, DecisionTree assertions, | ||
335 | DecisionTree defaultAssertions) { | ||
336 | public RelationInfo(String name, int arity, TruthValue value, TruthValue defaultValue) { | ||
337 | this(new PartialRelation(name, arity), value, defaultValue); | ||
338 | } | ||
339 | |||
340 | public RelationInfo(PartialRelation partialRelation, TruthValue value, TruthValue defaultValue) { | ||
341 | this(partialRelation, new DecisionTree(partialRelation.arity(), value), | ||
342 | new DecisionTree(partialRelation.arity(), defaultValue)); | ||
343 | } | ||
344 | |||
345 | public Seed<TruthValue> toSeed(int nodeCount) { | ||
346 | defaultAssertions.overwriteValues(assertions); | ||
347 | if (partialRelation.equals(ReasoningAdapter.EQUALS_SYMBOL)) { | ||
348 | for (int i = 0; i < nodeCount; i++) { | ||
349 | defaultAssertions.setIfMissing(Tuple.of(i, i), TruthValue.TRUE); | ||
350 | } | ||
351 | defaultAssertions.setAllMissing(TruthValue.FALSE); | ||
352 | } | ||
353 | return defaultAssertions; | ||
354 | } | ||
355 | } | ||
101 | } | 356 | } |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/SemanticsUtils.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/SemanticsUtils.java new file mode 100644 index 00000000..47c89e9b --- /dev/null +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/SemanticsUtils.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.semantics.model; | ||
7 | |||
8 | import com.google.inject.Inject; | ||
9 | import com.google.inject.Singleton; | ||
10 | import org.eclipse.emf.ecore.EObject; | ||
11 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | ||
12 | import org.eclipse.xtext.naming.IQualifiedNameProvider; | ||
13 | |||
14 | import java.util.Optional; | ||
15 | |||
16 | @Singleton | ||
17 | public class SemanticsUtils { | ||
18 | @Inject | ||
19 | private IQualifiedNameProvider qualifiedNameProvider; | ||
20 | |||
21 | @Inject | ||
22 | private IQualifiedNameConverter qualifiedNameConverter; | ||
23 | |||
24 | public Optional<String> getName(EObject eObject) { | ||
25 | var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(eObject); | ||
26 | if (qualifiedName == null) { | ||
27 | return Optional.empty(); | ||
28 | } | ||
29 | return Optional.of(qualifiedNameConverter.toString(qualifiedName)); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java index c1afecf9..d693dec3 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java | |||
@@ -7,10 +7,11 @@ package tools.refinery.language.semantics.model.internal; | |||
7 | 7 | ||
8 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; | 8 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; |
9 | import tools.refinery.store.map.Cursor; | 9 | import tools.refinery.store.map.Cursor; |
10 | import tools.refinery.store.reasoning.seed.Seed; | ||
10 | import tools.refinery.store.tuple.Tuple; | 11 | import tools.refinery.store.tuple.Tuple; |
11 | import tools.refinery.store.representation.TruthValue; | 12 | import tools.refinery.store.representation.TruthValue; |
12 | 13 | ||
13 | public class DecisionTree { | 14 | public class DecisionTree implements Seed<TruthValue> { |
14 | private final int levels; | 15 | private final int levels; |
15 | 16 | ||
16 | private final DecisionTreeNode root; | 17 | private final DecisionTreeNode root; |
@@ -29,6 +30,22 @@ public class DecisionTree { | |||
29 | this(levels, null); | 30 | this(levels, null); |
30 | } | 31 | } |
31 | 32 | ||
33 | @Override | ||
34 | public int arity() { | ||
35 | return levels; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public Class<TruthValue> valueType() { | ||
40 | return TruthValue.class; | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public TruthValue reducedValue() { | ||
45 | return root.getReducedValue().getTruthValue(); | ||
46 | } | ||
47 | |||
48 | @Override | ||
32 | public TruthValue get(Tuple tuple) { | 49 | public TruthValue get(Tuple tuple) { |
33 | return root.getValue(levels - 1, tuple).getTruthValue(); | 50 | return root.getValue(levels - 1, tuple).getTruthValue(); |
34 | } | 51 | } |
@@ -60,6 +77,7 @@ public class DecisionTree { | |||
60 | return reducedValue == null ? null : reducedValue.getTruthValue(); | 77 | return reducedValue == null ? null : reducedValue.getTruthValue(); |
61 | } | 78 | } |
62 | 79 | ||
80 | @Override | ||
63 | public Cursor<Tuple, TruthValue> getCursor(TruthValue defaultValue, int nodeCount) { | 81 | public Cursor<Tuple, TruthValue> getCursor(TruthValue defaultValue, int nodeCount) { |
64 | return new DecisionTreeCursor(levels, defaultValue, nodeCount, root); | 82 | return new DecisionTreeCursor(levels, defaultValue, nodeCount, root); |
65 | } | 83 | } |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java index 9a1e15a3..a9fc644a 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java | |||
@@ -67,6 +67,15 @@ class DecisionTreeCursor implements Cursor<Tuple, TruthValue> { | |||
67 | 67 | ||
68 | @Override | 68 | @Override |
69 | public boolean move() { | 69 | public boolean move() { |
70 | while (moveOne()) { | ||
71 | if (!value.equals(defaultValue)) { | ||
72 | return true; | ||
73 | } | ||
74 | } | ||
75 | return false; | ||
76 | } | ||
77 | |||
78 | private boolean moveOne() { | ||
70 | boolean found = false; | 79 | boolean found = false; |
71 | if (path.isEmpty() && !terminated) { | 80 | if (path.isEmpty() && !terminated) { |
72 | found = root.moveNext(levels - 1, this); | 81 | found = root.moveNext(levels - 1, this); |
diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java index b3fcbabb..3c43d3bd 100644 --- a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java +++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java | |||
@@ -134,6 +134,17 @@ class DecisionTreeTests { | |||
134 | } | 134 | } |
135 | 135 | ||
136 | @Test | 136 | @Test |
137 | void overwriteIterationTest() { | ||
138 | var sut = new DecisionTree(1, TruthValue.TRUE); | ||
139 | var overwrite = new DecisionTree(1, null); | ||
140 | overwrite.mergeValue(Tuple.of(0), TruthValue.UNKNOWN); | ||
141 | sut.overwriteValues(overwrite); | ||
142 | var map = iterateAll(sut, TruthValue.UNKNOWN, 2); | ||
143 | assertThat(map.keySet(), hasSize(1)); | ||
144 | assertThat(map, hasEntry(Tuple.of(1), TruthValue.TRUE)); | ||
145 | } | ||
146 | |||
147 | @Test | ||
137 | void overwriteNothingTest() { | 148 | void overwriteNothingTest() { |
138 | var sut = new DecisionTree(2, TruthValue.UNKNOWN); | 149 | var sut = new DecisionTree(2, TruthValue.UNKNOWN); |
139 | var values = new DecisionTree(2, null); | 150 | var values = new DecisionTree(2, null); |