diff options
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/BuildHelper.java')
-rw-r--r-- | subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/BuildHelper.java | 165 |
1 files changed, 165 insertions, 0 deletions
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 | |||
10 | package tools.refinery.viatra.runtime.matchers.planning.helpers; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | import java.util.HashSet; | ||
14 | import java.util.Map; | ||
15 | import java.util.Set; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | ||
18 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
19 | import tools.refinery.viatra.runtime.matchers.planning.QueryProcessingException; | ||
20 | import tools.refinery.viatra.runtime.matchers.planning.SubPlan; | ||
21 | import tools.refinery.viatra.runtime.matchers.planning.SubPlanFactory; | ||
22 | import tools.refinery.viatra.runtime.matchers.planning.operations.PProject; | ||
23 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
24 | import tools.refinery.viatra.runtime.matchers.psystem.PConstraint; | ||
25 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
26 | import tools.refinery.viatra.runtime.matchers.psystem.analysis.QueryAnalyzer; | ||
27 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.ExportedParameter; | ||
28 | |||
29 | /** | ||
30 | * @author Gabor Bergmann | ||
31 | * | ||
32 | */ | ||
33 | public 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 | } | ||