diff options
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/TypeHelper.java')
-rw-r--r-- | subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/planning/helpers/TypeHelper.java | 217 |
1 files changed, 217 insertions, 0 deletions
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 | |||
10 | package tools.refinery.viatra.runtime.matchers.planning.helpers; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.HashSet; | ||
15 | import java.util.LinkedList; | ||
16 | import java.util.Map; | ||
17 | import java.util.Map.Entry; | ||
18 | import java.util.Queue; | ||
19 | import java.util.Set; | ||
20 | import java.util.stream.Collectors; | ||
21 | |||
22 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
23 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
24 | import tools.refinery.viatra.runtime.matchers.psystem.ITypeInfoProviderConstraint; | ||
25 | import tools.refinery.viatra.runtime.matchers.psystem.PConstraint; | ||
26 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
27 | import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement; | ||
28 | |||
29 | /** | ||
30 | * @author Gabor Bergmann | ||
31 | * @author Tamas Szabo | ||
32 | */ | ||
33 | public 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 | } | ||