diff options
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem')
76 files changed, 6214 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/BasePConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/BasePConstraint.java new file mode 100644 index 00000000..eda4aa25 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/BasePConstraint.java | |||
@@ -0,0 +1,108 @@ | |||
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.psystem; | ||
11 | |||
12 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
13 | |||
14 | import java.util.Collections; | ||
15 | import java.util.HashSet; | ||
16 | import java.util.Map; | ||
17 | import java.util.Set; | ||
18 | import java.util.concurrent.atomic.AtomicInteger; | ||
19 | |||
20 | /** | ||
21 | * @author Gabor Bergmann | ||
22 | * | ||
23 | */ | ||
24 | public abstract class BasePConstraint implements PConstraint { | ||
25 | |||
26 | |||
27 | protected PBody pBody; | ||
28 | private final Set<PVariable> affectedVariables; | ||
29 | |||
30 | |||
31 | private final int sequentialID = nextID.getAndIncrement(); | ||
32 | |||
33 | // Use a static atomic integer to avoid race conditions when creating new constraints. | ||
34 | private static AtomicInteger nextID = new AtomicInteger(0); | ||
35 | |||
36 | public BasePConstraint(PBody pBody, Set<PVariable> affectedVariables) { | ||
37 | super(); | ||
38 | this.pBody = pBody; | ||
39 | this.affectedVariables = new HashSet<PVariable>(affectedVariables); | ||
40 | |||
41 | for (PVariable pVariable : affectedVariables) { | ||
42 | pVariable.refer(this); | ||
43 | } | ||
44 | pBody.registerConstraint(this); | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public String toString() { | ||
49 | return "PC[" + getClass().getSimpleName() + ":" + toStringRest() + "]"; | ||
50 | } | ||
51 | |||
52 | protected abstract String toStringRest(); | ||
53 | |||
54 | @Override | ||
55 | public Set<PVariable> getAffectedVariables() { | ||
56 | return affectedVariables; | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context) { | ||
61 | return Collections.emptyMap(); | ||
62 | } | ||
63 | |||
64 | @Override | ||
65 | public void replaceVariable(PVariable obsolete, PVariable replacement) { | ||
66 | pBody.checkMutability(); | ||
67 | if (affectedVariables.remove(obsolete)) { | ||
68 | affectedVariables.add(replacement); | ||
69 | obsolete.unrefer(this); | ||
70 | replacement.refer(this); | ||
71 | doReplaceVariable(obsolete, replacement); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | protected abstract void doReplaceVariable(PVariable obsolete, PVariable replacement); | ||
76 | |||
77 | @Override | ||
78 | public void delete() { | ||
79 | pBody.checkMutability(); | ||
80 | for (PVariable pVariable : affectedVariables) { | ||
81 | pVariable.unrefer(this); | ||
82 | } | ||
83 | pBody.unregisterConstraint(this); | ||
84 | } | ||
85 | |||
86 | @Override | ||
87 | public void checkSanity() { | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * For backwards compatibility. Equivalent to {@link #getBody()} | ||
92 | */ | ||
93 | public PBody getPSystem() { | ||
94 | return pBody; | ||
95 | } | ||
96 | /** | ||
97 | * @since 2.1 | ||
98 | */ | ||
99 | @Override | ||
100 | public PBody getBody() { | ||
101 | return pBody; | ||
102 | } | ||
103 | |||
104 | @Override | ||
105 | public int getMonotonousID() { | ||
106 | return sequentialID; | ||
107 | } | ||
108 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/DeferredPConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/DeferredPConstraint.java new file mode 100644 index 00000000..d2bf088c --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/DeferredPConstraint.java | |||
@@ -0,0 +1,31 @@ | |||
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.psystem; | ||
11 | |||
12 | import java.util.Set; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
15 | import tools.refinery.viatra.runtime.matchers.planning.SubPlan; | ||
16 | |||
17 | /** | ||
18 | * Any constraint that can only be checked on certain SubPlans (e.g. those plans that already contain some variables). | ||
19 | * | ||
20 | * @author Gabor Bergmann | ||
21 | * | ||
22 | */ | ||
23 | public abstract class DeferredPConstraint extends BasePConstraint { | ||
24 | |||
25 | public DeferredPConstraint(PBody pBody, Set<PVariable> affectedVariables) { | ||
26 | super(pBody, affectedVariables); | ||
27 | } | ||
28 | |||
29 | public abstract boolean isReadyAt(SubPlan plan, IQueryMetaContext context); | ||
30 | |||
31 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/EnumerablePConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/EnumerablePConstraint.java new file mode 100644 index 00000000..9129aa47 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/EnumerablePConstraint.java | |||
@@ -0,0 +1,59 @@ | |||
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.psystem; | ||
11 | |||
12 | import java.util.Set; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
15 | |||
16 | /** | ||
17 | * A constraint for which all satisfying tuples of variable values can be enumerated at any point during run-time. | ||
18 | * | ||
19 | * @author Gabor Bergmann | ||
20 | * | ||
21 | */ | ||
22 | public abstract class EnumerablePConstraint extends BasePConstraint { | ||
23 | protected Tuple variablesTuple; | ||
24 | |||
25 | protected EnumerablePConstraint(PBody pBody, Tuple variablesTuple) { | ||
26 | super(pBody, variablesTuple.<PVariable> getDistinctElements()); | ||
27 | this.variablesTuple = variablesTuple; | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public void doReplaceVariable(PVariable obsolete, PVariable replacement) { | ||
32 | variablesTuple = variablesTuple.replaceAll(obsolete, replacement); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | protected String toStringRest() { | ||
37 | String stringRestRest = toStringRestRest(); | ||
38 | String tupleString = "@" + variablesTuple.toString(); | ||
39 | return stringRestRest == null ? tupleString : ":" + stringRestRest + tupleString; | ||
40 | } | ||
41 | |||
42 | protected String toStringRestRest() { | ||
43 | return null; | ||
44 | } | ||
45 | |||
46 | public Tuple getVariablesTuple() { | ||
47 | return variablesTuple; | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public Set<PVariable> getDeducedVariables() { | ||
52 | return getAffectedVariables(); | ||
53 | } | ||
54 | |||
55 | public PVariable getVariableInTuple(int index) { | ||
56 | return (PVariable) this.variablesTuple.get(index); | ||
57 | } | ||
58 | |||
59 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IExpressionEvaluator.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IExpressionEvaluator.java new file mode 100644 index 00000000..686999f7 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IExpressionEvaluator.java | |||
@@ -0,0 +1,42 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem; | ||
10 | |||
11 | /** | ||
12 | * An expression evaluator is used to execute arbitrary Java code during pattern matching. In order to include the | ||
13 | * evaluation in the planning seemlessly it is expected from the evaluator implementors to report all used PVariables by | ||
14 | * name. | ||
15 | * | ||
16 | * @author Zoltan Ujhelyi | ||
17 | * | ||
18 | */ | ||
19 | public interface IExpressionEvaluator { | ||
20 | |||
21 | /** | ||
22 | * A textual description of the expression. Used only for debug purposes, but must not be null. | ||
23 | */ | ||
24 | String getShortDescription(); | ||
25 | |||
26 | /** | ||
27 | * All input parameter names should be reported correctly. | ||
28 | */ | ||
29 | Iterable<String> getInputParameterNames(); | ||
30 | |||
31 | /** | ||
32 | * The expression evaluator code | ||
33 | * | ||
34 | * @param provider | ||
35 | * the value provider is an engine-specific way of reading internal variable tuples to evaluate the | ||
36 | * expression with | ||
37 | * @return the result of the expression: in case of predicate evaluation the return value must be true or false; | ||
38 | * otherwise the result can be an arbitrary object. No null values should be returned. | ||
39 | * @throws Exception | ||
40 | */ | ||
41 | Object evaluateExpression(IValueProvider provider) throws Exception; | ||
42 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IMultiQueryReference.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IMultiQueryReference.java new file mode 100644 index 00000000..8f647c64 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IMultiQueryReference.java | |||
@@ -0,0 +1,26 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2022, Tamas Szabo, GitHub | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
14 | |||
15 | /** | ||
16 | * A {@link PConstraint} that implements this interface refers to a list of PQueries. | ||
17 | * | ||
18 | * @author Tamas Szabo | ||
19 | * @since 2.8 | ||
20 | * | ||
21 | */ | ||
22 | public interface IMultiQueryReference { | ||
23 | |||
24 | Collection<PQuery> getReferredQueries(); | ||
25 | |||
26 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IQueryReference.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IQueryReference.java new file mode 100644 index 00000000..9ee05b39 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IQueryReference.java | |||
@@ -0,0 +1,33 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.List; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
15 | |||
16 | /** | ||
17 | * A {@link PConstraint} that implements this interface refers to a {@link PQuery}. | ||
18 | * | ||
19 | * @author Zoltan Ujhelyi | ||
20 | * | ||
21 | */ | ||
22 | public interface IQueryReference extends IMultiQueryReference { | ||
23 | |||
24 | PQuery getReferredQuery(); | ||
25 | |||
26 | /** | ||
27 | * @since 2.8 | ||
28 | */ | ||
29 | @Override | ||
30 | default List<PQuery> getReferredQueries() { | ||
31 | return Collections.singletonList(getReferredQuery()); | ||
32 | } | ||
33 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IRelationEvaluator.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IRelationEvaluator.java new file mode 100644 index 00000000..e4c396d8 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IRelationEvaluator.java | |||
@@ -0,0 +1,47 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2022, Tamas Szabo, GitHub | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem; | ||
10 | |||
11 | import java.util.List; | ||
12 | import java.util.Set; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
15 | |||
16 | /** | ||
17 | * Implementations of this interface take an arbitrary number of input relations with their contents and compute the | ||
18 | * tuples of a single output relation. | ||
19 | * | ||
20 | * @author Tamas Szabo | ||
21 | * @since 2.8 | ||
22 | * | ||
23 | */ | ||
24 | public interface IRelationEvaluator { | ||
25 | |||
26 | /** | ||
27 | * A textual description of the evaluator. Used only for debug purposes, but must not be null. | ||
28 | */ | ||
29 | String getShortDescription(); | ||
30 | |||
31 | /** | ||
32 | * The relation evaluator code. For performance reasons, it is expected that the returned set is a mutable | ||
33 | * collection, and the caller must be allowed to actually perform mutations! | ||
34 | */ | ||
35 | Set<Tuple> evaluateRelation(List<Set<Tuple>> inputs) throws Exception; | ||
36 | |||
37 | /** | ||
38 | * For each input relation that this evaluator requires, this method returns the expected arities of the relations in order. | ||
39 | */ | ||
40 | List<Integer> getInputArities(); | ||
41 | |||
42 | /** | ||
43 | * Returns the arity of the output relation that this evaluator computes. | ||
44 | */ | ||
45 | int getOutputArity(); | ||
46 | |||
47 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/ITypeConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/ITypeConstraint.java new file mode 100644 index 00000000..b72035a8 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/ITypeConstraint.java | |||
@@ -0,0 +1,65 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem; | ||
10 | |||
11 | import java.util.HashMap; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Map; | ||
14 | import java.util.Map.Entry; | ||
15 | |||
16 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
17 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
18 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
19 | |||
20 | import java.util.Set; | ||
21 | |||
22 | /** | ||
23 | * Common superinterface of enumerable and deferred type constraints. | ||
24 | * @author Bergmann Gabor | ||
25 | * | ||
26 | */ | ||
27 | public interface ITypeConstraint extends ITypeInfoProviderConstraint { | ||
28 | |||
29 | public abstract TypeJudgement getEquivalentJudgement(); | ||
30 | |||
31 | /** | ||
32 | * Static internal utility class for implementations of {@link ITypeConstraint}s. | ||
33 | * @author Bergmann Gabor | ||
34 | */ | ||
35 | public static class TypeConstraintUtil { | ||
36 | |||
37 | private TypeConstraintUtil() { | ||
38 | // Hiding constructor for utility class | ||
39 | } | ||
40 | |||
41 | public static Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context, IInputKey inputKey, Tuple variablesTuple) { | ||
42 | final Map<Set<PVariable>, Set<PVariable>> result = new HashMap<Set<PVariable>, Set<PVariable>>(); | ||
43 | |||
44 | Set<Entry<Set<Integer>, Set<Integer>>> dependencies = context.getFunctionalDependencies(inputKey).entrySet(); | ||
45 | for (Entry<Set<Integer>, Set<Integer>> dependency : dependencies) { | ||
46 | result.put( | ||
47 | transcribeVariables(dependency.getKey(), variablesTuple), | ||
48 | transcribeVariables(dependency.getValue(), variablesTuple) | ||
49 | ); | ||
50 | } | ||
51 | |||
52 | return result; | ||
53 | } | ||
54 | |||
55 | private static Set<PVariable> transcribeVariables(Set<Integer> indices, Tuple variablesTuple) { | ||
56 | Set<PVariable> result = new HashSet<PVariable>(); | ||
57 | for (Integer index : indices) { | ||
58 | result.add((PVariable) variablesTuple.get(index)); | ||
59 | } | ||
60 | return result; | ||
61 | } | ||
62 | |||
63 | } | ||
64 | |||
65 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/ITypeInfoProviderConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/ITypeInfoProviderConstraint.java new file mode 100644 index 00000000..ff127d38 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/ITypeInfoProviderConstraint.java | |||
@@ -0,0 +1,28 @@ | |||
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.psystem; | ||
11 | |||
12 | import java.util.Set; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
15 | |||
16 | /** | ||
17 | * @author Gabor Bergmann | ||
18 | * | ||
19 | */ | ||
20 | public interface ITypeInfoProviderConstraint extends PConstraint { | ||
21 | |||
22 | /** | ||
23 | * Returns type information implied by this constraint. | ||
24 | * | ||
25 | */ | ||
26 | public Set<TypeJudgement> getImpliedJudgements(IQueryMetaContext context); | ||
27 | |||
28 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IValueProvider.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IValueProvider.java new file mode 100644 index 00000000..d959adc4 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/IValueProvider.java | |||
@@ -0,0 +1,27 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem; | ||
10 | |||
11 | /** | ||
12 | * Helper interface to get values from a tuple of variables. All pattern matching engines are expected to implement this | ||
13 | * to handle their internal structures. | ||
14 | * | ||
15 | * @author Zoltan Ujhelyi | ||
16 | * | ||
17 | */ | ||
18 | public interface IValueProvider { | ||
19 | |||
20 | /** | ||
21 | * Returns the value of the selected variable | ||
22 | * @param variableName | ||
23 | * @return the value of the variable; never null | ||
24 | * @throws IllegalArgumentException if the variable is not defined | ||
25 | */ | ||
26 | Object getValue(String variableName); | ||
27 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/InitializablePQuery.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/InitializablePQuery.java new file mode 100644 index 00000000..a82d12ec --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/InitializablePQuery.java | |||
@@ -0,0 +1,56 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem; | ||
10 | |||
11 | import java.util.Set; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | ||
14 | import tools.refinery.viatra.runtime.matchers.psystem.annotations.PAnnotation; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PProblem; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
17 | |||
18 | /** | ||
19 | * Adds extra methods to the PQuery interface to initialize its contents. | ||
20 | * | ||
21 | * @author Zoltan Ujhelyi | ||
22 | * | ||
23 | */ | ||
24 | public interface InitializablePQuery extends PQuery { | ||
25 | |||
26 | /** | ||
27 | * Sets the query status. Only applicable if the pattern is still {@link PQueryStatus#UNINITIALIZED uninitialized}. | ||
28 | * | ||
29 | * @param status the new status | ||
30 | */ | ||
31 | void setStatus(PQueryStatus status); | ||
32 | |||
33 | /** | ||
34 | * Adds a detected error. Only applicable if the pattern is still {@link PQueryStatus#UNINITIALIZED uninitialized}. | ||
35 | * | ||
36 | * @param problem the new problem | ||
37 | */ | ||
38 | void addError(PProblem problem); | ||
39 | |||
40 | /** | ||
41 | * Sets up the bodies of the pattern. Only applicable if the pattern is still {@link PQueryStatus#UNINITIALIZED | ||
42 | * uninitialized}. | ||
43 | * | ||
44 | * @param bodies | ||
45 | * @throws ViatraQueryRuntimeException | ||
46 | */ | ||
47 | void initializeBodies(Set<PBody> bodies); | ||
48 | |||
49 | /** | ||
50 | * Adds an annotation to the specification. Only applicable if the pattern is still | ||
51 | * {@link PQueryStatus#UNINITIALIZED uninitialized}. | ||
52 | * | ||
53 | * @param annotation | ||
54 | */ | ||
55 | void addAnnotation(PAnnotation annotation); | ||
56 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/KeyedEnumerablePConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/KeyedEnumerablePConstraint.java new file mode 100644 index 00000000..91eea817 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/KeyedEnumerablePConstraint.java | |||
@@ -0,0 +1,39 @@ | |||
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.psystem; | ||
11 | |||
12 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
13 | |||
14 | /** | ||
15 | * @author Gabor Bergmann | ||
16 | * | ||
17 | */ | ||
18 | public abstract class KeyedEnumerablePConstraint<KeyType> extends EnumerablePConstraint { | ||
19 | |||
20 | protected KeyType supplierKey; | ||
21 | |||
22 | public KeyedEnumerablePConstraint(PBody pBody, Tuple variablesTuple, | ||
23 | KeyType supplierKey) { | ||
24 | super(pBody, variablesTuple); | ||
25 | this.supplierKey = supplierKey; | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | protected String toStringRestRest() { | ||
30 | return supplierKey == null ? "$any(null)" : keyToString(); | ||
31 | } | ||
32 | |||
33 | protected abstract String keyToString(); | ||
34 | |||
35 | public KeyType getSupplierKey() { | ||
36 | return supplierKey; | ||
37 | } | ||
38 | |||
39 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PBody.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PBody.java new file mode 100644 index 00000000..c38dc23a --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PBody.java | |||
@@ -0,0 +1,289 @@ | |||
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.psystem; | ||
11 | |||
12 | import java.util.ArrayList; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.HashSet; | ||
15 | import java.util.LinkedHashSet; | ||
16 | import java.util.List; | ||
17 | import java.util.Map; | ||
18 | import java.util.Set; | ||
19 | import java.util.WeakHashMap; | ||
20 | import java.util.stream.Collectors; | ||
21 | |||
22 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
23 | import tools.refinery.viatra.runtime.matchers.planning.helpers.TypeHelper; | ||
24 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.ExportedParameter; | ||
25 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.ConstantValue; | ||
26 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PDisjunction; | ||
27 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
28 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery.PQueryStatus; | ||
29 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
30 | |||
31 | /** | ||
32 | * A set of constraints representing a pattern body | ||
33 | * | ||
34 | * @author Gabor Bergmann | ||
35 | * | ||
36 | */ | ||
37 | public class PBody implements PTraceable { | ||
38 | |||
39 | public static final String VIRTUAL_VARIABLE_PREFIX = ".virtual"; | ||
40 | private static final String VIRTUAL_VARIABLE_PATTERN = VIRTUAL_VARIABLE_PREFIX + "{%d}"; | ||
41 | |||
42 | private PQuery query; | ||
43 | |||
44 | /** | ||
45 | * If null, then parent query status is reused | ||
46 | */ | ||
47 | private PQueryStatus status = PQueryStatus.UNINITIALIZED; | ||
48 | |||
49 | private Set<PVariable> allVariables; | ||
50 | private Set<PVariable> uniqueVariables; | ||
51 | private List<ExportedParameter> symbolicParameters; | ||
52 | private Map<Object, PVariable> variablesByName; | ||
53 | private Set<PConstraint> constraints; | ||
54 | private int nextVirtualNodeID; | ||
55 | private PDisjunction containerDisjunction; | ||
56 | |||
57 | public PBody(PQuery query) { | ||
58 | super(); | ||
59 | this.query = query; | ||
60 | allVariables = new LinkedHashSet<>(); | ||
61 | uniqueVariables = new LinkedHashSet<>(); | ||
62 | variablesByName = new HashMap<>(); | ||
63 | constraints = new LinkedHashSet<>(); | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * @return whether the submission of the new variable was successful | ||
68 | */ | ||
69 | private boolean addVariable(PVariable var) { | ||
70 | checkMutability(); | ||
71 | Object name = var.getName(); | ||
72 | if (!variablesByName.containsKey(name)) { | ||
73 | allVariables.add(var); | ||
74 | if (var.isUnique()) | ||
75 | uniqueVariables.add(var); | ||
76 | variablesByName.put(name, var); | ||
77 | return true; | ||
78 | } else { | ||
79 | return false; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * Use this method to add a newly created constraint to the pSystem. | ||
85 | * | ||
86 | * @return whether the submission of the new constraint was successful | ||
87 | */ | ||
88 | boolean registerConstraint(PConstraint constraint) { | ||
89 | checkMutability(); | ||
90 | return constraints.add(constraint); | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * Use this method to remove an obsolete constraint from the pSystem. | ||
95 | * | ||
96 | * @return whether the removal of the constraint was successful | ||
97 | */ | ||
98 | boolean unregisterConstraint(PConstraint constraint) { | ||
99 | checkMutability(); | ||
100 | return constraints.remove(constraint); | ||
101 | } | ||
102 | |||
103 | @SuppressWarnings("unchecked") | ||
104 | public <ConstraintType> Set<ConstraintType> getConstraintsOfType(Class<ConstraintType> constraintClass) { | ||
105 | Set<ConstraintType> result = new HashSet<ConstraintType>(); | ||
106 | for (PConstraint pConstraint : constraints) { | ||
107 | if (constraintClass.isInstance(pConstraint)) | ||
108 | result.add((ConstraintType) pConstraint); | ||
109 | } | ||
110 | return result; | ||
111 | } | ||
112 | |||
113 | public PVariable newVirtualVariable() { | ||
114 | checkMutability(); | ||
115 | String name; | ||
116 | do { | ||
117 | |||
118 | name = String.format(VIRTUAL_VARIABLE_PATTERN, nextVirtualNodeID++); | ||
119 | } while (variablesByName.containsKey(name)); | ||
120 | PVariable var = new PVariable(this, name, true); | ||
121 | addVariable(var); | ||
122 | return var; | ||
123 | } | ||
124 | |||
125 | public PVariable newVirtualVariable(String name) { | ||
126 | checkMutability(); | ||
127 | Preconditions.checkArgument(!variablesByName.containsKey(name), "ID %s already used for a virtual variable", name); | ||
128 | PVariable var = new PVariable(this, name, true); | ||
129 | addVariable(var); | ||
130 | return var; | ||
131 | } | ||
132 | |||
133 | public PVariable newConstantVariable(Object value) { | ||
134 | checkMutability(); | ||
135 | PVariable virtual = newVirtualVariable(); | ||
136 | new ConstantValue(this, virtual, value); | ||
137 | return virtual; | ||
138 | } | ||
139 | |||
140 | public Set<PVariable> getAllVariables() { | ||
141 | return allVariables; | ||
142 | } | ||
143 | |||
144 | public Set<PVariable> getUniqueVariables() { | ||
145 | return uniqueVariables; | ||
146 | } | ||
147 | |||
148 | private PVariable getVariableByName(Object name) { | ||
149 | return variablesByName.get(name).getUnifiedIntoRoot(); | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * Find a PVariable by name | ||
154 | * | ||
155 | * @param name | ||
156 | * @return the found variable | ||
157 | * @throws IllegalArgumentException | ||
158 | * if no PVariable is found with the selected name | ||
159 | */ | ||
160 | public PVariable getVariableByNameChecked(Object name) { | ||
161 | if (!variablesByName.containsKey(name)) | ||
162 | throw new IllegalArgumentException(String.format("Cannot find PVariable %s", name)); | ||
163 | return getVariableByName(name); | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * Finds and returns a PVariable by name. If no PVariable exists with the name in the body, a new one is created. If | ||
168 | * the name of the variable starts with {@value #VIRTUAL_VARIABLE_PREFIX}, the created variable will be considered | ||
169 | * virtual. | ||
170 | * | ||
171 | * @param name | ||
172 | * @return a PVariable with the selected name; never null | ||
173 | */ | ||
174 | public PVariable getOrCreateVariableByName(String name) { | ||
175 | checkMutability(); | ||
176 | if (!variablesByName.containsKey(name)) { | ||
177 | addVariable(new PVariable(this, name, name.startsWith(VIRTUAL_VARIABLE_PREFIX))); | ||
178 | } | ||
179 | return getVariableByName(name); | ||
180 | } | ||
181 | |||
182 | public Set<PConstraint> getConstraints() { | ||
183 | return constraints; | ||
184 | } | ||
185 | |||
186 | public PQuery getPattern() { | ||
187 | return query; | ||
188 | } | ||
189 | |||
190 | void noLongerUnique(PVariable pVariable) { | ||
191 | assert (!pVariable.isUnique()); | ||
192 | uniqueVariables.remove(pVariable); | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * Returns the symbolic parameters of the body. </p> | ||
197 | * | ||
198 | * <p> | ||
199 | * <strong>Warning</strong>: if two PVariables are unified, the returned list changes. If you want to have a stable | ||
200 | * version, consider using {@link #getSymbolicParameters()}. | ||
201 | * | ||
202 | * @return a non-null, but possibly empty list | ||
203 | */ | ||
204 | public List<PVariable> getSymbolicParameterVariables() { | ||
205 | return getSymbolicParameters().stream().map(ExportedParameter::getParameterVariable) | ||
206 | .collect(Collectors.toList()); | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * Returns the exported parameter constraints of the body. | ||
211 | * | ||
212 | * @return a non-null, but possibly empty list | ||
213 | */ | ||
214 | public List<ExportedParameter> getSymbolicParameters() { | ||
215 | if (symbolicParameters == null) | ||
216 | symbolicParameters = new ArrayList<>(); | ||
217 | return symbolicParameters; | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * Sets the exported parameter constraints of the body, if this instance is mutable. | ||
222 | * @param symbolicParameters the new value | ||
223 | */ | ||
224 | public void setSymbolicParameters(List<ExportedParameter> symbolicParameters) { | ||
225 | checkMutability(); | ||
226 | this.symbolicParameters = new ArrayList<>(symbolicParameters); | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * Sets a specific status for the body. If set, the parent PQuery status will not be checked; if set to null, its corresponding PQuery | ||
231 | * status is checked for mutability. | ||
232 | * | ||
233 | * @param status | ||
234 | * the status to set | ||
235 | */ | ||
236 | public void setStatus(PQueryStatus status) { | ||
237 | this.status = status; | ||
238 | } | ||
239 | |||
240 | public boolean isMutable() { | ||
241 | if (status == null) { | ||
242 | return query.isMutable(); | ||
243 | } else { | ||
244 | return status.equals(PQueryStatus.UNINITIALIZED); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | void checkMutability() { | ||
249 | if (status == null) { | ||
250 | query.checkMutability(); | ||
251 | } else { | ||
252 | Preconditions.checkState(status.equals(PQueryStatus.UNINITIALIZED), "Initialized queries are not mutable"); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | /** | ||
257 | * Returns the disjunction the body is contained with. This disjunction may either be the | ||
258 | * {@link PQuery#getDisjunctBodies() canonical disjunction of the corresponding query} or something equivalent. | ||
259 | * | ||
260 | * @return the container disjunction of the body. Can be null if body is not in a disjunction yet. | ||
261 | */ | ||
262 | public PDisjunction getContainerDisjunction() { | ||
263 | return containerDisjunction; | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * @param containerDisjunction the containerDisjunction to set | ||
268 | */ | ||
269 | public void setContainerDisjunction(PDisjunction containerDisjunction) { | ||
270 | Preconditions.checkArgument(query.equals(containerDisjunction.getQuery()), "Disjunction of pattern %s incompatible with body %s", containerDisjunction.getQuery().getFullyQualifiedName(), query.getFullyQualifiedName()); | ||
271 | Preconditions.checkState(this.containerDisjunction == null, "Disjunction is already set."); | ||
272 | this.containerDisjunction = containerDisjunction; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * All unary input keys directly prescribed by constraints, grouped by variable. | ||
277 | * <p> to supertype inference or subsumption applied at this point. | ||
278 | */ | ||
279 | public Map<PVariable, Set<TypeJudgement>> getAllUnaryTypeRestrictions(IQueryMetaContext context) { | ||
280 | Map<PVariable, Set<TypeJudgement>> currentRestrictions = allUnaryTypeRestrictions.get(context); | ||
281 | if (currentRestrictions == null) { | ||
282 | currentRestrictions = TypeHelper.inferUnaryTypes(getConstraints(), context); | ||
283 | allUnaryTypeRestrictions.put(context, currentRestrictions); | ||
284 | } | ||
285 | return currentRestrictions; | ||
286 | } | ||
287 | private WeakHashMap<IQueryMetaContext, Map<PVariable, Set<TypeJudgement>>> allUnaryTypeRestrictions = new WeakHashMap<IQueryMetaContext, Map<PVariable,Set<TypeJudgement>>>(); | ||
288 | |||
289 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PConstraint.java new file mode 100644 index 00000000..ae2c4632 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PConstraint.java | |||
@@ -0,0 +1,70 @@ | |||
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.psystem; | ||
11 | |||
12 | import java.util.Comparator; | ||
13 | import java.util.Map; | ||
14 | import java.util.Set; | ||
15 | |||
16 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.analysis.QueryAnalyzer; | ||
18 | |||
19 | /** | ||
20 | * @author Gabor Bergmann | ||
21 | * | ||
22 | */ | ||
23 | public interface PConstraint extends PTraceable { | ||
24 | |||
25 | /** | ||
26 | * @since 2.1 | ||
27 | * @return the query body this constraint belongs to | ||
28 | */ | ||
29 | public PBody getBody(); | ||
30 | |||
31 | /** | ||
32 | * All variables affected by this constraint. | ||
33 | */ | ||
34 | public Set<PVariable> getAffectedVariables(); | ||
35 | |||
36 | /** | ||
37 | * The set of variables whose potential values can be enumerated (once all non-deduced variables have known values). | ||
38 | */ | ||
39 | public Set<PVariable> getDeducedVariables(); | ||
40 | |||
41 | /** | ||
42 | * A (preferably minimal) cover of known functional dependencies between variables. | ||
43 | * @noreference Use {@link QueryAnalyzer} instead to properly handle dependencies of pattern calls. | ||
44 | * @return non-trivial functional dependencies in the form of {variables} --> {variables}, where dependencies with the same lhs are unified. | ||
45 | */ | ||
46 | public Map<Set<PVariable>,Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context); | ||
47 | |||
48 | public void replaceVariable(PVariable obsolete, PVariable replacement); | ||
49 | |||
50 | public void delete(); | ||
51 | |||
52 | public void checkSanity(); | ||
53 | |||
54 | /** | ||
55 | * Returns an integer ID that is guaranteed to increase strictly monotonously for constraints within a pBody. | ||
56 | */ | ||
57 | public abstract int getMonotonousID(); | ||
58 | |||
59 | |||
60 | /** | ||
61 | * A comparator that orders constraints by their {@link #getMonotonousID() monotonous identifiers}. Should only used | ||
62 | * for tiebreaking in other comparators. | ||
63 | * | ||
64 | * @since 2.0 | ||
65 | */ | ||
66 | public static final Comparator<PConstraint> COMPARE_BY_MONOTONOUS_ID = (arg0, arg1) -> arg0.getMonotonousID() - arg1.getMonotonousID(); | ||
67 | |||
68 | |||
69 | |||
70 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PTraceable.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PTraceable.java new file mode 100644 index 00000000..f0241a9c --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PTraceable.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Dénes Harmath, IncQueryLabs 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem; | ||
10 | |||
11 | /** | ||
12 | * Marker interface for PSystem elements that can be traced. | ||
13 | * @since 1.6 | ||
14 | */ | ||
15 | public interface PTraceable { | ||
16 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PVariable.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PVariable.java new file mode 100644 index 00000000..b6ea4861 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/PVariable.java | |||
@@ -0,0 +1,203 @@ | |||
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.psystem; | ||
11 | |||
12 | import java.util.HashSet; | ||
13 | import java.util.Set; | ||
14 | |||
15 | /** | ||
16 | * @author Gabor Bergmann | ||
17 | * | ||
18 | */ | ||
19 | public class PVariable { | ||
20 | private PBody pBody; | ||
21 | /** | ||
22 | * The name of the pattern variable. This is the unique key of the pattern node. | ||
23 | */ | ||
24 | private String name; | ||
25 | /** | ||
26 | * virtual pVariables are nodes that do not correspond to actual pattern variables; they represent constants or Term | ||
27 | * substitutes | ||
28 | */ | ||
29 | private boolean virtual; | ||
30 | |||
31 | /** | ||
32 | * Set of constraints that mention this variable | ||
33 | */ | ||
34 | private Set<PConstraint> referringConstraints; | ||
35 | |||
36 | /** | ||
37 | * Determines whether there are any constraints that can deduce this variable | ||
38 | */ | ||
39 | private Boolean deducable; | ||
40 | |||
41 | /** | ||
42 | * Another PVariable this variable has been unified into. Please use the other variable instead of this. Null iff | ||
43 | * this is still a first-class variable. | ||
44 | */ | ||
45 | private PVariable unifiedInto; | ||
46 | |||
47 | PVariable(PBody pBody, String name) { | ||
48 | this(pBody, name, false); | ||
49 | } | ||
50 | |||
51 | PVariable(PBody pBody, String name, boolean virtual) { | ||
52 | super(); | ||
53 | this.pBody = pBody; | ||
54 | this.name = name; | ||
55 | this.virtual = virtual; | ||
56 | // this.exportedParameter = false; | ||
57 | this.referringConstraints = new HashSet<PConstraint>(); | ||
58 | this.unifiedInto = null; | ||
59 | this.deducable = false; | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * Replaces this variable with a given other, resulting in their unification. This variable will no longer be | ||
64 | * unique. | ||
65 | * | ||
66 | * @param replacement | ||
67 | */ | ||
68 | public void unifyInto(PVariable replacement) { | ||
69 | pBody.checkMutability(); | ||
70 | replacementCheck(); | ||
71 | replacement = replacement.getUnifiedIntoRoot(); | ||
72 | |||
73 | if (this.equals(replacement)) | ||
74 | return; | ||
75 | |||
76 | if (!this.isVirtual() && replacement.isVirtual()) { | ||
77 | replacement.unifyInto(this); | ||
78 | } else { | ||
79 | // replacement.referringConstraints.addAll(this.referringConstraints); | ||
80 | // replacement.exportedParameter |= this.exportedParameter; | ||
81 | replacement.virtual &= this.virtual; | ||
82 | if (replacement.deducable != null && this.deducable != null) | ||
83 | replacement.deducable |= this.deducable; | ||
84 | else | ||
85 | replacement.deducable = null; | ||
86 | Set<PConstraint> snapshotConstraints = // avoid ConcurrentModificationX | ||
87 | new HashSet<PConstraint>(this.referringConstraints); | ||
88 | for (PConstraint constraint : snapshotConstraints) { | ||
89 | constraint.replaceVariable(this, replacement); | ||
90 | } | ||
91 | // replacementCheck() will fail from this point | ||
92 | this.unifiedInto = replacement; | ||
93 | pBody.noLongerUnique(this); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * Determines whether there are any constraints that can deduce this variable | ||
99 | */ | ||
100 | public boolean isDeducable() { | ||
101 | replacementCheck(); | ||
102 | if (deducable == null) { | ||
103 | deducable = false; | ||
104 | for (PConstraint pConstraint : getReferringConstraints()) { | ||
105 | if (pConstraint.getDeducedVariables().contains(this)) { | ||
106 | deducable = true; | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | return deducable; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * Register that this variable is referred by the given constraint. | ||
116 | * | ||
117 | * @param constraint | ||
118 | */ | ||
119 | public void refer(PConstraint constraint) { | ||
120 | pBody.checkMutability(); | ||
121 | replacementCheck(); | ||
122 | deducable = null; | ||
123 | referringConstraints.add(constraint); | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Register that this variable is no longer referred by the given constraint. | ||
128 | * | ||
129 | * @param constraint | ||
130 | */ | ||
131 | public void unrefer(PConstraint constraint) { | ||
132 | pBody.checkMutability(); | ||
133 | replacementCheck(); | ||
134 | deducable = null; | ||
135 | referringConstraints.remove(constraint); | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * @return the name of the pattern variable. This is the unique key of the pattern node. | ||
140 | */ | ||
141 | public String getName() { | ||
142 | replacementCheck(); | ||
143 | return name; | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * @return the virtual | ||
148 | */ | ||
149 | public boolean isVirtual() { | ||
150 | replacementCheck(); | ||
151 | return virtual; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * @return the referringConstraints | ||
156 | */ | ||
157 | public Set<PConstraint> getReferringConstraints() { | ||
158 | replacementCheck(); | ||
159 | return referringConstraints; | ||
160 | } | ||
161 | |||
162 | @SuppressWarnings("unchecked") | ||
163 | public <ConstraintType> Set<ConstraintType> getReferringConstraintsOfType(Class<ConstraintType> constraintClass) { | ||
164 | replacementCheck(); | ||
165 | Set<ConstraintType> result = new HashSet<ConstraintType>(); | ||
166 | for (PConstraint pConstraint : referringConstraints) { | ||
167 | if (constraintClass.isInstance(pConstraint)) | ||
168 | result.add((ConstraintType) pConstraint); | ||
169 | } | ||
170 | return result; | ||
171 | } | ||
172 | |||
173 | @Override | ||
174 | public String toString() { | ||
175 | // replacementCheck(); | ||
176 | return name;// + ":PatternNode"; | ||
177 | } | ||
178 | |||
179 | public PVariable getDirectUnifiedInto() { | ||
180 | return unifiedInto; | ||
181 | } | ||
182 | |||
183 | public PVariable getUnifiedIntoRoot() { | ||
184 | PVariable nextUnified = unifiedInto; | ||
185 | PVariable oldUnifiedInto = this; | ||
186 | while (nextUnified != null) { | ||
187 | oldUnifiedInto = nextUnified; | ||
188 | nextUnified = oldUnifiedInto.getDirectUnifiedInto(); | ||
189 | } | ||
190 | return oldUnifiedInto; // unifiedInto; | ||
191 | } | ||
192 | |||
193 | public boolean isUnique() { | ||
194 | return unifiedInto == null; | ||
195 | } | ||
196 | |||
197 | private void replacementCheck() { | ||
198 | if (unifiedInto != null) | ||
199 | throw new IllegalStateException("Illegal usage of variable " + name + " which has been replaced with " | ||
200 | + unifiedInto.name); | ||
201 | } | ||
202 | |||
203 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/TypeJudgement.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/TypeJudgement.java new file mode 100644 index 00000000..4447b225 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/TypeJudgement.java | |||
@@ -0,0 +1,153 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.List; | ||
14 | import java.util.Map; | ||
15 | import java.util.stream.Collectors; | ||
16 | import java.util.Set; | ||
17 | |||
18 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
19 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
20 | import tools.refinery.viatra.runtime.matchers.context.InputKeyImplication; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.TypeFilterConstraint; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.TypeConstraint; | ||
23 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
24 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
25 | |||
26 | /** | ||
27 | * A judgement that means that the given tuple of variables will represent a tuple of values that is a member of the extensional relation identified by the given input key. | ||
28 | * @author Bergmann Gabor | ||
29 | * | ||
30 | */ | ||
31 | public class TypeJudgement { | ||
32 | |||
33 | private IInputKey inputKey; | ||
34 | private Tuple variablesTuple; | ||
35 | /** | ||
36 | * @param inputKey | ||
37 | * @param variablesTuple | ||
38 | */ | ||
39 | public TypeJudgement(IInputKey inputKey, Tuple variablesTuple) { | ||
40 | super(); | ||
41 | this.inputKey = inputKey; | ||
42 | this.variablesTuple = variablesTuple; | ||
43 | } | ||
44 | public IInputKey getInputKey() { | ||
45 | return inputKey; | ||
46 | } | ||
47 | public Tuple getVariablesTuple() { | ||
48 | return variablesTuple; | ||
49 | } | ||
50 | @Override | ||
51 | public int hashCode() { | ||
52 | final int prime = 31; | ||
53 | int result = 1; | ||
54 | result = prime * result | ||
55 | + ((inputKey == null) ? 0 : inputKey.hashCode()); | ||
56 | result = prime * result | ||
57 | + ((variablesTuple == null) ? 0 : variablesTuple.hashCode()); | ||
58 | return result; | ||
59 | } | ||
60 | @Override | ||
61 | public boolean equals(Object obj) { | ||
62 | if (this == obj) | ||
63 | return true; | ||
64 | if (obj == null) | ||
65 | return false; | ||
66 | if (!(obj instanceof TypeJudgement)) | ||
67 | return false; | ||
68 | TypeJudgement other = (TypeJudgement) obj; | ||
69 | if (inputKey == null) { | ||
70 | if (other.inputKey != null) | ||
71 | return false; | ||
72 | } else if (!inputKey.equals(other.inputKey)) | ||
73 | return false; | ||
74 | if (variablesTuple == null) { | ||
75 | if (other.variablesTuple != null) | ||
76 | return false; | ||
77 | } else if (!variablesTuple.equals(other.variablesTuple)) | ||
78 | return false; | ||
79 | return true; | ||
80 | } | ||
81 | |||
82 | public Set<TypeJudgement> getDirectlyImpliedJudgements(IQueryMetaContext context) { | ||
83 | Set<TypeJudgement> results = new HashSet<TypeJudgement>(); | ||
84 | results.add(this); | ||
85 | |||
86 | Collection<InputKeyImplication> implications = context.getImplications(this.inputKey); | ||
87 | for (InputKeyImplication inputKeyImplication : implications) { | ||
88 | results.add( | ||
89 | transcribeImplication(inputKeyImplication) | ||
90 | ); | ||
91 | } | ||
92 | |||
93 | return results; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * @since 1.6 | ||
98 | */ | ||
99 | public Set<TypeJudgement> getWeakenedAlternativeJudgements(IQueryMetaContext context) { | ||
100 | Set<TypeJudgement> results = new HashSet<TypeJudgement>(); | ||
101 | |||
102 | Collection<InputKeyImplication> implications = context.getWeakenedAlternatives(this.inputKey); | ||
103 | for (InputKeyImplication inputKeyImplication : implications) { | ||
104 | results.add( | ||
105 | transcribeImplication(inputKeyImplication) | ||
106 | ); | ||
107 | } | ||
108 | |||
109 | return results; | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * @since 2.0 | ||
114 | */ | ||
115 | public Map<TypeJudgement, Set<TypeJudgement>> getConditionalImpliedJudgements(IQueryMetaContext context) { | ||
116 | return context.getConditionalImplications(this.inputKey).entrySet().stream().collect(Collectors.toMap( | ||
117 | entry -> transcribeImplication(entry.getKey()), | ||
118 | entry -> entry.getValue().stream().map(this::transcribeImplication).collect(Collectors.toSet()))); | ||
119 | } | ||
120 | |||
121 | |||
122 | |||
123 | private TypeJudgement transcribeImplication(InputKeyImplication inputKeyImplication) { | ||
124 | return new TypeJudgement( | ||
125 | inputKeyImplication.getImpliedKey(), | ||
126 | transcribeVariablesToTuple(inputKeyImplication.getImpliedIndices()) | ||
127 | ); | ||
128 | } | ||
129 | private Tuple transcribeVariablesToTuple(List<Integer> indices) { | ||
130 | Object[] elements = new Object[indices.size()]; | ||
131 | for (int i = 0; i < indices.size(); ++i) | ||
132 | elements[i] = variablesTuple.get(indices.get(i)); | ||
133 | return Tuples.flatTupleOf(elements); | ||
134 | } | ||
135 | |||
136 | @Override | ||
137 | public String toString() { | ||
138 | return "TypeJudgement:" + inputKey.getPrettyPrintableName() + "@" + variablesTuple.toString(); | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * Creates this judgement as a direct type constraint in the given PBody under construction. | ||
143 | * <p> pre: the variables tuple must be formed of variables of that PBody. | ||
144 | * @since 1.6 | ||
145 | */ | ||
146 | public PConstraint createConstraintFor(PBody pBody) { | ||
147 | if (inputKey.isEnumerable()) { | ||
148 | return new TypeConstraint(pBody, variablesTuple, inputKey); | ||
149 | } else { | ||
150 | return new TypeFilterConstraint(pBody, variablesTuple, inputKey); | ||
151 | } | ||
152 | } | ||
153 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/VariableDeferredPConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/VariableDeferredPConstraint.java new file mode 100644 index 00000000..8ea6bb93 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/VariableDeferredPConstraint.java | |||
@@ -0,0 +1,40 @@ | |||
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.psystem; | ||
11 | |||
12 | import java.util.Set; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
15 | import tools.refinery.viatra.runtime.matchers.planning.SubPlan; | ||
16 | |||
17 | /** | ||
18 | * A kind of deferred constraint that can only be checked when a set of deferring variables are all present in a plan. | ||
19 | * | ||
20 | * @author Gabor Bergmann | ||
21 | * | ||
22 | */ | ||
23 | public abstract class VariableDeferredPConstraint extends DeferredPConstraint { | ||
24 | |||
25 | public VariableDeferredPConstraint(PBody pBody, | ||
26 | Set<PVariable> affectedVariables) { | ||
27 | super(pBody, affectedVariables); | ||
28 | } | ||
29 | |||
30 | public abstract Set<PVariable> getDeferringVariables(); | ||
31 | |||
32 | /** | ||
33 | * Refine further if needed | ||
34 | */ | ||
35 | @Override | ||
36 | public boolean isReadyAt(SubPlan plan, IQueryMetaContext context) { | ||
37 | return plan.getVisibleVariables().containsAll(getDeferringVariables()); | ||
38 | } | ||
39 | |||
40 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/AbstractMemorylessAggregationOperator.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/AbstractMemorylessAggregationOperator.java new file mode 100644 index 00000000..63a37bbe --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/AbstractMemorylessAggregationOperator.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Gabor Bergmann, IncQueryLabs 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.aggregations; | ||
10 | |||
11 | /** | ||
12 | * | ||
13 | * An aggregation operator that does not store interim results beyond the final aggregated value. | ||
14 | * @author Gabor Bergmann | ||
15 | * @since 1.4 | ||
16 | */ | ||
17 | public abstract class AbstractMemorylessAggregationOperator<Domain, AggregateResult> | ||
18 | implements IMultisetAggregationOperator<Domain, AggregateResult, AggregateResult> | ||
19 | { | ||
20 | |||
21 | @Override | ||
22 | public AggregateResult getAggregate(AggregateResult result) { | ||
23 | return result; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public AggregateResult clone(AggregateResult original) { | ||
28 | return original; | ||
29 | } | ||
30 | |||
31 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/AggregatorType.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/AggregatorType.java new file mode 100644 index 00000000..4cc40a2b --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/AggregatorType.java | |||
@@ -0,0 +1,49 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Zoltan Ujhelyi, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.aggregations; | ||
10 | |||
11 | import java.lang.annotation.ElementType; | ||
12 | import java.lang.annotation.Inherited; | ||
13 | import java.lang.annotation.Retention; | ||
14 | import java.lang.annotation.RetentionPolicy; | ||
15 | import java.lang.annotation.Target; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.matchers.aggregators.count; | ||
18 | |||
19 | /** | ||
20 | * The aggregator type annotation describes the type constraints for the selected aggregator. In version 1.4, two kinds of | ||
21 | * aggregators are supported: | ||
22 | * | ||
23 | * <ol> | ||
24 | * <li>An aggregator that does not consider any parameter value from the call ({@link count}), just calculates the | ||
25 | * number of matches. This is represented by a single {@link Void} and a single corresponding return type.</li> | ||
26 | * <li>An aggregator that considers a single parameter from the call, and executes some aggregate operations over it. | ||
27 | * Such an aggregate operation can be defined over multiple types, where each possible parameter type has a corresponding return type declared.</li> | ||
28 | * </ol> | ||
29 | * | ||
30 | * <strong>Important!</strong> The parameterTypes and returnTypes arrays must have | ||
31 | * <ul> | ||
32 | * <li>The same number of classes defined each.</li> | ||
33 | * <li>Items are corresponded by index.</li> | ||
34 | * <li>Items should represent data types</li> | ||
35 | * </ul> | ||
36 | * | ||
37 | * @author Zoltan Ujhelyi | ||
38 | * @since 1.4 | ||
39 | * | ||
40 | */ | ||
41 | @Target({ ElementType.TYPE }) | ||
42 | @Retention(RetentionPolicy.RUNTIME) | ||
43 | @Inherited | ||
44 | public @interface AggregatorType { | ||
45 | |||
46 | Class<?>[] parameterTypes(); | ||
47 | |||
48 | Class<?>[] returnTypes(); | ||
49 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/BoundAggregator.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/BoundAggregator.java new file mode 100644 index 00000000..e6972544 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/BoundAggregator.java | |||
@@ -0,0 +1,61 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Gabor Bergmann, IncQueryLabs 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.aggregations; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
12 | import tools.refinery.viatra.runtime.matchers.context.common.JavaTransitiveInstancesKey; | ||
13 | |||
14 | /** | ||
15 | * Augments an aggregator operator with type bindings for the type of values being aggregated and the aggregate result. | ||
16 | * <p> In case of <em>count</em>, the operator should be null. | ||
17 | * @author Gabor Bergmann | ||
18 | * @since 1.4 | ||
19 | */ | ||
20 | public class BoundAggregator { | ||
21 | private final IMultisetAggregationOperator<?, ?, ?> operator; | ||
22 | private final Class<?> domainType; | ||
23 | private final Class<?> aggregateResultType; | ||
24 | |||
25 | public BoundAggregator(IMultisetAggregationOperator<?, ?, ?> operator, | ||
26 | Class<?> domainType, | ||
27 | Class<?> aggregateResultType) { | ||
28 | super(); | ||
29 | this.operator = operator; | ||
30 | this.domainType = domainType; | ||
31 | this.aggregateResultType = aggregateResultType; | ||
32 | } | ||
33 | |||
34 | public IMultisetAggregationOperator<?, ?, ?> getOperator() { | ||
35 | return operator; | ||
36 | } | ||
37 | |||
38 | public Class<?> getDomainType() { | ||
39 | return domainType; | ||
40 | } | ||
41 | |||
42 | public Class<?> getAggregateResultType() { | ||
43 | return aggregateResultType; | ||
44 | } | ||
45 | |||
46 | public IInputKey getDomainTypeAsInputKey() { | ||
47 | return toJavaInputKey(domainType); | ||
48 | } | ||
49 | |||
50 | public IInputKey getAggregateResultTypeAsInputKey() { | ||
51 | return toJavaInputKey(aggregateResultType); | ||
52 | } | ||
53 | |||
54 | private static IInputKey toJavaInputKey(Class<?> type) { | ||
55 | if (type==null) { | ||
56 | return null; | ||
57 | } else { | ||
58 | return new JavaTransitiveInstancesKey(type); | ||
59 | } | ||
60 | } | ||
61 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/IAggregatorFactory.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/IAggregatorFactory.java new file mode 100644 index 00000000..c970bd6a --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/IAggregatorFactory.java | |||
@@ -0,0 +1,40 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Zoltan Ujhelyi, Tamas Szabo, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.aggregations; | ||
10 | |||
11 | /** | ||
12 | * | ||
13 | * Describes an aggregation operator keyword, potentially with type polymorphism. The actual runtime | ||
14 | * {@link IMultisetAggregationOperator} that implements the aggregation logic may depend on the type context. | ||
15 | * | ||
16 | * <p> | ||
17 | * Implementors are suggested to use lower-case classnames (as it will end up in the language) and are required use the | ||
18 | * annotation {@link AggregatorType} to indicate type inference rules. | ||
19 | * | ||
20 | * <p> | ||
21 | * <strong>Important!</strong> Implemented aggregators must be (1) deterministic (2) pure and (3)support incremental | ||
22 | * value updates in the internal operation. | ||
23 | * | ||
24 | * @author Zoltan Ujhelyi | ||
25 | * @since 1.4 | ||
26 | */ | ||
27 | |||
28 | public interface IAggregatorFactory { | ||
29 | |||
30 | /** | ||
31 | * Given type parameters selected from {@link AggregatorType} annotations, returns a run-time aggregator operator | ||
32 | * that is bound to the actual types. | ||
33 | * | ||
34 | * @param domainClass | ||
35 | * Java type of the values that are being aggregated | ||
36 | * @return the actual run-time aggregator logic, with type bindings | ||
37 | */ | ||
38 | public BoundAggregator getAggregatorLogic(Class<?> domainClass); | ||
39 | |||
40 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/IMultisetAggregationOperator.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/IMultisetAggregationOperator.java new file mode 100644 index 00000000..3bc22274 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/aggregations/IMultisetAggregationOperator.java | |||
@@ -0,0 +1,106 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Gabor Bergmann, IncQueryLabs 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.aggregations; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.stream.Stream; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.aggregators.ExtremumOperator; | ||
15 | |||
16 | /** | ||
17 | * A single column aggregator is used to incrementally compute the aggregate of a multiset of values according to an aggregator operator. | ||
18 | * | ||
19 | * <p> The operator provides two methods of computation: <ul> | ||
20 | * <li>Stateless aggregation of an explicit multiset, provided by {@link #aggregateStatelessly(Collection)}.</li> | ||
21 | * <li>Incremental aggregation, provided by {@link #createNeutral()}, {@link #update(Object, Object, boolean)}, {@link #isNeutral(Object)}, {@link #getAggregate(Object)}. | ||
22 | * </ul> | ||
23 | * | ||
24 | * <p> In case of incremental computation, the aggregable multiset is conceptual; it is not represented by an explicit Collection<Domain> object, but its update operations are tracked. | ||
25 | * | ||
26 | * <p> In case of incremental computation, internal results, potentially distinct from the final aggregate result, may be stored in a helper data structure called <b>accumulator</b>. | ||
27 | * The goal of this distinction is that the final result may not be sufficient for incremental updates (see e.g. {@link ExtremumOperator}). | ||
28 | * | ||
29 | * @author Gabor Bergmann | ||
30 | * | ||
31 | * @param <Domain> the type of elements to be aggregated. | ||
32 | * @param <Accumulator> the type used to store the interim results of the aggregate computation, | ||
33 | * that may be incrementally refreshed upon updates to the multiset, and that can easily yield the final result. | ||
34 | * @param <AggregateResult> the type of the final result of the aggregation to be output. | ||
35 | * | ||
36 | * @since 1.4 | ||
37 | */ | ||
38 | public interface IMultisetAggregationOperator<Domain, Accumulator, AggregateResult> { | ||
39 | |||
40 | /** | ||
41 | * A textual description of the operator. | ||
42 | */ | ||
43 | String getShortDescription(); | ||
44 | |||
45 | /** | ||
46 | * A name or identifier of the operator. | ||
47 | */ | ||
48 | String getName(); | ||
49 | |||
50 | /** | ||
51 | * @return the neutral element, i.e. the interim result of aggregating an empty multiset. | ||
52 | */ | ||
53 | Accumulator createNeutral(); | ||
54 | |||
55 | /** | ||
56 | * @return true if the interim result is equivalent to the neutral element, as if there are no values in the multiset. | ||
57 | * Must return true if the multiset is empty. | ||
58 | */ | ||
59 | boolean isNeutral(Accumulator result); | ||
60 | |||
61 | /** | ||
62 | * @return an updated intermediate result, | ||
63 | * changed to reflect that a given object was added to / removed from the multiset | ||
64 | * (as indicated by the parameter isInsertion) | ||
65 | */ | ||
66 | Accumulator update(Accumulator oldResult, Domain updateValue, boolean isInsertion); | ||
67 | |||
68 | /** | ||
69 | * @return the aggregate result obtained from the given intermediate result. | ||
70 | * May be null to indicate that the current multiset cannot be aggregated (e.g. 0 elements have no minimum). | ||
71 | */ | ||
72 | AggregateResult getAggregate(Accumulator result); | ||
73 | |||
74 | /** | ||
75 | * Calculates the aggregate results from a given stream of values; all values are considered as inserted | ||
76 | * @return the aggregate result, or null if no result can be calculated (e.g. because of an empty stream) | ||
77 | * @since 2.0 | ||
78 | */ | ||
79 | AggregateResult aggregateStream(Stream<Domain> stream); | ||
80 | |||
81 | /** | ||
82 | * Clones the given accumulator (with all its internal contents). | ||
83 | */ | ||
84 | default Accumulator clone(Accumulator original) { | ||
85 | throw new UnsupportedOperationException(); | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * Combines the given aggregate result and accumulator into a single aggregate result. | ||
90 | */ | ||
91 | default AggregateResult combine(AggregateResult left, Accumulator right) { | ||
92 | throw new UnsupportedOperationException(); | ||
93 | } | ||
94 | |||
95 | default boolean contains(Domain value, Accumulator accumulator) { | ||
96 | throw new UnsupportedOperationException(); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * Pretty prints the contents of the given accumulator. | ||
101 | */ | ||
102 | default String prettyPrint(final Accumulator accumulator) { | ||
103 | return accumulator.toString(); | ||
104 | } | ||
105 | |||
106 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/analysis/QueryAnalyzer.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/analysis/QueryAnalyzer.java new file mode 100644 index 00000000..e3f28cff --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/analysis/QueryAnalyzer.java | |||
@@ -0,0 +1,194 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Gabor Bergmann, IncQueryLabs 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.analysis; | ||
10 | |||
11 | import java.util.HashMap; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Map; | ||
14 | import java.util.Map.Entry; | ||
15 | import java.util.Set; | ||
16 | import java.util.stream.Collectors; | ||
17 | |||
18 | import tools.refinery.viatra.runtime.matchers.context.IQueryBackendContext; | ||
19 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
20 | import tools.refinery.viatra.runtime.matchers.planning.helpers.FunctionalDependencyHelper; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.PConstraint; | ||
23 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
24 | import tools.refinery.viatra.runtime.matchers.psystem.annotations.PAnnotation; | ||
25 | import tools.refinery.viatra.runtime.matchers.psystem.annotations.ParameterReference; | ||
26 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.ExportedParameter; | ||
27 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | ||
28 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter; | ||
29 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
30 | |||
31 | /** | ||
32 | * Object responsible for computing and caching static query analysis results. | ||
33 | * <p> Any client can instantiate this to statically analyze queries. | ||
34 | * Query backends should share an instance obtained via {@link IQueryBackendContext} to save resources. | ||
35 | * <p> Precondition: all involved queries must be initialized. | ||
36 | * @noinstantiate Considered unstable API; subject to change in future versions. | ||
37 | * Either use the analyzer provided by {@link IQueryBackendContext}, or anticipate | ||
38 | * potential future breakage when instantiating your own analyzer. | ||
39 | * @author Gabor Bergmann | ||
40 | * @since 1.5 | ||
41 | */ | ||
42 | public final class QueryAnalyzer { | ||
43 | |||
44 | private IQueryMetaContext metaContext; | ||
45 | |||
46 | public QueryAnalyzer(IQueryMetaContext metaContext) { | ||
47 | this.metaContext = metaContext; | ||
48 | } | ||
49 | |||
50 | // Functional dependencies | ||
51 | |||
52 | /** | ||
53 | * Maps query and strictness to functional dependencies | ||
54 | */ | ||
55 | private Map<PQuery, Map<Set<Integer>, Set<Integer>>> strictFunctionalDependencyGuarantees = | ||
56 | new HashMap<>(); | ||
57 | private Map<PQuery, Map<Set<Integer>, Set<Integer>>> softFunctionalDependencyGuarantees = | ||
58 | new HashMap<>(); | ||
59 | |||
60 | /** | ||
61 | * Functional dependency information, expressed on query parameters, that the match set of the query is guaranteed to respect. | ||
62 | * <p> The type dependencies shall be expressed on the <i>parameter index</i> integers, NOT the {@link PParameter} object. | ||
63 | * @return a non-null map of functional dependencies on parameters that can be processed by {@link FunctionalDependencyHelper} | ||
64 | * @param strict if true, only "hard" dependencies are taken into account that are strictly enforced by the model representation; | ||
65 | * if false, user-provided soft dependencies (@FunctionalDependency) are included as well, that are anticipated but not guaranteed by the storage mechanism; | ||
66 | * use true if superfluous dependencies may taint the correctness of a computation, false if they would merely impact performance | ||
67 | * @since 1.5 | ||
68 | */ | ||
69 | public Map<Set<Integer>, Set<Integer>> getProjectedFunctionalDependencies(PQuery query, boolean strict) { | ||
70 | Map<PQuery, Map<Set<Integer>, Set<Integer>>> guaranteeStore = strict ? strictFunctionalDependencyGuarantees : softFunctionalDependencyGuarantees; | ||
71 | Map<Set<Integer>, Set<Integer>> dependencies = guaranteeStore.get(query); | ||
72 | // Why not computeIfAbsent? See Bug 532507 | ||
73 | // Invoked method #computeFunctionalDependencies may trigger functional dependency computation for called queries; | ||
74 | // and may thus recurs back into #getProjectedFunctionalDependencies, causing a ConcurrentModificationException | ||
75 | // if the called query has not been previously analyzed. | ||
76 | // | ||
77 | // Note: if patterns are recursive, the empty accumulator will be found in the store | ||
78 | // (this yields a safe lower estimate and guarantees termination for #getProjectedFunctionalDependencies) | ||
79 | // But this case probably will not occur due to recursive queries having a disjunction at some point, | ||
80 | // and thus ignored by #computeFunctionalDependencies | ||
81 | if (dependencies == null) { | ||
82 | dependencies = new HashMap<>(); // accumulator | ||
83 | guaranteeStore.put(query, dependencies); | ||
84 | computeFunctionalDependencies(dependencies, query, strict); | ||
85 | } | ||
86 | return dependencies; | ||
87 | } | ||
88 | |||
89 | private void computeFunctionalDependencies(Map<Set<Integer>, Set<Integer>> accumulator, PQuery query, boolean strict) { | ||
90 | Set<PBody> bodies = query.getDisjunctBodies().getBodies(); | ||
91 | if (bodies.size() == 1) { // no support for recursion or disjunction | ||
92 | |||
93 | PBody body = bodies.iterator().next(); | ||
94 | |||
95 | // collect parameter variables | ||
96 | Map<PVariable, Integer> parameters = body.getSymbolicParameters().stream() | ||
97 | .collect(Collectors.toMap(ExportedParameter::getParameterVariable, | ||
98 | param -> query.getParameters().indexOf(param.getPatternParameter()))); | ||
99 | |||
100 | // collect all internal dependencies | ||
101 | Map<Set<PVariable>, Set<PVariable>> internalDependencies = | ||
102 | getFunctionalDependencies(body.getConstraints(), strict); | ||
103 | |||
104 | // project onto parameter variables | ||
105 | Map<Set<PVariable>, Set<PVariable>> projectedDeps = | ||
106 | FunctionalDependencyHelper.projectDependencies(internalDependencies, parameters.keySet()); | ||
107 | |||
108 | // translate into indices | ||
109 | for (Entry<Set<PVariable>, Set<PVariable>> entry : projectedDeps.entrySet()) { | ||
110 | Set<Integer> left = new HashSet<Integer>(); | ||
111 | Set<Integer> right = new HashSet<Integer>(); | ||
112 | for (PVariable pVariable : entry.getKey()) { | ||
113 | left.add(parameters.get(pVariable)); | ||
114 | } | ||
115 | for (PVariable pVariable : entry.getValue()) { | ||
116 | right.add(parameters.get(pVariable)); | ||
117 | } | ||
118 | accumulator.put(left, right); | ||
119 | } | ||
120 | |||
121 | } else { | ||
122 | // Disjunctive case, no dependencies are inferred | ||
123 | // TODO: we can still salvage the intersection of dependencies IF | ||
124 | // - all bodies have disjoint match sets | ||
125 | // - and we avoid recursion | ||
126 | } | ||
127 | |||
128 | // add annotation-based soft dependencies (regardless of number of bodies) | ||
129 | if (!strict) { | ||
130 | outer: | ||
131 | for (PAnnotation annotation : query.getAnnotationsByName("FunctionalDependency")) { | ||
132 | Set<Integer> lefts = new HashSet<Integer>(); | ||
133 | Set<Integer> rights = new HashSet<Integer>(); | ||
134 | |||
135 | for (Object object : annotation.getAllValues("forEach")) { | ||
136 | ParameterReference parameter = (ParameterReference) object; | ||
137 | Integer position = query.getPositionOfParameter(parameter.getName()); | ||
138 | if (position == null) continue outer; | ||
139 | lefts.add(position); | ||
140 | } | ||
141 | for (Object object : annotation.getAllValues("unique")) { | ||
142 | ParameterReference parameter = (ParameterReference) object; | ||
143 | Integer position = query.getPositionOfParameter(parameter.getName()); | ||
144 | if (position == null) continue outer; | ||
145 | rights.add(position); | ||
146 | } | ||
147 | |||
148 | FunctionalDependencyHelper.includeDependency(accumulator, lefts, rights); | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Functional dependency information, expressed on PVariables within a body, that the selected constraints imply. | ||
155 | * @return a non-null map of functional dependencies on PVariables that can be processed by {@link FunctionalDependencyHelper} | ||
156 | * @param constraints the set of constraints whose consequences will be analyzed | ||
157 | * @param strict if true, only "hard" dependencies are taken into account that are strictly enforced by the model representation; | ||
158 | * if false, user-provided soft dependencies (@FunctionalDependency) are included as well, that are anticipated but not guaranteed by the storage mechanism; | ||
159 | * use true if superfluous dependencies may taint the correctness of a computation, false if they would merely impact performance | ||
160 | * @since 1.5 | ||
161 | */ | ||
162 | public Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(Set<? extends PConstraint> constraints, boolean strict) { | ||
163 | Map<Set<PVariable>, Set<PVariable>> accumulator = new HashMap<Set<PVariable>, Set<PVariable>>(); | ||
164 | for (PConstraint pConstraint : constraints){ | ||
165 | if (pConstraint instanceof PositivePatternCall) { | ||
166 | // use query analysis results instead | ||
167 | PositivePatternCall call = (PositivePatternCall) pConstraint; | ||
168 | PQuery query = call.getSupplierKey(); | ||
169 | Map<Set<Integer>, Set<Integer>> paramDependencies = getProjectedFunctionalDependencies(query, strict); | ||
170 | for (Entry<Set<Integer>, Set<Integer>> entry : paramDependencies.entrySet()) { | ||
171 | Set<PVariable> lefts = new HashSet<PVariable>(); | ||
172 | Set<PVariable> rights = new HashSet<PVariable>(); | ||
173 | |||
174 | for (Integer index : entry.getKey()) { | ||
175 | lefts.add(call.getVariableInTuple(index)); | ||
176 | } | ||
177 | for (Integer index : entry.getValue()) { | ||
178 | rights.add(call.getVariableInTuple(index)); | ||
179 | } | ||
180 | |||
181 | FunctionalDependencyHelper.includeDependency(accumulator, | ||
182 | lefts, rights); | ||
183 | } | ||
184 | } else { | ||
185 | // delegate to PConstraint | ||
186 | FunctionalDependencyHelper.includeDependencies(accumulator, | ||
187 | pConstraint.getFunctionalDependencies(metaContext)); | ||
188 | } | ||
189 | } | ||
190 | return accumulator; | ||
191 | } | ||
192 | |||
193 | |||
194 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/annotations/PAnnotation.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/annotations/PAnnotation.java new file mode 100644 index 00000000..c4fbe0e9 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/annotations/PAnnotation.java | |||
@@ -0,0 +1,94 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.annotations; | ||
10 | |||
11 | import java.util.List; | ||
12 | import java.util.Optional; | ||
13 | import java.util.Set; | ||
14 | import java.util.function.BiConsumer; | ||
15 | |||
16 | import org.eclipse.collections.api.multimap.MutableMultimap; | ||
17 | import org.eclipse.collections.impl.multimap.list.FastListMultimap; | ||
18 | |||
19 | /** | ||
20 | * A container describing query annotations | ||
21 | * @author Zoltan Ujhelyi | ||
22 | * | ||
23 | */ | ||
24 | public class PAnnotation { | ||
25 | |||
26 | private final String name; | ||
27 | private MutableMultimap<String, Object> attributes = FastListMultimap.newMultimap(); | ||
28 | |||
29 | public PAnnotation(String name) { | ||
30 | this.name = name; | ||
31 | |||
32 | } | ||
33 | |||
34 | /** | ||
35 | * Adds an attribute to the annotation | ||
36 | * @param attributeName | ||
37 | * @param value | ||
38 | */ | ||
39 | public void addAttribute(String attributeName, Object value) { | ||
40 | attributes.put(attributeName, value); | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * Return the name of the annotation | ||
45 | */ | ||
46 | public String getName() { | ||
47 | return name; | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * Returns the value of the first occurrence of an attribute | ||
52 | * @param attributeName | ||
53 | * @return the attribute value, or null, if attribute is not available | ||
54 | * @since 2.0 | ||
55 | */ | ||
56 | public Optional<Object> getFirstValue(String attributeName) { | ||
57 | return getAllValues(attributeName).stream().findFirst(); | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * Returns the value of the first occurrence of an attribute | ||
62 | * @param attributeName | ||
63 | * @return the attribute value, or null, if attribute is not available | ||
64 | * @since 2.0 | ||
65 | */ | ||
66 | public <T> Optional<T> getFirstValue(String attributeName, Class<T> clazz) { | ||
67 | return getAllValues(attributeName).stream().filter(clazz::isInstance).map(clazz::cast).findFirst(); | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * Returns all values of a selected attribute | ||
72 | * @param attributeName | ||
73 | * @return a non-null, but possibly empty list of attributes | ||
74 | */ | ||
75 | public List<Object> getAllValues(String attributeName) { | ||
76 | return attributes.get(attributeName).toList(); | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * Executes a consumer over all attributes. A selected attribute name (key) can appear (and thus consumed) multiple times. | ||
81 | * @since 2.0 | ||
82 | */ | ||
83 | public void forEachValue(BiConsumer<String, Object> consumer) { | ||
84 | attributes.forEachKeyValue(consumer::accept); | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * Returns a set of all attribute names used in this annotation | ||
89 | * @since 2.1 | ||
90 | */ | ||
91 | public Set<String> getAllAttributeNames() { | ||
92 | return attributes.keySet().toSet(); | ||
93 | } | ||
94 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/annotations/ParameterReference.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/annotations/ParameterReference.java new file mode 100644 index 00000000..c67e9046 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/annotations/ParameterReference.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.annotations; | ||
10 | |||
11 | /** | ||
12 | * An annotation parameter referencing a query parameter by name. Does not check whether the parameter exists. | ||
13 | * | ||
14 | * @author Zoltan Ujhelyi | ||
15 | * | ||
16 | */ | ||
17 | public class ParameterReference { | ||
18 | |||
19 | final String name; | ||
20 | |||
21 | public ParameterReference(String name) { | ||
22 | super(); | ||
23 | this.name = name; | ||
24 | } | ||
25 | |||
26 | public String getName() { | ||
27 | return name; | ||
28 | } | ||
29 | |||
30 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/AggregatorConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/AggregatorConstraint.java new file mode 100644 index 00000000..56f86e89 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/AggregatorConstraint.java | |||
@@ -0,0 +1,98 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Tamas Szabo, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.basicdeferred; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.HashSet; | ||
14 | import java.util.Map; | ||
15 | import java.util.Set; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
18 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.ITypeInfoProviderConstraint; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement; | ||
23 | import tools.refinery.viatra.runtime.matchers.psystem.aggregations.BoundAggregator; | ||
24 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
25 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
26 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
27 | |||
28 | /** | ||
29 | * The PSystem representation of an aggregation. | ||
30 | * | ||
31 | * @author Tamas Szabo | ||
32 | * @since 1.4 | ||
33 | */ | ||
34 | public class AggregatorConstraint extends PatternCallBasedDeferred implements ITypeInfoProviderConstraint { | ||
35 | |||
36 | protected PVariable resultVariable; | ||
37 | private BoundAggregator aggregator; | ||
38 | protected int aggregatedColumn; | ||
39 | |||
40 | public AggregatorConstraint(BoundAggregator aggregator, PBody pBody, Tuple actualParametersTuple, PQuery query, | ||
41 | PVariable resultVariable, int aggregatedColumn) { | ||
42 | super(pBody, actualParametersTuple, query, Collections.singleton(resultVariable)); | ||
43 | this.resultVariable = resultVariable; | ||
44 | this.aggregatedColumn = aggregatedColumn; | ||
45 | this.aggregator = aggregator; | ||
46 | } | ||
47 | |||
48 | public int getAggregatedColumn() { | ||
49 | return this.aggregatedColumn; | ||
50 | } | ||
51 | |||
52 | public BoundAggregator getAggregator() { | ||
53 | return this.aggregator; | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public Set<PVariable> getDeducedVariables() { | ||
58 | return Collections.singleton(resultVariable); | ||
59 | } | ||
60 | |||
61 | @Override | ||
62 | public Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context) { | ||
63 | final Map<Set<PVariable>, Set<PVariable>> result = new HashMap<Set<PVariable>, Set<PVariable>>(); | ||
64 | result.put(getDeferringVariables(), getDeducedVariables()); | ||
65 | return result; | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | protected void doDoReplaceVariables(PVariable obsolete, PVariable replacement) { | ||
70 | if (resultVariable.equals(obsolete)) | ||
71 | resultVariable = replacement; | ||
72 | } | ||
73 | |||
74 | @Override | ||
75 | protected Set<PVariable> getCandidateQuantifiedVariables() { | ||
76 | return actualParametersTuple.<PVariable> getDistinctElements(); | ||
77 | } | ||
78 | |||
79 | @Override | ||
80 | protected String toStringRest() { | ||
81 | return query.getFullyQualifiedName() + "@" + actualParametersTuple.toString() + "->" | ||
82 | + resultVariable.toString(); | ||
83 | } | ||
84 | |||
85 | public PVariable getResultVariable() { | ||
86 | return resultVariable; | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public Set<TypeJudgement> getImpliedJudgements(IQueryMetaContext context) { | ||
91 | Set<TypeJudgement> result = new HashSet<TypeJudgement>(); | ||
92 | IInputKey aggregateResultType = aggregator.getAggregateResultTypeAsInputKey(); | ||
93 | if (aggregateResultType != null) { | ||
94 | result.add(new TypeJudgement(aggregateResultType, Tuples.staticArityFlatTupleOf(resultVariable))); | ||
95 | } | ||
96 | return result; | ||
97 | } | ||
98 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/BaseTypeSafeConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/BaseTypeSafeConstraint.java new file mode 100644 index 00000000..7bc949a8 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/BaseTypeSafeConstraint.java | |||
@@ -0,0 +1,99 @@ | |||
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.psystem.basicdeferred; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.Set; | ||
14 | import java.util.stream.Collectors; | ||
15 | import java.util.stream.Stream; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
18 | import tools.refinery.viatra.runtime.matchers.planning.SubPlan; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.VariableDeferredPConstraint; | ||
23 | |||
24 | /** | ||
25 | * @author Gabor Bergmann | ||
26 | * | ||
27 | */ | ||
28 | public abstract class BaseTypeSafeConstraint extends | ||
29 | VariableDeferredPConstraint { | ||
30 | |||
31 | protected Set<PVariable> inputVariables; | ||
32 | protected PVariable outputVariable; | ||
33 | |||
34 | public PVariable getOutputVariable() { | ||
35 | return outputVariable; | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * @param pBody | ||
40 | * @param inputVariables | ||
41 | * @param outputVariable null iff no output (check-only) | ||
42 | */ | ||
43 | public BaseTypeSafeConstraint(PBody pBody, | ||
44 | Set<PVariable> inputVariables, final PVariable outputVariable) { | ||
45 | super(pBody, | ||
46 | (outputVariable == null) ? | ||
47 | inputVariables : | ||
48 | Stream.concat(inputVariables.stream(), Stream.of(outputVariable)).collect(Collectors.toSet()) | ||
49 | ); | ||
50 | this.inputVariables = inputVariables; | ||
51 | this.outputVariable = outputVariable; | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public Set<PVariable> getDeducedVariables() { | ||
56 | if (outputVariable == null) | ||
57 | return Collections.emptySet(); | ||
58 | else | ||
59 | return Collections.singleton(outputVariable); | ||
60 | } | ||
61 | |||
62 | @Override | ||
63 | public Set<PVariable> getDeferringVariables() { | ||
64 | return inputVariables; | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public boolean isReadyAt(SubPlan plan, IQueryMetaContext context) { | ||
69 | if (super.isReadyAt(plan, context)) { | ||
70 | return checkTypeSafety(plan, context) == null; | ||
71 | } | ||
72 | return false; | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * Checks whether all type restrictions are already enforced on affected variables. | ||
77 | * | ||
78 | * @param plan | ||
79 | * @return a variable whose type safety is not enforced yet, or null if the plan is typesafe | ||
80 | */ | ||
81 | public PVariable checkTypeSafety(SubPlan plan, IQueryMetaContext context) { | ||
82 | Set<TypeJudgement> impliedJudgements = plan.getAllImpliedTypeJudgements(context); | ||
83 | |||
84 | for (PVariable pVariable : inputVariables) { | ||
85 | Set<TypeJudgement> allTypeRestrictionsForVariable = pBody.getAllUnaryTypeRestrictions(context).get(pVariable); | ||
86 | if (allTypeRestrictionsForVariable != null && !impliedJudgements.containsAll(allTypeRestrictionsForVariable)) | ||
87 | return pVariable; | ||
88 | } | ||
89 | return null; | ||
90 | } | ||
91 | |||
92 | @Override | ||
93 | protected void doReplaceVariable(PVariable obsolete, PVariable replacement) { | ||
94 | if (inputVariables.remove(obsolete)) | ||
95 | inputVariables.add(replacement); | ||
96 | if (outputVariable == obsolete) | ||
97 | outputVariable = replacement; | ||
98 | } | ||
99 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/Equality.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/Equality.java new file mode 100644 index 00000000..b978b62c --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/Equality.java | |||
@@ -0,0 +1,96 @@ | |||
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.psystem.basicdeferred; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.HashSet; | ||
15 | import java.util.Map; | ||
16 | import java.util.Set; | ||
17 | |||
18 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
19 | import tools.refinery.viatra.runtime.matchers.planning.SubPlan; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.DeferredPConstraint; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
23 | |||
24 | /** | ||
25 | * @author Gabor Bergmann | ||
26 | * | ||
27 | */ | ||
28 | public class Equality extends DeferredPConstraint { | ||
29 | |||
30 | private PVariable who; | ||
31 | private PVariable withWhom; | ||
32 | |||
33 | public Equality(PBody pBody, PVariable who, PVariable withWhom) { | ||
34 | super(pBody, buildSet(who, withWhom)); | ||
35 | this.who = who; | ||
36 | this.withWhom = withWhom; | ||
37 | } | ||
38 | |||
39 | private static Set<PVariable> buildSet(PVariable who, PVariable withWhom) { | ||
40 | Set<PVariable> set = new HashSet<PVariable>(); | ||
41 | set.add(who); | ||
42 | set.add(withWhom); | ||
43 | return set; | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * An equality is moot if it compares the a variable with itself. | ||
48 | * | ||
49 | * @return true, if the equality is moot | ||
50 | */ | ||
51 | public boolean isMoot() { | ||
52 | return who.equals(withWhom); | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public void doReplaceVariable(PVariable obsolete, PVariable replacement) { | ||
57 | if (obsolete.equals(who)) | ||
58 | who = replacement; | ||
59 | if (obsolete.equals(withWhom)) | ||
60 | withWhom = replacement; | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | protected String toStringRest() { | ||
65 | return who.getName() + "=" + withWhom.getName(); | ||
66 | } | ||
67 | |||
68 | public PVariable getWho() { | ||
69 | return who; | ||
70 | } | ||
71 | |||
72 | public PVariable getWithWhom() { | ||
73 | return withWhom; | ||
74 | } | ||
75 | |||
76 | @Override | ||
77 | public Set<PVariable> getDeducedVariables() { | ||
78 | return Collections.emptySet(); | ||
79 | } | ||
80 | |||
81 | @Override | ||
82 | public Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context) { | ||
83 | final Map<Set<PVariable>, Set<PVariable>> result = new HashMap<Set<PVariable>, Set<PVariable>>(); | ||
84 | result.put(Collections.singleton(who), Collections.singleton(withWhom)); | ||
85 | result.put(Collections.singleton(withWhom), Collections.singleton(who)); | ||
86 | return result; | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public boolean isReadyAt(SubPlan plan, IQueryMetaContext context) { | ||
91 | return plan.getVisibleVariables().contains(who) && plan.getVisibleVariables().contains(withWhom); | ||
92 | // will be replaced by || if copierNode is available; | ||
93 | // until then, LayoutHelper.unifyVariablesAlongEqualities(PSystem<PatternDescription, StubHandle, Collector>) is | ||
94 | // recommended. | ||
95 | } | ||
96 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/ExportedParameter.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/ExportedParameter.java new file mode 100644 index 00000000..80706792 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/ExportedParameter.java | |||
@@ -0,0 +1,108 @@ | |||
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.psystem.basicdeferred; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.matchers.planning.QueryProcessingException; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.VariableDeferredPConstraint; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
21 | |||
22 | /** | ||
23 | * @author Gabor Bergmann | ||
24 | * | ||
25 | */ | ||
26 | public class ExportedParameter extends VariableDeferredPConstraint { | ||
27 | PVariable parameterVariable; | ||
28 | final String parameterName; | ||
29 | final PParameter patternParameter; | ||
30 | |||
31 | /** | ||
32 | * @since 1.4 | ||
33 | */ | ||
34 | public ExportedParameter(PBody pBody, PVariable parameterVariable, PParameter patternParameter) { | ||
35 | super(pBody, Collections.singleton(parameterVariable)); | ||
36 | this.parameterVariable = parameterVariable; | ||
37 | this.patternParameter = patternParameter; | ||
38 | parameterName = patternParameter.getName(); | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public void doReplaceVariable(PVariable obsolete, PVariable replacement) { | ||
43 | if (obsolete.equals(parameterVariable)) | ||
44 | parameterVariable = replacement; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | protected String toStringRest() { | ||
49 | Object varName = parameterVariable.getName(); | ||
50 | return parameterName.equals(varName) ? parameterName : parameterName + "(" + varName + ")"; | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public Set<PVariable> getDeducedVariables() { | ||
55 | return Collections.emptySet(); | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * The name of the parameter; usually, it is expected that {@link #getParameterVariable()} is more useful, except | ||
60 | * maybe for debugging purposes. | ||
61 | * | ||
62 | * @return a non-null name of the parameter | ||
63 | */ | ||
64 | public String getParameterName() { | ||
65 | return parameterName; | ||
66 | } | ||
67 | |||
68 | public PVariable getParameterVariable() { | ||
69 | return parameterVariable; | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * @since 1.4 | ||
74 | */ | ||
75 | public PParameter getPatternParameter() { | ||
76 | if (patternParameter == null) { | ||
77 | PQuery query = pBody.getPattern(); | ||
78 | Integer index = query.getPositionOfParameter(parameterName); | ||
79 | if (index == null) { | ||
80 | throw new IllegalStateException(String.format("Pattern %s does not have a parameter named %s", | ||
81 | query.getFullyQualifiedName(), parameterName)); | ||
82 | } | ||
83 | return query.getParameters().get(index); | ||
84 | } else { | ||
85 | return patternParameter; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public Set<PVariable> getDeferringVariables() { | ||
91 | return Collections.singleton(parameterVariable); | ||
92 | } | ||
93 | |||
94 | @Override | ||
95 | public void checkSanity() { | ||
96 | super.checkSanity(); | ||
97 | if (!parameterVariable.isDeducable()) { | ||
98 | String[] args = { parameterName }; | ||
99 | String msg = "Impossible to match pattern: " | ||
100 | + "exported pattern variable {1} can not be determined based on the pattern constraints. " | ||
101 | + "HINT: certain constructs (e.g. negative patterns or check expressions) cannot output symbolic parameters."; | ||
102 | String shortMsg = "Could not deduce value of parameter"; | ||
103 | throw new QueryProcessingException(msg, args, shortMsg, null); | ||
104 | } | ||
105 | |||
106 | } | ||
107 | |||
108 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/ExpressionEvaluation.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/ExpressionEvaluation.java new file mode 100644 index 00000000..06688c36 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/ExpressionEvaluation.java | |||
@@ -0,0 +1,80 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.basicdeferred; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collections; | ||
13 | import java.util.LinkedHashSet; | ||
14 | import java.util.Map; | ||
15 | import java.util.Set; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.IExpressionEvaluator; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
21 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
22 | |||
23 | /** | ||
24 | * @author Zoltan Ujhelyi | ||
25 | * | ||
26 | */ | ||
27 | public class ExpressionEvaluation extends BaseTypeSafeConstraint { | ||
28 | |||
29 | private IExpressionEvaluator evaluator; | ||
30 | private boolean isUnwinding; | ||
31 | |||
32 | public ExpressionEvaluation(PBody pBody, IExpressionEvaluator evaluator, PVariable outputVariable) { | ||
33 | this(pBody, evaluator, outputVariable, false); | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * @since 2.4 | ||
38 | */ | ||
39 | public ExpressionEvaluation(PBody pBody, IExpressionEvaluator evaluator, PVariable outputVariable, | ||
40 | boolean isUnwinding) { | ||
41 | super(pBody, getPVariablesOfExpression(pBody, evaluator), outputVariable); | ||
42 | this.evaluator = evaluator; | ||
43 | this.isUnwinding = isUnwinding; | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * @since 2.4 | ||
48 | */ | ||
49 | public boolean isUnwinding() { | ||
50 | return isUnwinding; | ||
51 | } | ||
52 | |||
53 | public IExpressionEvaluator getEvaluator() { | ||
54 | return evaluator; | ||
55 | } | ||
56 | |||
57 | @Override | ||
58 | protected String toStringRest() { | ||
59 | return Tuples.flatTupleOf(new ArrayList<PVariable>(inputVariables).toArray()).toString() + "|=" | ||
60 | + evaluator.getShortDescription(); | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context) { | ||
65 | if (outputVariable == null) | ||
66 | return Collections.emptyMap(); | ||
67 | else | ||
68 | return Collections.singletonMap(inputVariables, Collections.singleton(outputVariable)); | ||
69 | } | ||
70 | |||
71 | private static Set<PVariable> getPVariablesOfExpression(PBody pBody, IExpressionEvaluator evaluator) { | ||
72 | // use a linked set, so that the variables will come in the order of the parameters | ||
73 | Set<PVariable> result = new LinkedHashSet<PVariable>(); | ||
74 | for (String name : evaluator.getInputParameterNames()) { | ||
75 | PVariable variable = pBody.getOrCreateVariableByName(name); | ||
76 | result.add(variable); | ||
77 | } | ||
78 | return result; | ||
79 | } | ||
80 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/Inequality.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/Inequality.java new file mode 100644 index 00000000..5cac33dc --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/Inequality.java | |||
@@ -0,0 +1,151 @@ | |||
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.psystem.basicdeferred; | ||
11 | |||
12 | import java.util.Arrays; | ||
13 | import java.util.Collections; | ||
14 | import java.util.HashSet; | ||
15 | import java.util.Set; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.VariableDeferredPConstraint; | ||
20 | |||
21 | /** | ||
22 | * @author Gabor Bergmann | ||
23 | * | ||
24 | */ | ||
25 | public class Inequality extends VariableDeferredPConstraint { | ||
26 | |||
27 | private PVariable who; | ||
28 | private PVariable withWhom; | ||
29 | |||
30 | /** | ||
31 | * The inequality constraint is weak if it can be ignored when who is the same as withWhom, or if any if them is | ||
32 | * undeducible. | ||
33 | */ | ||
34 | private boolean weak; | ||
35 | |||
36 | public Inequality(PBody pBody, PVariable who, PVariable withWhom) { | ||
37 | this(pBody, who, withWhom, false); | ||
38 | } | ||
39 | |||
40 | public Inequality(PBody pBody, PVariable who, PVariable withWhom, | ||
41 | boolean weak) { | ||
42 | super(pBody, new HashSet<>(Arrays.asList(who, withWhom) )); | ||
43 | this.who = who; | ||
44 | this.withWhom = withWhom; | ||
45 | this.weak = weak; | ||
46 | } | ||
47 | |||
48 | // private Inequality( | ||
49 | // PSystem<PatternDescription, StubHandle, ?> pSystem, | ||
50 | // PVariable subject, Set<PVariable> inequals) | ||
51 | // { | ||
52 | // super(pSystem, include(inequals, subject)); | ||
53 | // this.subject = subject; | ||
54 | // this.inequals = inequals; | ||
55 | // } | ||
56 | |||
57 | // private static HashSet<PVariable> include(Set<PVariable> inequals, PVariable subject) { | ||
58 | // HashSet<PVariable> hashSet = new HashSet<PVariable>(inequals); | ||
59 | // hashSet.add(subject); | ||
60 | // return hashSet; | ||
61 | // } | ||
62 | |||
63 | @Override | ||
64 | public Set<PVariable> getDeferringVariables() { | ||
65 | return getAffectedVariables(); | ||
66 | } | ||
67 | |||
68 | // private static int[] mapIndices(Map<Object, Integer> variablesIndex, Set<PVariable> keys) { | ||
69 | // int[] result = new int[keys.size()]; | ||
70 | // int k = 0; | ||
71 | // for (PVariable key : keys) { | ||
72 | // result[k++] = variablesIndex.get(key); | ||
73 | // } | ||
74 | // return result; | ||
75 | // } | ||
76 | |||
77 | // @Override | ||
78 | // public IFoldablePConstraint getIncorporator() { | ||
79 | // return incorporator; | ||
80 | // } | ||
81 | // | ||
82 | // @Override | ||
83 | // public void registerIncorporatationInto(IFoldablePConstraint incorporator) { | ||
84 | // this.incorporator = incorporator; | ||
85 | // } | ||
86 | // | ||
87 | // @Override | ||
88 | // public boolean incorporate(IFoldablePConstraint other) { | ||
89 | // if (other instanceof Inequality<?, ?>) { | ||
90 | // Inequality other2 = (Inequality) other; | ||
91 | // if (subject.equals(other2.subject)) { | ||
92 | // Set<PVariable> newInequals = new HashSet<PVariable>(inequals); | ||
93 | // newInequals.addAll(other2.inequals); | ||
94 | // return new Inequality<PatternDescription, StubHandle>(buildable, subject, newInequals); | ||
95 | // } | ||
96 | // } else return false; | ||
97 | // } | ||
98 | |||
99 | @Override | ||
100 | protected String toStringRest() { | ||
101 | return who.toString() + (isWeak() ? "!=?" : "!=") + withWhom.toString(); | ||
102 | } | ||
103 | |||
104 | @Override | ||
105 | public void doReplaceVariable(PVariable obsolete, PVariable replacement) { | ||
106 | if (obsolete.equals(who)) | ||
107 | who = replacement; | ||
108 | if (obsolete.equals(withWhom)) | ||
109 | withWhom = replacement; | ||
110 | } | ||
111 | |||
112 | @Override | ||
113 | public Set<PVariable> getDeducedVariables() { | ||
114 | return Collections.emptySet(); | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * The inequality constraint is weak if it can be ignored when who is the same as withWhom, or if any if them is | ||
119 | * undeducible. | ||
120 | * | ||
121 | * @return the weak | ||
122 | */ | ||
123 | public boolean isWeak() { | ||
124 | return weak; | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * A weak inequality constraint is eliminable if who is the same as withWhom, or if any if them is undeducible. | ||
129 | */ | ||
130 | public boolean isEliminable() { | ||
131 | return isWeak() && (who.equals(withWhom) || !who.isDeducable() || !withWhom.isDeducable()); | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * Eliminates a weak inequality constraint if it can be ignored when who is the same as withWhom, or if any if them | ||
136 | * is undeducible. | ||
137 | */ | ||
138 | public void eliminateWeak() { | ||
139 | if (isEliminable()) | ||
140 | delete(); | ||
141 | } | ||
142 | |||
143 | public PVariable getWho() { | ||
144 | return who; | ||
145 | } | ||
146 | |||
147 | public PVariable getWithWhom() { | ||
148 | return withWhom; | ||
149 | } | ||
150 | |||
151 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/NegativePatternCall.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/NegativePatternCall.java new file mode 100644 index 00000000..87d9d9fc --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/NegativePatternCall.java | |||
@@ -0,0 +1,52 @@ | |||
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.psystem.basicdeferred; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
18 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
19 | |||
20 | /** | ||
21 | * @author Gabor Bergmann | ||
22 | * | ||
23 | */ | ||
24 | public class NegativePatternCall extends PatternCallBasedDeferred { | ||
25 | |||
26 | public NegativePatternCall(PBody pBody, Tuple actualParametersTuple, PQuery query) { | ||
27 | super(pBody, actualParametersTuple, query); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public Set<PVariable> getDeducedVariables() { | ||
32 | return Collections.emptySet(); | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * @return all variables that may potentially be quantified they are not used anywhere else | ||
37 | */ | ||
38 | @Override | ||
39 | protected Set<PVariable> getCandidateQuantifiedVariables() { | ||
40 | return getAffectedVariables(); | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | protected void doDoReplaceVariables(PVariable obsolete, PVariable replacement) { | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | protected String toStringRest() { | ||
49 | return "!" + query.getFullyQualifiedName() + "@" + actualParametersTuple.toString(); | ||
50 | } | ||
51 | |||
52 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/PatternCallBasedDeferred.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/PatternCallBasedDeferred.java new file mode 100644 index 00000000..93eeffec --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/PatternCallBasedDeferred.java | |||
@@ -0,0 +1,118 @@ | |||
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.psystem.basicdeferred; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.HashSet; | ||
14 | import java.util.Set; | ||
15 | |||
16 | import tools.refinery.viatra.runtime.matchers.planning.QueryProcessingException; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.IQueryReference; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.PConstraint; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.VariableDeferredPConstraint; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
23 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
24 | |||
25 | /** | ||
26 | * @author Gabor Bergmann | ||
27 | * | ||
28 | */ | ||
29 | public abstract class PatternCallBasedDeferred extends VariableDeferredPConstraint implements IQueryReference { | ||
30 | |||
31 | protected Tuple actualParametersTuple; | ||
32 | |||
33 | protected abstract void doDoReplaceVariables(PVariable obsolete, PVariable replacement); | ||
34 | |||
35 | protected abstract Set<PVariable> getCandidateQuantifiedVariables(); | ||
36 | |||
37 | protected PQuery query; | ||
38 | private Set<PVariable> deferringVariables; | ||
39 | |||
40 | public PatternCallBasedDeferred(PBody pBody, Tuple actualParametersTuple, | ||
41 | PQuery pattern, Set<PVariable> additionalAffectedVariables) { | ||
42 | super(pBody, union(actualParametersTuple.<PVariable> getDistinctElements(), additionalAffectedVariables)); | ||
43 | this.actualParametersTuple = actualParametersTuple; | ||
44 | this.query = pattern; | ||
45 | } | ||
46 | |||
47 | public PatternCallBasedDeferred(PBody pBody, Tuple actualParametersTuple, | ||
48 | PQuery pattern) { | ||
49 | this(pBody, actualParametersTuple, pattern, Collections.<PVariable> emptySet()); | ||
50 | } | ||
51 | |||
52 | private static Set<PVariable> union(Set<PVariable> a, Set<PVariable> b) { | ||
53 | Set<PVariable> result = new HashSet<PVariable>(); | ||
54 | result.addAll(a); | ||
55 | result.addAll(b); | ||
56 | return result; | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public Set<PVariable> getDeferringVariables() { | ||
61 | if (deferringVariables == null) { | ||
62 | deferringVariables = new HashSet<PVariable>(); | ||
63 | for (PVariable var : getCandidateQuantifiedVariables()) { | ||
64 | if (var.isDeducable()) | ||
65 | deferringVariables.add(var); | ||
66 | } | ||
67 | } | ||
68 | return deferringVariables; | ||
69 | } | ||
70 | |||
71 | @Override | ||
72 | public void checkSanity() { | ||
73 | super.checkSanity(); | ||
74 | for (Object obj : this.actualParametersTuple.getDistinctElements()) { | ||
75 | PVariable var = (PVariable) obj; | ||
76 | if (!getDeferringVariables().contains(var)) { | ||
77 | // so this is a free variable of the NAC / aggregation? | ||
78 | for (PConstraint pConstraint : var.getReferringConstraints()) { | ||
79 | if (pConstraint != this | ||
80 | && !(pConstraint instanceof Equality && ((Equality) pConstraint).isMoot())) | ||
81 | throw new QueryProcessingException ( | ||
82 | "Variable {1} of constraint {2} is not a positively determined part of the pattern, yet it is also affected by {3}.", | ||
83 | new String[] { var.toString(), this.toString(), pConstraint.toString() }, | ||
84 | "Read-only variable can not be deduced", null); | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | } | ||
90 | |||
91 | // public SubPlan getSidePlan(IOperationCompiler compiler) throws QueryPlannerException { | ||
92 | // SubPlan sidePlan = compiler.patternCallPlan(actualParametersTuple, query); | ||
93 | // sidePlan = BuildHelper.enforceVariableCoincidences(compiler, sidePlan); | ||
94 | // return sidePlan; | ||
95 | // } | ||
96 | |||
97 | @Override | ||
98 | protected void doReplaceVariable(PVariable obsolete, PVariable replacement) { | ||
99 | if (deferringVariables != null) { | ||
100 | // FAIL instead of hopeless attempt to fix | ||
101 | // if (deferringVariables.remove(obsolete)) deferringVariables.add(replacement); | ||
102 | throw new IllegalStateException("Cannot replace variables on " + this | ||
103 | + " when deferring variables have already been identified."); | ||
104 | } | ||
105 | actualParametersTuple = actualParametersTuple.replaceAll(obsolete, replacement); | ||
106 | doDoReplaceVariables(obsolete, replacement); | ||
107 | } | ||
108 | |||
109 | public Tuple getActualParametersTuple() { | ||
110 | return actualParametersTuple; | ||
111 | } | ||
112 | |||
113 | @Override | ||
114 | public PQuery getReferredQuery() { | ||
115 | return query; | ||
116 | } | ||
117 | |||
118 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/PatternMatchCounter.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/PatternMatchCounter.java new file mode 100644 index 00000000..0c40d91e --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/PatternMatchCounter.java | |||
@@ -0,0 +1,70 @@ | |||
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.psystem.basicdeferred; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.Map; | ||
15 | import java.util.Set; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
21 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
22 | |||
23 | /** | ||
24 | * @author Gabor Bergmann | ||
25 | */ | ||
26 | public class PatternMatchCounter extends PatternCallBasedDeferred { | ||
27 | |||
28 | private PVariable resultVariable; | ||
29 | |||
30 | public PatternMatchCounter(PBody pBody, Tuple actualParametersTuple, | ||
31 | PQuery query, PVariable resultVariable) { | ||
32 | super(pBody, actualParametersTuple, query, Collections.singleton(resultVariable)); | ||
33 | this.resultVariable = resultVariable; | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public Set<PVariable> getDeducedVariables() { | ||
38 | return Collections.singleton(resultVariable); | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context) { | ||
43 | final Map<Set<PVariable>, Set<PVariable>> result = new HashMap<Set<PVariable>, Set<PVariable>>(); | ||
44 | result.put(getDeferringVariables(), getDeducedVariables()); | ||
45 | return result; | ||
46 | } | ||
47 | |||
48 | @Override | ||
49 | protected void doDoReplaceVariables(PVariable obsolete, PVariable replacement) { | ||
50 | if (resultVariable.equals(obsolete)) | ||
51 | resultVariable = replacement; | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | protected Set<PVariable> getCandidateQuantifiedVariables() { | ||
56 | return actualParametersTuple.<PVariable> getDistinctElements(); | ||
57 | } | ||
58 | |||
59 | |||
60 | @Override | ||
61 | protected String toStringRest() { | ||
62 | return query.getFullyQualifiedName() + "@" + actualParametersTuple.toString() + "->" | ||
63 | + resultVariable.toString(); | ||
64 | } | ||
65 | |||
66 | public PVariable getResultVariable() { | ||
67 | return resultVariable; | ||
68 | } | ||
69 | |||
70 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/RelationEvaluation.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/RelationEvaluation.java new file mode 100644 index 00000000..336a83fb --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/RelationEvaluation.java | |||
@@ -0,0 +1,57 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2022, Tamas Szabo, GitHub | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem.basicdeferred; | ||
10 | |||
11 | import java.util.List; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.matchers.psystem.EnumerablePConstraint; | ||
14 | import tools.refinery.viatra.runtime.matchers.psystem.IMultiQueryReference; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.IRelationEvaluator; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
18 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
19 | |||
20 | /** | ||
21 | * A constraint which prescribes the evaluation of custom Java logic that takes an arbitrary number of input relations | ||
22 | * and produces one output relation. Contrast this to {@link ExpressionEvaluation}, which produces a single output value | ||
23 | * given an input tuple. | ||
24 | * | ||
25 | * The assumption is that the relation evaluation logic is not incremental, that is, it can only perform from-scratch | ||
26 | * computation of the output relation given the complete input relations. To this end, the relation evaluator always | ||
27 | * receives the complete input relations with all their contents as input. However, the evaluator engine makes sure that | ||
28 | * the output of the relation evaluation is at least "seemingly" incremental. This means that the underlying computation | ||
29 | * network computes the delta on the output compared to the previous output and only propagates the delta further. | ||
30 | * | ||
31 | * @author Tamas Szabo | ||
32 | * | ||
33 | * @since 2.8 | ||
34 | * | ||
35 | */ | ||
36 | public class RelationEvaluation extends EnumerablePConstraint implements IMultiQueryReference { | ||
37 | |||
38 | private final IRelationEvaluator evaluator; | ||
39 | private final List<PQuery> inputQueries; | ||
40 | |||
41 | public RelationEvaluation(final PBody body, final Tuple variablesTuple, final List<PQuery> inputQueries, | ||
42 | final IRelationEvaluator evaluator) { | ||
43 | super(body, variablesTuple); | ||
44 | this.evaluator = evaluator; | ||
45 | this.inputQueries = inputQueries; | ||
46 | } | ||
47 | |||
48 | public IRelationEvaluator getEvaluator() { | ||
49 | return this.evaluator; | ||
50 | } | ||
51 | |||
52 | @Override | ||
53 | public List<PQuery> getReferredQueries() { | ||
54 | return this.inputQueries; | ||
55 | } | ||
56 | |||
57 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/TypeFilterConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/TypeFilterConstraint.java new file mode 100644 index 00000000..8b6e29ef --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicdeferred/TypeFilterConstraint.java | |||
@@ -0,0 +1,105 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.basicdeferred; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.Map; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
16 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.ITypeConstraint; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.VariableDeferredPConstraint; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.TypeConstraint; | ||
23 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
24 | |||
25 | /** | ||
26 | * Represents a non-enumerable type constraint that asserts that values substituted for the given tuple of variables | ||
27 | * form a tuple that belongs to a (typically non-enumerable) extensional relation identified by an {@link IInputKey}. | ||
28 | * | ||
29 | * <p> The InputKey is typically not enumerable. If it is enumerable, use {@link TypeConstraint} instead, so that the PConstraint carries over the property of enumerability. | ||
30 | * | ||
31 | * @author Bergmann Gabor | ||
32 | * | ||
33 | */ | ||
34 | public class TypeFilterConstraint extends VariableDeferredPConstraint implements | ||
35 | ITypeConstraint { | ||
36 | |||
37 | private Tuple variablesTuple; | ||
38 | private IInputKey inputKey; | ||
39 | |||
40 | private TypeJudgement equivalentJudgement; | ||
41 | |||
42 | |||
43 | public TypeFilterConstraint(PBody pBody, Tuple variablesTuple, IInputKey inputKey) { | ||
44 | super(pBody, variablesTuple.<PVariable> getDistinctElements()); | ||
45 | this.equivalentJudgement = new TypeJudgement(inputKey, variablesTuple); | ||
46 | |||
47 | this.variablesTuple = variablesTuple; | ||
48 | this.inputKey = inputKey; | ||
49 | |||
50 | if (variablesTuple.getSize() != inputKey.getArity()) | ||
51 | throw new IllegalArgumentException( | ||
52 | this.getClass().getSimpleName() + | ||
53 | " applied for variable tuple " + variablesTuple + " having wrong arity for input key " + | ||
54 | inputKey); | ||
55 | } | ||
56 | |||
57 | |||
58 | |||
59 | public Tuple getVariablesTuple() { | ||
60 | return variablesTuple; | ||
61 | } | ||
62 | |||
63 | public IInputKey getInputKey() { | ||
64 | return inputKey; | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public TypeJudgement getEquivalentJudgement() { | ||
69 | return equivalentJudgement; | ||
70 | } | ||
71 | |||
72 | @Override | ||
73 | protected void doReplaceVariable(PVariable obsolete, PVariable replacement) { | ||
74 | variablesTuple = variablesTuple.replaceAll(obsolete, replacement); | ||
75 | this.equivalentJudgement = new TypeJudgement(inputKey, variablesTuple); | ||
76 | } | ||
77 | |||
78 | @Override | ||
79 | public Set<TypeJudgement> getImpliedJudgements(IQueryMetaContext context) { | ||
80 | return Collections.singleton(equivalentJudgement); | ||
81 | } | ||
82 | |||
83 | @Override | ||
84 | public Set<PVariable> getDeducedVariables() { | ||
85 | return Collections.emptySet(); | ||
86 | } | ||
87 | |||
88 | @Override | ||
89 | public Set<PVariable> getDeferringVariables() { | ||
90 | return getAffectedVariables(); | ||
91 | } | ||
92 | |||
93 | @Override | ||
94 | protected String toStringRest() { | ||
95 | return inputKey.getPrettyPrintableName() + "@" + variablesTuple; | ||
96 | } | ||
97 | |||
98 | @Override | ||
99 | public Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context) { | ||
100 | return TypeConstraintUtil.getFunctionalDependencies(context, inputKey, variablesTuple); | ||
101 | } | ||
102 | |||
103 | |||
104 | |||
105 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/AbstractTransitiveClosure.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/AbstractTransitiveClosure.java new file mode 100644 index 00000000..7bbf7118 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/AbstractTransitiveClosure.java | |||
@@ -0,0 +1,44 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2018, Gabor Bergmann, Zoltan Ujhelyi, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.basicenumerables; | ||
10 | |||
11 | import java.util.Set; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
14 | import tools.refinery.viatra.runtime.matchers.psystem.IQueryReference; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.ITypeInfoProviderConstraint; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.KeyedEnumerablePConstraint; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
20 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
21 | |||
22 | /** | ||
23 | * @since 2.0 | ||
24 | */ | ||
25 | public abstract class AbstractTransitiveClosure extends KeyedEnumerablePConstraint<PQuery> implements IQueryReference, ITypeInfoProviderConstraint { | ||
26 | |||
27 | public AbstractTransitiveClosure(PBody pBody, Tuple variablesTuple, PQuery supplierKey) { | ||
28 | super(pBody, variablesTuple, supplierKey); | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public PQuery getReferredQuery() { | ||
33 | return supplierKey; | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * @since 1.3 | ||
38 | */ | ||
39 | @Override | ||
40 | public Set<TypeJudgement> getImpliedJudgements(IQueryMetaContext context) { | ||
41 | return PositivePatternCall.getTypesImpliedByCall(supplierKey, variablesTuple); | ||
42 | } | ||
43 | |||
44 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/BinaryReflexiveTransitiveClosure.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/BinaryReflexiveTransitiveClosure.java new file mode 100644 index 00000000..e3dae240 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/BinaryReflexiveTransitiveClosure.java | |||
@@ -0,0 +1,57 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2004-2010 Zoltan Ujhelyi, 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 | *******************************************************************************/ | ||
9 | |||
10 | package tools.refinery.viatra.runtime.matchers.psystem.basicenumerables; | ||
11 | |||
12 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
13 | import tools.refinery.viatra.runtime.matchers.planning.QueryProcessingException; | ||
14 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
16 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
17 | |||
18 | /** | ||
19 | * For a binary base pattern over an enumerable universe type, computes the reflexive transitive closure (base)* | ||
20 | * | ||
21 | * @author Gabor Bergmann, Zoltan Ujhelyi | ||
22 | * @since 2.0 | ||
23 | */ | ||
24 | public class BinaryReflexiveTransitiveClosure extends AbstractTransitiveClosure { | ||
25 | |||
26 | private final IInputKey universeType; | ||
27 | |||
28 | public BinaryReflexiveTransitiveClosure(PBody pBody, Tuple variablesTuple, | ||
29 | PQuery pattern, IInputKey universeType) { | ||
30 | super(pBody, variablesTuple, pattern); | ||
31 | this.universeType = universeType; | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | protected String keyToString() { | ||
36 | return supplierKey.getFullyQualifiedName() + "*"; | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * Returns the type whose instances should be returned as 0-long paths. | ||
41 | * @since 2.0 | ||
42 | */ | ||
43 | public IInputKey getUniverseType() { | ||
44 | return universeType; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public void checkSanity() { | ||
49 | if (!universeType.isEnumerable() || universeType.getArity() != 1) { | ||
50 | throw new QueryProcessingException( | ||
51 | String.format("Invalid universe type %s - it should be enumerable and must have an arity of 1.", | ||
52 | universeType.getPrettyPrintableName()), | ||
53 | pBody.getPattern()); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/BinaryTransitiveClosure.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/BinaryTransitiveClosure.java new file mode 100644 index 00000000..716d043b --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/BinaryTransitiveClosure.java | |||
@@ -0,0 +1,33 @@ | |||
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.psystem.basicenumerables; | ||
11 | |||
12 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
13 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
14 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
15 | |||
16 | /** | ||
17 | * For a binary base pattern, computes the irreflexive transitive closure (base)+ | ||
18 | * | ||
19 | * @author Gabor Bergmann | ||
20 | * | ||
21 | */ | ||
22 | public class BinaryTransitiveClosure extends AbstractTransitiveClosure { | ||
23 | |||
24 | public BinaryTransitiveClosure(PBody pBody, Tuple variablesTuple, | ||
25 | PQuery pattern) { | ||
26 | super(pBody, variablesTuple, pattern); | ||
27 | } | ||
28 | |||
29 | @Override | ||
30 | protected String keyToString() { | ||
31 | return supplierKey.getFullyQualifiedName() + "+"; | ||
32 | } | ||
33 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/Connectivity.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/Connectivity.java new file mode 100644 index 00000000..10da2e21 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/Connectivity.java | |||
@@ -0,0 +1,11 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.viatra.runtime.matchers.psystem.basicenumerables; | ||
7 | |||
8 | public enum Connectivity { | ||
9 | WEAK, | ||
10 | STRONG; | ||
11 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/ConstantValue.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/ConstantValue.java new file mode 100644 index 00000000..251146c8 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/ConstantValue.java | |||
@@ -0,0 +1,57 @@ | |||
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.psystem.basicenumerables; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.Map; | ||
15 | import java.util.Set; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.KeyedEnumerablePConstraint; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
21 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
22 | |||
23 | /** | ||
24 | * @author Gabor Bergmann | ||
25 | * | ||
26 | */ | ||
27 | public class ConstantValue extends KeyedEnumerablePConstraint<Object> { | ||
28 | |||
29 | private PVariable variable; | ||
30 | |||
31 | public ConstantValue(PBody pBody, PVariable variable, Object value) { | ||
32 | super(pBody, Tuples.staticArityFlatTupleOf(variable), value); | ||
33 | this.variable = variable; | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | protected String keyToString() { | ||
38 | return supplierKey.toString(); | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * @since 1.7 | ||
43 | */ | ||
44 | public PVariable getVariable() { | ||
45 | return variable; | ||
46 | } | ||
47 | |||
48 | @Override | ||
49 | public Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context) { | ||
50 | final Map<Set<PVariable>, Set<PVariable>> result = new HashMap<Set<PVariable>, Set<PVariable>>(); | ||
51 | final Set<PVariable> emptySet = Collections.emptySet(); // a constant value is functionally determined by everything | ||
52 | result.put(emptySet, Collections.singleton(getVariableInTuple(0))); | ||
53 | return result; | ||
54 | } | ||
55 | |||
56 | |||
57 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/PositivePatternCall.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/PositivePatternCall.java new file mode 100644 index 00000000..25ab34b4 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/PositivePatternCall.java | |||
@@ -0,0 +1,76 @@ | |||
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.psystem.basicenumerables; | ||
11 | |||
12 | import java.util.HashSet; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
16 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.IQueryReference; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.ITypeInfoProviderConstraint; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.KeyedEnumerablePConstraint; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
23 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
24 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
25 | |||
26 | /** | ||
27 | * @author Gabor Bergmann | ||
28 | * | ||
29 | */ | ||
30 | public class PositivePatternCall extends KeyedEnumerablePConstraint<PQuery> implements IQueryReference, ITypeInfoProviderConstraint { | ||
31 | |||
32 | public PositivePatternCall(PBody pBody, Tuple variablesTuple, | ||
33 | PQuery pattern) { | ||
34 | super(pBody, variablesTuple, pattern); | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | protected String keyToString() { | ||
39 | return supplierKey.getFullyQualifiedName(); | ||
40 | } | ||
41 | |||
42 | // Note: #getFunctionalDependencies is intentionally not implemented - use QueryAnalyzer instead! | ||
43 | // @Override | ||
44 | // public Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context) { | ||
45 | // return super.getFunctionalDependencies(context); | ||
46 | // } | ||
47 | |||
48 | @Override | ||
49 | public PQuery getReferredQuery() { | ||
50 | return supplierKey; | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public Set<TypeJudgement> getImpliedJudgements(IQueryMetaContext context) { | ||
55 | return getTypesImpliedByCall(supplierKey, variablesTuple); | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * @since 1.3 | ||
60 | */ | ||
61 | public static Set<TypeJudgement> getTypesImpliedByCall(PQuery calledQuery, Tuple actualParametersTuple) { | ||
62 | Set<TypeJudgement> result = new HashSet<TypeJudgement>(); | ||
63 | for (TypeJudgement parameterJudgement : calledQuery.getTypeGuarantees()) { | ||
64 | IInputKey inputKey = parameterJudgement.getInputKey(); | ||
65 | Tuple judgementIndexTuple = parameterJudgement.getVariablesTuple(); | ||
66 | |||
67 | Object[] judgementVariables = new Object[judgementIndexTuple.getSize()]; | ||
68 | for (int i=0; i<judgementVariables.length; ++i) | ||
69 | judgementVariables[i] = actualParametersTuple.get((int) judgementIndexTuple.get(i)); | ||
70 | |||
71 | result.add(new TypeJudgement(inputKey, Tuples.flatTupleOf(judgementVariables))); | ||
72 | } | ||
73 | return result; | ||
74 | } | ||
75 | |||
76 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/RepresentativeElectionConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/RepresentativeElectionConstraint.java new file mode 100644 index 00000000..b97ff55f --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/RepresentativeElectionConstraint.java | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.viatra.runtime.matchers.psystem.basicenumerables; | ||
7 | |||
8 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
9 | import tools.refinery.viatra.runtime.matchers.psystem.*; | ||
10 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
11 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
12 | |||
13 | import java.util.Set; | ||
14 | |||
15 | public class RepresentativeElectionConstraint extends KeyedEnumerablePConstraint<PQuery> | ||
16 | implements IQueryReference, ITypeInfoProviderConstraint { | ||
17 | private final Connectivity connectivity; | ||
18 | |||
19 | public RepresentativeElectionConstraint(PBody pBody, Tuple variablesTuple, PQuery supplierKey, | ||
20 | Connectivity connectivity) { | ||
21 | super(pBody, variablesTuple, supplierKey); | ||
22 | this.connectivity = connectivity; | ||
23 | } | ||
24 | |||
25 | public Connectivity getConnectivity() { | ||
26 | return connectivity; | ||
27 | } | ||
28 | |||
29 | @Override | ||
30 | public PQuery getReferredQuery() { | ||
31 | return supplierKey; | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | public Set<TypeJudgement> getImpliedJudgements(IQueryMetaContext context) { | ||
36 | return PositivePatternCall.getTypesImpliedByCall(supplierKey, variablesTuple); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | protected String keyToString() { | ||
41 | return supplierKey.getFullyQualifiedName() + "#" + connectivity + "#representative"; | ||
42 | } | ||
43 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/TypeConstraint.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/TypeConstraint.java new file mode 100644 index 00000000..2ca54cc0 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/basicenumerables/TypeConstraint.java | |||
@@ -0,0 +1,79 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.basicenumerables; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.Map; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
16 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.ITypeConstraint; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.KeyedEnumerablePConstraint; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement; | ||
22 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
23 | |||
24 | /** | ||
25 | * Represents an enumerable type constraint that asserts that values substituted for the given tuple of variables | ||
26 | * form a tuple that belongs to an enumerable extensional relation identified by an {@link IInputKey}. | ||
27 | * | ||
28 | * <p> The InputKey must be enumerable! | ||
29 | * | ||
30 | * @author Zoltan Ujhelyi | ||
31 | * | ||
32 | */ | ||
33 | public class TypeConstraint extends KeyedEnumerablePConstraint<IInputKey> implements ITypeConstraint { | ||
34 | |||
35 | private TypeJudgement equivalentJudgement; | ||
36 | |||
37 | public TypeConstraint(PBody pBody, Tuple variablesTuple, IInputKey inputKey) { | ||
38 | super(pBody, variablesTuple, inputKey); | ||
39 | this.equivalentJudgement = new TypeJudgement(inputKey, variablesTuple); | ||
40 | |||
41 | if (! inputKey.isEnumerable()) | ||
42 | throw new IllegalArgumentException( | ||
43 | this.getClass().getSimpleName() + | ||
44 | " applicable for enumerable input keys only; received instead " + | ||
45 | inputKey); | ||
46 | if (variablesTuple.getSize() != inputKey.getArity()) | ||
47 | throw new IllegalArgumentException( | ||
48 | this.getClass().getSimpleName() + | ||
49 | " applied for variable tuple " + variablesTuple + " having wrong arity for input key " + | ||
50 | inputKey); | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | protected String keyToString() { | ||
55 | return supplierKey.getPrettyPrintableName(); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public TypeJudgement getEquivalentJudgement() { | ||
60 | return equivalentJudgement; | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public Set<TypeJudgement> getImpliedJudgements(IQueryMetaContext context) { | ||
65 | return Collections.singleton(equivalentJudgement); | ||
66 | //return equivalentJudgement.getDirectlyImpliedJudgements(context); | ||
67 | } | ||
68 | |||
69 | @Override | ||
70 | public Map<Set<PVariable>, Set<PVariable>> getFunctionalDependencies(IQueryMetaContext context) { | ||
71 | return TypeConstraintUtil.getFunctionalDependencies(context, supplierKey, variablesTuple); | ||
72 | } | ||
73 | |||
74 | @Override | ||
75 | public void doReplaceVariable(PVariable obsolete, PVariable replacement) { | ||
76 | super.doReplaceVariable(obsolete, replacement); | ||
77 | this.equivalentJudgement = new TypeJudgement(getSupplierKey(), variablesTuple); | ||
78 | } | ||
79 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/BasePQuery.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/BasePQuery.java new file mode 100644 index 00000000..2c03a894 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/BasePQuery.java | |||
@@ -0,0 +1,231 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.queries; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collections; | ||
13 | import java.util.HashSet; | ||
14 | import java.util.List; | ||
15 | import java.util.Objects; | ||
16 | import java.util.Optional; | ||
17 | import java.util.Set; | ||
18 | import java.util.stream.Collectors; | ||
19 | import java.util.stream.Stream; | ||
20 | |||
21 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | ||
22 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactory; | ||
23 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
24 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
25 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
26 | import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement; | ||
27 | import tools.refinery.viatra.runtime.matchers.psystem.annotations.PAnnotation; | ||
28 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
29 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
30 | |||
31 | /** | ||
32 | * Default implementation of PQuery. | ||
33 | * | ||
34 | * @author Bergmann Gabor | ||
35 | */ | ||
36 | public abstract class BasePQuery implements PQuery { | ||
37 | |||
38 | protected PQueryStatus status = PQueryStatus.UNINITIALIZED; | ||
39 | /** | ||
40 | * @since 2.0 | ||
41 | */ | ||
42 | protected final PVisibility visibility; | ||
43 | protected List<PProblem> pProblems = new ArrayList<PProblem>(); | ||
44 | private List<PAnnotation> annotations = new ArrayList<PAnnotation>(); | ||
45 | private QueryEvaluationHint evaluationHints = new QueryEvaluationHint(null, (IQueryBackendFactory)null); | ||
46 | PDisjunction canonicalDisjunction; | ||
47 | private List<String> parameterNames = null; // Lazy initialization | ||
48 | |||
49 | /** For traceability only. */ | ||
50 | private List<Object> wrappingQuerySpecifications = new ArrayList<Object>(1); | ||
51 | |||
52 | @Override | ||
53 | public Integer getPositionOfParameter(String parameterName) { | ||
54 | ensureInitialized(); | ||
55 | int index = getParameterNames().indexOf(parameterName); | ||
56 | return index != -1 ? index : null; | ||
57 | } | ||
58 | |||
59 | protected void setStatus(PQueryStatus newStatus) { | ||
60 | this.status = newStatus; | ||
61 | } | ||
62 | |||
63 | protected void addError(PProblem problem) { | ||
64 | status = PQueryStatus.ERROR; | ||
65 | pProblems.add(problem); | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public PQueryStatus getStatus() { | ||
70 | return status; | ||
71 | } | ||
72 | |||
73 | @Override | ||
74 | public List<PProblem> getPProblems() { | ||
75 | return Collections.unmodifiableList(pProblems); | ||
76 | } | ||
77 | |||
78 | @Override | ||
79 | public boolean isMutable() { | ||
80 | return status.equals(PQueryStatus.UNINITIALIZED) || status.equals(PQueryStatus.INITIALIZING); | ||
81 | } | ||
82 | |||
83 | @Override | ||
84 | public void checkMutability() { | ||
85 | Preconditions.checkState(isMutable(), "Cannot edit query definition %s", getFullyQualifiedName()); | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * @since 1.5 | ||
90 | */ | ||
91 | public void setEvaluationHints(QueryEvaluationHint hints) { | ||
92 | checkMutability(); | ||
93 | this.evaluationHints = hints; | ||
94 | } | ||
95 | |||
96 | @Override | ||
97 | public QueryEvaluationHint getEvaluationHints() { | ||
98 | ensureInitialized(); | ||
99 | return evaluationHints; | ||
100 | // TODO instead of field, compute something from annotations? | ||
101 | } | ||
102 | |||
103 | protected void addAnnotation(PAnnotation annotation) { | ||
104 | checkMutability(); | ||
105 | annotations.add(annotation); | ||
106 | } | ||
107 | |||
108 | @Override | ||
109 | public List<PAnnotation> getAllAnnotations() { | ||
110 | ensureInitialized(); | ||
111 | return new ArrayList<>(annotations); | ||
112 | } | ||
113 | |||
114 | private Stream<PAnnotation> getAnnotationStreamByName(final String name) { | ||
115 | ensureInitialized(); | ||
116 | return annotations.stream().filter(Objects::nonNull).filter(annotation -> Objects.equals(name, annotation.getName())); | ||
117 | } | ||
118 | |||
119 | @Override | ||
120 | public List<PAnnotation> getAnnotationsByName(final String annotationName) { | ||
121 | return getAnnotationStreamByName(annotationName).collect(Collectors.toList()); | ||
122 | } | ||
123 | |||
124 | @Override | ||
125 | public Optional<PAnnotation> getFirstAnnotationByName(String annotationName) { | ||
126 | return getAnnotationStreamByName(annotationName).findFirst(); | ||
127 | } | ||
128 | |||
129 | @Override | ||
130 | public List<String> getParameterNames() { | ||
131 | ensureInitialized(); | ||
132 | if (parameterNames == null) { | ||
133 | parameterNames = getParameters().stream().map(PParameter::getName).collect(Collectors.toList()); | ||
134 | } | ||
135 | return parameterNames; | ||
136 | } | ||
137 | |||
138 | @Override | ||
139 | public Set<PQuery> getDirectReferredQueries() { | ||
140 | ensureInitialized(); | ||
141 | return canonicalDisjunction.getDirectReferredQueries(); | ||
142 | } | ||
143 | |||
144 | @Override | ||
145 | public Set<PQuery> getAllReferredQueries() { | ||
146 | ensureInitialized(); | ||
147 | return canonicalDisjunction.getAllReferredQueries(); | ||
148 | } | ||
149 | |||
150 | |||
151 | @Override | ||
152 | public List<Object> publishedAs() { | ||
153 | return wrappingQuerySpecifications; | ||
154 | } | ||
155 | |||
156 | @Override | ||
157 | public Set<TypeJudgement> getTypeGuarantees() { | ||
158 | ensureInitialized(); | ||
159 | Set<TypeJudgement> result = new HashSet<TypeJudgement>(); | ||
160 | |||
161 | List<PParameter> parameters = getParameters(); | ||
162 | for (int i=0; i<parameters.size(); ++i) { | ||
163 | PParameter parameter = parameters.get(i); | ||
164 | IInputKey declaredUnaryType = parameter.getDeclaredUnaryType(); | ||
165 | if (declaredUnaryType != null) { | ||
166 | result.add(new TypeJudgement(declaredUnaryType, Tuples.staticArityFlatTupleOf(i))); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | return result; | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * @since 2.0 | ||
175 | */ | ||
176 | public BasePQuery(PVisibility visibility) { | ||
177 | super(); | ||
178 | this.visibility = visibility; | ||
179 | } | ||
180 | |||
181 | @Override | ||
182 | public PDisjunction getDisjunctBodies() { | ||
183 | ensureInitialized(); | ||
184 | Preconditions.checkState(!status.equals(PQueryStatus.ERROR), "Query %s contains errors.", getFullyQualifiedName()); | ||
185 | return canonicalDisjunction; | ||
186 | } | ||
187 | |||
188 | @Override | ||
189 | public final void ensureInitialized() { | ||
190 | try { | ||
191 | if (status.equals(PQueryStatus.UNINITIALIZED)) { | ||
192 | setStatus(PQueryStatus.INITIALIZING); | ||
193 | setBodies(doGetContainedBodies()); | ||
194 | setStatus(PQueryStatus.OK); | ||
195 | } | ||
196 | } catch (QueryInitializationException e) { | ||
197 | addError(new PProblem(e, e.getShortMessage())); | ||
198 | throw e; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | protected final void setBodies(Set<PBody> bodies) { | ||
203 | canonicalDisjunction = new PDisjunction(this, bodies); | ||
204 | for (PBody body : canonicalDisjunction.getBodies()) { | ||
205 | body.setStatus(null); | ||
206 | } | ||
207 | setStatus(PQueryStatus.OK); | ||
208 | } | ||
209 | |||
210 | /** | ||
211 | * Creates and returns the bodies of the query. If recalled again, a new instance is created. | ||
212 | * | ||
213 | * @return | ||
214 | * @throws ViatraQueryRuntimeException | ||
215 | */ | ||
216 | protected abstract Set<PBody> doGetContainedBodies(); | ||
217 | |||
218 | @Override | ||
219 | public String toString() { | ||
220 | return String.format("PQuery<%s>=%s", getFullyQualifiedName(), super.toString()); | ||
221 | } | ||
222 | |||
223 | /** | ||
224 | * @since 2.0 | ||
225 | */ | ||
226 | @Override | ||
227 | public PVisibility getVisibility() { | ||
228 | return visibility; | ||
229 | } | ||
230 | |||
231 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PDisjunction.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PDisjunction.java new file mode 100644 index 00000000..eae4eacf --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PDisjunction.java | |||
@@ -0,0 +1,104 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.queries; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.LinkedHashSet; | ||
13 | import java.util.Set; | ||
14 | import java.util.stream.Collectors; | ||
15 | |||
16 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
17 | |||
18 | /** | ||
19 | * | ||
20 | * A disjunction is a set of bodies representing separate conditions. A {@link PQuery} has a single, canonical | ||
21 | * PDisjunction, that can be replaced using rewriter | ||
22 | * | ||
23 | * @author Zoltan Ujhelyi | ||
24 | * | ||
25 | */ | ||
26 | public class PDisjunction { | ||
27 | |||
28 | private Set<PBody> bodies; | ||
29 | private PQuery query; | ||
30 | |||
31 | public PDisjunction(Set<PBody> bodies) { | ||
32 | this(bodies.iterator().next().getPattern(), bodies); | ||
33 | } | ||
34 | |||
35 | public PDisjunction(PQuery query, Set<PBody> bodies) { | ||
36 | super(); | ||
37 | this.query = query; | ||
38 | this.bodies = Collections.unmodifiableSet(new LinkedHashSet<>(bodies)); | ||
39 | this.bodies.forEach(body -> body.setContainerDisjunction(this)); | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * Returns an immutable set of bodies that consists of this disjunction | ||
44 | * | ||
45 | * @return the bodies | ||
46 | */ | ||
47 | public Set<PBody> getBodies() { | ||
48 | return bodies; | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * Returns the corresponding query specification. May be null if not set. | ||
53 | */ | ||
54 | public PQuery getQuery() { | ||
55 | return query; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * Returns all queries directly referred in the constraints. They are all required to evaluate this query | ||
60 | * | ||
61 | * @return a non-null, but possibly empty list of query definitions | ||
62 | */ | ||
63 | public Set<PQuery> getDirectReferredQueries() { | ||
64 | return this.getBodies().stream(). | ||
65 | flatMap(PQueries.directlyReferencedQueriesFunction()). // flatten stream of streams | ||
66 | collect(Collectors.toCollection(LinkedHashSet::new)); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * Returns all queries required to evaluate this query (transitively). | ||
71 | * | ||
72 | * @return a non-null, but possibly empty list of query definitions | ||
73 | */ | ||
74 | public Set<PQuery> getAllReferredQueries() { | ||
75 | Set<PQuery> processedQueries = new LinkedHashSet<>(); | ||
76 | processedQueries.add(this.getQuery()); | ||
77 | Set<PQuery> foundQueries = getDirectReferredQueries(); | ||
78 | Set<PQuery> newQueries = new LinkedHashSet<>(foundQueries); | ||
79 | |||
80 | while(!processedQueries.containsAll(newQueries)) { | ||
81 | PQuery query = newQueries.iterator().next(); | ||
82 | processedQueries.add(query); | ||
83 | newQueries.remove(query); | ||
84 | Set<PQuery> referred = query.getDirectReferredQueries(); | ||
85 | referred.removeAll(processedQueries); | ||
86 | foundQueries.addAll(referred); | ||
87 | newQueries.addAll(referred); | ||
88 | } | ||
89 | return foundQueries; | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * Decides whether a disjunction is mutable. A disjunction is mutable if all its contained bodies are mutable. | ||
94 | * | ||
95 | */ | ||
96 | public boolean isMutable() { | ||
97 | for (PBody body : bodies) { | ||
98 | if (!body.isMutable()) { | ||
99 | return false; | ||
100 | } | ||
101 | } | ||
102 | return true; | ||
103 | } | ||
104 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PParameter.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PParameter.java new file mode 100644 index 00000000..07165aa2 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PParameter.java | |||
@@ -0,0 +1,105 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.queries; | ||
10 | |||
11 | import java.util.Objects; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
14 | |||
15 | /** | ||
16 | * A descriptor for declared PQuery parameters. A parameter has a name, a declared type and a direction constraint | ||
17 | * | ||
18 | * @author Zoltan Ujhelyi | ||
19 | * | ||
20 | */ | ||
21 | public class PParameter { | ||
22 | |||
23 | private final String name; | ||
24 | private final String typeName; | ||
25 | private final IInputKey declaredUnaryType; | ||
26 | private final PParameterDirection direction; | ||
27 | |||
28 | public PParameter(String name) { | ||
29 | this(name, (String) null); | ||
30 | } | ||
31 | |||
32 | public PParameter(String name, String typeName) { | ||
33 | this(name, typeName, (IInputKey) null); | ||
34 | } | ||
35 | |||
36 | public PParameter(String name, String typeName, IInputKey declaredUnaryType) { | ||
37 | this(name, typeName, declaredUnaryType, PParameterDirection.INOUT); | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * @since 1.4 | ||
42 | */ | ||
43 | public PParameter(String name, String typeName, IInputKey declaredUnaryType, PParameterDirection direction) { | ||
44 | super(); | ||
45 | this.name = name; | ||
46 | this.typeName = typeName; | ||
47 | this.declaredUnaryType = declaredUnaryType; | ||
48 | this.direction = direction; | ||
49 | |||
50 | if (declaredUnaryType != null && declaredUnaryType.getArity() != 1) { | ||
51 | throw new IllegalArgumentException( | ||
52 | "PParameter declared type must be unary instead of " + declaredUnaryType.getPrettyPrintableName()); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * @return the direction | ||
58 | * @since 1.4 | ||
59 | */ | ||
60 | public PParameterDirection getDirection() { | ||
61 | return direction; | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * @return the name of the parameter | ||
66 | */ | ||
67 | public String getName() { | ||
68 | return name; | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * Returns a textual representation of the declared type of the parameter | ||
73 | * | ||
74 | * @return the type description, or null if not available | ||
75 | */ | ||
76 | public String getTypeName() { | ||
77 | return typeName; | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * Yield an {@link IInputKey} representation of the type declared for this parameter. | ||
82 | * | ||
83 | * @return the unary type that was declared on this parameter in the query header, or null if not available | ||
84 | */ | ||
85 | public IInputKey getDeclaredUnaryType() { | ||
86 | return declaredUnaryType; | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public boolean equals(Object obj) { | ||
91 | if (obj instanceof PParameter) { | ||
92 | return Objects.equals(name, ((PParameter) obj).name) | ||
93 | && Objects.equals(typeName, ((PParameter) obj).typeName) | ||
94 | && Objects.equals(declaredUnaryType, ((PParameter) obj).declaredUnaryType) | ||
95 | && Objects.equals(direction, ((PParameter) obj).direction); | ||
96 | } | ||
97 | return false; | ||
98 | } | ||
99 | |||
100 | @Override | ||
101 | public int hashCode() { | ||
102 | return Objects.hash(name, typeName, declaredUnaryType); | ||
103 | } | ||
104 | |||
105 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PParameterDirection.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PParameterDirection.java new file mode 100644 index 00000000..c94d4797 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PParameterDirection.java | |||
@@ -0,0 +1,35 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Grill Balázs, IncQueryLabs | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem.queries; | ||
10 | |||
11 | /** | ||
12 | * Values of this enum describe a constraint to the calling of patterns regarding its parameters. | ||
13 | * | ||
14 | * @author Grill Balázs | ||
15 | * @since 1.4 | ||
16 | * | ||
17 | */ | ||
18 | public enum PParameterDirection { | ||
19 | |||
20 | /** | ||
21 | * Default value, no additional constraint is applied | ||
22 | */ | ||
23 | INOUT, | ||
24 | |||
25 | /** | ||
26 | * The parameters marked with this constraints shall be set to a value before calling the pattern | ||
27 | */ | ||
28 | IN, | ||
29 | |||
30 | /** | ||
31 | * The parameters marked with this constraints shall not be set to a value before calling the pattern | ||
32 | */ | ||
33 | OUT | ||
34 | |||
35 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PProblem.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PProblem.java new file mode 100644 index 00000000..1fe4f541 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PProblem.java | |||
@@ -0,0 +1,68 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.queries; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.planning.QueryProcessingException; | ||
12 | |||
13 | /** | ||
14 | * Represents an error that was detected while the {@link PQuery} object was built from a source. | ||
15 | * @author Bergmann Gabor | ||
16 | * | ||
17 | */ | ||
18 | public class PProblem { | ||
19 | |||
20 | private final String shortMessage; | ||
21 | private final String location; | ||
22 | private final Exception exception; | ||
23 | |||
24 | public PProblem(String shortMessage) { | ||
25 | this(null, shortMessage, null, null); | ||
26 | } | ||
27 | /** | ||
28 | * @since 2.0 | ||
29 | */ | ||
30 | public PProblem(String shortMessage, Integer line, Integer column) { | ||
31 | this(null, shortMessage, line, column); | ||
32 | } | ||
33 | public PProblem(QueryProcessingException exception) { | ||
34 | this(exception, exception.getShortMessage(), null, null); | ||
35 | } | ||
36 | public PProblem(Exception exception, String shortMessage) { | ||
37 | this(exception, shortMessage, null, null); | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * @since 2.0 | ||
42 | */ | ||
43 | public PProblem(Exception exception, String shortMessage, Integer line, Integer column) { | ||
44 | this.shortMessage = shortMessage; | ||
45 | this.exception = exception; | ||
46 | if (line == null) { | ||
47 | location = "Unspecified location"; | ||
48 | } else if (column == null) { | ||
49 | location = String.format("Line %d", line); | ||
50 | } else { | ||
51 | location = String.format("Line %d Column %d", line, column); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | public String getShortMessage() { | ||
56 | return shortMessage; | ||
57 | } | ||
58 | public Exception getException() { | ||
59 | return exception; | ||
60 | } | ||
61 | /** | ||
62 | * @since 2.0 | ||
63 | */ | ||
64 | public String getLocation() { | ||
65 | return location; | ||
66 | } | ||
67 | |||
68 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PQueries.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PQueries.java new file mode 100644 index 00000000..56f8ca76 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PQueries.java | |||
@@ -0,0 +1,110 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.queries; | ||
10 | |||
11 | import java.util.HashSet; | ||
12 | import java.util.Set; | ||
13 | import java.util.function.Function; | ||
14 | import java.util.function.Predicate; | ||
15 | import java.util.stream.Stream; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.IMultiQueryReference; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.ITypeConstraint; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.PTraceable; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.TypeConstraint; | ||
23 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery.PQueryStatus; | ||
24 | |||
25 | /** | ||
26 | * Utility class for using PQueries in functional/streaming collection operations effectively | ||
27 | * | ||
28 | * @author Zoltan Ujhelyi | ||
29 | * | ||
30 | */ | ||
31 | public final class PQueries { | ||
32 | |||
33 | /** | ||
34 | * Hidden constructor for utility class | ||
35 | */ | ||
36 | private PQueries() { | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * Predicate checking for the status of selected queries | ||
41 | * | ||
42 | */ | ||
43 | public static Predicate<PQuery> queryStatusPredicate(final PQueryStatus status) { | ||
44 | return query -> query.getStatus().equals(status); | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * Enumerates referred queries (without duplicates) for the given body | ||
49 | */ | ||
50 | public static Function<PBody, Stream<PQuery>> directlyReferencedQueriesFunction() { | ||
51 | return body -> (body.getConstraintsOfType(IMultiQueryReference.class).stream() | ||
52 | .flatMap(e -> e.getReferredQueries().stream()).distinct()); | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * Enumerates directly referred extensional relations (without duplicates) in the canonical form of the given query | ||
57 | * | ||
58 | * @param enumerablesOnly | ||
59 | * only enumerable type constraints are considered | ||
60 | * @since 2.0 | ||
61 | */ | ||
62 | public static Stream<IInputKey> directlyRequiredTypesOfQuery(PQuery query, boolean enumerablesOnly) { | ||
63 | return directlyRequiredTypesOfDisjunction(query.getDisjunctBodies(), enumerablesOnly); | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * Enumerates directly referred extensional relations (without duplicates) for the given formulation of a query. | ||
68 | * | ||
69 | * @param enumerablesOnly | ||
70 | * only enumerable type constraints are considered | ||
71 | * @since 2.0 | ||
72 | */ | ||
73 | public static Stream<IInputKey> directlyRequiredTypesOfDisjunction(PDisjunction disjunctBodies, | ||
74 | boolean enumerablesOnly) { | ||
75 | Class<? extends ITypeConstraint> filterClass = enumerablesOnly ? TypeConstraint.class : ITypeConstraint.class; | ||
76 | return disjunctBodies.getBodies().stream().flatMap(body -> body.getConstraintsOfType(filterClass).stream()) | ||
77 | .map(constraint -> constraint.getEquivalentJudgement().getInputKey()).distinct(); | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * @since 1.4 | ||
82 | */ | ||
83 | public static Predicate<PParameter> parameterDirectionPredicate(final PParameterDirection direction) { | ||
84 | return input -> input.getDirection() == direction; | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * Returns all {@link PTraceable}s contained in the given {@link PQuery}: itself, its bodies and their constraints. | ||
89 | * | ||
90 | * @since 1.6 | ||
91 | */ | ||
92 | public static Set<PTraceable> getTraceables(PQuery query) { | ||
93 | final Set<PTraceable> traceables = new HashSet<>(); | ||
94 | traceables.add(query); | ||
95 | query.getDisjunctBodies().getBodies().forEach(body -> { | ||
96 | traceables.add(body); | ||
97 | body.getConstraints().forEach(traceables::add); | ||
98 | }); | ||
99 | return traceables; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * Calculates the simple name related from a given qualified name by finding the part after the last '.' character. | ||
104 | * | ||
105 | * @since 2.0 | ||
106 | */ | ||
107 | public static String calculateSimpleName(String qualifiedName) { | ||
108 | return qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1); | ||
109 | } | ||
110 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PQuery.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PQuery.java new file mode 100644 index 00000000..a909c650 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PQuery.java | |||
@@ -0,0 +1,154 @@ | |||
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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.queries; | ||
10 | |||
11 | import java.util.List; | ||
12 | import java.util.Set; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | ||
15 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackend; | ||
16 | import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendHintProvider; | ||
17 | import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.PTraceable; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement; | ||
21 | |||
22 | /** | ||
23 | * Internal representation of a query / graph pattern (using a constraint system formalism), | ||
24 | * to be interpreted by a query evaluator ({@link IQueryBackend}). | ||
25 | * End-users of VIATRA Query should access a query as an IQuerySpecification instead. | ||
26 | * | ||
27 | * <p> | ||
28 | * PQuerys are definitions of queries usable inside pattern descriptions. Such description always has (a non-null) name. The query | ||
29 | * itself is defined as a (non-empty) set of {@link PBody} instances, the result is the disjunction of the single | ||
30 | * {@link PBody} instances. </p> | ||
31 | * <p> | ||
32 | * A PQuery might be constructed from erroneous patterns or might be uninitialized - this is represented by its status. | ||
33 | * | ||
34 | * @author Zoltan Ujhelyi | ||
35 | * @since 0.8.0 | ||
36 | * @noimplement This interface is not intended to be implemented by clients. Use {@link BasePQuery} as a base class instead. | ||
37 | */ | ||
38 | public interface PQuery extends PQueryHeader, PTraceable { | ||
39 | |||
40 | // TODO rewritten as / rewritten from traceability to PDisjunction? | ||
41 | |||
42 | /** | ||
43 | * @author Zoltan Ujhelyi | ||
44 | * | ||
45 | */ | ||
46 | public enum PQueryStatus { | ||
47 | /** | ||
48 | * Marks that the query definition is not initialized | ||
49 | */ | ||
50 | UNINITIALIZED, | ||
51 | /** | ||
52 | * Marks that the query definition is being initialized | ||
53 | * @since 1.4 | ||
54 | */ | ||
55 | INITIALIZING, | ||
56 | /** | ||
57 | * The query definition was successfully initialized | ||
58 | */ | ||
59 | OK, | ||
60 | /** | ||
61 | * The query definition was initialized, but some issues were present | ||
62 | */ | ||
63 | WARNING, | ||
64 | /** | ||
65 | * The query definition was not successfully initialized because of an error | ||
66 | */ | ||
67 | ERROR | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * Returns all bodies associated with the query in their canonical form. If called multiple times, the same set with | ||
72 | * the same contents will be returned. | ||
73 | * | ||
74 | */ | ||
75 | PDisjunction getDisjunctBodies(); | ||
76 | |||
77 | /** | ||
78 | * Returns all queries directly referred in the constraints. They are all required to evaluate this query | ||
79 | * | ||
80 | * @return a non-null, but possibly empty list of query definitions | ||
81 | */ | ||
82 | Set<PQuery> getDirectReferredQueries(); | ||
83 | |||
84 | /** | ||
85 | * Returns all queries required to evaluate this query (transitively). | ||
86 | * | ||
87 | * @return a non-null, but possibly empty list of query definitions | ||
88 | */ | ||
89 | Set<PQuery> getAllReferredQueries(); | ||
90 | |||
91 | /** | ||
92 | * Returns the initialization status of the definition | ||
93 | * | ||
94 | */ | ||
95 | PQueryStatus getStatus(); | ||
96 | |||
97 | /** | ||
98 | * Returns a list describing the problems that were found in this query. | ||
99 | * | ||
100 | * <p> TODO: formulate invariant connecting {@link #getPProblems()} and {@link #getStatus()}. | ||
101 | * | ||
102 | * @return a non-null, but possibly empty list of problems | ||
103 | */ | ||
104 | List<PProblem> getPProblems(); | ||
105 | |||
106 | /** | ||
107 | * Before a modification operation is executed, a mutability check is performed (via the {@link #getStatus()} | ||
108 | * implementation, and in case of problems an {@link IllegalStateException} is thrown. | ||
109 | */ | ||
110 | void checkMutability(); | ||
111 | |||
112 | /** | ||
113 | * An option to check mutability of the query. It can be used to avoid getting an {@link IllegalStateException} by | ||
114 | * the execution of {@link #checkMutability()}. | ||
115 | * | ||
116 | * @return true if the query specification is still editable | ||
117 | */ | ||
118 | boolean isMutable(); | ||
119 | |||
120 | /** | ||
121 | * Optional hints regarding the query evaluation strategy, to be interpreted by the query engine. | ||
122 | * <p> To ensure the possibility of external overrides, | ||
123 | * the evaluation engine should not directly consult this field, | ||
124 | * but use an {@link IQueryBackendHintProvider} instead. | ||
125 | */ | ||
126 | public QueryEvaluationHint getEvaluationHints(); | ||
127 | |||
128 | |||
129 | /** | ||
130 | * Type information, expressed on query parameters, that all matches of the query are guaranteed to respect. | ||
131 | * <p> At the very minimum, this should include the declared types of the parameters. | ||
132 | * <p> The type judgement tuples shall contain the <i>parameter index</i>, NOT the {@link PParameter} object. | ||
133 | * | ||
134 | * @return a non-null set of type judgements that the query guarantees for its matches | ||
135 | */ | ||
136 | public Set<TypeJudgement> getTypeGuarantees(); | ||
137 | |||
138 | /** | ||
139 | * If the query definition is uninitialized, initializes it. | ||
140 | * @throws ViatraQueryRuntimeException if initialization of query specification fails | ||
141 | */ | ||
142 | public abstract void ensureInitialized(); | ||
143 | |||
144 | /** | ||
145 | * Returns the end-user query specification API objects that wrap this query. | ||
146 | * | ||
147 | * <p> Intended for traceability and debug purposes, not part of normal operation. | ||
148 | * Returned list is intended to be appended during query specification construction time. | ||
149 | * | ||
150 | * @return a non-null, but possibly empty list of query specification objects; | ||
151 | */ | ||
152 | List<Object> publishedAs(); | ||
153 | |||
154 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PQueryHeader.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PQueryHeader.java new file mode 100644 index 00000000..f3671934 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PQueryHeader.java | |||
@@ -0,0 +1,101 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.queries; | ||
10 | |||
11 | import java.util.List; | ||
12 | import java.util.Optional; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.psystem.annotations.PAnnotation; | ||
15 | |||
16 | /** | ||
17 | * Represents header information (metainfo) about a query. | ||
18 | * <p> To be implemented both by IQuerySpecifications intended for end users, | ||
19 | * and the internal query representation {@link PQuery}. | ||
20 | * | ||
21 | * | ||
22 | * @author Bergmann Gabor | ||
23 | * @since 0.9 | ||
24 | */ | ||
25 | public interface PQueryHeader { | ||
26 | |||
27 | /** | ||
28 | * Identifies the pattern for which matchers can be instantiated. | ||
29 | */ | ||
30 | public String getFullyQualifiedName(); | ||
31 | |||
32 | /** | ||
33 | * Return the list of parameter names | ||
34 | * | ||
35 | * @return a non-null, but possibly empty list of parameter names | ||
36 | */ | ||
37 | public List<String> getParameterNames(); | ||
38 | |||
39 | /** | ||
40 | * Returns a list of parameter descriptions | ||
41 | * | ||
42 | * @return a non-null, but possibly empty list of parameter descriptions | ||
43 | */ | ||
44 | public List<PParameter> getParameters(); | ||
45 | |||
46 | /** | ||
47 | * Returns the index of a named parameter | ||
48 | * | ||
49 | * @param parameterName | ||
50 | * @return the index, or null of no such parameter is available | ||
51 | */ | ||
52 | public Integer getPositionOfParameter(String parameterName); | ||
53 | |||
54 | /** | ||
55 | * Returns a parameter by name if exists | ||
56 | * @since 2.1 | ||
57 | */ | ||
58 | default Optional<PParameter> getParameter(String parameterName) { | ||
59 | return Optional.ofNullable(getPositionOfParameter(parameterName)) | ||
60 | .map(getParameters()::get); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * Returns the list of annotations specified for this query | ||
65 | * | ||
66 | * @return a non-null, but possibly empty list of annotations | ||
67 | */ | ||
68 | public List<PAnnotation> getAllAnnotations(); | ||
69 | |||
70 | /** | ||
71 | * Returns the list of annotations with a specified name | ||
72 | * | ||
73 | * @param annotationName | ||
74 | * @return a non-null, but possibly empty list of annotations | ||
75 | */ | ||
76 | public List<PAnnotation> getAnnotationsByName(String annotationName); | ||
77 | |||
78 | /** | ||
79 | * Returns the first annotation with a specified name | ||
80 | * | ||
81 | * @since 2.0 | ||
82 | */ | ||
83 | public Optional<PAnnotation> getFirstAnnotationByName(String annotationName); | ||
84 | |||
85 | /** | ||
86 | * Returns the visibility information about the query. | ||
87 | * @since 2.0 | ||
88 | */ | ||
89 | public PVisibility getVisibility(); | ||
90 | |||
91 | /** | ||
92 | * Returns the non-qualified name of the query. By default this means returning the qualified name after the last | ||
93 | * '.' character. | ||
94 | * | ||
95 | * @since 2.0 | ||
96 | */ | ||
97 | public default String getSimpleName() { | ||
98 | return PQueries.calculateSimpleName(getFullyQualifiedName()); | ||
99 | } | ||
100 | |||
101 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PVisibility.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PVisibility.java new file mode 100644 index 00000000..7cb312bd --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/PVisibility.java | |||
@@ -0,0 +1,37 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Zoltan Ujhelyi, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.queries; | ||
10 | |||
11 | /** | ||
12 | * @author Zoltan Ujhelyi | ||
13 | * @since 2.0 | ||
14 | * | ||
15 | */ | ||
16 | public enum PVisibility { | ||
17 | |||
18 | /** | ||
19 | * A public (default) visibility means a pattern can be called at any time. | ||
20 | */ | ||
21 | PUBLIC, | ||
22 | /** | ||
23 | * A private query is not expected to be called directly, only by a different query matcher. | ||
24 | */ | ||
25 | PRIVATE, | ||
26 | /** | ||
27 | * A query that is only used inside a single caller query and is not visible outside its container query. Such | ||
28 | * patterns must also fulfill the following additional constraints: | ||
29 | * | ||
30 | * <ul> | ||
31 | * <li>An embedded query must have only a single body.</li> | ||
32 | * <li>An embedded query must not be recursice.</li> | ||
33 | * </ul> | ||
34 | */ | ||
35 | EMBEDDED | ||
36 | |||
37 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/QueryInitializationException.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/QueryInitializationException.java new file mode 100644 index 00000000..470d7287 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/queries/QueryInitializationException.java | |||
@@ -0,0 +1,35 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.queries; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.planning.QueryProcessingException; | ||
12 | |||
13 | /** | ||
14 | * Represent an exception that occurred while initializing the specification of a query. | ||
15 | * @author Bergmann Gabor | ||
16 | * @since 0.9 | ||
17 | * | ||
18 | */ | ||
19 | public class QueryInitializationException extends QueryProcessingException { | ||
20 | |||
21 | public QueryInitializationException(String message, String[] context, String shortMessage, Object patternDescription, | ||
22 | Throwable cause) { | ||
23 | super(message, context, shortMessage, patternDescription, cause); | ||
24 | } | ||
25 | |||
26 | public QueryInitializationException(String message, String[] context, String shortMessage, Object patternDescription) { | ||
27 | super(message, context, shortMessage, patternDescription); | ||
28 | } | ||
29 | |||
30 | private static final long serialVersionUID = 9106033062252951489L; | ||
31 | |||
32 | |||
33 | |||
34 | |||
35 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/AbstractRewriterTraceSource.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/AbstractRewriterTraceSource.java new file mode 100644 index 00000000..276b2b42 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/AbstractRewriterTraceSource.java | |||
@@ -0,0 +1,53 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Grill Balázs, IncQueryLabs | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import java.util.Objects; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.matchers.psystem.PConstraint; | ||
14 | import tools.refinery.viatra.runtime.matchers.psystem.PTraceable; | ||
15 | |||
16 | /** | ||
17 | * @since 1.6 | ||
18 | * | ||
19 | */ | ||
20 | public class AbstractRewriterTraceSource { | ||
21 | |||
22 | private IRewriterTraceCollector traceCollector = NopTraceCollector.INSTANCE; | ||
23 | |||
24 | public void setTraceCollector(IRewriterTraceCollector traceCollector) { | ||
25 | this.traceCollector = Objects.requireNonNull(traceCollector); | ||
26 | } | ||
27 | |||
28 | public IPTraceableTraceProvider getTraces() { | ||
29 | return traceCollector; | ||
30 | } | ||
31 | |||
32 | protected IRewriterTraceCollector getTraceCollector() { | ||
33 | return traceCollector; | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * Mark the given derivative to be originated from the given original constraint. | ||
38 | * @since 1.6 | ||
39 | */ | ||
40 | protected void addTrace(PTraceable original, PTraceable derivative){ | ||
41 | traceCollector.addTrace(original, derivative); | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * Indicate that the given derivative is removed from the resulting query, thus its trace | ||
46 | * information should be removed also. | ||
47 | * @since 1.6 | ||
48 | */ | ||
49 | protected void derivativeRemoved(PConstraint derivative, IDerivativeModificationReason reason){ | ||
50 | traceCollector.derivativeRemoved(derivative, reason); | ||
51 | } | ||
52 | |||
53 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/ConstraintRemovalReason.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/ConstraintRemovalReason.java new file mode 100644 index 00000000..237a762d --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/ConstraintRemovalReason.java | |||
@@ -0,0 +1,23 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Grill Balázs, IncQueryLabs | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | /** | ||
12 | * Common reasons for removing constraint through rewriters | ||
13 | * | ||
14 | * @noreference This enum is not intended to be referenced by clients. | ||
15 | */ | ||
16 | public enum ConstraintRemovalReason implements IDerivativeModificationReason { | ||
17 | |||
18 | MOOT_EQUALITY, | ||
19 | WEAK_INEQUALITY_SELF_LOOP, | ||
20 | TYPE_SUBSUMED, | ||
21 | DUPLICATE | ||
22 | |||
23 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/DefaultFlattenCallPredicate.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/DefaultFlattenCallPredicate.java new file mode 100644 index 00000000..3b5d7390 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/DefaultFlattenCallPredicate.java | |||
@@ -0,0 +1,23 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Marton Bur, Zoltan Ujhelyi, Akos Horvath, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | ||
11 | |||
12 | /** | ||
13 | * @author Marton Bur | ||
14 | * | ||
15 | */ | ||
16 | public class DefaultFlattenCallPredicate implements IFlattenCallPredicate { | ||
17 | |||
18 | @Override | ||
19 | public boolean shouldFlatten(PositivePatternCall positivePatternCall) { | ||
20 | return true; | ||
21 | } | ||
22 | |||
23 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/FlattenerCopier.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/FlattenerCopier.java new file mode 100644 index 00000000..06b8d372 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/FlattenerCopier.java | |||
@@ -0,0 +1,129 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Marton Bur, Akos Horvath, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import java.util.HashMap; | ||
12 | import java.util.List; | ||
13 | import java.util.Map; | ||
14 | import java.util.Map.Entry; | ||
15 | import java.util.Objects; | ||
16 | import java.util.Set; | ||
17 | import java.util.stream.Collectors; | ||
18 | |||
19 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.PConstraint; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.Equality; | ||
23 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.ExportedParameter; | ||
24 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.ExpressionEvaluation; | ||
25 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | ||
26 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
27 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
28 | |||
29 | /** | ||
30 | * This rewriter class can add new equality constraints to the copied body | ||
31 | * | ||
32 | * @author Marton Bur | ||
33 | * | ||
34 | */ | ||
35 | class FlattenerCopier extends PBodyCopier { | ||
36 | |||
37 | private final Map<PositivePatternCall, CallInformation> calls; | ||
38 | |||
39 | private static class CallInformation { | ||
40 | final PBody body; | ||
41 | final Map<PVariable, PVariable> variableMapping; | ||
42 | |||
43 | private CallInformation(PBody body) { | ||
44 | this.body = body; | ||
45 | this.variableMapping = new HashMap<>(); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | public FlattenerCopier(PQuery query, Map<PositivePatternCall, PBody> callsToFlatten) { | ||
50 | super(query); | ||
51 | this.calls = callsToFlatten.entrySet().stream().collect(Collectors.toMap(Entry::getKey, entry -> new CallInformation(entry.getValue()))); | ||
52 | } | ||
53 | |||
54 | protected void copyVariable(PositivePatternCall contextPatternCall, PVariable variable, String newName) { | ||
55 | PVariable newPVariable = body.getOrCreateVariableByName(newName); | ||
56 | calls.get(contextPatternCall).variableMapping.put(variable, newPVariable); | ||
57 | variableMapping.put(variable, newPVariable); | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * Merge all variables and constraints from the body called through the given pattern call to a target body. If | ||
62 | * multiple bodies are merged into a single one, use the renamer and filter options to avoid collisions. | ||
63 | * | ||
64 | * @param sourceBody | ||
65 | * @param namingTool | ||
66 | * @param filter | ||
67 | */ | ||
68 | public void mergeBody(PositivePatternCall contextPatternCall, IVariableRenamer namingTool, | ||
69 | IConstraintFilter filter) { | ||
70 | |||
71 | PBody sourceBody = calls.get(contextPatternCall).body; | ||
72 | |||
73 | // Copy variables | ||
74 | Set<PVariable> allVariables = sourceBody.getAllVariables(); | ||
75 | for (PVariable pVariable : allVariables) { | ||
76 | if (pVariable.isUnique()) { | ||
77 | copyVariable(contextPatternCall, pVariable, | ||
78 | namingTool.createVariableName(pVariable, sourceBody.getPattern())); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | // Copy constraints which are not filtered | ||
83 | Set<PConstraint> constraints = sourceBody.getConstraints(); | ||
84 | for (PConstraint pConstraint : constraints) { | ||
85 | if (!(pConstraint instanceof ExportedParameter) && !filter.filter(pConstraint)) { | ||
86 | copyConstraint(pConstraint); | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | |||
91 | @Override | ||
92 | protected void copyPositivePatternCallConstraint(PositivePatternCall positivePatternCall) { | ||
93 | |||
94 | if (!calls.containsKey(positivePatternCall)) { | ||
95 | // If the call was not flattened, copy the constraint | ||
96 | super.copyPositivePatternCallConstraint(positivePatternCall); | ||
97 | } else { | ||
98 | PBody calledBody = Objects.requireNonNull(calls.get(positivePatternCall).body); | ||
99 | Preconditions.checkArgument(positivePatternCall.getReferredQuery().equals(calledBody.getPattern())); | ||
100 | |||
101 | List<PVariable> symbolicParameters = calledBody.getSymbolicParameterVariables(); | ||
102 | Object[] elements = positivePatternCall.getVariablesTuple().getElements(); | ||
103 | for (int i = 0; i < elements.length; i++) { | ||
104 | // Create equality constraints between the caller PositivePatternCall and the corresponding body | ||
105 | // parameter variables | ||
106 | createEqualityConstraint((PVariable) elements[i], symbolicParameters.get(i), positivePatternCall); | ||
107 | } | ||
108 | |||
109 | } | ||
110 | } | ||
111 | |||
112 | private void createEqualityConstraint(PVariable pVariable1, PVariable pVariable2, | ||
113 | PositivePatternCall contextPatternCall) { | ||
114 | PVariable who = variableMapping.get(pVariable1); | ||
115 | PVariable withWhom = calls.get(contextPatternCall).variableMapping.get(pVariable2); | ||
116 | addTrace(contextPatternCall, new Equality(body, who, withWhom)); | ||
117 | } | ||
118 | |||
119 | @Override | ||
120 | protected void copyExpressionEvaluationConstraint(final ExpressionEvaluation expressionEvaluation) { | ||
121 | Map<PVariable, PVariable> variableMapping = this.variableMapping.entrySet().stream() | ||
122 | .filter(input -> expressionEvaluation.getPSystem().getAllVariables().contains(input.getKey())) | ||
123 | .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); | ||
124 | |||
125 | PVariable mappedOutputVariable = variableMapping.get(expressionEvaluation.getOutputVariable()); | ||
126 | addTrace(expressionEvaluation, new ExpressionEvaluation(body, new VariableMappingExpressionEvaluatorWrapper(expressionEvaluation.getEvaluator(), variableMapping), mappedOutputVariable, expressionEvaluation.isUnwinding())); | ||
127 | } | ||
128 | |||
129 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IConstraintFilter.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IConstraintFilter.java new file mode 100644 index 00000000..518b9c64 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IConstraintFilter.java | |||
@@ -0,0 +1,48 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Zoltan Ujhelyi, Marton Bur, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.psystem.PConstraint; | ||
12 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.ExportedParameter; | ||
13 | |||
14 | /** | ||
15 | * Helper interface to exclude constraints from PBody copy processes | ||
16 | * | ||
17 | * @author Marton Bur | ||
18 | * | ||
19 | */ | ||
20 | public interface IConstraintFilter { | ||
21 | /** | ||
22 | * Returns true, if the given constraint should be filtered (thus should not be copied) | ||
23 | * | ||
24 | * @param constraint | ||
25 | * to check | ||
26 | * @return true, if the constraint should be filtered | ||
27 | */ | ||
28 | boolean filter(PConstraint constraint); | ||
29 | |||
30 | public static class ExportedParameterFilter implements IConstraintFilter { | ||
31 | |||
32 | @Override | ||
33 | public boolean filter(PConstraint constraint) { | ||
34 | return constraint instanceof ExportedParameter; | ||
35 | } | ||
36 | |||
37 | } | ||
38 | |||
39 | public static class AllowAllFilter implements IConstraintFilter { | ||
40 | |||
41 | @Override | ||
42 | public boolean filter(PConstraint constraint) { | ||
43 | // Nothing is filtered | ||
44 | return false; | ||
45 | } | ||
46 | |||
47 | } | ||
48 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IDerivativeModificationReason.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IDerivativeModificationReason.java new file mode 100644 index 00000000..dbd6a78d --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IDerivativeModificationReason.java | |||
@@ -0,0 +1,19 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Grill Balázs, IncQueryLabs | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | /** | ||
12 | * This is a role indication interface, implementations may provide a reason about | ||
13 | * why a modification is made during PQuery normalization. | ||
14 | * @since 1.6 | ||
15 | * | ||
16 | */ | ||
17 | public interface IDerivativeModificationReason { | ||
18 | |||
19 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IFlattenCallPredicate.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IFlattenCallPredicate.java new file mode 100644 index 00000000..7e224e98 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IFlattenCallPredicate.java | |||
@@ -0,0 +1,50 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Marton Bur, Zoltan Ujhelyi, Akos Horvath, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | ||
12 | |||
13 | |||
14 | /** | ||
15 | * Interface used by the PQueryFlattener to decide which positive pattern calls to flatten | ||
16 | * | ||
17 | * @author Marton Bur | ||
18 | * | ||
19 | */ | ||
20 | public interface IFlattenCallPredicate { | ||
21 | |||
22 | /** | ||
23 | * Decides whether the called query by the pattern call should be flattened into the caller or not. | ||
24 | * | ||
25 | * @param positivePatternCall | ||
26 | * the pattern call | ||
27 | * @return true if the call should be flattened | ||
28 | */ | ||
29 | boolean shouldFlatten(PositivePatternCall positivePatternCall); | ||
30 | |||
31 | /** | ||
32 | * Flattens only if all operand predicates vote for flattening. | ||
33 | * @author Gabor Bergmann | ||
34 | * @since 2.1 | ||
35 | */ | ||
36 | public static class And implements IFlattenCallPredicate { | ||
37 | private IFlattenCallPredicate[] operands; | ||
38 | public And(IFlattenCallPredicate... operands) { | ||
39 | this.operands = operands; | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public boolean shouldFlatten(PositivePatternCall positivePatternCall) { | ||
44 | for (IFlattenCallPredicate operand : operands) { | ||
45 | if (!operand.shouldFlatten(positivePatternCall)) return false; | ||
46 | } | ||
47 | return true; | ||
48 | } | ||
49 | } | ||
50 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IPTraceableTraceProvider.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IPTraceableTraceProvider.java new file mode 100644 index 00000000..84da4d1b --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IPTraceableTraceProvider.java | |||
@@ -0,0 +1,55 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Grill Balázs, IncQueryLabs | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import java.util.stream.Stream; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.matchers.psystem.PTraceable; | ||
14 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
15 | |||
16 | /** | ||
17 | * This interface provides methods to trace the {@link PTraceable}s of a transformed {@link PQuery} produced by | ||
18 | * a {@link PDisjunctionRewriter}. In case the associated rewriter is a composite (a.k.a. {@link PDisjunctionRewriterCacher}), | ||
19 | * this trace provider handles traces end-to-end, hiding all the intermediate transformation steps. | ||
20 | * | ||
21 | * @since 1.6 | ||
22 | * @noimplement This interface is not intended to be implemented by clients. | ||
23 | */ | ||
24 | public interface IPTraceableTraceProvider { | ||
25 | |||
26 | /** | ||
27 | * Find and return the canonical {@link PTraceable}s in the original query which are the sources of the given derivative | ||
28 | * {@link PTraceable} according to the transformation. | ||
29 | * | ||
30 | * @param derivative a {@link PTraceable} which is contained by the {@link PQuery} produced by the associated rewriter | ||
31 | * @since 2.0 | ||
32 | */ | ||
33 | public Stream<PTraceable> getCanonicalTraceables(PTraceable derivative); | ||
34 | |||
35 | /** | ||
36 | * Find and return the {@link PTraceable}s in the rewritten query which are the destinations of the given source | ||
37 | * {@link PTraceable} according to the transformation. | ||
38 | * | ||
39 | * @param source a {@link PTraceable} which is contained by a {@link PQuery} before rewriting | ||
40 | * @since 2.0 | ||
41 | */ | ||
42 | public Stream<PTraceable> getRewrittenTraceables(PTraceable source); | ||
43 | |||
44 | /** | ||
45 | * Returns whether the given traceable element has been removed by every rewriter for a reason. | ||
46 | */ | ||
47 | public boolean isRemoved(PTraceable traceable); | ||
48 | |||
49 | /** | ||
50 | * Returns the reasons for which the traceable element has been removed by the rewriters. | ||
51 | * @return the reasons of removal during rewriting | ||
52 | * @since 2.0 | ||
53 | */ | ||
54 | public Stream<IDerivativeModificationReason> getRemovalReasons(PTraceable traceable); | ||
55 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IRewriterTraceCollector.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IRewriterTraceCollector.java new file mode 100644 index 00000000..70771ea7 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IRewriterTraceCollector.java | |||
@@ -0,0 +1,33 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Grill Balázs, IncQueryLabs | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.psystem.PTraceable; | ||
12 | |||
13 | /** | ||
14 | * This is the internal API of {@link IPTraceableTraceProvider} expected to be used by | ||
15 | * copier and rewriter implementations. | ||
16 | * | ||
17 | * @since 1.6 | ||
18 | * @noreference This interface is not intended to be referenced by clients. | ||
19 | */ | ||
20 | public interface IRewriterTraceCollector extends IPTraceableTraceProvider { | ||
21 | |||
22 | /** | ||
23 | * Mark the given derivative to be originated from the given original constraint. | ||
24 | */ | ||
25 | public void addTrace(PTraceable origin, PTraceable derivative); | ||
26 | |||
27 | /** | ||
28 | * Indicate that the given derivative is removed from the resulting query, thus its trace | ||
29 | * information should be removed also. | ||
30 | */ | ||
31 | public void derivativeRemoved(PTraceable derivative, IDerivativeModificationReason reason); | ||
32 | |||
33 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IVariableRenamer.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IVariableRenamer.java new file mode 100644 index 00000000..ce446e0d --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/IVariableRenamer.java | |||
@@ -0,0 +1,59 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Zoltan Ujhelyi, Marton Bur, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
12 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
13 | |||
14 | /** | ||
15 | * Helper interface to ease the naming of the new variables during flattening | ||
16 | * | ||
17 | * @author Marton Bur | ||
18 | * | ||
19 | */ | ||
20 | public interface IVariableRenamer { | ||
21 | /** | ||
22 | * Creates a variable name based on a given variable and a given query. It only creates a String, doesn't set | ||
23 | * anything. | ||
24 | * | ||
25 | * @param pVariable | ||
26 | * @param query | ||
27 | * @return the new variable name as a String | ||
28 | */ | ||
29 | String createVariableName(PVariable pVariable, PQuery query); | ||
30 | |||
31 | public class SameName implements IVariableRenamer { | ||
32 | @Override | ||
33 | public String createVariableName(PVariable pVariable, PQuery query) { | ||
34 | return pVariable.getName(); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | public class HierarchicalName implements IVariableRenamer { | ||
39 | |||
40 | private int callCount; | ||
41 | |||
42 | public void setCallCount(int callCount) { | ||
43 | this.callCount = callCount; | ||
44 | } | ||
45 | |||
46 | @Override | ||
47 | public String createVariableName(PVariable pVariable, PQuery query) { | ||
48 | // make sure to keep the "_" prefix before anonymous variables | ||
49 | String newVarName = getShortName(query) + "<" + callCount + ">" + "_" + pVariable.getName(); | ||
50 | return pVariable.getName().startsWith("_") ? "_" + newVarName : newVarName ; | ||
51 | } | ||
52 | |||
53 | private String getShortName(PQuery query) { | ||
54 | String fullyQualifiedName = query.getFullyQualifiedName(); | ||
55 | int beginIndex = fullyQualifiedName.lastIndexOf('.') + 1; | ||
56 | return fullyQualifiedName.substring(beginIndex); | ||
57 | } | ||
58 | } | ||
59 | } \ No newline at end of file | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/MappingTraceCollector.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/MappingTraceCollector.java new file mode 100644 index 00000000..7429fc60 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/MappingTraceCollector.java | |||
@@ -0,0 +1,135 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Grill Balázs, IncQueryLabs | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.HashSet; | ||
14 | import java.util.LinkedList; | ||
15 | import java.util.Map; | ||
16 | import java.util.Queue; | ||
17 | import java.util.Set; | ||
18 | import java.util.function.Predicate; | ||
19 | import java.util.stream.Stream; | ||
20 | |||
21 | import tools.refinery.viatra.runtime.matchers.psystem.PTraceable; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
23 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory; | ||
24 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory.MemoryType; | ||
25 | import tools.refinery.viatra.runtime.matchers.util.IMemoryView; | ||
26 | import tools.refinery.viatra.runtime.matchers.util.IMultiLookup; | ||
27 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
28 | |||
29 | /** | ||
30 | * Multimap-based implementation to contain and query traces | ||
31 | * | ||
32 | * @since 1.6 | ||
33 | * | ||
34 | */ | ||
35 | public class MappingTraceCollector implements IRewriterTraceCollector { | ||
36 | |||
37 | /** | ||
38 | * Traces from derivative to original | ||
39 | */ | ||
40 | private final IMultiLookup<PTraceable, PTraceable> traces = CollectionsFactory.createMultiLookup(Object.class, MemoryType.SETS, Object.class); | ||
41 | |||
42 | /** | ||
43 | * Traces from original to derivative | ||
44 | */ | ||
45 | private final IMultiLookup<PTraceable, PTraceable> inverseTraces = CollectionsFactory.createMultiLookup(Object.class, MemoryType.SETS, Object.class); | ||
46 | |||
47 | /** | ||
48 | * Reasons for removing {@link PTraceable}s | ||
49 | */ | ||
50 | private final Map<PTraceable, IDerivativeModificationReason> removals = new HashMap<>(); | ||
51 | |||
52 | /** | ||
53 | * Decides whether {@link PTraceable} is removed | ||
54 | */ | ||
55 | private final Predicate<PTraceable> removed = removals::containsKey; | ||
56 | |||
57 | /** | ||
58 | * @since 2.0 | ||
59 | */ | ||
60 | @Override | ||
61 | public Stream<PTraceable> getCanonicalTraceables(PTraceable derivative) { | ||
62 | return findTraceEnds(derivative, traces).stream(); | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * @since 2.0 | ||
67 | */ | ||
68 | @Override | ||
69 | public Stream<PTraceable> getRewrittenTraceables(PTraceable source) { | ||
70 | return findTraceEnds(source, inverseTraces).stream(); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * Returns the end of trace chains starting from the given {@link PTraceable} along the given trace edges. | ||
75 | */ | ||
76 | private Set<PTraceable> findTraceEnds(PTraceable traceable, IMultiLookup<PTraceable, PTraceable> traceRecords) { | ||
77 | if (traceable instanceof PQuery) { // PQueries are preserved | ||
78 | return Collections.singleton(traceable); | ||
79 | } | ||
80 | Set<PTraceable> visited = new HashSet<>(); | ||
81 | Set<PTraceable> result = new HashSet<>(); | ||
82 | Queue<PTraceable> queue = new LinkedList<>(); | ||
83 | queue.add(traceable); | ||
84 | while(!queue.isEmpty()){ | ||
85 | PTraceable aDerivative = queue.poll(); | ||
86 | // Track visited elements to avoid infinite loop via directed cycles in traces | ||
87 | visited.add(aDerivative); | ||
88 | IMemoryView<PTraceable> nextOrigins = traceRecords.lookup(aDerivative); | ||
89 | if (nextOrigins == null){ | ||
90 | // End of trace chain | ||
91 | result.add(aDerivative); | ||
92 | } else { | ||
93 | // Follow traces | ||
94 | for(PTraceable nextOrigin : nextOrigins){ | ||
95 | if (!visited.contains(nextOrigin)){ | ||
96 | queue.add(nextOrigin); | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | return result; | ||
102 | } | ||
103 | |||
104 | @Override | ||
105 | public void addTrace(PTraceable original, PTraceable derivative){ | ||
106 | traces.addPairOrNop(derivative, original); | ||
107 | inverseTraces.addPairOrNop(original, derivative); | ||
108 | // Even if this element was marked as removed earlier, now we replace it with another constraint! | ||
109 | removals.remove(original); | ||
110 | } | ||
111 | |||
112 | @Override | ||
113 | public void derivativeRemoved(PTraceable derivative, IDerivativeModificationReason reason){ | ||
114 | Preconditions.checkState(!removals.containsKey(derivative), "Traceable %s removed multiple times", derivative); | ||
115 | // XXX the derivative must not be removed from the trace chain, as some rewriters, e.g. the normalizer keeps trace links to deleted elements | ||
116 | if (!inverseTraces.lookupExists(derivative)) { | ||
117 | // If there already exists a trace link, this removal means an update | ||
118 | removals.put(derivative, reason); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | @Override | ||
123 | public boolean isRemoved(PTraceable traceable) { | ||
124 | return getRewrittenTraceables(traceable).allMatch(removed); | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * @since 2.0 | ||
129 | */ | ||
130 | @Override | ||
131 | public Stream<IDerivativeModificationReason> getRemovalReasons(PTraceable traceable) { | ||
132 | return getRewrittenTraceables(traceable).filter(removed).map(removals::get); | ||
133 | } | ||
134 | |||
135 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/NeverFlattenCallPredicate.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/NeverFlattenCallPredicate.java new file mode 100644 index 00000000..96c0b205 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/NeverFlattenCallPredicate.java | |||
@@ -0,0 +1,26 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Grill Balázs, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | ||
12 | |||
13 | /** | ||
14 | * @author Grill Balázs | ||
15 | * @since 1.4 | ||
16 | * | ||
17 | */ | ||
18 | public class NeverFlattenCallPredicate implements IFlattenCallPredicate { | ||
19 | |||
20 | |||
21 | @Override | ||
22 | public boolean shouldFlatten(PositivePatternCall positivePatternCall) { | ||
23 | return false; | ||
24 | } | ||
25 | |||
26 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/NopTraceCollector.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/NopTraceCollector.java new file mode 100644 index 00000000..15cf577e --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/NopTraceCollector.java | |||
@@ -0,0 +1,68 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Grill Balázs, IncQueryLabs | ||
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 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import java.util.stream.Stream; | ||
12 | |||
13 | import tools.refinery.viatra.runtime.matchers.psystem.PTraceable; | ||
14 | |||
15 | /** | ||
16 | * This implementation does not store any traces and scales to NOP for every traceability feature. | ||
17 | * @since 1.6 | ||
18 | * | ||
19 | */ | ||
20 | public class NopTraceCollector implements IRewriterTraceCollector { | ||
21 | |||
22 | public static final IRewriterTraceCollector INSTANCE = new NopTraceCollector(); | ||
23 | |||
24 | private NopTraceCollector() { | ||
25 | // Private constructor to force using the common instance | ||
26 | } | ||
27 | |||
28 | /** | ||
29 | * @since 2.0 | ||
30 | */ | ||
31 | @Override | ||
32 | public Stream<PTraceable> getCanonicalTraceables(PTraceable derivative) { | ||
33 | return Stream.empty(); | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * @since 2.0 | ||
38 | */ | ||
39 | @Override | ||
40 | public Stream<PTraceable> getRewrittenTraceables(PTraceable source) { | ||
41 | return Stream.empty(); | ||
42 | } | ||
43 | |||
44 | |||
45 | @Override | ||
46 | public void addTrace(PTraceable origin, PTraceable derivative) { | ||
47 | // ignored | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public void derivativeRemoved(PTraceable derivative, IDerivativeModificationReason reason) { | ||
52 | // ignored | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public boolean isRemoved(PTraceable traceable) { | ||
57 | return false; | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * @since 2.0 | ||
62 | */ | ||
63 | @Override | ||
64 | public Stream<IDerivativeModificationReason> getRemovalReasons(PTraceable traceable) { | ||
65 | return Stream.empty(); | ||
66 | } | ||
67 | |||
68 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PBodyCopier.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PBodyCopier.java new file mode 100644 index 00000000..e66c4eea --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PBodyCopier.java | |||
@@ -0,0 +1,306 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Marton Bur, Akos Horvath, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.planning.QueryProcessingException; | ||
12 | import tools.refinery.viatra.runtime.matchers.psystem.EnumerablePConstraint; | ||
13 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
14 | import tools.refinery.viatra.runtime.matchers.psystem.PConstraint; | ||
15 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.*; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.*; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IConstraintFilter.AllowAllFilter; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IVariableRenamer.SameName; | ||
22 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
23 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
24 | |||
25 | import java.util.*; | ||
26 | import java.util.stream.Collectors; | ||
27 | |||
28 | /** | ||
29 | * This class can create a new PBody for a PQuery. The result body contains a copy of given variables and constraints. | ||
30 | * | ||
31 | * @author Marton Bur | ||
32 | * | ||
33 | */ | ||
34 | public class PBodyCopier extends AbstractRewriterTraceSource { | ||
35 | |||
36 | /** | ||
37 | * The created body | ||
38 | */ | ||
39 | protected PBody body; | ||
40 | /** | ||
41 | * Mapping between the original and the copied variables | ||
42 | */ | ||
43 | protected Map<PVariable, PVariable> variableMapping = new HashMap<>(); | ||
44 | |||
45 | public Map<PVariable, PVariable> getVariableMapping() { | ||
46 | return variableMapping; | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * @since 1.6 | ||
51 | */ | ||
52 | public PBodyCopier(PBody body, IRewriterTraceCollector traceCollector) { | ||
53 | this.body = new PBody(body.getPattern()); | ||
54 | setTraceCollector(traceCollector); | ||
55 | |||
56 | // do the actual copying | ||
57 | mergeBody(body); | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * @since 1.6 | ||
62 | */ | ||
63 | public PBodyCopier(PQuery query) { | ||
64 | this.body = new PBody(query); | ||
65 | } | ||
66 | |||
67 | public void mergeBody(PBody sourceBody) { | ||
68 | mergeBody(sourceBody, new SameName(), new AllowAllFilter()); | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * Merge all variables and constraints from a source body to a target body. If multiple bodies are merged into a | ||
73 | * single one, use the renamer and filter options to avoid collisions. | ||
74 | */ | ||
75 | public void mergeBody(PBody sourceBody, IVariableRenamer namingTool, IConstraintFilter filter) { | ||
76 | |||
77 | // Copy variables | ||
78 | Set<PVariable> allVariables = sourceBody.getAllVariables(); | ||
79 | for (PVariable pVariable : allVariables) { | ||
80 | if (pVariable.isUnique()) { | ||
81 | copyVariable(pVariable, namingTool.createVariableName(pVariable, sourceBody.getPattern())); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | // Copy exported parameters | ||
86 | this.body.setSymbolicParameters(sourceBody.getSymbolicParameters().stream() | ||
87 | .map(this::copyExportedParameterConstraint).collect(Collectors.toList())); | ||
88 | |||
89 | // Copy constraints which are not filtered | ||
90 | Set<PConstraint> constraints = sourceBody.getConstraints(); | ||
91 | for (PConstraint pConstraint : constraints) { | ||
92 | if (!(pConstraint instanceof ExportedParameter) && !filter.filter(pConstraint)) { | ||
93 | copyConstraint(pConstraint); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | // Add trace between original and copied body | ||
98 | addTrace(sourceBody, body); | ||
99 | } | ||
100 | |||
101 | protected void copyVariable(PVariable variable, String newName) { | ||
102 | PVariable newPVariable = body.getOrCreateVariableByName(newName); | ||
103 | variableMapping.put(variable, newPVariable); | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * Returns the body with the copied variables and constraints. The returned body is still uninitialized. | ||
108 | */ | ||
109 | public PBody getCopiedBody() { | ||
110 | return body; | ||
111 | } | ||
112 | |||
113 | protected void copyConstraint(PConstraint constraint) { | ||
114 | if (constraint instanceof ExportedParameter) { | ||
115 | copyExportedParameterConstraint((ExportedParameter) constraint); | ||
116 | } else if (constraint instanceof Equality) { | ||
117 | copyEqualityConstraint((Equality) constraint); | ||
118 | } else if (constraint instanceof Inequality) { | ||
119 | copyInequalityConstraint((Inequality) constraint); | ||
120 | } else if (constraint instanceof TypeConstraint) { | ||
121 | copyTypeConstraint((TypeConstraint) constraint); | ||
122 | } else if (constraint instanceof TypeFilterConstraint) { | ||
123 | copyTypeFilterConstraint((TypeFilterConstraint) constraint); | ||
124 | } else if (constraint instanceof ConstantValue) { | ||
125 | copyConstantValueConstraint((ConstantValue) constraint); | ||
126 | } else if (constraint instanceof PositivePatternCall) { | ||
127 | copyPositivePatternCallConstraint((PositivePatternCall) constraint); | ||
128 | } else if (constraint instanceof NegativePatternCall) { | ||
129 | copyNegativePatternCallConstraint((NegativePatternCall) constraint); | ||
130 | } else if (constraint instanceof BinaryTransitiveClosure) { | ||
131 | copyBinaryTransitiveClosureConstraint((BinaryTransitiveClosure) constraint); | ||
132 | } else if (constraint instanceof RepresentativeElectionConstraint) { | ||
133 | copyRepresentativeElectionConstraint((RepresentativeElectionConstraint) constraint); | ||
134 | } else if (constraint instanceof RelationEvaluation) { | ||
135 | copyRelationEvaluationConstraint((RelationEvaluation) constraint); | ||
136 | } else if (constraint instanceof BinaryReflexiveTransitiveClosure) { | ||
137 | copyBinaryReflexiveTransitiveClosureConstraint((BinaryReflexiveTransitiveClosure) constraint); | ||
138 | } else if (constraint instanceof PatternMatchCounter) { | ||
139 | copyPatternMatchCounterConstraint((PatternMatchCounter) constraint); | ||
140 | } else if (constraint instanceof AggregatorConstraint) { | ||
141 | copyAggregatorConstraint((AggregatorConstraint) constraint); | ||
142 | } else if (constraint instanceof ExpressionEvaluation) { | ||
143 | copyExpressionEvaluationConstraint((ExpressionEvaluation) constraint); | ||
144 | } else { | ||
145 | throw new QueryProcessingException("Unknown PConstraint {0} encountered while copying PBody", | ||
146 | new String[] { constraint.getClass().getName() }, "Unknown PConstraint", body.getPattern()); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | protected ExportedParameter copyExportedParameterConstraint(ExportedParameter exportedParameter) { | ||
151 | PVariable mappedPVariable = variableMapping.get(exportedParameter.getParameterVariable()); | ||
152 | PParameter parameter = exportedParameter.getPatternParameter(); | ||
153 | ExportedParameter newExportedParameter; | ||
154 | newExportedParameter = new ExportedParameter(body, mappedPVariable, parameter); | ||
155 | body.getSymbolicParameters().add(newExportedParameter); | ||
156 | addTrace(exportedParameter, newExportedParameter); | ||
157 | return newExportedParameter; | ||
158 | } | ||
159 | |||
160 | protected void copyEqualityConstraint(Equality equality) { | ||
161 | PVariable who = equality.getWho(); | ||
162 | PVariable withWhom = equality.getWithWhom(); | ||
163 | addTrace(equality, new Equality(body, variableMapping.get(who), variableMapping.get(withWhom))); | ||
164 | } | ||
165 | |||
166 | protected void copyInequalityConstraint(Inequality inequality) { | ||
167 | PVariable who = inequality.getWho(); | ||
168 | PVariable withWhom = inequality.getWithWhom(); | ||
169 | addTrace(inequality, new Inequality(body, variableMapping.get(who), variableMapping.get(withWhom))); | ||
170 | } | ||
171 | |||
172 | protected void copyTypeConstraint(TypeConstraint typeConstraint) { | ||
173 | PVariable[] mappedVariables = extractMappedVariables(typeConstraint); | ||
174 | Tuple variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables); | ||
175 | addTrace(typeConstraint, new TypeConstraint(body, variablesTuple, typeConstraint.getSupplierKey())); | ||
176 | } | ||
177 | |||
178 | protected void copyTypeFilterConstraint(TypeFilterConstraint typeConstraint) { | ||
179 | PVariable[] mappedVariables = extractMappedVariables(typeConstraint); | ||
180 | Tuple variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables); | ||
181 | addTrace(typeConstraint, new TypeFilterConstraint(body, variablesTuple, typeConstraint.getInputKey())); | ||
182 | } | ||
183 | |||
184 | protected void copyConstantValueConstraint(ConstantValue constantValue) { | ||
185 | PVariable pVariable = (PVariable) constantValue.getVariablesTuple().getElements()[0]; | ||
186 | addTrace(constantValue, | ||
187 | new ConstantValue(body, variableMapping.get(pVariable), constantValue.getSupplierKey())); | ||
188 | } | ||
189 | |||
190 | protected void copyPositivePatternCallConstraint(PositivePatternCall positivePatternCall) { | ||
191 | PVariable[] mappedVariables = extractMappedVariables(positivePatternCall); | ||
192 | Tuple variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables); | ||
193 | addTrace(positivePatternCall, | ||
194 | new PositivePatternCall(body, variablesTuple, positivePatternCall.getReferredQuery())); | ||
195 | } | ||
196 | |||
197 | protected void copyNegativePatternCallConstraint(NegativePatternCall negativePatternCall) { | ||
198 | PVariable[] mappedVariables = extractMappedVariables(negativePatternCall); | ||
199 | Tuple variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables); | ||
200 | addTrace(negativePatternCall, | ||
201 | new NegativePatternCall(body, variablesTuple, negativePatternCall.getReferredQuery())); | ||
202 | } | ||
203 | |||
204 | protected void copyBinaryTransitiveClosureConstraint(BinaryTransitiveClosure binaryTransitiveClosure) { | ||
205 | PVariable[] mappedVariables = extractMappedVariables(binaryTransitiveClosure); | ||
206 | Tuple variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables); | ||
207 | addTrace(binaryTransitiveClosure, | ||
208 | new BinaryTransitiveClosure(body, variablesTuple, binaryTransitiveClosure.getReferredQuery())); | ||
209 | } | ||
210 | |||
211 | protected void copyRepresentativeElectionConstraint(RepresentativeElectionConstraint constraint) { | ||
212 | var mappedVariables = extractMappedVariables(constraint); | ||
213 | var variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables); | ||
214 | addTrace(constraint, new RepresentativeElectionConstraint(body, variablesTuple, constraint.getReferredQuery(), | ||
215 | constraint.getConnectivity())); | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * @since 2.8 | ||
220 | */ | ||
221 | protected void copyRelationEvaluationConstraint(RelationEvaluation relationEvaluation) { | ||
222 | PVariable[] mappedVariables = extractMappedVariables(relationEvaluation); | ||
223 | Tuple variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables); | ||
224 | addTrace(relationEvaluation, new RelationEvaluation(body, variablesTuple, relationEvaluation.getReferredQueries(), | ||
225 | relationEvaluation.getEvaluator())); | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * @since 2.0 | ||
230 | */ | ||
231 | protected void copyBinaryReflexiveTransitiveClosureConstraint( | ||
232 | BinaryReflexiveTransitiveClosure binaryReflexiveTransitiveClosure) { | ||
233 | PVariable[] mappedVariables = extractMappedVariables(binaryReflexiveTransitiveClosure); | ||
234 | Tuple variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables); | ||
235 | addTrace(binaryReflexiveTransitiveClosure, | ||
236 | new BinaryReflexiveTransitiveClosure(body, variablesTuple, | ||
237 | binaryReflexiveTransitiveClosure.getReferredQuery(), | ||
238 | binaryReflexiveTransitiveClosure.getUniverseType())); | ||
239 | } | ||
240 | |||
241 | protected void copyPatternMatchCounterConstraint(PatternMatchCounter patternMatchCounter) { | ||
242 | PVariable[] mappedVariables = extractMappedVariables(patternMatchCounter); | ||
243 | PVariable mappedResultVariable = variableMapping.get(patternMatchCounter.getResultVariable()); | ||
244 | Tuple variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables); | ||
245 | addTrace(patternMatchCounter, new PatternMatchCounter(body, variablesTuple, | ||
246 | patternMatchCounter.getReferredQuery(), mappedResultVariable)); | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * @since 1.4 | ||
251 | */ | ||
252 | protected void copyAggregatorConstraint(AggregatorConstraint constraint) { | ||
253 | PVariable[] mappedVariables = extractMappedVariables(constraint); | ||
254 | PVariable mappedResultVariable = variableMapping.get(constraint.getResultVariable()); | ||
255 | Tuple variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables); | ||
256 | addTrace(constraint, new AggregatorConstraint(constraint.getAggregator(), body, variablesTuple, | ||
257 | constraint.getReferredQuery(), mappedResultVariable, constraint.getAggregatedColumn())); | ||
258 | } | ||
259 | |||
260 | protected void copyExpressionEvaluationConstraint(ExpressionEvaluation expressionEvaluation) { | ||
261 | PVariable mappedOutputVariable = variableMapping.get(expressionEvaluation.getOutputVariable()); | ||
262 | addTrace(expressionEvaluation, new ExpressionEvaluation(body, | ||
263 | new VariableMappingExpressionEvaluatorWrapper(expressionEvaluation.getEvaluator(), variableMapping), | ||
264 | mappedOutputVariable, expressionEvaluation.isUnwinding())); | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * For positive pattern calls | ||
269 | * | ||
270 | * @param positivePatternCall | ||
271 | * @return the mapped variables to the pattern's parameters | ||
272 | */ | ||
273 | protected PVariable[] extractMappedVariables(EnumerablePConstraint enumerablePConstraint) { | ||
274 | Object[] pVariables = enumerablePConstraint.getVariablesTuple().getElements(); | ||
275 | return mapVariableList(pVariables); | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * For negative and count pattern calls. | ||
280 | * | ||
281 | * @param patternMatchCounter | ||
282 | * @return the mapped variables to the pattern's parameters | ||
283 | */ | ||
284 | private PVariable[] extractMappedVariables(PatternCallBasedDeferred patternCallBasedDeferred) { | ||
285 | Object[] pVariables = patternCallBasedDeferred.getActualParametersTuple().getElements(); | ||
286 | return mapVariableList(pVariables); | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * For type filters. | ||
291 | */ | ||
292 | private PVariable[] extractMappedVariables(TypeFilterConstraint typeFilterConstraint) { | ||
293 | Object[] pVariables = typeFilterConstraint.getVariablesTuple().getElements(); | ||
294 | return mapVariableList(pVariables); | ||
295 | } | ||
296 | |||
297 | private PVariable[] mapVariableList(Object[] pVariables) { | ||
298 | List<PVariable> list = new ArrayList<PVariable>(); | ||
299 | for (int i = 0; i < pVariables.length; i++) { | ||
300 | PVariable mappedVariable = variableMapping.get(pVariables[i]); | ||
301 | list.add(mappedVariable); | ||
302 | } | ||
303 | return list.toArray(new PVariable[0]); | ||
304 | } | ||
305 | |||
306 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PBodyNormalizer.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PBodyNormalizer.java new file mode 100644 index 00000000..90943129 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PBodyNormalizer.java | |||
@@ -0,0 +1,310 @@ | |||
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.psystem.rewriters; | ||
11 | |||
12 | import java.util.ArrayList; | ||
13 | import java.util.Collection; | ||
14 | import java.util.Collections; | ||
15 | import java.util.Comparator; | ||
16 | import java.util.HashMap; | ||
17 | import java.util.HashSet; | ||
18 | import java.util.Iterator; | ||
19 | import java.util.LinkedHashSet; | ||
20 | import java.util.LinkedList; | ||
21 | import java.util.List; | ||
22 | import java.util.Map; | ||
23 | import java.util.Queue; | ||
24 | import java.util.Set; | ||
25 | |||
26 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
27 | import tools.refinery.viatra.runtime.matchers.context.IQueryMetaContext; | ||
28 | import tools.refinery.viatra.runtime.matchers.planning.QueryProcessingException; | ||
29 | import tools.refinery.viatra.runtime.matchers.planning.helpers.TypeHelper; | ||
30 | import tools.refinery.viatra.runtime.matchers.psystem.ITypeConstraint; | ||
31 | import tools.refinery.viatra.runtime.matchers.psystem.ITypeInfoProviderConstraint; | ||
32 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
33 | import tools.refinery.viatra.runtime.matchers.psystem.PConstraint; | ||
34 | import tools.refinery.viatra.runtime.matchers.psystem.TypeJudgement; | ||
35 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.Equality; | ||
36 | import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.Inequality; | ||
37 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PDisjunction; | ||
38 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
39 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery.PQueryStatus; | ||
40 | import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory; | ||
41 | |||
42 | /** | ||
43 | * A disjunction rewriter for creating a normalized form of specification, unifying variables and running basic sanity | ||
44 | * checks. This rewriter does not copy but modifies directly the original specification, requiring a mutable | ||
45 | * disjunction. | ||
46 | * | ||
47 | * @author Gabor Bergmann | ||
48 | * | ||
49 | */ | ||
50 | public class PBodyNormalizer extends PDisjunctionRewriter { | ||
51 | |||
52 | private IQueryMetaContext context; | ||
53 | |||
54 | public PBodyNormalizer(IQueryMetaContext context) { | ||
55 | this.context = context; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * Returns whether unary constraint elimination is enabled. This behavior can be customized by creating a subclass | ||
60 | * with a custom implementation. | ||
61 | * | ||
62 | * @since 1.6 | ||
63 | */ | ||
64 | protected boolean shouldCalculateImpliedTypes(PQuery query) { | ||
65 | return true; | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * Returns whether 'weakened alternative' suggestions of the context shall be expanded as additional PConstraints. | ||
70 | * This behavior can be customized by creating a subclass | ||
71 | * with a custom implementation. | ||
72 | * | ||
73 | * @since 1.6 | ||
74 | */ | ||
75 | protected boolean shouldExpandWeakenedAlternatives(PQuery query) { | ||
76 | return false; | ||
77 | } | ||
78 | |||
79 | @Override | ||
80 | public PDisjunction rewrite(PDisjunction disjunction) { | ||
81 | Set<PBody> normalizedBodies = new LinkedHashSet<>(); | ||
82 | for (PBody body : disjunction.getBodies()) { | ||
83 | PBodyCopier copier = new PBodyCopier(body, getTraceCollector()); | ||
84 | PBody modifiedBody = copier.getCopiedBody(); | ||
85 | normalizeBody(modifiedBody); | ||
86 | normalizedBodies.add(modifiedBody); | ||
87 | modifiedBody.setStatus(PQueryStatus.OK); | ||
88 | } | ||
89 | return new PDisjunction(normalizedBodies); | ||
90 | } | ||
91 | |||
92 | public void setContext(IQueryMetaContext context) { | ||
93 | this.context = context; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * Provides a normalized version of the pattern body. May return a different version than the original version if | ||
98 | * needed. | ||
99 | * | ||
100 | * @param body | ||
101 | */ | ||
102 | public PBody normalizeBody(PBody body) { | ||
103 | try { | ||
104 | return normalizeBodyInternal(body); | ||
105 | } catch (QueryProcessingException e) { | ||
106 | throw new RewriterException("Error during rewriting: {1}", new String[] { e.getMessage() }, | ||
107 | e.getShortMessage(), body.getPattern(), e); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | PBody normalizeBodyInternal(PBody body) { | ||
112 | // UNIFICATION AND WEAK INEQUALITY ELIMINATION | ||
113 | unifyVariablesAlongEqualities(body); | ||
114 | eliminateWeakInequalities(body); | ||
115 | removeMootEqualities(body); | ||
116 | |||
117 | // ADDING WEAKENED ALTERNATIVES | ||
118 | if (shouldExpandWeakenedAlternatives(body.getPattern())) { | ||
119 | expandWeakenedAlternativeConstraints(body); | ||
120 | } | ||
121 | |||
122 | // CONSTRAINT ELIMINATION WITH TYPE INFERENCE | ||
123 | if (shouldCalculateImpliedTypes(body.getPattern())) { | ||
124 | eliminateInferrableTypes(body, context); | ||
125 | } else { | ||
126 | // ELIMINATE DUPLICATE TYPE CONSTRAINTS | ||
127 | eliminateDuplicateTypeConstraints(body); | ||
128 | } | ||
129 | |||
130 | |||
131 | // PREVENTIVE CHECKS | ||
132 | checkSanity(body); | ||
133 | return body; | ||
134 | } | ||
135 | |||
136 | private void removeMootEqualities(PBody body) { | ||
137 | Set<Equality> equals = body.getConstraintsOfType(Equality.class); | ||
138 | for (Equality equality : equals) { | ||
139 | if (equality.isMoot()) { | ||
140 | equality.delete(); | ||
141 | derivativeRemoved(equality, ConstraintRemovalReason.MOOT_EQUALITY); | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * Unifies allVariables along equalities so that they can be handled as one. | ||
148 | * | ||
149 | * @param body | ||
150 | */ | ||
151 | void unifyVariablesAlongEqualities(PBody body) { | ||
152 | Set<Equality> equals = body.getConstraintsOfType(Equality.class); | ||
153 | for (Equality equality : equals) { | ||
154 | if (!equality.isMoot()) { | ||
155 | equality.getWho().unifyInto(equality.getWithWhom()); | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * Eliminates weak inequalities if they are not substantiated. | ||
162 | * | ||
163 | * @param body | ||
164 | */ | ||
165 | void eliminateWeakInequalities(PBody body) { | ||
166 | for (Inequality inequality : body.getConstraintsOfType(Inequality.class)){ | ||
167 | if (inequality.isEliminable()){ | ||
168 | inequality.eliminateWeak(); | ||
169 | derivativeRemoved(inequality, ConstraintRemovalReason.WEAK_INEQUALITY_SELF_LOOP); | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | |||
174 | /** | ||
175 | * Eliminates all type constraints that are inferrable from other constraints. | ||
176 | */ | ||
177 | void eliminateInferrableTypes(final PBody body, IQueryMetaContext context) { | ||
178 | Set<TypeJudgement> subsumedByRetainedConstraints = new HashSet<TypeJudgement>(); | ||
179 | LinkedList<ITypeConstraint> allTypeConstraints = new LinkedList<ITypeConstraint>(); | ||
180 | for (PConstraint pConstraint : body.getConstraints()) { | ||
181 | if (pConstraint instanceof ITypeConstraint) { | ||
182 | allTypeConstraints.add((ITypeConstraint) pConstraint); | ||
183 | } else if (pConstraint instanceof ITypeInfoProviderConstraint) { | ||
184 | // non-type constraints are all retained | ||
185 | final Set<TypeJudgement> directJudgements = ((ITypeInfoProviderConstraint) pConstraint) | ||
186 | .getImpliedJudgements(context); | ||
187 | subsumedByRetainedConstraints = TypeHelper.typeClosure(subsumedByRetainedConstraints, directJudgements, | ||
188 | context); | ||
189 | } | ||
190 | } | ||
191 | Comparator<ITypeConstraint> eliminationOrder = (o1, o2) -> { | ||
192 | IInputKey type1 = o1.getEquivalentJudgement().getInputKey(); | ||
193 | IInputKey type2 = o2.getEquivalentJudgement().getInputKey(); | ||
194 | |||
195 | int result = context.getSuggestedEliminationOrdering().compare(type1, type2); | ||
196 | return (result == 0) | ||
197 | ? PConstraint.COMPARE_BY_MONOTONOUS_ID.compare(o1, o2) | ||
198 | : result; | ||
199 | }; | ||
200 | |||
201 | Collections.sort(allTypeConstraints, eliminationOrder); | ||
202 | Queue<ITypeConstraint> potentialConstraints = allTypeConstraints; // rename for better comprehension | ||
203 | |||
204 | while (!potentialConstraints.isEmpty()) { | ||
205 | ITypeConstraint candidate = potentialConstraints.poll(); | ||
206 | |||
207 | boolean isSubsumed = subsumedByRetainedConstraints.contains(candidate.getEquivalentJudgement()); | ||
208 | if (!isSubsumed) { | ||
209 | Set<TypeJudgement> typeClosure = subsumedByRetainedConstraints; | ||
210 | for (ITypeConstraint subsuming : potentialConstraints) { // the remaining ones | ||
211 | final Set<TypeJudgement> directJudgements = subsuming.getImpliedJudgements(context); | ||
212 | typeClosure = TypeHelper.typeClosure(typeClosure, directJudgements, context); | ||
213 | |||
214 | if (typeClosure.contains(candidate.getEquivalentJudgement())) { | ||
215 | isSubsumed = true; | ||
216 | break; | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | if (isSubsumed) { // eliminated | ||
221 | candidate.delete(); | ||
222 | derivativeRemoved(candidate, ConstraintRemovalReason.TYPE_SUBSUMED); | ||
223 | } else { // retained | ||
224 | subsumedByRetainedConstraints = TypeHelper.typeClosure(subsumedByRetainedConstraints, | ||
225 | candidate.getImpliedJudgements(context), context); | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * Inserts "weakened alternative" constraints suggested by the meta context that aid in coming up with a query plan. | ||
232 | */ | ||
233 | void expandWeakenedAlternativeConstraints(PBody body) { | ||
234 | Set<TypeJudgement> allJudgements = new HashSet<TypeJudgement>(); | ||
235 | Set<TypeJudgement> newJudgementsToAdd = new HashSet<TypeJudgement>(); | ||
236 | Queue<TypeJudgement> judgementsToProcess = new LinkedList<TypeJudgement>(); | ||
237 | Map<TypeJudgement, List<PConstraint>> traceability = CollectionsFactory.createMap(); | ||
238 | |||
239 | for (ITypeConstraint typeConstraint : body.getConstraintsOfType(ITypeConstraint.class)) { | ||
240 | TypeJudgement equivalentJudgement = typeConstraint.getEquivalentJudgement(); | ||
241 | judgementsToProcess.add(equivalentJudgement); | ||
242 | allJudgements.add(equivalentJudgement); | ||
243 | traceability.computeIfAbsent(equivalentJudgement, k-> new ArrayList<>()).add(typeConstraint); | ||
244 | } | ||
245 | |||
246 | while (!judgementsToProcess.isEmpty()) { | ||
247 | TypeJudgement judgement = judgementsToProcess.poll(); | ||
248 | for (TypeJudgement alternativeJudgement : judgement.getWeakenedAlternativeJudgements(context)) { | ||
249 | if (allJudgements.add(alternativeJudgement)) { | ||
250 | newJudgementsToAdd.add(alternativeJudgement); | ||
251 | judgementsToProcess.add(alternativeJudgement); | ||
252 | traceability.merge( | ||
253 | alternativeJudgement, | ||
254 | traceability.getOrDefault(judgement, new ArrayList<>()), | ||
255 | (old,further) -> {old.addAll(further); return old;} | ||
256 | ); | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | |||
261 | for (TypeJudgement typeJudgement : newJudgementsToAdd) { | ||
262 | PConstraint newConstraint = typeJudgement.createConstraintFor(body); | ||
263 | for (PConstraint source : traceability.getOrDefault(typeJudgement, Collections.emptyList())) { | ||
264 | addTrace(source, newConstraint); | ||
265 | } | ||
266 | } | ||
267 | } | ||
268 | |||
269 | private Object getConstraintKey(PConstraint constraint) { | ||
270 | if (constraint instanceof ITypeConstraint) { | ||
271 | return ((ITypeConstraint) constraint).getEquivalentJudgement(); | ||
272 | } | ||
273 | // Do not check duplication for any other types | ||
274 | return constraint; | ||
275 | } | ||
276 | |||
277 | void eliminateDuplicateTypeConstraints(PBody body) { | ||
278 | Map<Object, PConstraint> constraints = new HashMap<>(); | ||
279 | for (PConstraint constraint : body.getConstraints()) { | ||
280 | Object key = getConstraintKey(constraint); | ||
281 | // Retain first found instance of a constraint | ||
282 | if (!constraints.containsKey(key)) { | ||
283 | constraints.put(key, constraint); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | // Retain collected constraints, remove everything else | ||
288 | Iterator<PConstraint> iterator = body.getConstraints().iterator(); | ||
289 | Collection<PConstraint> toRetain = constraints.values(); | ||
290 | while(iterator.hasNext()){ | ||
291 | PConstraint next = iterator.next(); | ||
292 | if (!toRetain.contains(next)){ | ||
293 | derivativeRemoved(next, ConstraintRemovalReason.DUPLICATE); | ||
294 | iterator.remove(); | ||
295 | } | ||
296 | } | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * Verifies the sanity of all constraints. Should be issued as a preventive check before layouting. | ||
301 | * | ||
302 | * @param body | ||
303 | * @throws RetePatternBuildException | ||
304 | */ | ||
305 | void checkSanity(PBody body) { | ||
306 | for (PConstraint pConstraint : body.getConstraints()) | ||
307 | pConstraint.checkSanity(); | ||
308 | } | ||
309 | |||
310 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PDisjunctionRewriter.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PDisjunctionRewriter.java new file mode 100644 index 00000000..c844ccf7 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PDisjunctionRewriter.java | |||
@@ -0,0 +1,27 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PDisjunction; | ||
12 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
13 | |||
14 | /** | ||
15 | * An abstract base class for creating alternative representations for PDisjunctions. | ||
16 | * @author Zoltan Ujhelyi | ||
17 | * | ||
18 | */ | ||
19 | public abstract class PDisjunctionRewriter extends AbstractRewriterTraceSource{ | ||
20 | |||
21 | public abstract PDisjunction rewrite(PDisjunction disjunction); | ||
22 | |||
23 | public PDisjunction rewrite(PQuery query) { | ||
24 | return rewrite(query.getDisjunctBodies()); | ||
25 | } | ||
26 | |||
27 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PDisjunctionRewriterCacher.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PDisjunctionRewriterCacher.java new file mode 100644 index 00000000..eb5422ca --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PDisjunctionRewriterCacher.java | |||
@@ -0,0 +1,64 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Arrays; | ||
13 | import java.util.Collections; | ||
14 | import java.util.List; | ||
15 | import java.util.WeakHashMap; | ||
16 | |||
17 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PDisjunction; | ||
18 | |||
19 | /** | ||
20 | * A rewriter that stores the previously computed results of a rewriter or a rewriter chain. | ||
21 | * | ||
22 | * @author Zoltan Ujhelyi | ||
23 | * @since 1.0 | ||
24 | */ | ||
25 | public class PDisjunctionRewriterCacher extends PDisjunctionRewriter { | ||
26 | |||
27 | private final List<PDisjunctionRewriter> rewriterChain; | ||
28 | private WeakHashMap<PDisjunction, PDisjunction> cachedResults = | ||
29 | new WeakHashMap<PDisjunction, PDisjunction>(); | ||
30 | |||
31 | private void setupTraceCollectorInChain(){ | ||
32 | IRewriterTraceCollector collector = getTraceCollector(); | ||
33 | for(PDisjunctionRewriter rewriter: rewriterChain){ | ||
34 | rewriter.setTraceCollector(collector); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | public PDisjunctionRewriterCacher(PDisjunctionRewriter rewriter) { | ||
39 | rewriterChain = Collections.singletonList(rewriter); | ||
40 | } | ||
41 | |||
42 | public PDisjunctionRewriterCacher(PDisjunctionRewriter... rewriters) { | ||
43 | rewriterChain = new ArrayList<>(Arrays.asList(rewriters)); | ||
44 | } | ||
45 | |||
46 | public PDisjunctionRewriterCacher(List<PDisjunctionRewriter> rewriterChain) { | ||
47 | this.rewriterChain = new ArrayList<>(rewriterChain); | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public PDisjunction rewrite(PDisjunction disjunction) { | ||
52 | if (!cachedResults.containsKey(disjunction)) { | ||
53 | PDisjunction rewritten = disjunction; | ||
54 | setupTraceCollectorInChain(); | ||
55 | for (PDisjunctionRewriter rewriter : rewriterChain) { | ||
56 | rewritten = rewriter.rewrite(rewritten); | ||
57 | } | ||
58 | |||
59 | cachedResults.put(disjunction, rewritten); | ||
60 | } | ||
61 | return cachedResults.get(disjunction); | ||
62 | } | ||
63 | |||
64 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PQueryFlattener.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PQueryFlattener.java new file mode 100644 index 00000000..76311d8f --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/PQueryFlattener.java | |||
@@ -0,0 +1,253 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Marton Bur, Akos Horvath, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import java.util.ArrayDeque; | ||
12 | import java.util.ArrayList; | ||
13 | import java.util.Collections; | ||
14 | import java.util.Deque; | ||
15 | import java.util.HashMap; | ||
16 | import java.util.HashSet; | ||
17 | import java.util.LinkedHashSet; | ||
18 | import java.util.LinkedList; | ||
19 | import java.util.List; | ||
20 | import java.util.Map; | ||
21 | import java.util.Set; | ||
22 | |||
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.basicenumerables.PositivePatternCall; | ||
26 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PDisjunction; | ||
27 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
28 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery.PQueryStatus; | ||
29 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IConstraintFilter.AllowAllFilter; | ||
30 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IConstraintFilter.ExportedParameterFilter; | ||
31 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IVariableRenamer.HierarchicalName; | ||
32 | import tools.refinery.viatra.runtime.matchers.psystem.rewriters.IVariableRenamer.SameName; | ||
33 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
34 | import tools.refinery.viatra.runtime.matchers.util.Sets; | ||
35 | |||
36 | /** | ||
37 | * This rewriter class holds the query flattening logic | ||
38 | * | ||
39 | * @author Marton Bur | ||
40 | * | ||
41 | */ | ||
42 | public class PQueryFlattener extends PDisjunctionRewriter { | ||
43 | |||
44 | /** | ||
45 | * Utility function to produce the permutation of every possible mapping of values. | ||
46 | * | ||
47 | * @param values | ||
48 | * @return | ||
49 | */ | ||
50 | private static <K, V> Set<Map<K, V>> permutation(Map<K, Set<V>> values) { | ||
51 | // An ordering of keys is defined here which will help restoring the appropriate values after the execution of | ||
52 | // the cartesian product | ||
53 | List<K> keyList = new ArrayList<>(values.keySet()); | ||
54 | |||
55 | // Produce list of value sets with the ordering defined by keyList | ||
56 | List<Set<V>> valuesList = new ArrayList<Set<V>>(keyList.size()); | ||
57 | for (K key : keyList) { | ||
58 | valuesList.add(values.get(key)); | ||
59 | } | ||
60 | |||
61 | // Cartesian product will obey ordering of the list | ||
62 | Set<List<V>> valueMappings = Sets.cartesianProduct(valuesList); | ||
63 | |||
64 | // Build result | ||
65 | Set<Map<K, V>> result = new LinkedHashSet<>(); | ||
66 | for (List<V> valueList : valueMappings) { | ||
67 | Map<K, V> map = new HashMap<>(); | ||
68 | for (int i = 0; i < keyList.size(); i++) { | ||
69 | map.put(keyList.get(i), valueList.get(i)); | ||
70 | } | ||
71 | result.add(map); | ||
72 | } | ||
73 | |||
74 | return result; | ||
75 | } | ||
76 | |||
77 | private IFlattenCallPredicate flattenCallPredicate; | ||
78 | |||
79 | public PQueryFlattener(IFlattenCallPredicate flattenCallPredicate) { | ||
80 | this.flattenCallPredicate = flattenCallPredicate; | ||
81 | } | ||
82 | |||
83 | @Override | ||
84 | public PDisjunction rewrite(PDisjunction disjunction) { | ||
85 | PQuery query = disjunction.getQuery(); | ||
86 | |||
87 | // Check for recursion | ||
88 | Set<PQuery> allReferredQueries = disjunction.getAllReferredQueries(); | ||
89 | for (PQuery referredQuery : allReferredQueries) { | ||
90 | if (referredQuery.getAllReferredQueries().contains(referredQuery)) { | ||
91 | throw new RewriterException("Recursive queries are not supported, can't flatten query named \"{1}\"", | ||
92 | new String[] { query.getFullyQualifiedName() }, "Unsupported recursive query", query); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | return this.doFlatten(disjunction); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * Return the list of dependencies (including the root) in chronological order | ||
101 | * | ||
102 | * @param rootDisjunction | ||
103 | * @return | ||
104 | */ | ||
105 | private List<PDisjunction> disjunctionDependencies(PDisjunction rootDisjunction) { | ||
106 | // Disjunctions are first collected into a list usign a depth-first approach, | ||
107 | // which can be iterated backwards while removing duplicates | ||
108 | Deque<PDisjunction> stack = new ArrayDeque<>(); | ||
109 | LinkedList<PDisjunction> list = new LinkedList<>(); | ||
110 | stack.push(rootDisjunction); | ||
111 | list.add(rootDisjunction); | ||
112 | |||
113 | while (!stack.isEmpty()) { | ||
114 | PDisjunction disjunction = stack.pop(); | ||
115 | // Collect dependencies | ||
116 | for (PBody pBody : disjunction.getBodies()) { | ||
117 | for (PConstraint constraint : pBody.getConstraints()) { | ||
118 | if (constraint instanceof PositivePatternCall) { | ||
119 | PositivePatternCall positivePatternCall = (PositivePatternCall) constraint; | ||
120 | if (flattenCallPredicate.shouldFlatten(positivePatternCall)) { | ||
121 | // If the above preconditions meet, the call should be flattened | ||
122 | PDisjunction calledDisjunction = positivePatternCall.getReferredQuery().getDisjunctBodies(); | ||
123 | stack.push(calledDisjunction); | ||
124 | list.add(calledDisjunction); | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | |||
131 | // Remove duplicates (keeping the last instance) and reverse order | ||
132 | Set<PDisjunction> visited = new HashSet<PDisjunction>(); | ||
133 | List<PDisjunction> result = new ArrayList<PDisjunction>(list.size()); | ||
134 | |||
135 | list.descendingIterator().forEachRemaining(item -> { | ||
136 | if (!visited.contains(item)) { | ||
137 | result.add(item); | ||
138 | visited.add(item); | ||
139 | } | ||
140 | |||
141 | }); | ||
142 | |||
143 | return result; | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * This function holds the actual flattening logic for a PQuery | ||
148 | * | ||
149 | * @param rootDisjunction | ||
150 | * to be flattened | ||
151 | * @return the flattened bodies of the pQuery | ||
152 | */ | ||
153 | private PDisjunction doFlatten(PDisjunction rootDisjunction) { | ||
154 | |||
155 | Map<PDisjunction, Set<PBody>> flatBodyMapping = new HashMap<>(); | ||
156 | |||
157 | List<PDisjunction> dependencies = disjunctionDependencies(rootDisjunction); | ||
158 | |||
159 | for (PDisjunction disjunction : dependencies) { | ||
160 | Set<PBody> flatBodies = new LinkedHashSet<>(); | ||
161 | for (PBody body : disjunction.getBodies()) { | ||
162 | if (isFlatteningNeeded(body)) { | ||
163 | Map<PositivePatternCall, Set<PBody>> flattenedBodies = new HashMap<>(); | ||
164 | for (PConstraint pConstraint : body.getConstraints()) { | ||
165 | |||
166 | if (pConstraint instanceof PositivePatternCall) { | ||
167 | PositivePatternCall positivePatternCall = (PositivePatternCall) pConstraint; | ||
168 | if (flattenCallPredicate.shouldFlatten(positivePatternCall)) { | ||
169 | // If the above preconditions meet, do the flattening and return the disjoint bodies | ||
170 | PDisjunction calledDisjunction = positivePatternCall.getReferredQuery() | ||
171 | .getDisjunctBodies(); | ||
172 | |||
173 | Set<PBody> flattenedBodySet = flatBodyMapping.get(calledDisjunction); | ||
174 | Preconditions.checkArgument(!flattenedBodySet.isEmpty()); | ||
175 | flattenedBodies.put(positivePatternCall, flattenedBodySet); | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | flatBodies.addAll(createSetOfFlatPBodies(body, flattenedBodies)); | ||
180 | } else { | ||
181 | flatBodies.add(prepareFlatPBody(body)); | ||
182 | } | ||
183 | } | ||
184 | flatBodyMapping.put(disjunction, flatBodies); | ||
185 | } | ||
186 | |||
187 | return new PDisjunction(rootDisjunction.getQuery(), flatBodyMapping.get(rootDisjunction)); | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * Creates the flattened bodies based on the caller body and the called (and already flattened) disjunctions | ||
192 | * | ||
193 | * @param pBody | ||
194 | * the body to flatten | ||
195 | * @param flattenedDisjunctions | ||
196 | * the | ||
197 | * @param flattenedCalls | ||
198 | * @return | ||
199 | */ | ||
200 | private Set<PBody> createSetOfFlatPBodies(PBody pBody, Map<PositivePatternCall, Set<PBody>> flattenedCalls) { | ||
201 | PQuery pQuery = pBody.getPattern(); | ||
202 | |||
203 | Set<Map<PositivePatternCall, PBody>> conjunctedCalls = permutation(flattenedCalls); | ||
204 | |||
205 | // The result set containing the merged conjuncted bodies | ||
206 | Set<PBody> conjunctedBodies = new HashSet<>(); | ||
207 | |||
208 | for (Map<PositivePatternCall, PBody> calledBodies : conjunctedCalls) { | ||
209 | FlattenerCopier copier = createBodyCopier(pQuery, calledBodies); | ||
210 | |||
211 | int i = 0; | ||
212 | HierarchicalName hierarchicalNamingTool = new HierarchicalName(); | ||
213 | for (PositivePatternCall patternCall : calledBodies.keySet()) { | ||
214 | // Merge each called body | ||
215 | hierarchicalNamingTool.setCallCount(i++); | ||
216 | copier.mergeBody(patternCall, hierarchicalNamingTool, new ExportedParameterFilter()); | ||
217 | } | ||
218 | |||
219 | // Merge the caller's constraints to the conjunct body | ||
220 | copier.mergeBody(pBody); | ||
221 | |||
222 | PBody copiedBody = copier.getCopiedBody(); | ||
223 | copiedBody.setStatus(PQueryStatus.OK); | ||
224 | conjunctedBodies.add(copiedBody); | ||
225 | } | ||
226 | |||
227 | return conjunctedBodies; | ||
228 | } | ||
229 | |||
230 | private FlattenerCopier createBodyCopier(PQuery query, Map<PositivePatternCall, PBody> calledBodies) { | ||
231 | FlattenerCopier flattenerCopier = new FlattenerCopier(query, calledBodies); | ||
232 | flattenerCopier.setTraceCollector(getTraceCollector()); | ||
233 | return flattenerCopier; | ||
234 | } | ||
235 | |||
236 | private PBody prepareFlatPBody(PBody pBody) { | ||
237 | PBodyCopier copier = createBodyCopier(pBody.getPattern(), Collections.<PositivePatternCall, PBody> emptyMap()); | ||
238 | copier.mergeBody(pBody, new SameName(), new AllowAllFilter()); | ||
239 | // the copying of the body here is necessary for only one containing PDisjunction can be assigned to a PBody | ||
240 | return copier.getCopiedBody(); | ||
241 | } | ||
242 | |||
243 | private boolean isFlatteningNeeded(PBody pBody) { | ||
244 | // Check if the body contains positive pattern call AND if it should be flattened | ||
245 | for (PConstraint pConstraint : pBody.getConstraints()) { | ||
246 | if (pConstraint instanceof PositivePatternCall) { | ||
247 | return flattenCallPredicate.shouldFlatten((PositivePatternCall) pConstraint); | ||
248 | } | ||
249 | } | ||
250 | return false; | ||
251 | } | ||
252 | |||
253 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/RewriterException.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/RewriterException.java new file mode 100644 index 00000000..d0fc286b --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/RewriterException.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.matchers.psystem.queries.QueryInitializationException; | ||
12 | |||
13 | /** | ||
14 | * An exception to wrap various issues during PDisjunction rewriting. | ||
15 | * @author Zoltan Ujhelyi | ||
16 | * | ||
17 | */ | ||
18 | public class RewriterException extends QueryInitializationException { | ||
19 | |||
20 | private static final long serialVersionUID = -4703825954995497932L; | ||
21 | |||
22 | public RewriterException(String message, String[] context, String shortMessage, Object patternDescription, | ||
23 | Throwable cause) { | ||
24 | super(message, context, shortMessage, patternDescription, cause); | ||
25 | } | ||
26 | |||
27 | public RewriterException(String message, String[] context, String shortMessage, Object patternDescription) { | ||
28 | super(message, context, shortMessage, patternDescription); | ||
29 | } | ||
30 | |||
31 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/SurrogateQueryRewriter.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/SurrogateQueryRewriter.java new file mode 100644 index 00000000..71459558 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/SurrogateQueryRewriter.java | |||
@@ -0,0 +1,63 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import java.util.LinkedHashSet; | ||
12 | import java.util.Set; | ||
13 | |||
14 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
15 | import tools.refinery.viatra.runtime.matchers.context.surrogate.SurrogateQueryRegistry; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.PBody; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
18 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | ||
19 | import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.TypeConstraint; | ||
20 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PDisjunction; | ||
21 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery; | ||
22 | import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery.PQueryStatus; | ||
23 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
24 | import tools.refinery.viatra.runtime.matchers.tuple.Tuples; | ||
25 | |||
26 | /** | ||
27 | * @author Zoltan Ujhelyi | ||
28 | * | ||
29 | */ | ||
30 | public class SurrogateQueryRewriter extends PDisjunctionRewriter { | ||
31 | |||
32 | @Override | ||
33 | public PDisjunction rewrite(PDisjunction disjunction) { | ||
34 | Set<PBody> replacedBodies = new LinkedHashSet<>(); | ||
35 | for (PBody body : disjunction.getBodies()) { | ||
36 | PBodyCopier copier = new PBodyCopier(body, getTraceCollector()) { | ||
37 | |||
38 | @Override | ||
39 | protected void copyTypeConstraint(TypeConstraint typeConstraint) { | ||
40 | PVariable[] mappedVariables = extractMappedVariables(typeConstraint); | ||
41 | Tuple variablesTuple = Tuples.flatTupleOf((Object[])mappedVariables); | ||
42 | final IInputKey supplierKey = typeConstraint.getSupplierKey(); | ||
43 | if(SurrogateQueryRegistry.instance().hasSurrogateQueryFQN(supplierKey)) { | ||
44 | PQuery surrogateQuery = SurrogateQueryRegistry.instance().getSurrogateQuery(supplierKey); | ||
45 | if (surrogateQuery == null) { | ||
46 | throw new IllegalStateException( | ||
47 | String.format("Surrogate query for feature %s not found", | ||
48 | supplierKey.getPrettyPrintableName())); | ||
49 | } | ||
50 | addTrace(typeConstraint, new PositivePatternCall(getCopiedBody(), variablesTuple, surrogateQuery)); | ||
51 | } else { | ||
52 | addTrace(typeConstraint, new TypeConstraint(getCopiedBody(), variablesTuple, supplierKey)); | ||
53 | } | ||
54 | } | ||
55 | }; | ||
56 | PBody modifiedBody = copier.getCopiedBody(); | ||
57 | replacedBodies.add(modifiedBody); | ||
58 | modifiedBody.setStatus(PQueryStatus.OK); | ||
59 | } | ||
60 | return new PDisjunction(replacedBodies); | ||
61 | } | ||
62 | |||
63 | } | ||
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/VariableMappingExpressionEvaluatorWrapper.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/VariableMappingExpressionEvaluatorWrapper.java new file mode 100644 index 00000000..10337979 --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/psystem/rewriters/VariableMappingExpressionEvaluatorWrapper.java | |||
@@ -0,0 +1,88 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Grill Balázs, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.matchers.psystem.rewriters; | ||
10 | |||
11 | import java.util.HashMap; | ||
12 | import java.util.LinkedHashMap; | ||
13 | import java.util.Map; | ||
14 | |||
15 | import tools.refinery.viatra.runtime.matchers.psystem.IExpressionEvaluator; | ||
16 | import tools.refinery.viatra.runtime.matchers.psystem.IValueProvider; | ||
17 | import tools.refinery.viatra.runtime.matchers.psystem.PVariable; | ||
18 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
19 | |||
20 | /** | ||
21 | * A wrapper for {@link IExpressionEvaluator} which is capable of correctly mapping variable names used by the | ||
22 | * expression. | ||
23 | * | ||
24 | * @author Grill Balázs | ||
25 | * | ||
26 | */ | ||
27 | class VariableMappingExpressionEvaluatorWrapper implements IExpressionEvaluator { | ||
28 | |||
29 | private final IExpressionEvaluator wrapped; | ||
30 | private final Map<String, String> variableMapping; | ||
31 | |||
32 | public VariableMappingExpressionEvaluatorWrapper(IExpressionEvaluator wrapped, | ||
33 | Map<PVariable, PVariable> variableMapping) { | ||
34 | |||
35 | // Support to rewrap an already wrapped expression. | ||
36 | boolean rewrap = wrapped instanceof VariableMappingExpressionEvaluatorWrapper; | ||
37 | this.wrapped = rewrap ? ((VariableMappingExpressionEvaluatorWrapper)wrapped).wrapped : wrapped; | ||
38 | |||
39 | // Instead of just saving the reference of the mapping, save the actual (trimmed) state of the mapping as it | ||
40 | // may change during copying (especially during flattening). A LinkedHashMap is used to retain ordering of | ||
41 | // original parameter names iterator. | ||
42 | this.variableMapping = new LinkedHashMap<>(); | ||
43 | |||
44 | // Index map by variable names | ||
45 | Map<String, PVariable> names = new HashMap<>(); | ||
46 | for (PVariable originalVar : variableMapping.keySet()) { | ||
47 | names.put(originalVar.getName(), originalVar); | ||
48 | } | ||
49 | |||
50 | // In case of rewrapping, current names are contained by the previous mapping | ||
51 | Map<String, String> previousMapping = null; | ||
52 | if (rewrap){ | ||
53 | previousMapping = ((VariableMappingExpressionEvaluatorWrapper)wrapped).variableMapping; | ||
54 | } | ||
55 | |||
56 | // Populate mapping | ||
57 | for (String inputParameterName : this.wrapped.getInputParameterNames()) { | ||
58 | String parameterName = rewrap ? previousMapping.get(inputParameterName) : inputParameterName; | ||
59 | Preconditions.checkArgument(parameterName != null); | ||
60 | PVariable original = names.get(parameterName); | ||
61 | Preconditions.checkArgument(original != null); | ||
62 | PVariable mapped = variableMapping.get(original); | ||
63 | if (mapped != null){ | ||
64 | this.variableMapping.put(inputParameterName, mapped.getName()); | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | |||
69 | @Override | ||
70 | public String getShortDescription() { | ||
71 | return wrapped.getShortDescription(); | ||
72 | } | ||
73 | |||
74 | @Override | ||
75 | public Iterable<String> getInputParameterNames() { | ||
76 | return variableMapping.values(); | ||
77 | } | ||
78 | |||
79 | @Override | ||
80 | public Object evaluateExpression(final IValueProvider provider) throws Exception { | ||
81 | return wrapped.evaluateExpression(variableName -> { | ||
82 | String mappedVariableName = variableMapping.get(variableName); | ||
83 | Preconditions.checkArgument(mappedVariableName != null, "Could not find variable %s", variableName); | ||
84 | return provider.getValue(mappedVariableName); | ||
85 | }); | ||
86 | } | ||
87 | |||
88 | } | ||