diff options
author | 2021-10-12 23:35:43 +0200 | |
---|---|---|
committer | 2021-10-12 23:35:43 +0200 | |
commit | 8a2a7efaaee2616beea139d816aafcdc57699aee (patch) | |
tree | 969ada77d54c82e37d5edc1ea096bfb6d76f7b2c /store/src/main | |
parent | chore(web): bump Jetty version (diff) | |
download | refinery-8a2a7efaaee2616beea139d816aafcdc57699aee.tar.gz refinery-8a2a7efaaee2616beea139d816aafcdc57699aee.tar.zst refinery-8a2a7efaaee2616beea139d816aafcdc57699aee.zip |
Add DNF to PQuery translator
Also added tests for the translator
Diffstat (limited to 'store/src/main')
-rw-r--r-- | store/src/main/java/tools/refinery/store/query/internal/DNF2PQuery.java | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/store/src/main/java/tools/refinery/store/query/internal/DNF2PQuery.java b/store/src/main/java/tools/refinery/store/query/internal/DNF2PQuery.java new file mode 100644 index 00000000..c9c8245b --- /dev/null +++ b/store/src/main/java/tools/refinery/store/query/internal/DNF2PQuery.java | |||
@@ -0,0 +1,184 @@ | |||
1 | package tools.refinery.store.query.internal; | ||
2 | |||
3 | import java.util.ArrayList; | ||
4 | import java.util.HashMap; | ||
5 | import java.util.InputMismatchException; | ||
6 | import java.util.LinkedHashSet; | ||
7 | import java.util.List; | ||
8 | import java.util.Map; | ||
9 | import java.util.Set; | ||
10 | |||
11 | import org.eclipse.viatra.query.runtime.api.GenericPatternMatcher; | ||
12 | import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; | ||
13 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
14 | import org.eclipse.viatra.query.runtime.api.scope.QueryScope; | ||
15 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | ||
16 | import org.eclipse.viatra.query.runtime.matchers.psystem.PBody; | ||
17 | import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable; | ||
18 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Equality; | ||
19 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExportedParameter; | ||
20 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Inequality; | ||
21 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall; | ||
22 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure; | ||
23 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | ||
24 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; | ||
25 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.BasePQuery; | ||
26 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; | ||
27 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PVisibility; | ||
28 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | ||
29 | |||
30 | import tools.refinery.store.query.RelationalScope; | ||
31 | import tools.refinery.store.query.building.DNFAnd; | ||
32 | import tools.refinery.store.query.building.DNFAtom; | ||
33 | import tools.refinery.store.query.building.DNFPredicate; | ||
34 | import tools.refinery.store.query.building.EquivalenceAtom; | ||
35 | import tools.refinery.store.query.building.PredicateAtom; | ||
36 | import tools.refinery.store.query.building.RelationAtom; | ||
37 | import tools.refinery.store.query.building.Variable; | ||
38 | |||
39 | public class DNF2PQuery { | ||
40 | private static Map<DNFPredicate, SimplePQuery> DNF2PQueryMap = new HashMap<>(); | ||
41 | |||
42 | public static SimplePQuery translate(DNFPredicate predicate) { | ||
43 | SimplePQuery query = DNF2PQueryMap.get(predicate); | ||
44 | if (query != null) { | ||
45 | return query; | ||
46 | } | ||
47 | query = new DNF2PQuery().new SimplePQuery(predicate.getName()); | ||
48 | Map<Variable, PParameter> parameters = new HashMap<>(); | ||
49 | |||
50 | predicate.getVariables().forEach(variable -> parameters.put(variable, new PParameter(variable.getName()))); | ||
51 | query.setParameter(new ArrayList<>(parameters.values())); | ||
52 | for (DNFAnd clause : predicate.getClauses()) { | ||
53 | PBody body = new PBody(query); | ||
54 | List<ExportedParameter> symbolicParameters = new ArrayList<>(); | ||
55 | parameters.forEach((variable, parameter) -> { | ||
56 | PVariable pVar = body.getOrCreateVariableByName(variable.getName()); | ||
57 | symbolicParameters.add(new ExportedParameter(body, pVar, parameter)); | ||
58 | }); | ||
59 | body.setSymbolicParameters(symbolicParameters); | ||
60 | query.addBody(body); | ||
61 | for (DNFAtom constraint : clause.getConstraints()) { | ||
62 | translateDNFAtom(constraint, body); | ||
63 | } | ||
64 | } | ||
65 | DNF2PQueryMap.put(predicate, query); | ||
66 | return query; | ||
67 | } | ||
68 | |||
69 | private static void translateDNFAtom(DNFAtom constraint, PBody body) { | ||
70 | if (constraint instanceof EquivalenceAtom equivalence) { | ||
71 | translateEquivalenceAtom(equivalence, body); | ||
72 | } | ||
73 | if (constraint instanceof RelationAtom relation) { | ||
74 | translateRelationAtom(relation, body); | ||
75 | } | ||
76 | if (constraint instanceof PredicateAtom predicate) { | ||
77 | translatePredicateAtom(predicate, body); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | private static void translateEquivalenceAtom(EquivalenceAtom equivalence, PBody body) { | ||
82 | PVariable varSource = body.getOrCreateVariableByName(equivalence.getLeft().getName()); | ||
83 | PVariable varTarget = body.getOrCreateVariableByName(equivalence.getRight().getName()); | ||
84 | if (equivalence.isPositive()) | ||
85 | new Equality(body, varSource, varTarget); | ||
86 | else | ||
87 | new Inequality(body, varSource, varTarget); | ||
88 | } | ||
89 | |||
90 | private static void translateRelationAtom(RelationAtom relation, PBody body) { | ||
91 | if (relation.getSubstitution().size() != relation.getView().getArity()) { | ||
92 | throw new IllegalArgumentException("Arity (" + relation.getView().getArity() | ||
93 | + ") does not match parameter numbers (" + relation.getSubstitution().size() + ")"); | ||
94 | } | ||
95 | Object[] variables = new Object[relation.getSubstitution().size()]; | ||
96 | for (int i = 0; i < relation.getSubstitution().size(); i++) { | ||
97 | variables[i] = body.getOrCreateVariableByName(relation.getSubstitution().get(i).getName()); | ||
98 | } | ||
99 | new TypeConstraint(body, Tuples.flatTupleOf(variables), relation.getView()); | ||
100 | } | ||
101 | |||
102 | private static void translatePredicateAtom(PredicateAtom predicate, PBody body) { | ||
103 | Object[] variables = new Object[predicate.getSubstitution().size()]; | ||
104 | for (int i = 0; i < predicate.getSubstitution().size(); i++) { | ||
105 | variables[i] = body.getOrCreateVariableByName(predicate.getSubstitution().get(i).getName()); | ||
106 | } | ||
107 | if (predicate.isPositive()) { | ||
108 | if (predicate.isTransitive()) { | ||
109 | if (predicate.getSubstitution().size() != 2) { | ||
110 | throw new IllegalArgumentException("Transitive Predicate Atoms must be binary."); | ||
111 | } | ||
112 | new BinaryTransitiveClosure(body, Tuples.flatTupleOf(variables), | ||
113 | DNF2PQuery.translate(predicate.getReferred())); | ||
114 | } else { | ||
115 | new PositivePatternCall(body, Tuples.flatTupleOf(variables), | ||
116 | DNF2PQuery.translate(predicate.getReferred())); | ||
117 | } | ||
118 | } else { | ||
119 | if (predicate.isTransitive()) { | ||
120 | throw new InputMismatchException("Transitive Predicate Atoms cannot be negative."); | ||
121 | } else { | ||
122 | new NegativePatternCall(body, Tuples.flatTupleOf(variables), | ||
123 | DNF2PQuery.translate(predicate.getReferred())); | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | |||
128 | public class SimplePQuery extends BasePQuery { | ||
129 | |||
130 | private String fullyQualifiedName; | ||
131 | private List<PParameter> parameters; | ||
132 | private LinkedHashSet<PBody> bodies = new LinkedHashSet<>(); | ||
133 | |||
134 | public SimplePQuery(String name) { | ||
135 | super(PVisibility.PUBLIC); | ||
136 | fullyQualifiedName = name; | ||
137 | } | ||
138 | |||
139 | @Override | ||
140 | public String getFullyQualifiedName() { | ||
141 | return fullyQualifiedName; | ||
142 | } | ||
143 | |||
144 | public void setParameter(List<PParameter> parameters) { | ||
145 | this.parameters = parameters; | ||
146 | } | ||
147 | |||
148 | @Override | ||
149 | public List<PParameter> getParameters() { | ||
150 | return parameters; | ||
151 | } | ||
152 | |||
153 | public void addBody(PBody body) { | ||
154 | bodies.add(body); | ||
155 | } | ||
156 | |||
157 | @Override | ||
158 | protected Set<PBody> doGetContainedBodies() { | ||
159 | setEvaluationHints(new QueryEvaluationHint(null, QueryEvaluationHint.BackendRequirement.UNSPECIFIED)); | ||
160 | return bodies; | ||
161 | } | ||
162 | |||
163 | public GenericQuerySpecification<GenericPatternMatcher> build() { | ||
164 | return new GenericQuerySpecification<GenericPatternMatcher>(this) { | ||
165 | |||
166 | @Override | ||
167 | public Class<? extends QueryScope> getPreferredScopeClass() { | ||
168 | return RelationalScope.class; | ||
169 | } | ||
170 | |||
171 | @Override | ||
172 | protected GenericPatternMatcher instantiate(ViatraQueryEngine engine) { | ||
173 | return defaultInstantiate(engine); | ||
174 | } | ||
175 | |||
176 | @Override | ||
177 | public GenericPatternMatcher instantiate() { | ||
178 | return new GenericPatternMatcher(this); | ||
179 | } | ||
180 | |||
181 | }; | ||
182 | } | ||
183 | } | ||
184 | } \ No newline at end of file | ||