diff options
36 files changed, 777 insertions, 614 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java b/subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java new file mode 100644 index 00000000..708e10a9 --- /dev/null +++ b/subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java | |||
@@ -0,0 +1,17 @@ | |||
1 | package tools.refinery.language.utils; | ||
2 | |||
3 | import tools.refinery.language.model.problem.PredicateKind; | ||
4 | |||
5 | public enum ContainmentRole { | ||
6 | NONE, | ||
7 | CONTAINED, | ||
8 | CONTAINMENT; | ||
9 | |||
10 | public static ContainmentRole fromPredicateKind(PredicateKind predicateKind) { | ||
11 | return switch (predicateKind) { | ||
12 | case CONTAINED -> CONTAINED; | ||
13 | case CONTAINMENT -> CONTAINMENT; | ||
14 | default -> NONE; | ||
15 | }; | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java index a63abc3a..702eb659 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraQueryableModelStore.java | |||
@@ -5,9 +5,11 @@ import tools.refinery.store.model.ModelDiffCursor; | |||
5 | import tools.refinery.store.model.ModelStore; | 5 | import tools.refinery.store.model.ModelStore; |
6 | import tools.refinery.store.model.ModelStoreImpl; | 6 | import tools.refinery.store.model.ModelStoreImpl; |
7 | import tools.refinery.store.model.representation.DataRepresentation; | 7 | import tools.refinery.store.model.representation.DataRepresentation; |
8 | import tools.refinery.store.query.QueryableModel; | 8 | import tools.refinery.store.query.*; |
9 | import tools.refinery.store.query.QueryableModelStore; | 9 | import tools.refinery.store.query.atom.DNFAtom; |
10 | import tools.refinery.store.query.building.*; | 10 | import tools.refinery.store.query.atom.DNFCallAtom; |
11 | import tools.refinery.store.query.atom.EquivalenceAtom; | ||
12 | import tools.refinery.store.query.atom.RelationViewAtom; | ||
11 | import tools.refinery.store.query.viatra.internal.RawPatternMatcher; | 13 | import tools.refinery.store.query.viatra.internal.RawPatternMatcher; |
12 | import tools.refinery.store.query.viatra.internal.ViatraQueryableModel; | 14 | import tools.refinery.store.query.viatra.internal.ViatraQueryableModel; |
13 | import tools.refinery.store.query.viatra.internal.pquery.DNF2PQuery; | 15 | import tools.refinery.store.query.viatra.internal.pquery.DNF2PQuery; |
@@ -23,10 +25,10 @@ public class ViatraQueryableModelStore implements QueryableModelStore { | |||
23 | 25 | ||
24 | protected final Set<RelationView<?>> relationViews; | 26 | protected final Set<RelationView<?>> relationViews; |
25 | 27 | ||
26 | protected final Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> predicates; | 28 | protected final Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates; |
27 | 29 | ||
28 | public ViatraQueryableModelStore(ModelStore store, Set<RelationView<?>> relationViews, | 30 | public ViatraQueryableModelStore(ModelStore store, Set<RelationView<?>> relationViews, |
29 | Set<DNFPredicate> predicates) { | 31 | Set<DNF> predicates) { |
30 | this.store = store; | 32 | this.store = store; |
31 | validateViews(store.getDataRepresentations(), relationViews); | 33 | validateViews(store.getDataRepresentations(), relationViews); |
32 | this.relationViews = Collections.unmodifiableSet(relationViews); | 34 | this.relationViews = Collections.unmodifiableSet(relationViews); |
@@ -35,7 +37,7 @@ public class ViatraQueryableModelStore implements QueryableModelStore { | |||
35 | } | 37 | } |
36 | 38 | ||
37 | public ViatraQueryableModelStore(Set<DataRepresentation<?, ?>> dataRepresentations, | 39 | public ViatraQueryableModelStore(Set<DataRepresentation<?, ?>> dataRepresentations, |
38 | Set<RelationView<?>> relationViews, Set<DNFPredicate> predicates) { | 40 | Set<RelationView<?>> relationViews, Set<DNF> predicates) { |
39 | this(new ModelStoreImpl(dataRepresentations), relationViews, predicates); | 41 | this(new ModelStoreImpl(dataRepresentations), relationViews, predicates); |
40 | } | 42 | } |
41 | 43 | ||
@@ -49,44 +51,46 @@ public class ViatraQueryableModelStore implements QueryableModelStore { | |||
49 | } | 51 | } |
50 | } | 52 | } |
51 | 53 | ||
52 | private void validatePredicates(Set<RelationView<?>> relationViews, Set<DNFPredicate> predicates) { | 54 | private void validatePredicates(Set<RelationView<?>> relationViews, Set<DNF> predicates) { |
53 | for (DNFPredicate dnfPredicate : predicates) { | 55 | for (DNF dnfPredicate : predicates) { |
54 | for (DNFAnd clause : dnfPredicate.getClauses()) { | 56 | for (DNFAnd clause : dnfPredicate.getClauses()) { |
55 | for (DNFAtom atom : clause.getConstraints()) { | 57 | for (DNFAtom atom : clause.constraints()) { |
56 | if (atom instanceof RelationAtom relationAtom) { | 58 | if (atom instanceof RelationViewAtom relationViewAtom) { |
57 | validateRelationAtom(relationViews, dnfPredicate, relationAtom); | 59 | validateRelationAtom(relationViews, dnfPredicate, relationViewAtom); |
58 | } else if (atom instanceof PredicateAtom predicateAtom) { | 60 | } else if (atom instanceof DNFCallAtom queryCallAtom) { |
59 | validatePredicateAtom(predicates, dnfPredicate, predicateAtom); | 61 | validatePredicateAtom(predicates, dnfPredicate, queryCallAtom); |
62 | } else if (!(atom instanceof EquivalenceAtom)) { | ||
63 | throw new IllegalArgumentException("Unknown constraint: " + atom.toString()); | ||
60 | } | 64 | } |
61 | } | 65 | } |
62 | } | 66 | } |
63 | } | 67 | } |
64 | } | 68 | } |
65 | 69 | ||
66 | private void validateRelationAtom(Set<RelationView<?>> relationViews, DNFPredicate dnfPredicate, | 70 | private void validateRelationAtom(Set<RelationView<?>> relationViews, DNF dnfPredicate, |
67 | RelationAtom relationAtom) { | 71 | RelationViewAtom relationViewAtom) { |
68 | if (!relationViews.contains(relationAtom.view())) { | 72 | if (!relationViews.contains(relationViewAtom.getTarget())) { |
69 | throw new IllegalArgumentException( | 73 | throw new IllegalArgumentException( |
70 | "%s %s contains reference to a view %s that is not in the model.".formatted( | 74 | "%s %s contains reference to a view %s that is not in the model.".formatted( |
71 | DNFPredicate.class.getSimpleName(), dnfPredicate.getUniqueName(), | 75 | DNF.class.getSimpleName(), dnfPredicate.getUniqueName(), |
72 | relationAtom.view().getName())); | 76 | relationViewAtom.getTarget().getName())); |
73 | } | 77 | } |
74 | } | 78 | } |
75 | 79 | ||
76 | private void validatePredicateAtom(Set<DNFPredicate> predicates, DNFPredicate dnfPredicate, | 80 | private void validatePredicateAtom(Set<DNF> predicates, DNF dnfPredicate, |
77 | PredicateAtom predicateAtom) { | 81 | DNFCallAtom queryCallAtom) { |
78 | if (!predicates.contains(predicateAtom.getReferred())) { | 82 | if (!predicates.contains(queryCallAtom.getTarget())) { |
79 | throw new IllegalArgumentException( | 83 | throw new IllegalArgumentException( |
80 | "%s %s contains reference to a predicate %s that is not in the model.".formatted( | 84 | "%s %s contains reference to a predicate %s that is not in the model.".formatted( |
81 | DNFPredicate.class.getSimpleName(), dnfPredicate.getUniqueName(), | 85 | DNF.class.getSimpleName(), dnfPredicate.getUniqueName(), |
82 | predicateAtom.getReferred().getName())); | 86 | queryCallAtom.getTarget().getName())); |
83 | } | 87 | } |
84 | } | 88 | } |
85 | 89 | ||
86 | private Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> initPredicates(Set<DNFPredicate> predicates) { | 90 | private Map<DNF, GenericQuerySpecification<RawPatternMatcher>> initPredicates(Set<DNF> predicates) { |
87 | Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> result = new HashMap<>(); | 91 | Map<DNF, GenericQuerySpecification<RawPatternMatcher>> result = new HashMap<>(); |
88 | var dnf2PQuery = new DNF2PQuery(); | 92 | var dnf2PQuery = new DNF2PQuery(); |
89 | for (DNFPredicate dnfPredicate : predicates) { | 93 | for (DNF dnfPredicate : predicates) { |
90 | GenericQuerySpecification<RawPatternMatcher> query = dnf2PQuery.translate(dnfPredicate).build(); | 94 | GenericQuerySpecification<RawPatternMatcher> query = dnf2PQuery.translate(dnfPredicate).build(); |
91 | result.put(dnfPredicate, query); | 95 | result.put(dnfPredicate, query); |
92 | } | 96 | } |
@@ -105,7 +109,7 @@ public class ViatraQueryableModelStore implements QueryableModelStore { | |||
105 | } | 109 | } |
106 | 110 | ||
107 | @Override | 111 | @Override |
108 | public Set<DNFPredicate> getPredicates() { | 112 | public Set<DNF> getPredicates() { |
109 | return predicates.keySet(); | 113 | return predicates.keySet(); |
110 | } | 114 | } |
111 | 115 | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java index 1c15e8f9..cd9fb180 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java | |||
@@ -12,7 +12,7 @@ import tools.refinery.store.model.representation.DataRepresentation; | |||
12 | import tools.refinery.store.model.representation.Relation; | 12 | import tools.refinery.store.model.representation.Relation; |
13 | import tools.refinery.store.query.QueryableModel; | 13 | import tools.refinery.store.query.QueryableModel; |
14 | import tools.refinery.store.query.QueryableModelStore; | 14 | import tools.refinery.store.query.QueryableModelStore; |
15 | import tools.refinery.store.query.building.DNFPredicate; | 15 | import tools.refinery.store.query.DNF; |
16 | import tools.refinery.store.tuple.Tuple; | 16 | import tools.refinery.store.tuple.Tuple; |
17 | import tools.refinery.store.tuple.TupleLike; | 17 | import tools.refinery.store.tuple.TupleLike; |
18 | 18 | ||
@@ -27,16 +27,16 @@ public class ViatraQueryableModel implements QueryableModel { | |||
27 | 27 | ||
28 | protected final Model model; | 28 | protected final Model model; |
29 | 29 | ||
30 | protected final Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> predicates2PQuery; | 30 | protected final Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates2PQuery; |
31 | 31 | ||
32 | protected RelationalScope scope; | 32 | protected RelationalScope scope; |
33 | 33 | ||
34 | protected AdvancedViatraQueryEngine engine; | 34 | protected AdvancedViatraQueryEngine engine; |
35 | 35 | ||
36 | protected Map<DNFPredicate, RawPatternMatcher> predicate2Matcher; | 36 | protected Map<DNF, RawPatternMatcher> predicate2Matcher; |
37 | 37 | ||
38 | public ViatraQueryableModel(QueryableModelStore store, Model model, | 38 | public ViatraQueryableModel(QueryableModelStore store, Model model, |
39 | Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> predicates2PQuery) { | 39 | Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates2PQuery) { |
40 | this.store = store; | 40 | this.store = store; |
41 | this.model = model; | 41 | this.model = model; |
42 | this.predicates2PQuery = predicates2PQuery; | 42 | this.predicates2PQuery = predicates2PQuery; |
@@ -49,15 +49,15 @@ public class ViatraQueryableModel implements QueryableModel { | |||
49 | this.predicate2Matcher = initMatchers(this.engine, this.predicates2PQuery); | 49 | this.predicate2Matcher = initMatchers(this.engine, this.predicates2PQuery); |
50 | } | 50 | } |
51 | 51 | ||
52 | private Map<DNFPredicate, RawPatternMatcher> initMatchers( | 52 | private Map<DNF, RawPatternMatcher> initMatchers( |
53 | AdvancedViatraQueryEngine engine, | 53 | AdvancedViatraQueryEngine engine, |
54 | Map<DNFPredicate, GenericQuerySpecification<RawPatternMatcher>> predicates2pQuery) { | 54 | Map<DNF, GenericQuerySpecification<RawPatternMatcher>> predicates2pQuery) { |
55 | // 1. prepare group | 55 | // 1. prepare group |
56 | IQueryGroup queryGroup = GenericQueryGroup.of(Set.copyOf(predicates2pQuery.values())); | 56 | IQueryGroup queryGroup = GenericQueryGroup.of(Set.copyOf(predicates2pQuery.values())); |
57 | engine.prepareGroup(queryGroup, null); | 57 | engine.prepareGroup(queryGroup, null); |
58 | 58 | ||
59 | // 2. then get all matchers | 59 | // 2. then get all matchers |
60 | Map<DNFPredicate, RawPatternMatcher> result = new HashMap<>(); | 60 | Map<DNF, RawPatternMatcher> result = new HashMap<>(); |
61 | for (var entry : predicates2pQuery.entrySet()) { | 61 | for (var entry : predicates2pQuery.entrySet()) { |
62 | var matcher = engine.getMatcher(entry.getValue()); | 62 | var matcher = engine.getMatcher(entry.getValue()); |
63 | result.put(entry.getKey(), matcher); | 63 | result.put(entry.getKey(), matcher); |
@@ -71,7 +71,7 @@ public class ViatraQueryableModel implements QueryableModel { | |||
71 | } | 71 | } |
72 | 72 | ||
73 | @Override | 73 | @Override |
74 | public Set<DNFPredicate> getPredicates() { | 74 | public Set<DNF> getPredicates() { |
75 | return store.getPredicates(); | 75 | return store.getPredicates(); |
76 | } | 76 | } |
77 | 77 | ||
@@ -117,7 +117,7 @@ public class ViatraQueryableModel implements QueryableModel { | |||
117 | return model.getSize(representation); | 117 | return model.getSize(representation); |
118 | } | 118 | } |
119 | 119 | ||
120 | protected RawPatternMatcher getMatcher(DNFPredicate predicate) { | 120 | protected RawPatternMatcher getMatcher(DNF predicate) { |
121 | var result = this.predicate2Matcher.get(predicate); | 121 | var result = this.predicate2Matcher.get(predicate); |
122 | if (result == null) { | 122 | if (result == null) { |
123 | throw new IllegalArgumentException("Model does not contain predicate %s".formatted(predicate.getName())); | 123 | throw new IllegalArgumentException("Model does not contain predicate %s".formatted(predicate.getName())); |
@@ -125,8 +125,8 @@ public class ViatraQueryableModel implements QueryableModel { | |||
125 | return result; | 125 | return result; |
126 | } | 126 | } |
127 | 127 | ||
128 | protected void validateParameters(DNFPredicate predicate, Tuple parameters) { | 128 | protected void validateParameters(DNF predicate, Tuple parameters) { |
129 | int predicateArity = predicate.getVariables().size(); | 129 | int predicateArity = predicate.getParameters().size(); |
130 | int parameterArity = parameters.getSize(); | 130 | int parameterArity = parameters.getSize(); |
131 | if (parameterArity != predicateArity) { | 131 | if (parameterArity != predicateArity) { |
132 | throw new IllegalArgumentException( | 132 | throw new IllegalArgumentException( |
@@ -136,45 +136,45 @@ public class ViatraQueryableModel implements QueryableModel { | |||
136 | } | 136 | } |
137 | 137 | ||
138 | @Override | 138 | @Override |
139 | public boolean hasResult(DNFPredicate predicate) { | 139 | public boolean hasResult(DNF predicate) { |
140 | return getMatcher(predicate).hasResult(); | 140 | return getMatcher(predicate).hasResult(); |
141 | } | 141 | } |
142 | 142 | ||
143 | @Override | 143 | @Override |
144 | public boolean hasResult(DNFPredicate predicate, Tuple parameters) { | 144 | public boolean hasResult(DNF predicate, Tuple parameters) { |
145 | validateParameters(predicate, parameters); | 145 | validateParameters(predicate, parameters); |
146 | return getMatcher(predicate).hasResult(parameters); | 146 | return getMatcher(predicate).hasResult(parameters); |
147 | } | 147 | } |
148 | 148 | ||
149 | @Override | 149 | @Override |
150 | public Optional<TupleLike> oneResult(DNFPredicate predicate) { | 150 | public Optional<TupleLike> oneResult(DNF predicate) { |
151 | return getMatcher(predicate).oneResult(); | 151 | return getMatcher(predicate).oneResult(); |
152 | } | 152 | } |
153 | 153 | ||
154 | @Override | 154 | @Override |
155 | public Optional<TupleLike> oneResult(DNFPredicate predicate, Tuple parameters) { | 155 | public Optional<TupleLike> oneResult(DNF predicate, Tuple parameters) { |
156 | validateParameters(predicate, parameters); | 156 | validateParameters(predicate, parameters); |
157 | return getMatcher(predicate).oneResult(parameters); | 157 | return getMatcher(predicate).oneResult(parameters); |
158 | } | 158 | } |
159 | 159 | ||
160 | @Override | 160 | @Override |
161 | public Stream<TupleLike> allResults(DNFPredicate predicate) { | 161 | public Stream<TupleLike> allResults(DNF predicate) { |
162 | return getMatcher(predicate).allResults(); | 162 | return getMatcher(predicate).allResults(); |
163 | } | 163 | } |
164 | 164 | ||
165 | @Override | 165 | @Override |
166 | public Stream<TupleLike> allResults(DNFPredicate predicate, Tuple parameters) { | 166 | public Stream<TupleLike> allResults(DNF predicate, Tuple parameters) { |
167 | validateParameters(predicate, parameters); | 167 | validateParameters(predicate, parameters); |
168 | return getMatcher(predicate).allResults(parameters); | 168 | return getMatcher(predicate).allResults(parameters); |
169 | } | 169 | } |
170 | 170 | ||
171 | @Override | 171 | @Override |
172 | public int countResults(DNFPredicate predicate) { | 172 | public int countResults(DNF predicate) { |
173 | return getMatcher(predicate).countResults(); | 173 | return getMatcher(predicate).countResults(); |
174 | } | 174 | } |
175 | 175 | ||
176 | @Override | 176 | @Override |
177 | public int countResults(DNFPredicate predicate, Tuple parameters) { | 177 | public int countResults(DNF predicate, Tuple parameters) { |
178 | validateParameters(predicate, parameters); | 178 | validateParameters(predicate, parameters); |
179 | return getMatcher(predicate).countResults(parameters); | 179 | return getMatcher(predicate).countResults(parameters); |
180 | 180 | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java index b6468e76..e3c586a0 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/DNF2PQuery.java | |||
@@ -11,130 +11,124 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.Positi | |||
11 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; | 11 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; |
12 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; | 12 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; |
13 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 13 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
14 | import tools.refinery.store.query.building.*; | 14 | import tools.refinery.store.query.*; |
15 | import tools.refinery.store.query.atom.DNFAtom; | ||
16 | import tools.refinery.store.query.atom.EquivalenceAtom; | ||
17 | import tools.refinery.store.query.atom.DNFCallAtom; | ||
18 | import tools.refinery.store.query.atom.RelationViewAtom; | ||
15 | import tools.refinery.store.query.view.RelationView; | 19 | import tools.refinery.store.query.view.RelationView; |
16 | 20 | ||
17 | import java.util.*; | 21 | import java.util.*; |
18 | import java.util.stream.Collectors; | 22 | import java.util.stream.Collectors; |
19 | 23 | ||
20 | public class DNF2PQuery { | 24 | public class DNF2PQuery { |
21 | private final Set<DNFPredicate> translating = new LinkedHashSet<>(); | 25 | private final Set<DNF> translating = new LinkedHashSet<>(); |
22 | 26 | ||
23 | private final Map<DNFPredicate, SimplePQuery> dnf2PQueryMap = new HashMap<>(); | 27 | private final Map<DNF, SimplePQuery> dnf2PQueryMap = new HashMap<>(); |
24 | 28 | ||
25 | private final Map<RelationView<?>, RelationViewWrapper> view2WrapperMap = new HashMap<>(); | 29 | private final Map<RelationView<?>, RelationViewWrapper> view2WrapperMap = new HashMap<>(); |
26 | 30 | ||
27 | public SimplePQuery translate(DNFPredicate predicate) { | 31 | public SimplePQuery translate(DNF dnfQuery) { |
28 | if (translating.contains(predicate)) { | 32 | if (translating.contains(dnfQuery)) { |
29 | var path = translating.stream().map(DNFPredicate::getName).collect(Collectors.joining(" -> ")); | 33 | var path = translating.stream().map(DNF::getName).collect(Collectors.joining(" -> ")); |
30 | throw new IllegalStateException("Circular reference %s -> %s detected".formatted(path, | 34 | throw new IllegalStateException("Circular reference %s -> %s detected".formatted(path, |
31 | predicate.getName())); | 35 | dnfQuery.getName())); |
32 | } | 36 | } |
33 | // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant | 37 | // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant |
34 | // way, which would cause a ConcurrentModificationException with computeIfAbsent. | 38 | // way, which would cause a ConcurrentModificationException with computeIfAbsent. |
35 | var pQuery = dnf2PQueryMap.get(predicate); | 39 | var pQuery = dnf2PQueryMap.get(dnfQuery); |
36 | if (pQuery == null) { | 40 | if (pQuery == null) { |
37 | translating.add(predicate); | 41 | translating.add(dnfQuery); |
38 | try { | 42 | try { |
39 | pQuery = doTranslate(predicate); | 43 | pQuery = doTranslate(dnfQuery); |
40 | dnf2PQueryMap.put(predicate, pQuery); | 44 | dnf2PQueryMap.put(dnfQuery, pQuery); |
41 | } finally { | 45 | } finally { |
42 | translating.remove(predicate); | 46 | translating.remove(dnfQuery); |
43 | } | 47 | } |
44 | } | 48 | } |
45 | return pQuery; | 49 | return pQuery; |
46 | } | 50 | } |
47 | 51 | ||
48 | private SimplePQuery doTranslate(DNFPredicate predicate) { | 52 | private SimplePQuery doTranslate(DNF dnfQuery) { |
49 | var query = new SimplePQuery(predicate.getName()); | 53 | var pQuery = new SimplePQuery(dnfQuery.getUniqueName()); |
50 | 54 | ||
51 | Map<Variable, PParameter> parameters = new HashMap<>(); | 55 | Map<Variable, PParameter> parameters = new HashMap<>(); |
52 | for (Variable variable : predicate.getVariables()) { | 56 | for (Variable variable : dnfQuery.getParameters()) { |
53 | parameters.put(variable, new PParameter(variable.getName())); | 57 | parameters.put(variable, new PParameter(variable.getUniqueName())); |
54 | } | 58 | } |
55 | 59 | ||
56 | List<PParameter> parameterList = new ArrayList<>(); | 60 | List<PParameter> parameterList = new ArrayList<>(); |
57 | for (var param : predicate.getVariables()) { | 61 | for (var param : dnfQuery.getParameters()) { |
58 | parameterList.add(parameters.get(param)); | 62 | parameterList.add(parameters.get(param)); |
59 | } | 63 | } |
60 | query.setParameters(parameterList); | 64 | pQuery.setParameters(parameterList); |
61 | 65 | ||
62 | for (DNFAnd clause : predicate.getClauses()) { | 66 | for (DNFAnd clause : dnfQuery.getClauses()) { |
63 | PBody body = new PBody(query); | 67 | PBody body = new PBody(pQuery); |
64 | List<ExportedParameter> symbolicParameters = new ArrayList<>(); | 68 | List<ExportedParameter> symbolicParameters = new ArrayList<>(); |
65 | for (var param : predicate.getVariables()) { | 69 | for (var param : dnfQuery.getParameters()) { |
66 | PVariable pVar = body.getOrCreateVariableByName(param.getName()); | 70 | PVariable pVar = body.getOrCreateVariableByName(param.getUniqueName()); |
67 | symbolicParameters.add(new ExportedParameter(body, pVar, parameters.get(param))); | 71 | symbolicParameters.add(new ExportedParameter(body, pVar, parameters.get(param))); |
68 | } | 72 | } |
69 | body.setSymbolicParameters(symbolicParameters); | 73 | body.setSymbolicParameters(symbolicParameters); |
70 | query.addBody(body); | 74 | pQuery.addBody(body); |
71 | for (DNFAtom constraint : clause.getConstraints()) { | 75 | for (DNFAtom constraint : clause.constraints()) { |
72 | translateDNFAtom(constraint, body); | 76 | translateDNFAtom(constraint, body); |
73 | } | 77 | } |
74 | } | 78 | } |
75 | 79 | ||
76 | return query; | 80 | return pQuery; |
77 | } | 81 | } |
78 | 82 | ||
79 | private void translateDNFAtom(DNFAtom constraint, PBody body) { | 83 | private void translateDNFAtom(DNFAtom constraint, PBody body) { |
80 | if (constraint instanceof EquivalenceAtom equivalence) { | 84 | if (constraint instanceof EquivalenceAtom equivalenceAtom) { |
81 | translateEquivalenceAtom(equivalence, body); | 85 | translateEquivalenceAtom(equivalenceAtom, body); |
82 | } | 86 | } else if (constraint instanceof RelationViewAtom relationViewAtom) { |
83 | if (constraint instanceof RelationAtom relation) { | 87 | translateRelationViewAtom(relationViewAtom, body); |
84 | translateRelationAtom(relation, body); | 88 | } else if (constraint instanceof DNFCallAtom dnfCallAtom) { |
85 | } | 89 | translateDNFCallAtom(dnfCallAtom, body); |
86 | if (constraint instanceof PredicateAtom predicate) { | 90 | } else { |
87 | translatePredicateAtom(predicate, body); | 91 | throw new IllegalArgumentException("Unknown constraint: " + constraint.toString()); |
88 | } | 92 | } |
89 | } | 93 | } |
90 | 94 | ||
91 | private void translateEquivalenceAtom(EquivalenceAtom equivalence, PBody body) { | 95 | private void translateEquivalenceAtom(EquivalenceAtom equivalence, PBody body) { |
92 | PVariable varSource = body.getOrCreateVariableByName(equivalence.getLeft().getName()); | 96 | PVariable varSource = body.getOrCreateVariableByName(equivalence.left().getUniqueName()); |
93 | PVariable varTarget = body.getOrCreateVariableByName(equivalence.getRight().getName()); | 97 | PVariable varTarget = body.getOrCreateVariableByName(equivalence.right().getUniqueName()); |
94 | if (equivalence.isPositive()) | 98 | if (equivalence.positive()) { |
95 | new Equality(body, varSource, varTarget); | 99 | new Equality(body, varSource, varTarget); |
96 | else | 100 | } else { |
97 | new Inequality(body, varSource, varTarget); | 101 | new Inequality(body, varSource, varTarget); |
102 | } | ||
98 | } | 103 | } |
99 | 104 | ||
100 | private void translateRelationAtom(RelationAtom relation, PBody body) { | 105 | private void translateRelationViewAtom(RelationViewAtom relationViewAtom, PBody body) { |
101 | if (relation.substitution().size() != relation.view().getArity()) { | 106 | int arity = relationViewAtom.getSubstitution().size(); |
102 | throw new IllegalArgumentException("Arity (%d) does not match parameter numbers (%d)".formatted( | 107 | Object[] variables = new Object[arity]; |
103 | relation.view().getArity(), relation.substitution().size())); | 108 | for (int i = 0; i < arity; i++) { |
104 | } | 109 | var variable = relationViewAtom.getSubstitution().get(i); |
105 | Object[] variables = new Object[relation.substitution().size()]; | 110 | variables[i] = body.getOrCreateVariableByName(variable.getUniqueName()); |
106 | for (int i = 0; i < relation.substitution().size(); i++) { | ||
107 | variables[i] = body.getOrCreateVariableByName(relation.substitution().get(i).getName()); | ||
108 | } | 111 | } |
109 | new TypeConstraint(body, Tuples.flatTupleOf(variables), wrapView(relation.view())); | 112 | new TypeConstraint(body, Tuples.flatTupleOf(variables), wrapView(relationViewAtom.getTarget())); |
110 | } | 113 | } |
111 | 114 | ||
112 | private RelationViewWrapper wrapView(RelationView<?> relationView) { | 115 | private RelationViewWrapper wrapView(RelationView<?> relationView) { |
113 | return view2WrapperMap.computeIfAbsent(relationView, RelationViewWrapper::new); | 116 | return view2WrapperMap.computeIfAbsent(relationView, RelationViewWrapper::new); |
114 | } | 117 | } |
115 | 118 | ||
116 | private void translatePredicateAtom(PredicateAtom predicate, PBody body) { | 119 | private void translateDNFCallAtom(DNFCallAtom queryCallAtom, PBody body) { |
117 | Object[] variables = new Object[predicate.getSubstitution().size()]; | 120 | int arity = queryCallAtom.getSubstitution().size(); |
118 | for (int i = 0; i < predicate.getSubstitution().size(); i++) { | 121 | Object[] variables = new Object[arity]; |
119 | variables[i] = body.getOrCreateVariableByName(predicate.getSubstitution().get(i).getName()); | 122 | for (int i = 0; i < arity; i++) { |
123 | var variable = queryCallAtom.getSubstitution().get(i); | ||
124 | variables[i] = body.getOrCreateVariableByName(variable.getUniqueName()); | ||
120 | } | 125 | } |
121 | var variablesTuple = Tuples.flatTupleOf(variables); | 126 | var variablesTuple = Tuples.flatTupleOf(variables); |
122 | var translatedReferred = translate(predicate.getReferred()); | 127 | var translatedReferred = translate(queryCallAtom.getTarget()); |
123 | if (predicate.isPositive()) { | 128 | switch (queryCallAtom.getKind()) { |
124 | if (predicate.isTransitive()) { | 129 | case POSITIVE -> new PositivePatternCall(body, variablesTuple, translatedReferred); |
125 | if (predicate.getSubstitution().size() != 2) { | 130 | case TRANSITIVE -> new BinaryTransitiveClosure(body, variablesTuple, translatedReferred); |
126 | throw new IllegalArgumentException("Transitive Predicate Atoms must be binary."); | 131 | case NEGATIVE -> new NegativePatternCall(body, variablesTuple, translatedReferred); |
127 | } | ||
128 | new BinaryTransitiveClosure(body, variablesTuple, translatedReferred); | ||
129 | } else { | ||
130 | new PositivePatternCall(body, variablesTuple, translatedReferred); | ||
131 | } | ||
132 | } else { | ||
133 | if (predicate.isTransitive()) { | ||
134 | throw new IllegalArgumentException("Transitive Predicate Atoms cannot be negative."); | ||
135 | } else { | ||
136 | new NegativePatternCall(body, variablesTuple, translatedReferred); | ||
137 | } | ||
138 | } | 132 | } |
139 | } | 133 | } |
140 | } | 134 | } |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java index d6213b02..8984cb2c 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java | |||
@@ -3,9 +3,11 @@ package tools.refinery.store.query.viatra.tests; | |||
3 | import org.junit.jupiter.api.Test; | 3 | import org.junit.jupiter.api.Test; |
4 | import tools.refinery.store.model.representation.Relation; | 4 | import tools.refinery.store.model.representation.Relation; |
5 | import tools.refinery.store.model.representation.TruthValue; | 5 | import tools.refinery.store.model.representation.TruthValue; |
6 | import tools.refinery.store.query.QueryableModel; | 6 | import tools.refinery.store.query.*; |
7 | import tools.refinery.store.query.QueryableModelStore; | 7 | import tools.refinery.store.query.atom.CallKind; |
8 | import tools.refinery.store.query.building.*; | 8 | import tools.refinery.store.query.atom.EquivalenceAtom; |
9 | import tools.refinery.store.query.atom.DNFCallAtom; | ||
10 | import tools.refinery.store.query.atom.RelationViewAtom; | ||
9 | import tools.refinery.store.query.viatra.ViatraQueryableModelStore; | 11 | import tools.refinery.store.query.viatra.ViatraQueryableModelStore; |
10 | import tools.refinery.store.query.view.FilteredRelationView; | 12 | import tools.refinery.store.query.view.FilteredRelationView; |
11 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 13 | import tools.refinery.store.query.view.KeyOnlyRelationView; |
@@ -25,10 +27,11 @@ class QueryTest { | |||
25 | Relation<Boolean> asset = new Relation<>("Asset", 1, false); | 27 | Relation<Boolean> asset = new Relation<>("Asset", 1, false); |
26 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 28 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); |
27 | 29 | ||
28 | List<Variable> parameters = List.of(new Variable("p1")); | 30 | var p1 = new Variable("p1"); |
29 | RelationAtom personRelationAtom = new RelationAtom(personView, parameters); | 31 | DNF predicate = DNF.builder("TypeConstraint") |
30 | DNFAnd clause = new DNFAnd(Collections.emptySet(), List.of(personRelationAtom)); | 32 | .parameters(p1) |
31 | DNFPredicate predicate = new DNFPredicate("TypeConstraint", parameters, List.of(clause)); | 33 | .clause(new RelationViewAtom(personView, p1)) |
34 | .build(); | ||
32 | 35 | ||
33 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, asset), Set.of(personView), | 36 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, asset), Set.of(personView), |
34 | Set.of(predicate)); | 37 | Set.of(predicate)); |
@@ -54,14 +57,14 @@ class QueryTest { | |||
54 | 57 | ||
55 | Variable p1 = new Variable("p1"); | 58 | Variable p1 = new Variable("p1"); |
56 | Variable p2 = new Variable("p2"); | 59 | Variable p2 = new Variable("p2"); |
57 | List<Variable> parameters = Arrays.asList(p1, p2); | 60 | DNF predicate = DNF.builder("RelationConstraint") |
58 | 61 | .parameters(p1, p2) | |
59 | RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); | 62 | .clause( |
60 | RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); | 63 | new RelationViewAtom(personView, p1), |
61 | RelationAtom friendRelationAtom = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); | 64 | new RelationViewAtom(personView, p1), |
62 | DNFAnd clause = new DNFAnd(Collections.emptySet(), | 65 | new RelationViewAtom(friendMustView, p1, p2) |
63 | Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom)); | 66 | ) |
64 | DNFPredicate predicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); | 67 | .build(); |
65 | 68 | ||
66 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 69 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), |
67 | Set.of(personView, friendMustView), Set.of(predicate)); | 70 | Set.of(personView, friendMustView), Set.of(predicate)); |
@@ -93,15 +96,15 @@ class QueryTest { | |||
93 | 96 | ||
94 | Variable p1 = new Variable("p1"); | 97 | Variable p1 = new Variable("p1"); |
95 | Variable p2 = new Variable("p2"); | 98 | Variable p2 = new Variable("p2"); |
96 | List<Variable> parameters = Arrays.asList(p1, p2); | 99 | DNF predicate = DNF.builder("RelationConstraint") |
97 | 100 | .parameters(p1, p2) | |
98 | RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); | 101 | .clause( |
99 | RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); | 102 | new RelationViewAtom(personView, p1), |
100 | RelationAtom friendRelationAtom1 = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); | 103 | new RelationViewAtom(personView, p2), |
101 | RelationAtom friendRelationAtom2 = new RelationAtom(friendMustView, Arrays.asList(p2, p1)); | 104 | new RelationViewAtom(friendMustView, p1, p2), |
102 | DNFAnd clause = new DNFAnd(Collections.emptySet(), | 105 | new RelationViewAtom(friendMustView, p2, p1) |
103 | Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom1, friendRelationAtom2)); | 106 | ) |
104 | DNFPredicate predicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); | 107 | .build(); |
105 | 108 | ||
106 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 109 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), |
107 | Set.of(personView, friendMustView), Set.of(predicate)); | 110 | Set.of(personView, friendMustView), Set.of(predicate)); |
@@ -141,14 +144,14 @@ class QueryTest { | |||
141 | 144 | ||
142 | Variable p1 = new Variable("p1"); | 145 | Variable p1 = new Variable("p1"); |
143 | Variable p2 = new Variable("p2"); | 146 | Variable p2 = new Variable("p2"); |
144 | List<Variable> parameters = List.of(p1); | 147 | DNF predicate = DNF.builder("RelationConstraint") |
145 | 148 | .parameters(p1) | |
146 | RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); | 149 | .clause( |
147 | RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); | 150 | new RelationViewAtom(personView, p1), |
148 | RelationAtom friendRelationAtom = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); | 151 | new RelationViewAtom(personView, p2), |
149 | DNFAnd clause = new DNFAnd(Set.of(p2), | 152 | new RelationViewAtom(friendMustView, p1, p2) |
150 | Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom)); | 153 | ) |
151 | DNFPredicate predicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); | 154 | .build(); |
152 | 155 | ||
153 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 156 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), |
154 | Set.of(personView, friendMustView), Set.of(predicate)); | 157 | Set.of(personView, friendMustView), Set.of(predicate)); |
@@ -182,24 +185,19 @@ class QueryTest { | |||
182 | 185 | ||
183 | Variable p1 = new Variable("p1"); | 186 | Variable p1 = new Variable("p1"); |
184 | Variable p2 = new Variable("p2"); | 187 | Variable p2 = new Variable("p2"); |
185 | List<Variable> parameters = Arrays.asList(p1, p2); | 188 | DNF predicate = DNF.builder("Or") |
186 | 189 | .parameters(p1, p2) | |
187 | // Person-Person friendship | 190 | .clause( |
188 | RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); | 191 | new RelationViewAtom(personView, p1), |
189 | RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); | 192 | new RelationViewAtom(personView, p2), |
190 | RelationAtom friendRelationAtom1 = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); | 193 | new RelationViewAtom(friendMustView, p1, p2) |
191 | DNFAnd clause1 = new DNFAnd(Collections.emptySet(), | 194 | ) |
192 | Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom1)); | 195 | .clause( |
193 | 196 | new RelationViewAtom(animalView, p1), | |
194 | // Animal-Animal friendship | 197 | new RelationViewAtom(animalView, p2), |
195 | RelationAtom animalRelationAtom1 = new RelationAtom(animalView, List.of(p1)); | 198 | new RelationViewAtom(friendMustView, p1, p2) |
196 | RelationAtom animalRelationAtom2 = new RelationAtom(animalView, List.of(p2)); | 199 | ) |
197 | RelationAtom friendRelationAtom2 = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); | 200 | .build(); |
198 | DNFAnd clause2 = new DNFAnd(Collections.emptySet(), | ||
199 | Arrays.asList(animalRelationAtom1, animalRelationAtom2, friendRelationAtom2)); | ||
200 | |||
201 | // No friendship between species | ||
202 | DNFPredicate predicate = new DNFPredicate("Or", parameters, Arrays.asList(clause1, clause2)); | ||
203 | 201 | ||
204 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, animal, friend), | 202 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, animal, friend), |
205 | Set.of(personView, animalView, friendMustView), Set.of(predicate)); | 203 | Set.of(personView, animalView, friendMustView), Set.of(predicate)); |
@@ -226,14 +224,14 @@ class QueryTest { | |||
226 | 224 | ||
227 | Variable p1 = new Variable("p1"); | 225 | Variable p1 = new Variable("p1"); |
228 | Variable p2 = new Variable("p2"); | 226 | Variable p2 = new Variable("p2"); |
229 | List<Variable> parameters = Arrays.asList(p1, p2); | 227 | DNF predicate = DNF.builder("Equality") |
230 | 228 | .parameters(p1, p2) | |
231 | RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); | 229 | .clause( |
232 | RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); | 230 | new RelationViewAtom(personView, p1), |
233 | EquivalenceAtom equivalenceAtom = new EquivalenceAtom(true, p1, p2); | 231 | new RelationViewAtom(personView, p2), |
234 | DNFAnd clause = new DNFAnd(Collections.emptySet(), | 232 | new EquivalenceAtom(p1, p2) |
235 | Arrays.asList(personRelationAtom1, personRelationAtom2, equivalenceAtom)); | 233 | ) |
236 | DNFPredicate predicate = new DNFPredicate("Equality", parameters, List.of(clause)); | 234 | .build(); |
237 | 235 | ||
238 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person), Set.of(personView), Set.of(predicate)); | 236 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person), Set.of(personView), Set.of(predicate)); |
239 | QueryableModel model = store.createModel(); | 237 | QueryableModel model = store.createModel(); |
@@ -258,16 +256,16 @@ class QueryTest { | |||
258 | Variable p1 = new Variable("p1"); | 256 | Variable p1 = new Variable("p1"); |
259 | Variable p2 = new Variable("p2"); | 257 | Variable p2 = new Variable("p2"); |
260 | Variable p3 = new Variable("p3"); | 258 | Variable p3 = new Variable("p3"); |
261 | List<Variable> parameters = Arrays.asList(p1, p2, p3); | 259 | DNF predicate = DNF.builder("Inequality") |
262 | 260 | .parameters(p1, p2, p3) | |
263 | RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); | 261 | .clause( |
264 | RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); | 262 | new RelationViewAtom(personView, p1), |
265 | RelationAtom friendRelationAtom1 = new RelationAtom(friendMustView, Arrays.asList(p1, p3)); | 263 | new RelationViewAtom(personView, p2), |
266 | RelationAtom friendRelationAtom2 = new RelationAtom(friendMustView, Arrays.asList(p2, p3)); | 264 | new RelationViewAtom(friendMustView, p1, p3), |
267 | EquivalenceAtom inequivalenceAtom = new EquivalenceAtom(false, p1, p2); | 265 | new RelationViewAtom(friendMustView, p2, p3), |
268 | DNFAnd clause = new DNFAnd(Collections.emptySet(), Arrays.asList(personRelationAtom1, personRelationAtom2, | 266 | new EquivalenceAtom(false, p1, p2) |
269 | friendRelationAtom1, friendRelationAtom2, inequivalenceAtom)); | 267 | ) |
270 | DNFPredicate predicate = new DNFPredicate("Inequality", parameters, List.of(clause)); | 268 | .build(); |
271 | 269 | ||
272 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 270 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), |
273 | Set.of(personView, friendMustView), Set.of(predicate)); | 271 | Set.of(personView, friendMustView), Set.of(predicate)); |
@@ -294,24 +292,25 @@ class QueryTest { | |||
294 | 292 | ||
295 | Variable p1 = new Variable("p1"); | 293 | Variable p1 = new Variable("p1"); |
296 | Variable p2 = new Variable("p2"); | 294 | Variable p2 = new Variable("p2"); |
297 | List<Variable> parameters = Arrays.asList(p1, p2); | 295 | DNF friendPredicate = DNF.builder("RelationConstraint") |
298 | 296 | .parameters(p1, p2) | |
299 | RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); | 297 | .clause( |
300 | RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); | 298 | new RelationViewAtom(personView, p1), |
301 | RelationAtom friendRelationAtom = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); | 299 | new RelationViewAtom(personView, p2), |
302 | DNFAnd clause = new DNFAnd(Collections.emptySet(), | 300 | new RelationViewAtom(friendMustView, p1, p2) |
303 | Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom)); | 301 | ) |
304 | DNFPredicate friendPredicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); | 302 | .build(); |
305 | 303 | ||
306 | Variable p3 = new Variable("p3"); | 304 | Variable p3 = new Variable("p3"); |
307 | Variable p4 = new Variable("p4"); | 305 | Variable p4 = new Variable("p4"); |
308 | List<Variable> substitution = Arrays.asList(p3, p4); | 306 | DNF predicate = DNF.builder("PositivePatternCall") |
309 | RelationAtom personRelationAtom3 = new RelationAtom(personView, List.of(p3)); | 307 | .parameters(p3, p4) |
310 | RelationAtom personRelationAtom4 = new RelationAtom(personView, List.of(p4)); | 308 | .clause( |
311 | PredicateAtom friendPredicateAtom = new PredicateAtom(true, false, friendPredicate, substitution); | 309 | new RelationViewAtom(personView, p3), |
312 | DNFAnd patternCallClause = new DNFAnd(Collections.emptySet(), | 310 | new RelationViewAtom(personView, p4), |
313 | Arrays.asList(personRelationAtom3, personRelationAtom4, friendPredicateAtom)); | 311 | new DNFCallAtom(friendPredicate, p3, p4) |
314 | DNFPredicate predicate = new DNFPredicate("PatternCall", substitution, List.of(patternCallClause)); | 312 | ) |
313 | .build(); | ||
315 | 314 | ||
316 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 315 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), |
317 | Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); | 316 | Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); |
@@ -339,25 +338,25 @@ class QueryTest { | |||
339 | 338 | ||
340 | Variable p1 = new Variable("p1"); | 339 | Variable p1 = new Variable("p1"); |
341 | Variable p2 = new Variable("p2"); | 340 | Variable p2 = new Variable("p2"); |
342 | List<Variable> parameters = Arrays.asList(p1, p2); | 341 | DNF friendPredicate = DNF.builder("RelationConstraint") |
343 | 342 | .parameters(p1, p2) | |
344 | RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); | 343 | .clause( |
345 | RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); | 344 | new RelationViewAtom(personView, p1), |
346 | RelationAtom friendRelationAtom = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); | 345 | new RelationViewAtom(personView, p2), |
347 | DNFAnd clause = new DNFAnd(Collections.emptySet(), | 346 | new RelationViewAtom(friendMustView, p1, p2) |
348 | Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom)); | 347 | ) |
349 | DNFPredicate friendPredicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); | 348 | .build(); |
350 | 349 | ||
351 | Variable p3 = new Variable("p3"); | 350 | Variable p3 = new Variable("p3"); |
352 | Variable p4 = new Variable("p4"); | 351 | Variable p4 = new Variable("p4"); |
353 | List<Variable> substitution = Arrays.asList(p3, p4); | 352 | DNF predicate = DNF.builder("NegativePatternCall") |
354 | RelationAtom personRelationAtom3 = new RelationAtom(personView, List.of(p3)); | 353 | .parameters(p3, p4) |
355 | RelationAtom personRelationAtom4 = new RelationAtom(personView, List.of(p4)); | 354 | .clause( |
356 | PredicateAtom friendPredicateAtom = new PredicateAtom(false, false, friendPredicate, substitution); | 355 | new RelationViewAtom(personView, p3), |
357 | DNFAnd negativePatternCallClause = new DNFAnd(Collections.emptySet(), | 356 | new RelationViewAtom(personView, p4), |
358 | Arrays.asList(personRelationAtom3, personRelationAtom4, friendPredicateAtom)); | 357 | new DNFCallAtom(CallKind.NEGATIVE, friendPredicate, p3, p4) |
359 | DNFPredicate predicate = new DNFPredicate("NegativePatternCall", substitution, | 358 | ) |
360 | List.of(negativePatternCallClause)); | 359 | .build(); |
361 | 360 | ||
362 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 361 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), |
363 | Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); | 362 | Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); |
@@ -384,25 +383,25 @@ class QueryTest { | |||
384 | 383 | ||
385 | Variable p1 = new Variable("p1"); | 384 | Variable p1 = new Variable("p1"); |
386 | Variable p2 = new Variable("p2"); | 385 | Variable p2 = new Variable("p2"); |
387 | List<Variable> parameters = Arrays.asList(p1, p2); | 386 | DNF friendPredicate = DNF.builder("RelationConstraint") |
388 | 387 | .parameters(p1, p2) | |
389 | RelationAtom personRelationAtom1 = new RelationAtom(personView, List.of(p1)); | 388 | .clause( |
390 | RelationAtom personRelationAtom2 = new RelationAtom(personView, List.of(p2)); | 389 | new RelationViewAtom(personView, p1), |
391 | RelationAtom friendRelationAtom = new RelationAtom(friendMustView, Arrays.asList(p1, p2)); | 390 | new RelationViewAtom(personView, p2), |
392 | DNFAnd clause = new DNFAnd(Collections.emptySet(), | 391 | new RelationViewAtom(friendMustView, p1, p2) |
393 | Arrays.asList(personRelationAtom1, personRelationAtom2, friendRelationAtom)); | 392 | ) |
394 | DNFPredicate friendPredicate = new DNFPredicate("RelationConstraint", parameters, List.of(clause)); | 393 | .build(); |
395 | 394 | ||
396 | Variable p3 = new Variable("p3"); | 395 | Variable p3 = new Variable("p3"); |
397 | Variable p4 = new Variable("p4"); | 396 | Variable p4 = new Variable("p4"); |
398 | List<Variable> substitution = Arrays.asList(p3, p4); | 397 | DNF predicate = DNF.builder("TransitivePatternCall") |
399 | RelationAtom personRelationAtom3 = new RelationAtom(personView, List.of(p3)); | 398 | .parameters(p3, p4) |
400 | RelationAtom personRelationAtom4 = new RelationAtom(personView, List.of(p4)); | 399 | .clause( |
401 | PredicateAtom friendPredicateAtom = new PredicateAtom(true, true, friendPredicate, substitution); | 400 | new RelationViewAtom(personView, p3), |
402 | DNFAnd patternCallClause = new DNFAnd(Collections.emptySet(), | 401 | new RelationViewAtom(personView, p4), |
403 | Arrays.asList(personRelationAtom3, personRelationAtom4, friendPredicateAtom)); | 402 | new DNFCallAtom(CallKind.TRANSITIVE, friendPredicate, p3, p4) |
404 | DNFPredicate predicate = new DNFPredicate("TransitivePatternCall", substitution, | 403 | ) |
405 | List.of(patternCallClause)); | 404 | .build(); |
406 | 405 | ||
407 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), | 406 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, friend), |
408 | Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); | 407 | Set.of(personView, friendMustView), Set.of(friendPredicate, predicate)); |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java index f57bca2b..a555f024 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java | |||
@@ -1,20 +1,17 @@ | |||
1 | package tools.refinery.store.query.viatra.tests; | 1 | package tools.refinery.store.query.viatra.tests; |
2 | 2 | ||
3 | import org.junit.jupiter.api.Test; | 3 | import org.junit.jupiter.api.Test; |
4 | import tools.refinery.store.tuple.Tuple; | ||
5 | import tools.refinery.store.model.representation.Relation; | 4 | import tools.refinery.store.model.representation.Relation; |
5 | import tools.refinery.store.query.DNF; | ||
6 | import tools.refinery.store.query.QueryableModel; | 6 | import tools.refinery.store.query.QueryableModel; |
7 | import tools.refinery.store.query.QueryableModelStore; | 7 | import tools.refinery.store.query.QueryableModelStore; |
8 | import tools.refinery.store.query.building.DNFAnd; | 8 | import tools.refinery.store.query.Variable; |
9 | import tools.refinery.store.query.building.DNFPredicate; | 9 | import tools.refinery.store.query.atom.RelationViewAtom; |
10 | import tools.refinery.store.query.building.RelationAtom; | ||
11 | import tools.refinery.store.query.building.Variable; | ||
12 | import tools.refinery.store.query.viatra.ViatraQueryableModelStore; | 10 | import tools.refinery.store.query.viatra.ViatraQueryableModelStore; |
13 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 11 | import tools.refinery.store.query.view.KeyOnlyRelationView; |
14 | import tools.refinery.store.query.view.RelationView; | 12 | import tools.refinery.store.query.view.RelationView; |
13 | import tools.refinery.store.tuple.Tuple; | ||
15 | 14 | ||
16 | import java.util.Collections; | ||
17 | import java.util.List; | ||
18 | import java.util.Set; | 15 | import java.util.Set; |
19 | 16 | ||
20 | import static org.junit.jupiter.api.Assertions.assertEquals; | 17 | import static org.junit.jupiter.api.Assertions.assertEquals; |
@@ -26,10 +23,11 @@ class QueryTransactionTest { | |||
26 | Relation<Boolean> asset = new Relation<>("Asset", 1, false); | 23 | Relation<Boolean> asset = new Relation<>("Asset", 1, false); |
27 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); | 24 | RelationView<Boolean> personView = new KeyOnlyRelationView(person); |
28 | 25 | ||
29 | List<Variable> parameters = List.of(new Variable("p1")); | 26 | var p1 = new Variable("p1"); |
30 | RelationAtom personRelationAtom = new RelationAtom(personView, parameters); | 27 | DNF predicate = DNF.builder("TypeConstraint") |
31 | DNFAnd clause = new DNFAnd(Collections.emptySet(), List.of(personRelationAtom)); | 28 | .parameters(p1) |
32 | DNFPredicate predicate = new DNFPredicate("TypeConstraint", parameters, List.of(clause)); | 29 | .clause(new RelationViewAtom(personView, p1)) |
30 | .build(); | ||
33 | 31 | ||
34 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, asset), Set.of(personView), | 32 | QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, asset), Set.of(personView), |
35 | Set.of(predicate)); | 33 | Set.of(predicate)); |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java index b5e1c453..d08cf0f8 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java | |||
@@ -1,24 +1,15 @@ | |||
1 | package tools.refinery.store.model; | 1 | package tools.refinery.store.model; |
2 | 2 | ||
3 | import java.util.HashMap; | 3 | import tools.refinery.store.map.*; |
4 | import java.util.LinkedList; | ||
5 | import java.util.List; | ||
6 | import java.util.Map; | ||
7 | import java.util.Map.Entry; | ||
8 | |||
9 | import tools.refinery.store.map.ContinousHashProvider; | ||
10 | import tools.refinery.store.map.DiffCursor; | ||
11 | import tools.refinery.store.map.VersionedMap; | ||
12 | import tools.refinery.store.map.VersionedMapStore; | ||
13 | import tools.refinery.store.map.VersionedMapStoreImpl; | ||
14 | import tools.refinery.store.model.internal.ModelImpl; | 4 | import tools.refinery.store.model.internal.ModelImpl; |
15 | import tools.refinery.store.model.internal.SimilarRelationEquivalenceClass; | 5 | import tools.refinery.store.model.internal.SimilarRelationEquivalenceClass; |
16 | import tools.refinery.store.model.representation.AuxilaryData; | 6 | import tools.refinery.store.model.representation.AuxiliaryData; |
17 | import tools.refinery.store.model.representation.DataRepresentation; | 7 | import tools.refinery.store.model.representation.DataRepresentation; |
18 | import tools.refinery.store.model.representation.Relation; | 8 | import tools.refinery.store.model.representation.Relation; |
19 | import tools.refinery.store.tuple.Tuple; | 9 | import tools.refinery.store.tuple.Tuple; |
20 | 10 | ||
21 | import java.util.Set; | 11 | import java.util.*; |
12 | import java.util.Map.Entry; | ||
22 | 13 | ||
23 | public class ModelStoreImpl implements ModelStore { | 14 | public class ModelStoreImpl implements ModelStore { |
24 | 15 | ||
@@ -38,7 +29,7 @@ public class ModelStoreImpl implements ModelStore { | |||
38 | if (dataRepresentation instanceof Relation<?> symbolRepresentation) { | 29 | if (dataRepresentation instanceof Relation<?> symbolRepresentation) { |
39 | addOrCreate(symbolRepresentationsPerHashPerArity, | 30 | addOrCreate(symbolRepresentationsPerHashPerArity, |
40 | new SimilarRelationEquivalenceClass(symbolRepresentation), symbolRepresentation); | 31 | new SimilarRelationEquivalenceClass(symbolRepresentation), symbolRepresentation); |
41 | } else if (dataRepresentation instanceof AuxilaryData<?, ?>) { | 32 | } else if (dataRepresentation instanceof AuxiliaryData<?, ?>) { |
42 | VersionedMapStoreImpl<?, ?> store = new VersionedMapStoreImpl<>(dataRepresentation.getHashProvider(), | 33 | VersionedMapStoreImpl<?, ?> store = new VersionedMapStoreImpl<>(dataRepresentation.getHashProvider(), |
43 | dataRepresentation.getDefaultValue()); | 34 | dataRepresentation.getDefaultValue()); |
44 | result.put(dataRepresentation, store); | 35 | result.put(dataRepresentation, store); |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/RelationLike.java b/subprojects/store/src/main/java/tools/refinery/store/model/RelationLike.java new file mode 100644 index 00000000..6a5fdcd5 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/model/RelationLike.java | |||
@@ -0,0 +1,7 @@ | |||
1 | package tools.refinery.store.model; | ||
2 | |||
3 | public interface RelationLike { | ||
4 | String getName(); | ||
5 | |||
6 | int getArity(); | ||
7 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxilaryData.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxilaryData.java deleted file mode 100644 index ddd8a5f2..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxilaryData.java +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | package tools.refinery.store.model.representation; | ||
2 | |||
3 | import tools.refinery.store.map.ContinousHashProvider; | ||
4 | |||
5 | public class AuxilaryData<K,V> extends DataRepresentation<K, V> { | ||
6 | private final String name; | ||
7 | |||
8 | public AuxilaryData(String name, ContinousHashProvider<K> hashProvider, V defaultValue) { | ||
9 | super(hashProvider, defaultValue); | ||
10 | this.name = name; | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public String getName() { | ||
15 | return name; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public boolean isValidKey(K key) { | ||
20 | return true; | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java new file mode 100644 index 00000000..1a968f50 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/AuxiliaryData.java | |||
@@ -0,0 +1,22 @@ | |||
1 | package tools.refinery.store.model.representation; | ||
2 | |||
3 | import tools.refinery.store.map.ContinousHashProvider; | ||
4 | |||
5 | public final class AuxiliaryData<K, V> extends DataRepresentation<K, V> { | ||
6 | private final ContinousHashProvider<K> hashProvider; | ||
7 | |||
8 | public AuxiliaryData(String name, ContinousHashProvider<K> hashProvider, V defaultValue) { | ||
9 | super(name, defaultValue); | ||
10 | this.hashProvider = hashProvider; | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public ContinousHashProvider<K> getHashProvider() { | ||
15 | return hashProvider; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public boolean isValidKey(K key) { | ||
20 | return true; | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java index 585e7b88..49f74717 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/DataRepresentation.java | |||
@@ -2,20 +2,22 @@ package tools.refinery.store.model.representation; | |||
2 | 2 | ||
3 | import tools.refinery.store.map.ContinousHashProvider; | 3 | import tools.refinery.store.map.ContinousHashProvider; |
4 | 4 | ||
5 | public abstract class DataRepresentation<K, V> { | 5 | public abstract sealed class DataRepresentation<K, V> permits Relation, AuxiliaryData { |
6 | protected final ContinousHashProvider<K> hashProvider; | 6 | private final String name; |
7 | protected final V defaultValue; | ||
8 | 7 | ||
9 | protected DataRepresentation(ContinousHashProvider<K> hashProvider, V defaultValue) { | 8 | private final V defaultValue; |
10 | this.hashProvider = hashProvider; | 9 | |
10 | protected DataRepresentation(String name, V defaultValue) { | ||
11 | this.name = name; | ||
11 | this.defaultValue = defaultValue; | 12 | this.defaultValue = defaultValue; |
12 | } | 13 | } |
13 | 14 | ||
14 | public abstract String getName(); | 15 | public String getName() { |
15 | 16 | return name; | |
16 | public ContinousHashProvider<K> getHashProvider() { | ||
17 | return hashProvider; | ||
18 | } | 17 | } |
18 | |||
19 | public abstract ContinousHashProvider<K> getHashProvider(); | ||
20 | |||
19 | public abstract boolean isValidKey(K key); | 21 | public abstract boolean isValidKey(K key); |
20 | 22 | ||
21 | public V getDefaultValue() { | 23 | public V getDefaultValue() { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java index c0f31d08..2e21ea37 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java | |||
@@ -1,31 +1,34 @@ | |||
1 | package tools.refinery.store.model.representation; | 1 | package tools.refinery.store.model.representation; |
2 | 2 | ||
3 | import tools.refinery.store.map.ContinousHashProvider; | ||
4 | import tools.refinery.store.model.RelationLike; | ||
3 | import tools.refinery.store.tuple.Tuple; | 5 | import tools.refinery.store.tuple.Tuple; |
4 | import tools.refinery.store.model.TupleHashProvider; | 6 | import tools.refinery.store.model.TupleHashProvider; |
5 | 7 | ||
6 | public class Relation<D> extends DataRepresentation<Tuple, D> { | 8 | public final class Relation<D> extends DataRepresentation<Tuple, D> implements RelationLike { |
7 | private final String name; | ||
8 | private final int arity; | 9 | private final int arity; |
9 | 10 | ||
10 | public Relation(String name, int arity, D defaultValue) { | 11 | public Relation(String name, int arity, D defaultValue) { |
11 | super(TupleHashProvider.singleton(), defaultValue); | 12 | super(name, defaultValue); |
12 | this.name = name; | ||
13 | this.arity = arity; | 13 | this.arity = arity; |
14 | } | 14 | } |
15 | 15 | ||
16 | @Override | 16 | @Override |
17 | public String getName() { | ||
18 | return name; | ||
19 | } | ||
20 | |||
21 | public int getArity() { | 17 | public int getArity() { |
22 | return arity; | 18 | return arity; |
23 | } | 19 | } |
24 | 20 | ||
25 | @Override | 21 | @Override |
22 | public ContinousHashProvider<Tuple> getHashProvider() { | ||
23 | return TupleHashProvider.singleton(); | ||
24 | } | ||
25 | |||
26 | @Override | ||
26 | public boolean isValidKey(Tuple key) { | 27 | public boolean isValidKey(Tuple key) { |
27 | if(key == null) { | 28 | if (key == null) { |
28 | return false; | 29 | return false; |
29 | } else return key.getSize() == getArity(); | 30 | } else { |
31 | return key.getSize() == getArity(); | ||
32 | } | ||
30 | } | 33 | } |
31 | } | 34 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java new file mode 100644 index 00000000..7d4b3091 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java | |||
@@ -0,0 +1,121 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.model.RelationLike; | ||
4 | import tools.refinery.store.query.atom.DNFAtom; | ||
5 | |||
6 | import java.util.*; | ||
7 | |||
8 | public class DNF implements RelationLike { | ||
9 | private final String name; | ||
10 | |||
11 | private final String uniqueName; | ||
12 | |||
13 | private final List<Variable> parameters; | ||
14 | |||
15 | private final List<DNFAnd> clauses; | ||
16 | |||
17 | private DNF(String name, List<Variable> parameters, List<DNFAnd> clauses) { | ||
18 | this.name = name; | ||
19 | this.uniqueName = DNFUtils.generateUniqueName(name); | ||
20 | this.parameters = parameters; | ||
21 | this.clauses = clauses; | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | public String getName() { | ||
26 | return name; | ||
27 | } | ||
28 | |||
29 | public String getUniqueName() { | ||
30 | return uniqueName; | ||
31 | } | ||
32 | |||
33 | public List<Variable> getParameters() { | ||
34 | return parameters; | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public int getArity() { | ||
39 | return parameters.size(); | ||
40 | } | ||
41 | |||
42 | public List<DNFAnd> getClauses() { | ||
43 | return clauses; | ||
44 | } | ||
45 | |||
46 | public static Builder builder() { | ||
47 | return builder(null); | ||
48 | } | ||
49 | |||
50 | public static Builder builder(String name) { | ||
51 | return new Builder(name); | ||
52 | } | ||
53 | |||
54 | @SuppressWarnings("UnusedReturnValue") | ||
55 | public static class Builder { | ||
56 | private final String name; | ||
57 | |||
58 | private final List<Variable> parameters = new ArrayList<>(); | ||
59 | |||
60 | private final List<List<DNFAtom>> clauses = new ArrayList<>(); | ||
61 | |||
62 | private Builder(String name) { | ||
63 | this.name = name; | ||
64 | } | ||
65 | |||
66 | public Builder parameter(Variable variable) { | ||
67 | this.parameters.add(variable); | ||
68 | return this; | ||
69 | } | ||
70 | |||
71 | public Builder parameters(Variable... variables) { | ||
72 | return parameters(List.of(variables)); | ||
73 | } | ||
74 | |||
75 | public Builder parameters(Collection<Variable> variables) { | ||
76 | this.parameters.addAll(variables); | ||
77 | return this; | ||
78 | } | ||
79 | |||
80 | public Builder clause(DNFAtom... atoms) { | ||
81 | clauses.add(List.of(atoms)); | ||
82 | return this; | ||
83 | } | ||
84 | |||
85 | public Builder clause(Collection<DNFAtom> atoms) { | ||
86 | clauses.add(List.copyOf(atoms)); | ||
87 | return this; | ||
88 | } | ||
89 | |||
90 | public Builder clause(DNFAnd clause) { | ||
91 | return clause(clause.constraints()); | ||
92 | } | ||
93 | |||
94 | public Builder clauses(DNFAnd... clauses) { | ||
95 | for (var clause : clauses) { | ||
96 | this.clause(clause); | ||
97 | } | ||
98 | return this; | ||
99 | } | ||
100 | |||
101 | public Builder clauses(Collection<DNFAnd> clauses) { | ||
102 | for (var clause : clauses) { | ||
103 | this.clause(clause); | ||
104 | } | ||
105 | return this; | ||
106 | } | ||
107 | |||
108 | public DNF build() { | ||
109 | var postProcessedClauses = new ArrayList<DNFAnd>(); | ||
110 | for (var constraints : clauses) { | ||
111 | var variables = new HashSet<Variable>(); | ||
112 | for (var constraint : constraints) { | ||
113 | constraint.collectAllVariables(variables); | ||
114 | } | ||
115 | parameters.forEach(variables::remove); | ||
116 | postProcessedClauses.add(new DNFAnd(variables, constraints)); | ||
117 | } | ||
118 | return new DNF(name, List.copyOf(parameters), postProcessedClauses); | ||
119 | } | ||
120 | } | ||
121 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java new file mode 100644 index 00000000..8c3bf05d --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java | |||
@@ -0,0 +1,9 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.query.atom.DNFAtom; | ||
4 | |||
5 | import java.util.List; | ||
6 | import java.util.Set; | ||
7 | |||
8 | public record DNFAnd(Set<Variable> quantifiedVariables, List<DNFAtom> constraints) { | ||
9 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java new file mode 100644 index 00000000..0ef77d49 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java | |||
@@ -0,0 +1,19 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import java.util.UUID; | ||
4 | |||
5 | public final class DNFUtils { | ||
6 | private DNFUtils() { | ||
7 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
8 | } | ||
9 | |||
10 | public static String generateUniqueName(String originalName) { | ||
11 | UUID uuid = UUID.randomUUID(); | ||
12 | String uniqueString = "_" + uuid.toString().replace('-', '_'); | ||
13 | if (originalName == null) { | ||
14 | return uniqueString; | ||
15 | } else { | ||
16 | return originalName + uniqueString; | ||
17 | } | ||
18 | } | ||
19 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java index 648c3a36..9655d1a1 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java | |||
@@ -1,7 +1,6 @@ | |||
1 | package tools.refinery.store.query; | 1 | package tools.refinery.store.query; |
2 | 2 | ||
3 | import tools.refinery.store.model.Model; | 3 | import tools.refinery.store.model.Model; |
4 | import tools.refinery.store.query.building.DNFPredicate; | ||
5 | import tools.refinery.store.tuple.Tuple; | 4 | import tools.refinery.store.tuple.Tuple; |
6 | import tools.refinery.store.tuple.TupleLike; | 5 | import tools.refinery.store.tuple.TupleLike; |
7 | 6 | ||
@@ -10,25 +9,25 @@ import java.util.Set; | |||
10 | import java.util.stream.Stream; | 9 | import java.util.stream.Stream; |
11 | 10 | ||
12 | public interface QueryableModel extends Model { | 11 | public interface QueryableModel extends Model { |
13 | Set<DNFPredicate> getPredicates(); | 12 | Set<DNF> getPredicates(); |
14 | 13 | ||
15 | boolean hasChanges(); | 14 | boolean hasChanges(); |
16 | 15 | ||
17 | void flushChanges(); | 16 | void flushChanges(); |
18 | 17 | ||
19 | boolean hasResult(DNFPredicate predicate); | 18 | boolean hasResult(DNF predicate); |
20 | 19 | ||
21 | boolean hasResult(DNFPredicate predicate, Tuple parameters); | 20 | boolean hasResult(DNF predicate, Tuple parameters); |
22 | 21 | ||
23 | Optional<TupleLike> oneResult(DNFPredicate predicate); | 22 | Optional<TupleLike> oneResult(DNF predicate); |
24 | 23 | ||
25 | Optional<TupleLike> oneResult(DNFPredicate predicate, Tuple parameters); | 24 | Optional<TupleLike> oneResult(DNF predicate, Tuple parameters); |
26 | 25 | ||
27 | Stream<TupleLike> allResults(DNFPredicate predicate); | 26 | Stream<TupleLike> allResults(DNF predicate); |
28 | 27 | ||
29 | Stream<TupleLike> allResults(DNFPredicate predicate, Tuple parameters); | 28 | Stream<TupleLike> allResults(DNF predicate, Tuple parameters); |
30 | 29 | ||
31 | int countResults(DNFPredicate predicate); | 30 | int countResults(DNF predicate); |
32 | 31 | ||
33 | int countResults(DNFPredicate predicate, Tuple parameters); | 32 | int countResults(DNF predicate, Tuple parameters); |
34 | } | 33 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java index 878e1058..41f47e64 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java | |||
@@ -2,7 +2,6 @@ package tools.refinery.store.query; | |||
2 | 2 | ||
3 | import tools.refinery.store.model.ModelStore; | 3 | import tools.refinery.store.model.ModelStore; |
4 | import tools.refinery.store.model.representation.DataRepresentation; | 4 | import tools.refinery.store.model.representation.DataRepresentation; |
5 | import tools.refinery.store.query.building.DNFPredicate; | ||
6 | import tools.refinery.store.query.view.RelationView; | 5 | import tools.refinery.store.query.view.RelationView; |
7 | 6 | ||
8 | import java.util.Set; | 7 | import java.util.Set; |
@@ -14,7 +13,7 @@ public interface QueryableModelStore extends ModelStore { | |||
14 | @SuppressWarnings("squid:S1452") | 13 | @SuppressWarnings("squid:S1452") |
15 | Set<RelationView<?>> getViews(); | 14 | Set<RelationView<?>> getViews(); |
16 | 15 | ||
17 | Set<DNFPredicate> getPredicates(); | 16 | Set<DNF> getPredicates(); |
18 | 17 | ||
19 | QueryableModel createModel(); | 18 | QueryableModel createModel(); |
20 | 19 | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java b/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java new file mode 100644 index 00000000..3632f3c5 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java | |||
@@ -0,0 +1,43 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import java.util.Objects; | ||
4 | |||
5 | public class Variable { | ||
6 | private final String name; | ||
7 | private final String uniqueName; | ||
8 | |||
9 | public Variable() { | ||
10 | this(null); | ||
11 | } | ||
12 | |||
13 | public Variable(String name) { | ||
14 | super(); | ||
15 | this.name = name; | ||
16 | this.uniqueName = DNFUtils.generateUniqueName(name); | ||
17 | |||
18 | } | ||
19 | public String getName() { | ||
20 | return name; | ||
21 | } | ||
22 | |||
23 | public String getUniqueName() { | ||
24 | return uniqueName; | ||
25 | } | ||
26 | |||
27 | public boolean isNamed() { | ||
28 | return name != null; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public boolean equals(Object o) { | ||
33 | if (this == o) return true; | ||
34 | if (o == null || getClass() != o.getClass()) return false; | ||
35 | Variable variable = (Variable) o; | ||
36 | return Objects.equals(uniqueName, variable.uniqueName); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public int hashCode() { | ||
41 | return Objects.hash(uniqueName); | ||
42 | } | ||
43 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractCallAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractCallAtom.java new file mode 100644 index 00000000..fb8d7432 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractCallAtom.java | |||
@@ -0,0 +1,30 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.model.RelationLike; | ||
4 | import tools.refinery.store.query.Variable; | ||
5 | |||
6 | import java.util.List; | ||
7 | import java.util.Set; | ||
8 | |||
9 | public abstract class AbstractCallAtom<T extends RelationLike> extends AbstractSubstitutionAtom<T> { | ||
10 | private final CallKind kind; | ||
11 | |||
12 | protected AbstractCallAtom(CallKind kind, T target, List<Variable> substitution) { | ||
13 | super(target, substitution); | ||
14 | if (kind.isTransitive() && target.getArity() != 2) { | ||
15 | throw new IllegalArgumentException("Transitive closures can only take binary relations"); | ||
16 | } | ||
17 | this.kind = kind; | ||
18 | } | ||
19 | |||
20 | public CallKind getKind() { | ||
21 | return kind; | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | public void collectAllVariables(Set<Variable> variables) { | ||
26 | if (kind.isPositive()) { | ||
27 | super.collectAllVariables(variables); | ||
28 | } | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractSubstitutionAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractSubstitutionAtom.java new file mode 100644 index 00000000..e8a8b5e1 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/AbstractSubstitutionAtom.java | |||
@@ -0,0 +1,35 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.model.RelationLike; | ||
4 | import tools.refinery.store.query.Variable; | ||
5 | |||
6 | import java.util.List; | ||
7 | import java.util.Set; | ||
8 | |||
9 | public abstract class AbstractSubstitutionAtom<T extends RelationLike> implements DNFAtom { | ||
10 | private final T target; | ||
11 | |||
12 | private final List<Variable> substitution; | ||
13 | |||
14 | protected AbstractSubstitutionAtom(T target, List<Variable> substitution) { | ||
15 | if (substitution.size() != target.getArity()) { | ||
16 | throw new IllegalArgumentException("%s needs %d arguments, but got %s".formatted(target.getName(), | ||
17 | target.getArity(), substitution.size())); | ||
18 | } | ||
19 | this.target = target; | ||
20 | this.substitution = substitution; | ||
21 | } | ||
22 | |||
23 | public T getTarget() { | ||
24 | return target; | ||
25 | } | ||
26 | |||
27 | public List<Variable> getSubstitution() { | ||
28 | return substitution; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public void collectAllVariables(Set<Variable> variables) { | ||
33 | variables.addAll(substitution); | ||
34 | } | ||
35 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallKind.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallKind.java new file mode 100644 index 00000000..c7cbc955 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallKind.java | |||
@@ -0,0 +1,24 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | public enum CallKind { | ||
4 | POSITIVE(true, false), | ||
5 | NEGATIVE(false, false), | ||
6 | TRANSITIVE(true, true); | ||
7 | |||
8 | private final boolean positive; | ||
9 | |||
10 | private final boolean transitive; | ||
11 | |||
12 | CallKind(boolean positive, boolean transitive) { | ||
13 | this.positive = positive; | ||
14 | this.transitive = transitive; | ||
15 | } | ||
16 | |||
17 | public boolean isPositive() { | ||
18 | return positive; | ||
19 | } | ||
20 | |||
21 | public boolean isTransitive() { | ||
22 | return transitive; | ||
23 | } | ||
24 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java new file mode 100644 index 00000000..ebf71236 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java | |||
@@ -0,0 +1,9 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | |||
5 | import java.util.Set; | ||
6 | |||
7 | public interface DNFAtom { | ||
8 | void collectAllVariables(Set<Variable> variables); | ||
9 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java new file mode 100644 index 00000000..9d2efa53 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java | |||
@@ -0,0 +1,40 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.DNF; | ||
4 | import tools.refinery.store.query.Variable; | ||
5 | |||
6 | import java.util.List; | ||
7 | import java.util.Objects; | ||
8 | |||
9 | public final class DNFCallAtom extends AbstractCallAtom<DNF> { | ||
10 | public DNFCallAtom(CallKind kind, DNF target, List<Variable> substitution) { | ||
11 | super(kind, target, substitution); | ||
12 | } | ||
13 | |||
14 | public DNFCallAtom(CallKind kind, DNF target, Variable... substitution) { | ||
15 | super(kind, target, List.of(substitution)); | ||
16 | } | ||
17 | |||
18 | public DNFCallAtom(DNF target, List<Variable> substitution) { | ||
19 | this(CallKind.POSITIVE, target, substitution); | ||
20 | } | ||
21 | |||
22 | public DNFCallAtom(DNF target, Variable... substitution) { | ||
23 | this(target, List.of(substitution)); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public boolean equals(Object o) { | ||
28 | if (this == o) return true; | ||
29 | if (o == null || getClass() != o.getClass()) return false; | ||
30 | DNFCallAtom dnfCallAtom = (DNFCallAtom) o; | ||
31 | return Objects.equals(getKind(), dnfCallAtom.getKind()) | ||
32 | && Objects.equals(getTarget(), dnfCallAtom.getTarget()) | ||
33 | && Objects.equals(getSubstitution(), dnfCallAtom.getSubstitution()); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public int hashCode() { | ||
38 | return Objects.hash(getKind(), getTarget(), getSubstitution()); | ||
39 | } | ||
40 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java new file mode 100644 index 00000000..b1b3a6f7 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java | |||
@@ -0,0 +1,17 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | |||
5 | import java.util.Set; | ||
6 | |||
7 | public record EquivalenceAtom(boolean positive, Variable left, Variable right) implements DNFAtom { | ||
8 | public EquivalenceAtom(Variable left, Variable right) { | ||
9 | this(true, left, right); | ||
10 | } | ||
11 | |||
12 | @Override | ||
13 | public void collectAllVariables(Set<Variable> variables) { | ||
14 | variables.add(left); | ||
15 | variables.add(right); | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/ModalRelationAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/ModalRelationAtom.java new file mode 100644 index 00000000..2480e82e --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/ModalRelationAtom.java | |||
@@ -0,0 +1,38 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.model.representation.Relation; | ||
4 | import tools.refinery.store.model.representation.TruthValue; | ||
5 | import tools.refinery.store.query.Variable; | ||
6 | |||
7 | import java.util.List; | ||
8 | import java.util.Objects; | ||
9 | |||
10 | public final class ModalRelationAtom extends AbstractCallAtom<Relation<TruthValue>> { | ||
11 | private final Modality modality; | ||
12 | |||
13 | public ModalRelationAtom(CallKind kind, Modality modality, Relation<TruthValue> target, | ||
14 | List<Variable> substitution) { | ||
15 | super(kind, target, substitution); | ||
16 | this.modality = modality; | ||
17 | } | ||
18 | |||
19 | public ModalRelationAtom(Modality modality, Relation<TruthValue> target, List<Variable> substitution) { | ||
20 | this(CallKind.POSITIVE, modality, target, substitution); | ||
21 | } | ||
22 | |||
23 | @Override | ||
24 | public boolean equals(Object o) { | ||
25 | if (this == o) return true; | ||
26 | if (o == null || getClass() != o.getClass()) return false; | ||
27 | ModalRelationAtom modalRelationAtom = (ModalRelationAtom) o; | ||
28 | return Objects.equals(getKind(), modalRelationAtom.getKind()) | ||
29 | && modality == modalRelationAtom.modality | ||
30 | && Objects.equals(getTarget(), modalRelationAtom.getTarget()) | ||
31 | && Objects.equals(getSubstitution(), modalRelationAtom.getSubstitution()); | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | public int hashCode() { | ||
36 | return Objects.hash(getKind(), modality, getTarget(), getSubstitution()); | ||
37 | } | ||
38 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java new file mode 100644 index 00000000..9344a9d3 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java | |||
@@ -0,0 +1,7 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | public enum Modality { | ||
4 | MUST, | ||
5 | MAY, | ||
6 | CURRENT; | ||
7 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationAtom.java new file mode 100644 index 00000000..06098139 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationAtom.java | |||
@@ -0,0 +1,32 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.model.representation.Relation; | ||
4 | import tools.refinery.store.query.Variable; | ||
5 | |||
6 | import java.util.List; | ||
7 | import java.util.Objects; | ||
8 | |||
9 | public final class RelationAtom extends AbstractCallAtom<Relation<?>> { | ||
10 | public RelationAtom(CallKind kind, Relation<?> target, List<Variable> substitution) { | ||
11 | super(kind, target, substitution); | ||
12 | } | ||
13 | |||
14 | public RelationAtom(Relation<?> target, List<Variable> substitution) { | ||
15 | this(CallKind.POSITIVE, target, substitution); | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public boolean equals(Object o) { | ||
20 | if (this == o) return true; | ||
21 | if (o == null || getClass() != o.getClass()) return false; | ||
22 | RelationAtom relationAtom = (RelationAtom) o; | ||
23 | return Objects.equals(getKind(), relationAtom.getKind()) | ||
24 | && Objects.equals(getTarget(), relationAtom.getTarget()) | ||
25 | && Objects.equals(getSubstitution(), relationAtom.getSubstitution()); | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public int hashCode() { | ||
30 | return Objects.hash(getKind(), getTarget(), getSubstitution()); | ||
31 | } | ||
32 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java new file mode 100644 index 00000000..762a41f1 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java | |||
@@ -0,0 +1,31 @@ | |||
1 | package tools.refinery.store.query.atom; | ||
2 | |||
3 | import tools.refinery.store.query.Variable; | ||
4 | import tools.refinery.store.query.view.RelationView; | ||
5 | |||
6 | import java.util.List; | ||
7 | import java.util.Objects; | ||
8 | |||
9 | public final class RelationViewAtom extends AbstractSubstitutionAtom<RelationView<?>> { | ||
10 | public RelationViewAtom(RelationView<?> target, List<Variable> substitution) { | ||
11 | super(target, substitution); | ||
12 | } | ||
13 | |||
14 | public RelationViewAtom(RelationView<?> target, Variable... substitution) { | ||
15 | this(target, List.of(substitution)); | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public boolean equals(Object o) { | ||
20 | if (this == o) return true; | ||
21 | if (o == null || getClass() != o.getClass()) return false; | ||
22 | RelationViewAtom relationViewAtom = (RelationViewAtom) o; | ||
23 | return Objects.equals(getTarget(), relationViewAtom.getTarget()) | ||
24 | && Objects.equals(getSubstitution(), relationViewAtom.getSubstitution()); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public int hashCode() { | ||
29 | return Objects.hash(getTarget(), getSubstitution()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAnd.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAnd.java deleted file mode 100644 index 48dabce2..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAnd.java +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | package tools.refinery.store.query.building; | ||
2 | |||
3 | import java.util.HashMap; | ||
4 | import java.util.HashSet; | ||
5 | import java.util.List; | ||
6 | import java.util.Map; | ||
7 | import java.util.Set; | ||
8 | |||
9 | public class DNFAnd { | ||
10 | private Set<Variable> existentiallyQuantified; | ||
11 | private List<DNFAtom> constraints; | ||
12 | public DNFAnd(Set<Variable> quantifiedVariables, List<DNFAtom> constraints) { | ||
13 | super(); | ||
14 | this.existentiallyQuantified = quantifiedVariables; | ||
15 | this.constraints = constraints; | ||
16 | } | ||
17 | public Set<Variable> getExistentiallyQuantified() { | ||
18 | return existentiallyQuantified; | ||
19 | } | ||
20 | public List<DNFAtom> getConstraints() { | ||
21 | return constraints; | ||
22 | } | ||
23 | void unifyVariables(Map<String,Variable> uniqueVariableMap) { | ||
24 | Map<String,Variable> uniqueVariableMapForClause = new HashMap<>(uniqueVariableMap); | ||
25 | for(DNFAtom atom : constraints) { | ||
26 | atom.unifyVariables(uniqueVariableMapForClause); | ||
27 | } | ||
28 | } | ||
29 | void collectQuantifiedVariables(Set<Variable> parameters) { | ||
30 | Set<Variable> result = new HashSet<>(); | ||
31 | for(DNFAtom constraint : constraints) { | ||
32 | constraint.collectAllVariables(result); | ||
33 | } | ||
34 | result.removeAll(parameters); | ||
35 | existentiallyQuantified = result; | ||
36 | } | ||
37 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAtom.java deleted file mode 100644 index b047d7c8..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFAtom.java +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | package tools.refinery.store.query.building; | ||
2 | |||
3 | import java.util.Collection; | ||
4 | import java.util.Iterator; | ||
5 | import java.util.Map; | ||
6 | import java.util.Set; | ||
7 | |||
8 | public interface DNFAtom { | ||
9 | void unifyVariables(Map<String,Variable> variables); | ||
10 | static Variable unifyVariables(Map<String,Variable> unifiedVariables, Variable variable) { | ||
11 | if(variable != null) { | ||
12 | if(variable.isNamed() && unifiedVariables.containsKey(variable.getName())) { | ||
13 | return unifiedVariables.get(variable.getName()); | ||
14 | } | ||
15 | return variable; | ||
16 | } else { | ||
17 | return null; | ||
18 | } | ||
19 | } | ||
20 | void collectAllVariables(Set<Variable> variables); | ||
21 | static void addToCollection(Set<Variable> variables, Variable variable) { | ||
22 | if(variable != null) { | ||
23 | variables.add(variable); | ||
24 | } | ||
25 | } | ||
26 | static void addToCollection(Set<Variable> variables, Collection<Variable> variableCollection) { | ||
27 | Iterator<Variable> iterator = variableCollection.iterator(); | ||
28 | while(iterator.hasNext()) { | ||
29 | Variable variable = iterator.next(); | ||
30 | addToCollection(variables, variable); | ||
31 | } | ||
32 | } | ||
33 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFPredicate.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFPredicate.java deleted file mode 100644 index f0c9ac42..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/building/DNFPredicate.java +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | package tools.refinery.store.query.building; | ||
2 | |||
3 | import java.util.HashMap; | ||
4 | import java.util.HashSet; | ||
5 | import java.util.List; | ||
6 | import java.util.Map; | ||
7 | import java.util.UUID; | ||
8 | |||
9 | public class DNFPredicate { | ||
10 | private final String name; | ||
11 | private final String uniqueName; | ||
12 | private final List<Variable> parameters; | ||
13 | private final List<DNFAnd> clauses; | ||
14 | |||
15 | public DNFPredicate(String name, List<Variable> parameters, List<DNFAnd> clauses) { | ||
16 | this.name = name; | ||
17 | this.uniqueName = generateUniqueName(name,"predicate"); | ||
18 | this.parameters = parameters; | ||
19 | this.clauses = clauses; | ||
20 | |||
21 | postProcess(); | ||
22 | } | ||
23 | |||
24 | public static String generateUniqueName(String originalName, String defaultPrefix) { | ||
25 | UUID uuid = UUID.randomUUID(); | ||
26 | String uniqueString = uuid.toString().replace('-', '_'); | ||
27 | if(originalName == null) { | ||
28 | return defaultPrefix+uniqueString; | ||
29 | } else { | ||
30 | return originalName+uniqueString; | ||
31 | } | ||
32 | } | ||
33 | |||
34 | public String getName() { | ||
35 | return name; | ||
36 | } | ||
37 | public String getUniqueName() { | ||
38 | return uniqueName; | ||
39 | } | ||
40 | public List<Variable> getVariables() { | ||
41 | return parameters; | ||
42 | } | ||
43 | public List<DNFAnd> getClauses() { | ||
44 | return clauses; | ||
45 | } | ||
46 | |||
47 | public void unifyVariables() { | ||
48 | Map<String,Variable> uniqueVariableMap = new HashMap<>(); | ||
49 | for(Variable parameter : this.parameters) { | ||
50 | if(parameter.isNamed()) { | ||
51 | String parameterName = parameter.getName(); | ||
52 | if(uniqueVariableMap.containsKey(parameterName)) { | ||
53 | throw new IllegalArgumentException("Multiple parameters has the name "+parameterName); | ||
54 | } else { | ||
55 | uniqueVariableMap.put(parameterName, parameter); | ||
56 | } | ||
57 | } | ||
58 | } | ||
59 | for(DNFAnd clause : this.clauses) { | ||
60 | clause.unifyVariables(uniqueVariableMap); | ||
61 | } | ||
62 | } | ||
63 | public void collectQuantifiedVariables() { | ||
64 | for(DNFAnd clause : this.clauses) { | ||
65 | clause.collectQuantifiedVariables(new HashSet<>(parameters)); | ||
66 | } | ||
67 | } | ||
68 | public void postProcess() { | ||
69 | unifyVariables(); | ||
70 | collectQuantifiedVariables(); | ||
71 | } | ||
72 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/EquivalenceAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/EquivalenceAtom.java deleted file mode 100644 index fede2518..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/building/EquivalenceAtom.java +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | package tools.refinery.store.query.building; | ||
2 | |||
3 | import java.util.Map; | ||
4 | import java.util.Set; | ||
5 | |||
6 | public class EquivalenceAtom implements DNFAtom{ | ||
7 | private boolean positive; | ||
8 | private Variable left; | ||
9 | private Variable right; | ||
10 | public EquivalenceAtom(boolean positive, Variable left, Variable right) { | ||
11 | this.positive = positive; | ||
12 | this.left = left; | ||
13 | this.right = right; | ||
14 | } | ||
15 | public boolean isPositive() { | ||
16 | return positive; | ||
17 | } | ||
18 | public void setPositive(boolean positive) { | ||
19 | this.positive = positive; | ||
20 | } | ||
21 | public Variable getLeft() { | ||
22 | return left; | ||
23 | } | ||
24 | public void setLeft(Variable left) { | ||
25 | this.left = left; | ||
26 | } | ||
27 | public Variable getRight() { | ||
28 | return right; | ||
29 | } | ||
30 | public void setRight(Variable right) { | ||
31 | this.right = right; | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | public void unifyVariables(Map<String, Variable> variables) { | ||
36 | this.left = DNFAtom.unifyVariables(variables,left); | ||
37 | this.right = DNFAtom.unifyVariables(variables,right); | ||
38 | } | ||
39 | @Override | ||
40 | public void collectAllVariables(Set<Variable> variables) { | ||
41 | DNFAtom.addToCollection(variables, left); | ||
42 | DNFAtom.addToCollection(variables, right); | ||
43 | } | ||
44 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/PredicateAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/PredicateAtom.java deleted file mode 100644 index 42394922..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/building/PredicateAtom.java +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | package tools.refinery.store.query.building; | ||
2 | |||
3 | import java.util.List; | ||
4 | import java.util.Map; | ||
5 | import java.util.Set; | ||
6 | |||
7 | public class PredicateAtom implements DNFAtom { | ||
8 | private DNFPredicate referred; | ||
9 | private List<Variable> substitution; | ||
10 | private boolean positive; | ||
11 | private boolean transitive; | ||
12 | |||
13 | public PredicateAtom(boolean positive, boolean transitive, DNFPredicate referred, List<Variable> substitution) { | ||
14 | this.positive = positive; | ||
15 | this.referred = referred; | ||
16 | this.substitution = substitution; | ||
17 | this.transitive = transitive; | ||
18 | } | ||
19 | |||
20 | public DNFPredicate getReferred() { | ||
21 | return referred; | ||
22 | } | ||
23 | |||
24 | public void setReferred(DNFPredicate referred) { | ||
25 | this.referred = referred; | ||
26 | } | ||
27 | |||
28 | public List<Variable> getSubstitution() { | ||
29 | return substitution; | ||
30 | } | ||
31 | |||
32 | public void setSubstitution(List<Variable> substitution) { | ||
33 | this.substitution = substitution; | ||
34 | } | ||
35 | |||
36 | public boolean isPositive() { | ||
37 | return positive; | ||
38 | } | ||
39 | |||
40 | public void setPositive(boolean positive) { | ||
41 | this.positive = positive; | ||
42 | } | ||
43 | |||
44 | public boolean isTransitive() { | ||
45 | return transitive; | ||
46 | } | ||
47 | |||
48 | public void setTransitive(boolean transitive) { | ||
49 | this.transitive = transitive; | ||
50 | } | ||
51 | |||
52 | @Override | ||
53 | public void unifyVariables(Map<String, Variable> variables) { | ||
54 | for (int i = 0; i < this.substitution.size(); i++) { | ||
55 | final Object term = this.substitution.get(i); | ||
56 | if (term instanceof Variable variableReference) { | ||
57 | this.substitution.set(i, DNFAtom.unifyVariables(variables, variableReference)); | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | |||
62 | @Override | ||
63 | public void collectAllVariables(Set<Variable> variables) { | ||
64 | DNFAtom.addToCollection(variables, substitution); | ||
65 | } | ||
66 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/RelationAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/RelationAtom.java deleted file mode 100644 index f66245fc..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/building/RelationAtom.java +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | package tools.refinery.store.query.building; | ||
2 | |||
3 | import tools.refinery.store.query.view.RelationView; | ||
4 | |||
5 | import java.util.ArrayList; | ||
6 | import java.util.List; | ||
7 | import java.util.Map; | ||
8 | import java.util.Set; | ||
9 | |||
10 | public record RelationAtom(RelationView<?> view, List<Variable> substitution) implements DNFAtom { | ||
11 | public RelationAtom(RelationView<?> view, List<Variable> substitution) { | ||
12 | this.view = view; | ||
13 | // Create a mutable copy of substitution so that unifyVariables can change it. | ||
14 | this.substitution = new ArrayList<>(substitution); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | public void unifyVariables(Map<String, Variable> variables) { | ||
19 | for (int i = 0; i < this.substitution.size(); i++) { | ||
20 | final Object term = this.substitution.get(i); | ||
21 | if (term instanceof Variable variableReference) { | ||
22 | this.substitution.set(i, DNFAtom.unifyVariables(variables, variableReference)); | ||
23 | } | ||
24 | } | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public void collectAllVariables(Set<Variable> variables) { | ||
29 | DNFAtom.addToCollection(variables, substitution); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/building/Variable.java b/subprojects/store/src/main/java/tools/refinery/store/query/building/Variable.java deleted file mode 100644 index 9ea7ce83..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/query/building/Variable.java +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | package tools.refinery.store.query.building; | ||
2 | |||
3 | public class Variable { | ||
4 | private final String name; | ||
5 | private final String uniqueName; | ||
6 | |||
7 | public Variable(String name) { | ||
8 | super(); | ||
9 | this.name = name; | ||
10 | this.uniqueName = DNFPredicate.generateUniqueName(name, "variable"); | ||
11 | |||
12 | } | ||
13 | public String getName() { | ||
14 | return name; | ||
15 | } | ||
16 | public String getUniqueName() { | ||
17 | return uniqueName; | ||
18 | } | ||
19 | public boolean isNamed() { | ||
20 | return name != null; | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java index ceaf7d55..96f8584a 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java | |||
@@ -2,6 +2,7 @@ package tools.refinery.store.query.view; | |||
2 | 2 | ||
3 | import tools.refinery.store.map.CursorAsIterator; | 3 | import tools.refinery.store.map.CursorAsIterator; |
4 | import tools.refinery.store.model.Model; | 4 | import tools.refinery.store.model.Model; |
5 | import tools.refinery.store.model.RelationLike; | ||
5 | import tools.refinery.store.tuple.Tuple; | 6 | import tools.refinery.store.tuple.Tuple; |
6 | import tools.refinery.store.model.representation.Relation; | 7 | import tools.refinery.store.model.representation.Relation; |
7 | 8 | ||
@@ -14,7 +15,7 @@ import java.util.UUID; | |||
14 | * @param <D> | 15 | * @param <D> |
15 | * @author Oszkar Semerath | 16 | * @author Oszkar Semerath |
16 | */ | 17 | */ |
17 | public abstract class RelationView<D> { | 18 | public abstract class RelationView<D> implements RelationLike { |
18 | private final Relation<D> representation; | 19 | private final Relation<D> representation; |
19 | 20 | ||
20 | private final String name; | 21 | private final String name; |
@@ -28,12 +29,11 @@ public abstract class RelationView<D> { | |||
28 | this(representation, UUID.randomUUID().toString()); | 29 | this(representation, UUID.randomUUID().toString()); |
29 | } | 30 | } |
30 | 31 | ||
31 | public abstract int getArity(); | ||
32 | |||
33 | public Relation<D> getRepresentation() { | 32 | public Relation<D> getRepresentation() { |
34 | return representation; | 33 | return representation; |
35 | } | 34 | } |
36 | 35 | ||
36 | @Override | ||
37 | public String getName() { | 37 | public String getName() { |
38 | return representation.getName() + "#" + name; | 38 | return representation.getName() + "#" + name; |
39 | } | 39 | } |