diff options
author | Kristóf Marussy <kristof@marussy.com> | 2023-08-17 17:07:12 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2023-08-17 17:07:12 +0200 |
commit | 263e7c025ab19573fba087f050b9dc1f1ade193f (patch) | |
tree | f6aed07a24e179f0db9d0e463dfad7ef2eb6ad4b | |
parent | feat: basic semantics mapping and visualization (diff) | |
download | refinery-263e7c025ab19573fba087f050b9dc1f1ade193f.tar.gz refinery-263e7c025ab19573fba087f050b9dc1f1ade193f.tar.zst refinery-263e7c025ab19573fba087f050b9dc1f1ade193f.zip |
fix: containment link translation
Improper equality implementation of representative election literals merged weak
and strong connected components during query canonicalization.
4 files changed, 72 insertions, 5 deletions
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsService.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsService.java index 483d24f6..eb7ab204 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsService.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsService.java | |||
@@ -54,7 +54,10 @@ public class SemanticsService extends AbstractCachedService<SemanticsResult> { | |||
54 | 54 | ||
55 | @Override | 55 | @Override |
56 | public SemanticsResult compute(IXtextWebDocument doc, CancelIndicator cancelIndicator) { | 56 | public SemanticsResult compute(IXtextWebDocument doc, CancelIndicator cancelIndicator) { |
57 | long start = System.currentTimeMillis(); | 57 | long start = 0; |
58 | if (LOG.isTraceEnabled()) { | ||
59 | start = System.currentTimeMillis(); | ||
60 | } | ||
58 | Problem problem = getProblem(doc, cancelIndicator); | 61 | Problem problem = getProblem(doc, cancelIndicator); |
59 | if (problem == null) { | 62 | if (problem == null) { |
60 | return null; | 63 | return null; |
@@ -73,8 +76,11 @@ public class SemanticsService extends AbstractCachedService<SemanticsResult> { | |||
73 | var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed); | 76 | var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed); |
74 | operationCanceledManager.checkCanceled(cancelIndicator); | 77 | operationCanceledManager.checkCanceled(cancelIndicator); |
75 | var partialInterpretation = getPartialInterpretation(initializer, model, cancelIndicator); | 78 | var partialInterpretation = getPartialInterpretation(initializer, model, cancelIndicator); |
76 | long end = System.currentTimeMillis(); | 79 | if (LOG.isTraceEnabled()) { |
77 | LOG.info("Computed semantics for {} ({}) in {}ms", doc.getResourceId(), doc.getStateId(), end - start); | 80 | long end = System.currentTimeMillis(); |
81 | LOG.trace("Computed semantics for {} ({}) in {}ms", doc.getResourceId(), doc.getStateId(), | ||
82 | end - start); | ||
83 | } | ||
78 | return new SemanticsSuccessResult(nodeTrace, partialInterpretation); | 84 | return new SemanticsSuccessResult(nodeTrace, partialInterpretation); |
79 | } catch (RuntimeException e) { | 85 | } catch (RuntimeException e) { |
80 | LOG.error("Error while computing semantics", e); | 86 | LOG.error("Error while computing semantics", e); |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/RepresentativeElectionLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/RepresentativeElectionLiteral.java index 5d57c06c..f6545f9f 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/RepresentativeElectionLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/RepresentativeElectionLiteral.java | |||
@@ -6,6 +6,8 @@ | |||
6 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
7 | 7 | ||
8 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
10 | import tools.refinery.store.query.equality.LiteralHashCodeHelper; | ||
9 | import tools.refinery.store.query.substitution.Substitution; | 11 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.NodeVariable; | 12 | import tools.refinery.store.query.term.NodeVariable; |
11 | import tools.refinery.store.query.term.ParameterDirection; | 13 | import tools.refinery.store.query.term.ParameterDirection; |
@@ -82,6 +84,20 @@ public class RepresentativeElectionLiteral extends AbstractCallLiteral { | |||
82 | } | 84 | } |
83 | 85 | ||
84 | @Override | 86 | @Override |
87 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, Literal other) { | ||
88 | if (!super.equalsWithSubstitution(helper, other)) { | ||
89 | return false; | ||
90 | } | ||
91 | var otherRepresentativeElectionLiteral = (RepresentativeElectionLiteral) other; | ||
92 | return connectivity.equals(otherRepresentativeElectionLiteral.connectivity); | ||
93 | } | ||
94 | |||
95 | @Override | ||
96 | public int hashCodeWithSubstitution(LiteralHashCodeHelper helper) { | ||
97 | return super.hashCodeWithSubstitution(helper) * 31 + connectivity.hashCode(); | ||
98 | } | ||
99 | |||
100 | @Override | ||
85 | public String toString() { | 101 | public String toString() { |
86 | var builder = new StringBuilder(); | 102 | var builder = new StringBuilder(); |
87 | builder.append("@Representative(\""); | 103 | builder.append("@Representative(\""); |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/containment/ContainmentHierarchyTranslator.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/containment/ContainmentHierarchyTranslator.java index 9d1b8cf4..eb112d0e 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/containment/ContainmentHierarchyTranslator.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/containment/ContainmentHierarchyTranslator.java | |||
@@ -156,7 +156,7 @@ public class ContainmentHierarchyTranslator implements ModelStoreConfiguration { | |||
156 | ) | 156 | ) |
157 | .clause(representative -> List.of( | 157 | .clause(representative -> List.of( |
158 | mayNewHelper.call(parent, child), | 158 | mayNewHelper.call(parent, child), |
159 | weakComponents.call(child, representative), | 159 | weakComponents.call(parent, representative), |
160 | // Violation of para-consistency: | 160 | // Violation of para-consistency: |
161 | // If there is a surely existing node with at least two containers, its (transitive) containers | 161 | // If there is a surely existing node with at least two containers, its (transitive) containers |
162 | // will end up in the same weakly connected component, and we will spuriously mark the | 162 | // will end up in the same weakly connected component, and we will spuriously mark the |
@@ -178,7 +178,7 @@ public class ContainmentHierarchyTranslator implements ModelStoreConfiguration { | |||
178 | .clause(representative -> List.of( | 178 | .clause(representative -> List.of( |
179 | mayExistingHelper.call(parent, child), | 179 | mayExistingHelper.call(parent, child), |
180 | strongComponents.call(parent, representative), | 180 | strongComponents.call(parent, representative), |
181 | not(strongComponents.call(parent, representative)) | 181 | not(strongComponents.call(child, representative)) |
182 | ))); | 182 | ))); |
183 | 183 | ||
184 | storeBuilder.with(PartialRelationTranslator.of(linkType) | 184 | storeBuilder.with(PartialRelationTranslator.of(linkType) |
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java index 9e74cf02..87e28e80 100644 --- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java | |||
@@ -105,4 +105,49 @@ class MetamodelTest { | |||
105 | assertThat(enrolledStudentsInterpretation.get(Tuple.of(1, 3)), is(TruthValue.FALSE)); | 105 | assertThat(enrolledStudentsInterpretation.get(Tuple.of(1, 3)), is(TruthValue.FALSE)); |
106 | assertThat(enrolledStudentsInterpretation.get(Tuple.of(1, 4)), is(TruthValue.UNKNOWN)); | 106 | assertThat(enrolledStudentsInterpretation.get(Tuple.of(1, 4)), is(TruthValue.UNKNOWN)); |
107 | } | 107 | } |
108 | |||
109 | @Test | ||
110 | void simpleContainmentTest() { | ||
111 | var metamodel = Metamodel.builder() | ||
112 | .type(university) | ||
113 | .type(course) | ||
114 | .reference(courses, university, true, course) | ||
115 | .build(); | ||
116 | |||
117 | var store = ModelStore.builder() | ||
118 | .with(ViatraModelQueryAdapter.builder()) | ||
119 | .with(ReasoningAdapter.builder()) | ||
120 | .with(new MultiObjectTranslator()) | ||
121 | .with(new MetamodelTranslator(metamodel)) | ||
122 | .build(); | ||
123 | |||
124 | var seed = ModelSeed.builder(4) | ||
125 | .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
126 | .reducedValue(CardinalityIntervals.ONE) | ||
127 | .put(Tuple.of(0), CardinalityIntervals.SET) | ||
128 | .put(Tuple.of(1), CardinalityIntervals.SET)) | ||
129 | .seed(ContainmentHierarchyTranslator.CONTAINED_SYMBOL, builder -> builder | ||
130 | .reducedValue(TruthValue.UNKNOWN)) | ||
131 | .seed(ContainmentHierarchyTranslator.CONTAINS_SYMBOL, builder -> builder | ||
132 | .reducedValue(TruthValue.UNKNOWN)) | ||
133 | .seed(university, builder -> builder | ||
134 | .reducedValue(TruthValue.UNKNOWN) | ||
135 | .put(Tuple.of(0), TruthValue.TRUE)) | ||
136 | .seed(course, builder -> builder | ||
137 | .reducedValue(TruthValue.UNKNOWN) | ||
138 | .put(Tuple.of(1), TruthValue.TRUE)) | ||
139 | .seed(courses, builder -> builder | ||
140 | .reducedValue(TruthValue.UNKNOWN) | ||
141 | .put(Tuple.of(2, 3), TruthValue.TRUE)) | ||
142 | .build(); | ||
143 | |||
144 | var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(seed); | ||
145 | var coursesInterpretation = model.getAdapter(ReasoningAdapter.class) | ||
146 | .getPartialInterpretation(Concreteness.PARTIAL, courses); | ||
147 | |||
148 | assertThat(coursesInterpretation.get(Tuple.of(0, 1)), is(TruthValue.UNKNOWN)); | ||
149 | assertThat(coursesInterpretation.get(Tuple.of(0, 3)), is(TruthValue.FALSE)); | ||
150 | assertThat(coursesInterpretation.get(Tuple.of(2, 1)), is(TruthValue.UNKNOWN)); | ||
151 | assertThat(coursesInterpretation.get(Tuple.of(2, 3)), is(TruthValue.TRUE)); | ||
152 | } | ||
108 | } | 153 | } |