aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning')
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/IOperationCompiler.java108
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/IQueryPlannerStrategy.java29
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/QueryProcessingException.java102
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/SubPlan.java240
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/SubPlanFactory.java33
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/BuildHelper.java165
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/FunctionalDependencyHelper.java143
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/StatisticsHelper.java62
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/TypeHelper.java217
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PApply.java94
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PEnumerate.java76
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PJoin.java64
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/POperation.java52
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PProject.java109
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PStart.java90
15 files changed, 1584 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/IOperationCompiler.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/IOperationCompiler.java
new file mode 100644
index 00000000..c9f4b305
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/IOperationCompiler.java
@@ -0,0 +1,108 @@
1/*******************************************************************************
2 * Copyright (c) 2004-2008 Gabor Bergmann and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9
10package tools.refinery.viatra.runtime.matchers.planning;
11
12import java.util.Map;
13
14import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException;
15import tools.refinery.viatra.runtime.matchers.psystem.IExpressionEvaluator;
16import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery;
17import tools.refinery.viatra.runtime.matchers.tuple.Tuple;
18import tools.refinery.viatra.runtime.matchers.tuple.TupleMask;
19
20/**
21 *
22 * An implicit common parameter is the "effort" PatternDescription. This
23 * indicates that the build request is part of an effort to build the matcher of
24 * the given pattern; it it important to record this during code generation so
25 * that the generated code can be separated according to patterns.
26 *
27 * @param <Collector>
28 * the handle of a receiver-like RETE ending to which plans can be
29 * connected
30 * @author Gabor Bergmann
31 * @noimplement This interface is not intended to be implemented by clients.
32 */
33public interface IOperationCompiler<Collector> {
34
35 /**
36 * @throws ViatraQueryRuntimeException
37 */
38 public Collector patternCollector(PQuery pattern);
39
40 public void buildConnection(SubPlan parentPlan, Collector collector);
41
42 /**
43 * @since 0.9
44 */
45 public void patternFinished(PQuery pattern, Collector collector);
46
47 /**
48 * @throws ViatraQueryRuntimeException
49 */
50 public SubPlan patternCallPlan(Tuple nodes, PQuery supplierKey);
51
52 public SubPlan transitiveInstantiationPlan(Tuple nodes);
53
54 public SubPlan directInstantiationPlan(Tuple nodes);
55
56 public SubPlan transitiveGeneralizationPlan(Tuple nodes);
57
58 public SubPlan directGeneralizationPlan(Tuple nodes);
59
60 public SubPlan transitiveContainmentPlan(Tuple nodes);
61
62 public SubPlan directContainmentPlan(Tuple nodes);
63
64 public SubPlan binaryEdgeTypePlan(Tuple nodes, Object supplierKey);
65
66 public SubPlan ternaryEdgeTypePlan(Tuple nodes, Object supplierKey);
67
68 public SubPlan unaryTypePlan(Tuple nodes, Object supplierKey);
69
70 public SubPlan buildStartingPlan(Object[] constantValues, Object[] constantNames);
71
72 public SubPlan buildEqualityChecker(SubPlan parentPlan, int[] indices);
73
74 public SubPlan buildInjectivityChecker(SubPlan parentPlan, int subject, int[] inequalIndices);
75
76 public SubPlan buildTransitiveClosure(SubPlan parentPlan);
77
78 public SubPlan buildTrimmer(SubPlan parentPlan, TupleMask trimMask, boolean enforceUniqueness);
79
80 public SubPlan buildBetaNode(SubPlan primaryPlan, SubPlan sidePlan,
81 TupleMask primaryMask, TupleMask sideMask, TupleMask complementer, boolean negative);
82
83 public SubPlan buildCounterBetaNode(SubPlan primaryPlan, SubPlan sidePlan,
84 TupleMask primaryMask, TupleMask originalSideMask, TupleMask complementer,
85 Object aggregateResultCalibrationElement);
86
87 public SubPlan buildCountCheckBetaNode(SubPlan primaryPlan, SubPlan sidePlan,
88 TupleMask primaryMask, TupleMask originalSideMask, int resultPositionInSignature);
89
90 public SubPlan buildPredicateChecker(IExpressionEvaluator evaluator, Map<String, Integer> tupleNameMap,
91 SubPlan parentPlan);
92 public SubPlan buildFunctionEvaluator(IExpressionEvaluator evaluator, Map<String, Integer> tupleNameMap,
93 SubPlan parentPlan, Object computedResultCalibrationElement);
94
95 /**
96 * @return an operation compiler that potentially acts on a separate container
97 */
98 public IOperationCompiler<Collector> getNextContainer();
99
100 /**
101 * @return an operation compiler that puts build actions on the tab of the given pattern
102 * @since 0.9
103 */
104 public IOperationCompiler<Collector> putOnTab(PQuery effort /*, IPatternMatcherContext context*/);
105
106 public void reinitialize();
107
108} \ No newline at end of file
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/IQueryPlannerStrategy.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/IQueryPlannerStrategy.java
new file mode 100644
index 00000000..6ce9d91b
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/IQueryPlannerStrategy.java
@@ -0,0 +1,29 @@
1/*******************************************************************************
2 * Copyright (c) 2004-2010 Gabor Bergmann and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9
10package tools.refinery.viatra.runtime.matchers.planning;
11
12import org.apache.log4j.Logger;
13import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException;
14import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext;
15import tools.refinery.viatra.runtime.matchers.psystem.PBody;
16
17/**
18 * An algorithm that builds a query plan based on a PSystem representation of a body of constraints. This interface is
19 * for internal use of the various query backends.
20 *
21 * @author Gabor Bergmann
22 */
23public interface IQueryPlannerStrategy {
24
25 /**
26 * @throws ViatraQueryRuntimeException
27 */
28 public SubPlan plan(PBody pSystem, Logger logger, IQueryMetaContext context);
29}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/QueryProcessingException.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/QueryProcessingException.java
new file mode 100644
index 00000000..501ddf73
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/QueryProcessingException.java
@@ -0,0 +1,102 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2013, Zoltan Ujhelyi, Istvan Rath and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.planning;
10
11import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException;
12
13/**
14 * @author Zoltan Ujhelyi
15 * @since 0.9
16 */
17public class QueryProcessingException extends ViatraQueryRuntimeException {
18
19 private static final long serialVersionUID = -8272290113656867086L;
20 /**
21 * Binding the '{n}' (n = 1..N) strings to contextual conditions in 'context'
22 *
23 * @param context
24 * : array of context-sensitive Strings
25 */
26 protected static String bind(String message, String[] context) {
27 if (context == null)
28 return message;
29
30 String internal = message;
31 for (int i = 0; i < context.length; i++) {
32 internal = internal.replace("{" + (i + 1) + "}", context[i] != null ? context[i] : "<<null>>");
33 }
34 return internal;
35 }
36
37 private Object patternDescription;
38 private String shortMessage;
39
40 /**
41 * @param message
42 * The template of the exception message
43 * @param context
44 * The data elements to be used to instantiate the template. Can be null if no context parameter is
45 * defined
46 * @param patternDescription
47 * the PatternDescription where the exception occurred
48 * @since 2.0
49 */
50 public QueryProcessingException(String message, Object patternDescription) {
51 super(message);
52 initializeFields(message, patternDescription);
53 }
54
55 /**
56 * @param message
57 * The template of the exception message
58 * @param context
59 * The data elements to be used to instantiate the template. Can be null if no context parameter is
60 * defined
61 * @param patternDescription
62 * the PatternDescription where the exception occurred
63 */
64 public QueryProcessingException(String message, String[] context, String shortMessage, Object patternDescription) {
65 super(bind(message, context));
66 initializeFields(shortMessage, patternDescription);
67 }
68
69 /**
70 * @param message
71 * The template of the exception message
72 * @param context
73 * The data elements to be used to instantiate the template. Can be null if no context parameter is
74 * defined
75 * @param patternDescription
76 * the PatternDescription where the exception occurred
77 */
78 public QueryProcessingException(String message, String[] context, String shortMessage, Object patternDescription,
79 Throwable cause) {
80 super(bind(message, context), cause);
81 initializeFields(shortMessage, patternDescription);
82 }
83
84 public Object getPatternDescription() {
85 return patternDescription;
86 }
87
88 public String getShortMessage() {
89 return shortMessage;
90 }
91
92 private void initializeFields(String shortMessage, Object patternDescription) {
93 this.patternDescription = patternDescription;
94 this.shortMessage = shortMessage;
95 }
96
97
98 public void setPatternDescription(Object patternDescription) {
99 this.patternDescription = patternDescription;
100 }
101
102} \ No newline at end of file
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/SubPlan.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/SubPlan.java
new file mode 100644
index 00000000..1998df9d
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/SubPlan.java
@@ -0,0 +1,240 @@
1/*******************************************************************************
2 * Copyright (c) 2004-2008 Gabor Bergmann and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9
10package tools.refinery.viatra.runtime.matchers.planning;
11
12import java.util.Arrays;
13import java.util.HashSet;
14import java.util.List;
15import java.util.Set;
16import java.util.WeakHashMap;
17import java.util.stream.Collectors;
18
19import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext;
20import tools.refinery.viatra.runtime.matchers.planning.helpers.TypeHelper;
21import tools.refinery.viatra.runtime.matchers.planning.operations.POperation;
22import tools.refinery.viatra.runtime.matchers.planning.operations.PProject;
23import tools.refinery.viatra.runtime.matchers.planning.operations.PStart;
24import tools.refinery.viatra.runtime.matchers.psystem.PBody;
25import tools.refinery.viatra.runtime.matchers.psystem.PConstraint;
26import tools.refinery.viatra.runtime.matchers.psystem.PVariable;
27import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement;
28
29/**
30 * A plan representing a subset of (or possibly all the) constraints evaluated. A SubPlan instance is responsible for
31 * representing a state of the plan; but after it is initialized it is expected be immutable
32 * (exception: inferred constraints, see {@link #inferConstraint(PConstraint)}).
33 *
34 * <p> A SubPlan is constructed by applying a {@link POperation} on zero or more parent SubPlans.
35 * Important maintained information: <ul>
36 * <li>set of <b>variables</b> whose values are known when the runtime evaluation is at this stage,
37 * <li>set of <b>constraints</b> that are known to hold true at this point.
38 * </ul>
39 *
40 * <p> Recommended to instantiate via a {@link SubPlanFactory} or subclasses,
41 * so that query planners can subclass SubPlan if needed.
42 *
43 * @author Gabor Bergmann
44 *
45 */
46public class SubPlan {
47 private PBody body;
48 private List<? extends SubPlan> parentPlans;
49 private POperation operation;
50
51 private final Set<PVariable> visibleVariables;
52 private final Set<PVariable> allVariables;
53 private final Set<PVariable> introducedVariables; // delta compared to first parent
54 private Set<PConstraint> allConstraints;
55 private Set<PConstraint> deltaConstraints; // delta compared to all parents
56 private Set<PConstraint> externallyInferredConstraints; // inferred in addition to direct consequences of the operation and parents
57
58
59
60
61
62 /**
63 * A SubPlan is constructed by applying a {@link POperation} on zero or more parent SubPlans.
64 */
65 public SubPlan(PBody body, POperation operation, SubPlan... parentPlans) {
66 this(body, operation, Arrays.asList(parentPlans));
67 }
68 /**
69 * A SubPlan is constructed by applying a {@link POperation} on zero or more parent SubPlans.
70 */
71 public SubPlan(PBody body, POperation operation, List<? extends SubPlan> parentPlans) {
72 super();
73 this.body = body;
74 this.parentPlans = parentPlans;
75 this.operation = operation;
76
77 this.externallyInferredConstraints = new HashSet<PConstraint>();
78 this.deltaConstraints = new HashSet<PConstraint>(operation.getDeltaConstraints());
79
80 this.allVariables = new HashSet<PVariable>();
81 for (PConstraint constraint: deltaConstraints) {
82 this.allVariables.addAll(constraint.getDeducedVariables());
83 }
84 this.allConstraints = new HashSet<PConstraint>(deltaConstraints);
85 for (SubPlan parentPlan: parentPlans) {
86 this.allConstraints.addAll(parentPlan.getAllEnforcedConstraints());
87 this.allVariables.addAll(parentPlan.getAllDeducedVariables());
88 }
89
90 // TODO this is ugly a bit
91 if (operation instanceof PStart) {
92 this.visibleVariables = new HashSet<PVariable>(((PStart) operation).getAPrioriVariables());
93 this.allVariables.addAll(visibleVariables);
94 } else if (operation instanceof PProject) {
95 this.visibleVariables = new HashSet<PVariable>(((PProject) operation).getToVariables());
96 } else {
97 this.visibleVariables = new HashSet<PVariable>();
98 for (SubPlan parentPlan: parentPlans)
99 this.visibleVariables.addAll(parentPlan.getVisibleVariables());
100 for (PConstraint constraint: deltaConstraints)
101 this.visibleVariables.addAll(constraint.getDeducedVariables());
102 }
103
104 this.introducedVariables = new HashSet<PVariable>(this.visibleVariables);
105 if (!parentPlans.isEmpty())
106 introducedVariables.removeAll(parentPlans.get(0).getVisibleVariables());
107
108 operation.checkConsistency(this);
109 }
110
111
112 @Override
113 public String toString() {
114 return toLongString();
115 }
116 public String toShortString() {
117 return String.format("Plan{%s}:%s",
118 visibleVariables.stream().map(PVariable::getName).collect(Collectors.joining(",")),
119 operation.getShortName());
120 }
121 public String toLongString() {
122 return String.format("%s<%s>",
123 toShortString(),
124 parentPlans.stream().map(Object::toString).collect(Collectors.joining("; ")));
125 }
126
127
128 /**
129 * All constraints that are known to hold at this point
130 */
131 public Set<PConstraint> getAllEnforcedConstraints() {
132 return allConstraints;
133 }
134
135 /**
136 * The new constraints enforced at this stage of plan, that aren't yet enforced at parents
137 * (results are also included in {@link SubPlan#getAllEnforcedConstraints()})
138 */
139 public Set<PConstraint> getDeltaEnforcedConstraints() {
140 return deltaConstraints;
141 }
142
143 /**
144 * Indicate that a given constraint was found to be automatically satisfied at this point
145 * without additional operations.
146 * (results are also included in {@link SubPlan#getDeltaEnforcedConstraints()})
147 *
148 * <p>Warning: not propagated automatically to child plans,
149 * so best to invoke before constructing further SubPlans. </p>
150 */
151 public void inferConstraint(PConstraint constraint) {
152 externallyInferredConstraints.add(constraint);
153 deltaConstraints.add(constraint);
154 allConstraints.add(constraint);
155 }
156
157 public PBody getBody() {
158 return body;
159 }
160
161 /**
162 * Variables which are assigned a value at this point
163 * (results are also included in {@link SubPlan#getAllDeducedVariables()})
164 */
165 public Set<PVariable> getVisibleVariables() {
166 return visibleVariables;
167 }
168 /**
169 * Variables which have been assigned a value;
170 * includes visible variables (see {@link #getVisibleVariables()})
171 * and additionally any variables hidden by a projection (see {@link PProject}).
172 */
173 public Set<PVariable> getAllDeducedVariables() {
174 return allVariables;
175 }
176 /**
177 * Delta compared to first parent: variables that are visible here but were not visible at the first parent.
178 */
179 public Set<PVariable> getIntroducedVariables() {
180 return introducedVariables;
181 }
182 public List<? extends SubPlan> getParentPlans() {
183 return parentPlans;
184 }
185 public POperation getOperation() {
186 return operation;
187 }
188
189
190 /**
191 * The closure of all type judgments of enforced constraints at this point.
192 * <p> No subsumption applied.
193 */
194 public Set<TypeJudgement> getAllImpliedTypeJudgements(IQueryMetaContext context) {
195 Set<TypeJudgement> impliedJudgements = allImpliedTypeJudgements.get(context);
196 if (impliedJudgements == null) {
197 Set<TypeJudgement> equivalentJudgements = TypeHelper.getDirectJudgements(getAllEnforcedConstraints(), context);
198 impliedJudgements = TypeHelper.typeClosure(equivalentJudgements, context);
199
200 allImpliedTypeJudgements.put(context, impliedJudgements);
201 }
202 return impliedJudgements;
203 }
204 private WeakHashMap<IQueryMetaContext, Set<TypeJudgement>> allImpliedTypeJudgements = new WeakHashMap<IQueryMetaContext, Set<TypeJudgement>>();
205
206
207 @Override
208 public int hashCode() {
209 final int prime = 31;
210 int result = 1;
211 result = prime * result
212 + ((operation == null) ? 0 : operation.hashCode());
213 result = prime * result
214 + ((parentPlans == null) ? 0 : parentPlans.hashCode());
215 return result;
216 }
217 @Override
218 public boolean equals(Object obj) {
219 if (this == obj)
220 return true;
221 if (obj == null)
222 return false;
223 if (!(obj instanceof SubPlan))
224 return false;
225 SubPlan other = (SubPlan) obj;
226 if (operation == null) {
227 if (other.operation != null)
228 return false;
229 } else if (!operation.equals(other.operation))
230 return false;
231 if (parentPlans == null) {
232 if (other.parentPlans != null)
233 return false;
234 } else if (!parentPlans.equals(other.parentPlans))
235 return false;
236 return true;
237 }
238
239
240}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/SubPlanFactory.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/SubPlanFactory.java
new file mode 100644
index 00000000..d0df5fac
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/SubPlanFactory.java
@@ -0,0 +1,33 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Bergmann Gabor, Istvan Rath and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.planning;
10
11import tools.refinery.viatra.runtime.matchers.planning.operations.POperation;
12import tools.refinery.viatra.runtime.matchers.psystem.PBody;
13
14/**
15 * Single entry point for creating subplans.
16 * Can be subclassed by query planner to provide specialized SubPlans.
17 * @author Bergmann Gabor
18 *
19 */
20public class SubPlanFactory {
21
22 protected PBody body;
23
24 public SubPlanFactory(PBody body) {
25 super();
26 this.body = body;
27 }
28
29 public SubPlan createSubPlan(POperation operation, SubPlan... parentPlans) {
30 return new SubPlan(body, operation, parentPlans);
31 }
32
33}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/BuildHelper.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/BuildHelper.java
new file mode 100644
index 00000000..ed5d1cbb
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/BuildHelper.java
@@ -0,0 +1,165 @@
1/*******************************************************************************
2 * Copyright (c) 2004-2010 Gabor Bergmann and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9
10package tools.refinery.viatra.runtime.matchers.planning.helpers;
11
12import java.util.Collection;
13import java.util.HashSet;
14import java.util.Map;
15import java.util.Set;
16
17import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException;
18import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext;
19import tools.refinery.viatra.runtime.matchers.planning.QueryProcessingException;
20import tools.refinery.viatra.runtime.matchers.planning.SubPlan;
21import tools.refinery.viatra.runtime.matchers.planning.SubPlanFactory;
22import tools.refinery.viatra.runtime.matchers.planning.operations.PProject;
23import tools.refinery.viatra.runtime.matchers.psystem.PBody;
24import tools.refinery.viatra.runtime.matchers.psystem.PConstraint;
25import tools.refinery.viatra.runtime.matchers.psystem.PVariable;
26import tools.refinery.viatra.runtime.matchers.psystem.analysis.QueryAnalyzer;
27import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.ExportedParameter;
28
29/**
30 * @author Gabor Bergmann
31 *
32 */
33public class BuildHelper {
34
35 private BuildHelper() {
36 // Hiding constructor for utility class
37 }
38
39// public static SubPlan naturalJoin(IOperationCompiler buildable,
40// SubPlan primaryPlan, SubPlan secondaryPlan) {
41// JoinHelper joinHelper = new JoinHelper(primaryPlan, secondaryPlan);
42// return buildable.buildBetaNode(primaryPlan, secondaryPlan, joinHelper.getPrimaryMask(),
43// joinHelper.getSecondaryMask(), joinHelper.getComplementerMask(), false);
44// }
45
46
47 /**
48 * Reduces the number of tuples by trimming (existentially quantifying) the set of variables that <ul>
49 * <li> are visible in the subplan,
50 * <li> are not exported parameters,
51 * <li> have all their constraints already enforced in the subplan,
52 * </ul> and thus will not be needed anymore.
53 *
54 * @param onlyIfNotDetermined if true, no trimming performed unless there is at least one variable that is not functionally determined
55 * @return the plan after the trimming (possibly the original)
56 * @since 1.5
57 */
58 public static SubPlan trimUnneccessaryVariables(SubPlanFactory planFactory, /*IOperationCompiler buildable,*/
59 SubPlan plan, boolean onlyIfNotDetermined, QueryAnalyzer analyzer) {
60 Set<PVariable> canBeTrimmed = new HashSet<PVariable>();
61 Set<PVariable> variablesInPlan = plan.getVisibleVariables();
62 for (PVariable trimCandidate : variablesInPlan) {
63 if (trimCandidate.getReferringConstraintsOfType(ExportedParameter.class).isEmpty()) {
64 if (plan.getAllEnforcedConstraints().containsAll(trimCandidate.getReferringConstraints()))
65 canBeTrimmed.add(trimCandidate);
66 }
67 }
68 final Set<PVariable> retainedVars = setMinus(variablesInPlan, canBeTrimmed);
69 if (!canBeTrimmed.isEmpty() && !(onlyIfNotDetermined && areVariablesDetermined(plan, retainedVars, canBeTrimmed, analyzer, false))) {
70 // TODO add smart ordering?
71 plan = planFactory.createSubPlan(new PProject(retainedVars), plan);
72 }
73 return plan;
74 }
75
76 /**
77 * @return true iff a set of given variables functionally determine all visible variables in the subplan according to the subplan's constraints
78 * @param strict if true, only "hard" dependencies are taken into account that are strictly enforced by the model representation;
79 * if false, user-provided soft dependencies are included as well, that are anticipated but not guaranteed by the storage mechanism;
80 * use true if superfluous dependencies may taint the correctness of a computation, false if they would merely impact performance
81 * @since 1.5
82 */
83 public static boolean areAllVariablesDetermined(SubPlan plan, Collection<PVariable> determining, QueryAnalyzer analyzer, boolean strict) {
84 return areVariablesDetermined(plan, determining, plan.getVisibleVariables(), analyzer, strict);
85 }
86
87 /**
88 * @return true iff one set of given variables functionally determine the other set according to the subplan's constraints
89 * @param strict if true, only "hard" dependencies are taken into account that are strictly enforced by the model representation;
90 * if false, user-provided soft dependencies are included as well, that are anticipated but not guaranteed by the storage mechanism;
91 * use true if superfluous dependencies may taint the correctness of a computation, false if they would merely impact performance
92 * @since 1.5
93 */
94 public static boolean areVariablesDetermined(SubPlan plan, Collection<PVariable> determining, Collection<PVariable> determined,
95 QueryAnalyzer analyzer, boolean strict) {
96 Map<Set<PVariable>, Set<PVariable>> dependencies = analyzer.getFunctionalDependencies(plan.getAllEnforcedConstraints(), strict);
97 final Set<PVariable> closure = FunctionalDependencyHelper.closureOf(determining, dependencies);
98 final boolean isDetermined = closure.containsAll(determined);
99 return isDetermined;
100 }
101
102 private static <T> Set<T> setMinus(Set<T> a, Set<T> b) {
103 Set<T> difference = new HashSet<T>(a);
104 difference.removeAll(b);
105 return difference;
106 }
107
108 /**
109 * Finds an arbitrary constraint that is not enforced at the given plan.
110 *
111 * @param pSystem
112 * @param plan
113 * @return a PConstraint that is not enforced, if any, or null if all are enforced
114 */
115 public static PConstraint getAnyUnenforcedConstraint(PBody pSystem,
116 SubPlan plan) {
117 Set<PConstraint> allEnforcedConstraints = plan.getAllEnforcedConstraints();
118 Set<PConstraint> constraints = pSystem.getConstraints();
119 for (PConstraint pConstraint : constraints) {
120 if (!allEnforcedConstraints.contains(pConstraint))
121 return pConstraint;
122 }
123 return null;
124 }
125
126 /**
127 * Skips the last few steps, if any, that are projections, so that a custom projection can be added instead.
128 * Useful for connecting body final plans into the production node.
129 *
130 * @since 2.1
131 */
132 public static SubPlan eliminateTrailingProjections(SubPlan plan) {
133 while (plan.getOperation() instanceof PProject)
134 plan = plan.getParentPlans().get(0);
135 return plan;
136 }
137
138 /**
139 * Verifies whether all constraints are enforced and exported parameters are present.
140 *
141 * @param pSystem
142 * @param plan
143 * @throws ViatraQueryRuntimeException
144 */
145 public static void finalCheck(final PBody pSystem, SubPlan plan, IQueryMetaContext context) {
146 PConstraint unenforcedConstraint = getAnyUnenforcedConstraint(pSystem, plan);
147 if (unenforcedConstraint != null) {
148 throw new QueryProcessingException(
149 "Pattern matcher construction terminated without successfully enforcing constraint {1}."
150 + " Could be caused if the value of some variables can not be deduced, e.g. by circularity of pattern constraints.",
151 new String[] { unenforcedConstraint.toString() }, "Could not enforce a pattern constraint", null);
152 }
153 for (ExportedParameter export : pSystem
154 .getConstraintsOfType(ExportedParameter.class)) {
155 if (!export.isReadyAt(plan, context)) {
156 throw new QueryProcessingException(
157 "Exported pattern parameter {1} could not be deduced during pattern matcher construction."
158 + " A pattern constraint is required to positively deduce its value.",
159 new String[] { export.getParameterName() }, "Could not calculate pattern parameter",
160 null);
161 }
162 }
163 }
164
165}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/FunctionalDependencyHelper.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/FunctionalDependencyHelper.java
new file mode 100644
index 00000000..40835f52
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/FunctionalDependencyHelper.java
@@ -0,0 +1,143 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2013, Adam Dudas, Istvan Rath and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.planning.helpers;
10
11import java.util.Collection;
12import java.util.Collections;
13import java.util.HashMap;
14import java.util.HashSet;
15import java.util.Map;
16import java.util.Map.Entry;
17import java.util.Set;
18
19import tools.refinery.viatra.runtime.matchers.util.Sets;
20
21/**
22 * Helper utility class for functional dependency analysis.
23 *
24 * Throughout this class attribute sets are represented as generic sets and functional dependencies as maps from
25 * attribute set (generic sets) to attribute set (generic sets)
26 *
27 * @author Adam Dudas
28 *
29 */
30public class FunctionalDependencyHelper {
31
32 private FunctionalDependencyHelper() {
33 // Hiding constructor for utility class
34 }
35
36 /**
37 * Get the closure of the specified attribute set relative to the specified functional dependencies.
38 *
39 * @param attributes
40 * The attributes to get the closure of.
41 * @param dependencies
42 * The functional dependencies of which the closure operation is relative to.
43 * @return The closure of the specified attribute set relative to the specified functional dependencies.
44 */
45 public static <A> Set<A> closureOf(Collection<A> attributes, Map<Set<A>, Set<A>> dependencies) {
46 Set<A> closureSet = new HashSet<A>();
47
48 for (Set<A> closureSet1 = new HashSet<A>(attributes); closureSet.addAll(closureSet1);) {
49 closureSet1 = new HashSet<A>();
50 for (Entry<Set<A>, Set<A>> dependency : dependencies.entrySet()) {
51 if (closureSet.containsAll(dependency.getKey()))
52 closureSet1.addAll(dependency.getValue());
53 }
54 }
55
56 return closureSet;
57 }
58
59 /**
60 * @return true if the dependency from the left set to the right set is trivial
61 * @since 1.5
62 */
63 public static <A> boolean isTrivial(Set<A> left, Set<A> right) {
64 return left.containsAll(right);
65 }
66
67 /***
68 * Returns the dependency set over attributes in {@link targetAttributes} that are implied by a given source dependency set.
69 * <p> Note: exponential in the size of the target attribute set.
70 * <p> Note: minimality of the returned dependency set is currently not guaranteed.
71 * @param originalDependencies all dependencies that are known to hold on a wider set of attributes
72 * @param targetAttributes the set of attributes we are interested in
73 * @since 1.5
74 */
75 public static <A> Map<Set<A>, Set<A>> projectDependencies(Map<Set<A>, Set<A>> originalDependencies, Set<A> targetAttributes) {
76 // only those attributes are considered as left-hand-side candidates that occur at least once in dependencies
77 Set<A> leftCandidates = new HashSet<A>();
78 for (Entry<Set<A>, Set<A>> dependency : originalDependencies.entrySet()) {
79 if (!isTrivial(dependency.getKey(), dependency.getValue())) // only if non-trivial
80 leftCandidates.addAll(Sets.intersection(dependency.getKey(), targetAttributes));
81 }
82
83 // Compute an initial list of nontrivial projected dependencies - it does not have to be minimal yet
84 Map<Set<A>, Set<A>> initialDependencies = new HashMap<Set<A>, Set<A>>();
85 for (Set<A> leftSet : Sets.powerSet(leftCandidates)) {
86 Set<A> rightSet = Sets.intersection(closureOf(leftSet, originalDependencies), targetAttributes);
87 if (!isTrivial(leftSet, rightSet)) {
88 initialDependencies.put(leftSet, rightSet);
89 }
90 }
91 // Don't forget to include constants!
92 Set<A> constants = Sets.intersection(closureOf(Collections.<A>emptySet(), originalDependencies), targetAttributes);
93 if (! constants.isEmpty()) {
94 initialDependencies.put(Collections.<A>emptySet(), constants);
95 }
96
97 // Omit those dependencies where the LHS has superfluous attributes
98 Map<Set<A>, Set<A>> solidDependencies = new HashMap<Set<A>, Set<A>>();
99 for (Entry<Set<A>, Set<A>> dependency : initialDependencies.entrySet()) {
100 Set<A> leftSet = dependency.getKey();
101 Set<A> rightSet = dependency.getValue();
102 boolean solid = true;
103 for (A skipped : leftSet) { // what if we skip one attribute from the left set?
104 Set<A> singleton = Collections.singleton(skipped);
105 Set<A> candidate = Sets.difference(leftSet, singleton);
106 Set<A> rightCandidate = initialDependencies.get(candidate);
107 if (rightCandidate != null) {
108 if (Sets.union(rightCandidate, singleton).containsAll(rightSet)) {
109 solid = false;
110 break;
111 }
112 }
113 }
114 if (solid) {
115 solidDependencies.put(leftSet, rightSet);
116 }
117 }
118
119 // TODO perform proper minimization,
120 // see e.g. page 45 in http://www.cs.ubc.ca/~hkhosrav/db/slides/03.design%20theory.pdf
121
122 return Collections.unmodifiableMap(solidDependencies);
123 }
124
125 /**
126 * Adds a given dependency to a mutable accumulator.
127 * @since 1.5
128 */
129 public static <A> void includeDependency(Map<Set<A>, Set<A>> accumulator, Set<A> left, Set<A> right) {
130 Set<A> accumulatorRights = accumulator.computeIfAbsent(left, l -> new HashSet<>());
131 accumulatorRights.addAll(right);
132 }
133
134 /**
135 * Adds all given dependencies to a mutable accumulator.
136 * @since 1.5
137 */
138 public static <A> void includeDependencies(Map<Set<A>, Set<A>> accumulator, Map<Set<A>, Set<A>> additionalDependencies) {
139 for (Entry<Set<A>, Set<A>> entry : additionalDependencies.entrySet()) {
140 includeDependency(accumulator, entry.getKey(), entry.getValue());
141 }
142 }
143}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/StatisticsHelper.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/StatisticsHelper.java
new file mode 100644
index 00000000..b4f848a7
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/StatisticsHelper.java
@@ -0,0 +1,62 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2018, Gabor Bergmann, IncQuery Labs Ltd.
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.planning.helpers;
10
11import java.util.Optional;
12import java.util.function.BiFunction;
13
14import tools.refinery.viatra.runtime.matchers.tuple.TupleMask;
15import tools.refinery.viatra.runtime.matchers.util.Accuracy;
16
17/**
18 * Helpers dealing with optionally present statistics information
19 *
20 * @author Gabor Bergmann
21 * @since 2.1
22 *
23 */
24public class StatisticsHelper {
25
26 private StatisticsHelper() {
27 // Hidden utility class constructor
28 }
29
30 public static Optional<Double> estimateAverageBucketSize(TupleMask groupMask, Accuracy requiredAccuracy,
31 BiFunction<TupleMask, Accuracy, Optional<Long>> estimateCardinality)
32 {
33 if (groupMask.isIdentity()) return Optional.of(1.0);
34
35 Accuracy numeratorAccuracy = requiredAccuracy;
36 Accuracy denominatorAccuracy = requiredAccuracy.reciprocal();
37 TupleMask identityMask = TupleMask.identity(groupMask.sourceWidth);
38
39 Optional<Long> totalCountEstimate = estimateCardinality.apply(identityMask, numeratorAccuracy);
40 Optional<Long> bucketCountEstimate = estimateCardinality.apply(groupMask, denominatorAccuracy);
41
42 return totalCountEstimate.flatMap(matchCount ->
43 bucketCountEstimate.map(bucketCount ->
44 bucketCount == 0L ? 0L : ((double) matchCount) / bucketCount
45 ));
46 }
47
48 public static Optional<Double> min(Optional<Double> a, Optional<Double> b) {
49 if (b.isPresent()) {
50 if (a.isPresent()) {
51 return Optional.of(Math.min(a.get(), b.get()));
52 } else return b;
53 } else return a;
54 }
55 public static Optional<Double> min(Optional<Double> a, double b) {
56 if (a.isPresent()) {
57 return Optional.of(Math.min(a.get(), b));
58 } else return Optional.of(b);
59 }
60
61
62}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/TypeHelper.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/TypeHelper.java
new file mode 100644
index 00000000..926a591f
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/TypeHelper.java
@@ -0,0 +1,217 @@
1/*******************************************************************************
2 * Copyright (c) 2004-2010 Gabor Bergmann and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9
10package tools.refinery.viatra.runtime.matchers.planning.helpers;
11
12import java.util.Collections;
13import java.util.HashMap;
14import java.util.HashSet;
15import java.util.LinkedList;
16import java.util.Map;
17import java.util.Map.Entry;
18import java.util.Queue;
19import java.util.Set;
20import java.util.stream.Collectors;
21
22import tools.refinery.viatra.runtime.matchers.context.IInputKey;
23import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext;
24import tools.refinery.viatra.runtime.matchers.psystem.ITypeInfoProviderConstraint;
25import tools.refinery.viatra.runtime.matchers.psystem.PConstraint;
26import tools.refinery.viatra.runtime.matchers.psystem.PVariable;
27import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement;
28
29/**
30 * @author Gabor Bergmann
31 * @author Tamas Szabo
32 */
33public class TypeHelper {
34
35 private TypeHelper() {
36 // Hiding constructor for utility class
37 }
38
39 /**
40 * Collects the type constraints for the specified collection of variables. The type constraints consist of the
41 * constraints directly enforced on the variable itself, plus all of those that the given variable is unified with
42 * through equalities.
43 *
44 * @param variables
45 * the variables in question
46 * @param constraints
47 * the constraints in the pattern body
48 * @param context
49 * the query meta context
50 * @return the mapping from variable to set of type constraints
51 * @since 1.6
52 */
53 public static Map<PVariable, Set<IInputKey>> inferUnaryTypesFor(Iterable<PVariable> variables,
54 Set<PConstraint> constraints, IQueryMetaContext context) {
55 Map<PVariable, Set<TypeJudgement>> typeMap = TypeHelper.inferUnaryTypes(constraints, context);
56 return inferUnaryTypesFor(variables, typeMap);
57 }
58
59 /**
60 * Collects the type constraints for the specified collection of variables. The type constraints consist of the
61 * constraints directly enforced on the variable itself, plus all of those that the given variable is unified with
62 * through equalities.
63 *
64 * The method accepts a type map which is the result of the basic type inference from the
65 * {@link TypeHelper.inferUnaryTypes} method. The purpose of this method is that the type map can be reused across
66 * several calls to this method.
67 *
68 * @param variables
69 * the variables in question
70 * @param typeMap
71 * the type map of inference results
72 * @return the mapping from variable to set of type constraints
73 * @since 1.6
74 */
75 public static Map<PVariable, Set<IInputKey>> inferUnaryTypesFor(Iterable<PVariable> variables,
76 Map<PVariable, Set<TypeJudgement>> typeMap) {
77 Map<PVariable, Set<IInputKey>> result = new HashMap<PVariable, Set<IInputKey>>();
78
79 for (PVariable original : variables) {
80 // it can happen that the variable was unified into an other one due to equalities
81 Set<IInputKey> keys = new HashSet<IInputKey>();
82 PVariable current = original;
83
84 while (current != null) {
85 Set<TypeJudgement> judgements = typeMap.get(current);
86 if (judgements != null) {
87 for (TypeJudgement judgement : judgements) {
88 keys.add(judgement.getInputKey());
89 }
90 }
91 current = current.getDirectUnifiedInto();
92 }
93
94 result.put(original, keys);
95 }
96
97 return result;
98 }
99
100 /**
101 * Infers unary type information for variables, based on the given constraints.
102 *
103 * Subsumptions are not taken into account.
104 *
105 * @param constraints
106 * the set of constraints to extract type info from
107 */
108 public static Map<PVariable, Set<TypeJudgement>> inferUnaryTypes(Set<PConstraint> constraints,
109 IQueryMetaContext context) {
110 Set<TypeJudgement> equivalentJudgements = getDirectJudgements(constraints, context);
111 Set<TypeJudgement> impliedJudgements = typeClosure(equivalentJudgements, context);
112
113 Map<PVariable, Set<TypeJudgement>> results = new HashMap<PVariable, Set<TypeJudgement>>();
114 for (TypeJudgement typeJudgement : impliedJudgements) {
115 final IInputKey inputKey = typeJudgement.getInputKey();
116 if (inputKey.getArity() == 1) {
117 PVariable variable = (PVariable) typeJudgement.getVariablesTuple().get(0);
118 Set<TypeJudgement> inferredTypes = results.computeIfAbsent(variable, v -> new HashSet<>());
119 inferredTypes.add(typeJudgement);
120 }
121 }
122 return results;
123 }
124
125 /**
126 * Gets direct judgements reported by constraints. No closure is applied yet.
127 */
128 public static Set<TypeJudgement> getDirectJudgements(Set<PConstraint> constraints, IQueryMetaContext context) {
129 Set<TypeJudgement> equivalentJudgements = new HashSet<TypeJudgement>();
130 for (PConstraint pConstraint : constraints) {
131 if (pConstraint instanceof ITypeInfoProviderConstraint) {
132 equivalentJudgements.addAll(((ITypeInfoProviderConstraint) pConstraint).getImpliedJudgements(context));
133 }
134 }
135 return equivalentJudgements;
136 }
137
138 /**
139 * Calculates the closure of a set of type judgements, with respect to supertyping.
140 *
141 * @return the set of all type judgements in typesToClose and all their direct and indirect supertypes
142 */
143 public static Set<TypeJudgement> typeClosure(Set<TypeJudgement> typesToClose, IQueryMetaContext context) {
144 return typeClosure(Collections.<TypeJudgement> emptySet(), typesToClose, context);
145 }
146
147 /**
148 * Calculates the closure of a set of type judgements (with respect to supertyping), where the closure has been
149 * calculated before for a given base set, but not for a separate delta set.
150 * <p>
151 * Precondition: the set (typesToClose MINUS delta) is already closed w.r.t. supertyping.
152 *
153 * @return the set of all type judgements in typesToClose and all their direct and indirect supertypes
154 * @since 1.6
155 */
156 public static Set<TypeJudgement> typeClosure(Set<TypeJudgement> preclosedBaseSet, Set<TypeJudgement> delta,
157 IQueryMetaContext context) {
158 Queue<TypeJudgement> queue = delta.stream().filter(input -> !preclosedBaseSet.contains(input)).collect(Collectors.toCollection(LinkedList::new));
159 if (queue.isEmpty())
160 return preclosedBaseSet;
161
162 Set<TypeJudgement> closure = new HashSet<TypeJudgement>(preclosedBaseSet);
163
164 Map<TypeJudgement, Set<TypeJudgement>> conditionalImplications = new HashMap<>();
165 for (TypeJudgement typeJudgement : closure) {
166 conditionalImplications.putAll(typeJudgement.getConditionalImpliedJudgements(context));
167 }
168
169 do {
170 TypeJudgement deltaType = queue.poll();
171 if (closure.add(deltaType)) {
172 // direct implications
173 queue.addAll(deltaType.getDirectlyImpliedJudgements(context));
174
175 // conditional implications, source key processed before, this is the condition key
176 final Set<TypeJudgement> implicationSet = conditionalImplications.get(deltaType);
177 if (implicationSet != null) {
178 queue.addAll(implicationSet);
179 }
180
181 // conditional implications, this is the source key
182 Map<TypeJudgement, Set<TypeJudgement>> deltaConditionalImplications = deltaType
183 .getConditionalImpliedJudgements(context);
184 for (Entry<TypeJudgement, Set<TypeJudgement>> entry : deltaConditionalImplications.entrySet()) {
185 if (closure.contains(entry.getKey())) {
186 // condition processed before
187 queue.addAll(entry.getValue());
188 } else {
189 // condition not processed yet
190 conditionalImplications.computeIfAbsent(entry.getKey(), key -> new HashSet<>())
191 .addAll(entry.getValue());
192 }
193 }
194 }
195 } while (!queue.isEmpty());
196
197 return closure;
198 }
199
200 /**
201 * Calculates a remainder set of types from a larger set, that are not subsumed by a given set of subsuming types.
202 *
203 * @param subsumableTypes
204 * a set of types from which some may be implied by the subsuming types
205 * @param subsumingTypes
206 * a set of types that may imply some of the subsuming types
207 * @return the collection of types in subsumableTypes that are NOT identical to or supertypes of any type in
208 * subsumingTypes.
209 */
210 public static Set<TypeJudgement> subsumeTypes(Set<TypeJudgement> subsumableTypes, Set<TypeJudgement> subsumingTypes,
211 IQueryMetaContext context) {
212 Set<TypeJudgement> closure = typeClosure(subsumingTypes, context);
213 Set<TypeJudgement> subsumed = new HashSet<TypeJudgement>(subsumableTypes);
214 subsumed.removeAll(closure);
215 return subsumed;
216 }
217}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PApply.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PApply.java
new file mode 100644
index 00000000..2c285b54
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PApply.java
@@ -0,0 +1,94 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Bergmann Gabor, Istvan Rath and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.planning.operations;
10
11import java.util.Collections;
12import java.util.Set;
13
14import tools.refinery.viatra.runtime.matchers.planning.SubPlan;
15import tools.refinery.viatra.runtime.matchers.psystem.PConstraint;
16import tools.refinery.viatra.runtime.matchers.util.Preconditions;
17
18/**
19 * Represents a constraint application on a single parent SubPlan.
20 * <p> Either a "selection" filter operation according to a deferred PConstraint (or transform in case of eval/aggregate), or
21 * alternatively a shorthand for PJoin + a PEnumerate on the right input for an enumerable PConstraint.
22 *
23 * <p> <b>WARNING</b>: if there are coinciding variables in the variable tuple of the enumerable constraint,
24 * it is the responsibility of the compiler to check them for equality.
25 *
26 * @author Bergmann Gabor
27 *
28 */
29public class PApply extends POperation {
30
31 private PConstraint pConstraint;
32
33 public PApply(PConstraint pConstraint) {
34 super();
35 this.pConstraint = pConstraint;
36 }
37 public PConstraint getPConstraint() {
38 return pConstraint;
39 }
40
41 @Override
42 public String getShortName() {
43 return String.format("APPLY_%s", pConstraint.toString());
44 }
45
46 @Override
47 public Set<? extends PConstraint> getDeltaConstraints() {
48 return Collections.singleton(pConstraint);
49 }
50
51 @Override
52 public int numParentSubPlans() {
53 return 1;
54 }
55
56 @Override
57 public void checkConsistency(SubPlan subPlan) {
58 super.checkConsistency(subPlan);
59 for (SubPlan parentPlan : subPlan.getParentPlans())
60 Preconditions.checkArgument(!parentPlan.getAllEnforcedConstraints().contains(pConstraint),
61 "Double-checking constraint %s", pConstraint);
62 // TODO obtain context?
63 //if (pConstraint instanceof DeferredPConstraint)
64 // Preconditions.checkArgument(((DeferredPConstraint) pConstraint).isReadyAt(subPlan, context))
65 }
66
67 @Override
68 public int hashCode() {
69 final int prime = 31;
70 int result = 1;
71 result = prime
72 * result
73 + ((pConstraint == null) ? 0 : pConstraint
74 .hashCode());
75 return result;
76 }
77 @Override
78 public boolean equals(Object obj) {
79 if (this == obj)
80 return true;
81 if (obj == null)
82 return false;
83 if (!(obj instanceof PApply))
84 return false;
85 PApply other = (PApply) obj;
86 if (pConstraint == null) {
87 if (other.pConstraint != null)
88 return false;
89 } else if (!pConstraint.equals(other.pConstraint))
90 return false;
91 return true;
92 }
93
94}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PEnumerate.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PEnumerate.java
new file mode 100644
index 00000000..a975d50c
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PEnumerate.java
@@ -0,0 +1,76 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Bergmann Gabor, Istvan Rath and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.planning.operations;
10
11import java.util.Collections;
12import java.util.Set;
13
14import tools.refinery.viatra.runtime.matchers.psystem.EnumerablePConstraint;
15import tools.refinery.viatra.runtime.matchers.psystem.PConstraint;
16
17/**
18 * Represents a base relation defined by the instance set of an enumerable PConstraint; there are no parent SubPlans.
19 *
20 * <p> <b>WARNING</b>: if there are coinciding variables in the variable tuple of the enumerable constraint,
21 * it is the responsibility of the compiler to check them for equality.
22 * @author Bergmann Gabor
23 *
24 */
25public class PEnumerate extends POperation {
26
27 EnumerablePConstraint enumerablePConstraint;
28
29 public PEnumerate(EnumerablePConstraint enumerablePConstraint) {
30 super();
31 this.enumerablePConstraint = enumerablePConstraint;
32 }
33 public EnumerablePConstraint getEnumerablePConstraint() {
34 return enumerablePConstraint;
35 }
36
37 @Override
38 public Set<? extends PConstraint> getDeltaConstraints() {
39 return Collections.singleton(enumerablePConstraint);
40 }
41 @Override
42 public int numParentSubPlans() {
43 return 0;
44 }
45 @Override
46 public String getShortName() {
47 return enumerablePConstraint.toString();
48 }
49 @Override
50 public int hashCode() {
51 final int prime = 31;
52 int result = 1;
53 result = prime
54 * result
55 + ((enumerablePConstraint == null) ? 0 : enumerablePConstraint
56 .hashCode());
57 return result;
58 }
59 @Override
60 public boolean equals(Object obj) {
61 if (this == obj)
62 return true;
63 if (obj == null)
64 return false;
65 if (!(obj instanceof PEnumerate))
66 return false;
67 PEnumerate other = (PEnumerate) obj;
68 if (enumerablePConstraint == null) {
69 if (other.enumerablePConstraint != null)
70 return false;
71 } else if (!enumerablePConstraint.equals(other.enumerablePConstraint))
72 return false;
73 return true;
74 }
75
76}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PJoin.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PJoin.java
new file mode 100644
index 00000000..10e0a85a
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PJoin.java
@@ -0,0 +1,64 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Bergmann Gabor, Istvan Rath and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.planning.operations;
10
11import java.util.Collections;
12import java.util.Set;
13
14import tools.refinery.viatra.runtime.matchers.psystem.PConstraint;
15
16/**
17 * Represents a natural join of two parent SubPlans.
18 * @author Bergmann Gabor
19 *
20 */
21public class PJoin extends POperation {
22
23// // TODO leave here? is this a problem in equivalnece checking?
24// private Set<PVariable> onVariables;
25
26 public PJoin(/*Set<PVariable> onVariables*/) {
27 super();
28 //this.onVariables = new HashSet<PVariable>(onVariables);
29 }
30// public Set<PVariable> getOnVariables() {
31// return onVariables;
32// }
33
34 @Override
35 public Set<? extends PConstraint> getDeltaConstraints() {
36 return Collections.emptySet();
37 }
38 @Override
39 public int numParentSubPlans() {
40 return 2;
41 }
42
43 @Override
44 public String getShortName() {
45 return "JOIN"; //String.format("JOIN_{%s}", Joiner.on(",").join(onVariables));
46 }
47
48 @Override
49 public int hashCode() {
50 return getClass().hashCode();
51 }
52 @Override
53 public boolean equals(Object obj) {
54 if (this == obj)
55 return true;
56 if (obj == null)
57 return false;
58 if (!(obj instanceof PJoin))
59 return false;
60 return true;
61 }
62
63
64}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/POperation.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/POperation.java
new file mode 100644
index 00000000..e71cf217
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/POperation.java
@@ -0,0 +1,52 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Bergmann Gabor, Istvan Rath and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.planning.operations;
10
11import java.util.Set;
12
13import tools.refinery.viatra.runtime.matchers.planning.SubPlan;
14import tools.refinery.viatra.runtime.matchers.psystem.PConstraint;
15import tools.refinery.viatra.runtime.matchers.util.Preconditions;
16
17/**
18 * Abstract superclass for representing a high-level query evaluation operation.
19 *
20 * <p> Subclasses correspond to various POperations modeled after relational algebra.
21 *
22 * @author Bergmann Gabor
23 *
24 */
25public abstract class POperation {
26
27 /**
28 * Newly enforced constraints
29 */
30 public abstract Set<? extends PConstraint> getDeltaConstraints();
31
32 public abstract String getShortName();
33
34 /**
35 * @return the number of SubPlans that must be specified as parents
36 */
37 public abstract int numParentSubPlans();
38
39 /**
40 * Checks whether this constraint can be properly applied at the given SubPlan.
41 */
42 public void checkConsistency(SubPlan subPlan) {
43 Preconditions.checkArgument(this == subPlan.getOperation(), "POperation misalignment");
44 Preconditions.checkArgument(subPlan.getParentPlans().size() == numParentSubPlans(), "Incorrect number of parent SubPlans");
45 }
46
47 @Override
48 public String toString() {
49 return getShortName();
50 }
51
52}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PProject.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PProject.java
new file mode 100644
index 00000000..d0539b2c
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PProject.java
@@ -0,0 +1,109 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Bergmann Gabor, Istvan Rath and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.planning.operations;
10
11import java.util.Collection;
12import java.util.Collections;
13import java.util.List;
14import java.util.Set;
15import java.util.stream.Collectors;
16
17import tools.refinery.viatra.runtime.matchers.planning.SubPlan;
18import tools.refinery.viatra.runtime.matchers.psystem.PConstraint;
19import tools.refinery.viatra.runtime.matchers.psystem.PVariable;
20import tools.refinery.viatra.runtime.matchers.util.Preconditions;
21
22/**
23 * Represents a projection of a single parent SubPlan onto a limited set of variables.
24 * <p> May optionally prescribe an ordering of variables (List, as opposed to Set).
25 *
26 * @author Bergmann Gabor
27 *
28 */
29public class PProject extends POperation {
30
31 private Collection<PVariable> toVariables;
32 private boolean ordered;
33
34
35 public PProject(Set<PVariable> toVariables) {
36 super();
37 this.toVariables = toVariables;
38 this.ordered = false;
39 }
40 public PProject(List<PVariable> toVariables) {
41 super();
42 this.toVariables = toVariables;
43 this.ordered = true;
44 }
45
46 public Collection<PVariable> getToVariables() {
47 return toVariables;
48 }
49 public boolean isOrdered() {
50 return ordered;
51 }
52
53 @Override
54 public Set<? extends PConstraint> getDeltaConstraints() {
55 return Collections.emptySet();
56 }
57 @Override
58 public int numParentSubPlans() {
59 return 1;
60 }
61 @Override
62 public void checkConsistency(SubPlan subPlan) {
63 super.checkConsistency(subPlan);
64 final SubPlan parentPlan = subPlan.getParentPlans().get(0);
65
66 Preconditions.checkArgument(parentPlan.getVisibleVariables().containsAll(toVariables),
67 () -> toVariables.stream()
68 .filter(input -> !parentPlan.getVisibleVariables().contains(input)).map(PVariable::getName)
69 .collect(Collectors.joining(",", "Variables missing from project: ", "")));
70 }
71
72 @Override
73 public String getShortName() {
74 return String.format("PROJECT%s_{%s}", ordered? "!" : "",
75 toVariables.stream().map(PVariable::getName).collect(Collectors.joining(",")));
76 }
77
78 @Override
79 public int hashCode() {
80 final int prime = 31;
81 int result = 1;
82 result = prime * result + (ordered ? 1231 : 1237);
83 result = prime * result
84 + ((toVariables == null) ? 0 : toVariables.hashCode());
85 return result;
86 }
87 @Override
88 public boolean equals(Object obj) {
89 if (this == obj)
90 return true;
91 if (obj == null)
92 return false;
93 if (!(obj instanceof PProject))
94 return false;
95 PProject other = (PProject) obj;
96 if (ordered != other.ordered)
97 return false;
98 if (toVariables == null) {
99 if (other.toVariables != null)
100 return false;
101 } else if (!toVariables.equals(other.toVariables))
102 return false;
103 return true;
104 }
105
106
107
108
109}
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PStart.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PStart.java
new file mode 100644
index 00000000..9e6ea10e
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/operations/PStart.java
@@ -0,0 +1,90 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Bergmann Gabor, Istvan Rath and Daniel Varro
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.planning.operations;
10
11import java.util.Arrays;
12import java.util.Collections;
13import java.util.HashSet;
14import java.util.Set;
15import java.util.stream.Collectors;
16
17import tools.refinery.viatra.runtime.matchers.psystem.PConstraint;
18import tools.refinery.viatra.runtime.matchers.psystem.PVariable;
19
20/**
21 * No constraints, and no parent SubPlan, just a (possibly empty) set of a priori known (input) variables. Satisfied by a single tuple.
22 *
23 * <p> Can also be used without a priori variables,
24 * e.g. as a "virtual parent" in extreme cases,
25 * such as <code>pattern foo(Bar) = {Bar = eval (3*4)} </code>
26 *
27 * @author Bergmann Gabor
28 *
29 */
30public class PStart extends POperation {
31
32 private Set<PVariable> aPrioriVariables;
33
34
35 public PStart(Set<PVariable> aPrioriVariables) {
36 super();
37 this.aPrioriVariables = aPrioriVariables;
38 }
39 public PStart(PVariable... aPrioriVariables) {
40 this(new HashSet<PVariable>(Arrays.asList(aPrioriVariables)));
41 }
42 public Set<PVariable> getAPrioriVariables() {
43 return aPrioriVariables;
44 }
45
46 @Override
47 public String getShortName() {
48 return aPrioriVariables.stream().map(PVariable::getName).collect(Collectors.joining(",", "START_{", "}"));
49 }
50 @Override
51 public int numParentSubPlans() {
52 return 0;
53 }
54
55 @Override
56 public Set<? extends PConstraint> getDeltaConstraints() {
57 return Collections.emptySet();
58 }
59
60 @Override
61 public int hashCode() {
62 final int prime = 31;
63 int result = 1;
64 result = prime
65 * result
66 + ((aPrioriVariables == null) ? 0 : aPrioriVariables.hashCode());
67 return result;
68 }
69
70 @Override
71 public boolean equals(Object obj) {
72 if (this == obj)
73 return true;
74 if (obj == null)
75 return false;
76 if (!(obj instanceof PStart))
77 return false;
78 PStart other = (PStart) obj;
79 if (aPrioriVariables == null) {
80 if (other.aPrioriVariables != null)
81 return false;
82 } else if (!aPrioriVariables.equals(other.aPrioriVariables))
83 return false;
84 return true;
85 }
86
87
88
89
90}