diff options
Diffstat (limited to 'subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/check/BinaryTransitiveClosureCheck.java')
-rw-r--r-- | subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/check/BinaryTransitiveClosureCheck.java | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/check/BinaryTransitiveClosureCheck.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/check/BinaryTransitiveClosureCheck.java new file mode 100644 index 00000000..8f818542 --- /dev/null +++ b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/check/BinaryTransitiveClosureCheck.java | |||
@@ -0,0 +1,135 @@ | |||
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.localsearch.operations.check; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.LinkedList; | ||
14 | import java.util.List; | ||
15 | import java.util.Objects; | ||
16 | import java.util.Queue; | ||
17 | import java.util.Set; | ||
18 | import java.util.function.Function; | ||
19 | |||
20 | import tools.refinery.viatra.runtime.localsearch.MatchingFrame; | ||
21 | import tools.refinery.viatra.runtime.localsearch.matcher.ISearchContext; | ||
22 | import tools.refinery.viatra.runtime.localsearch.operations.CheckOperationExecutor; | ||
23 | import tools.refinery.viatra.runtime.localsearch.operations.IPatternMatcherOperation; | ||
24 | import tools.refinery.viatra.runtime.localsearch.operations.ISearchOperation; | ||
25 | import tools.refinery.viatra.runtime.localsearch.operations.util.CallInformation; | ||
26 | import tools.refinery.viatra.runtime.matchers.backend.IQueryResultProvider; | ||
27 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
28 | |||
29 | /** | ||
30 | * Checking for a transitive closure expressed as a local search pattern matcher. The matched pattern must have two | ||
31 | * parameters of the same model type. | ||
32 | * | ||
33 | * @author Zoltan Ujhelyi | ||
34 | * @noextend This class is not intended to be subclassed by clients. | ||
35 | * @noinstantiate This class is not intended to be instantiated by clients. | ||
36 | * | ||
37 | */ | ||
38 | public class BinaryTransitiveClosureCheck implements ISearchOperation, IPatternMatcherOperation { | ||
39 | |||
40 | private class Executor extends CheckOperationExecutor { | ||
41 | |||
42 | @Override | ||
43 | public void onInitialize(MatchingFrame frame, ISearchContext context) { | ||
44 | super.onInitialize(frame, context); | ||
45 | matcher = context.getMatcher(information.getCallWithAdornment()); | ||
46 | // Note: second parameter is NOT bound during execution, but the first is | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | protected boolean check(MatchingFrame frame, ISearchContext context) { | ||
51 | if (checkReflexive(frame)) { | ||
52 | return true; | ||
53 | } | ||
54 | |||
55 | Object targetValue = frame.get(targetPosition); | ||
56 | Queue<Object> sourcesToEvaluate = new LinkedList<>(); | ||
57 | sourcesToEvaluate.add(frame.get(sourcePosition)); | ||
58 | Set<Object> sourceEvaluated = new HashSet<>(); | ||
59 | final Object[] mappedFrame = new Object[] {null, null}; | ||
60 | while (!sourcesToEvaluate.isEmpty()) { | ||
61 | Object currentValue = sourcesToEvaluate.poll(); | ||
62 | sourceEvaluated.add(currentValue); | ||
63 | mappedFrame[0] = currentValue; | ||
64 | for (Tuple match : (Iterable<Tuple>) () -> matcher.getAllMatches(mappedFrame).iterator()) { | ||
65 | Object foundTarget = match.get(1); | ||
66 | if (targetValue.equals(foundTarget)) { | ||
67 | return true; | ||
68 | } else if (!sourceEvaluated.contains(foundTarget)) { | ||
69 | sourcesToEvaluate.add(foundTarget); | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | return false; | ||
74 | } | ||
75 | |||
76 | protected boolean checkReflexive(MatchingFrame frame) { | ||
77 | return reflexive && Objects.equals(frame.get(sourcePosition), frame.get(targetPosition)); | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public ISearchOperation getOperation() { | ||
82 | return BinaryTransitiveClosureCheck.this; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | private final CallInformation information; | ||
87 | private IQueryResultProvider matcher; | ||
88 | private final int sourcePosition; | ||
89 | private final int targetPosition; | ||
90 | private final boolean reflexive; | ||
91 | |||
92 | /** | ||
93 | * The source position will be matched in the called pattern to the first parameter; while target to the second. | ||
94 | * </p> | ||
95 | * <strong>NOTE</strong>: the reflexive check call does not include the parameter type checks; appropriate type checks should be | ||
96 | * added as necessary by the operation compiler. | ||
97 | * | ||
98 | * @since 2.0 | ||
99 | */ | ||
100 | public BinaryTransitiveClosureCheck(CallInformation information, int sourcePosition, int targetPosition, boolean reflexive) { | ||
101 | super(); | ||
102 | this.sourcePosition = sourcePosition; | ||
103 | this.targetPosition = targetPosition; | ||
104 | this.information = information; | ||
105 | this.reflexive = reflexive; | ||
106 | } | ||
107 | |||
108 | @Override | ||
109 | public ISearchOperationExecutor createExecutor() { | ||
110 | return new Executor(); | ||
111 | } | ||
112 | |||
113 | @Override | ||
114 | public String toString() { | ||
115 | return toString(Object::toString); | ||
116 | } | ||
117 | |||
118 | @Override | ||
119 | public String toString(Function<Integer, String> variableMapping) { | ||
120 | String c = information.toString(variableMapping); | ||
121 | int p = c.indexOf('('); | ||
122 | String modifier = reflexive ? "*" : "+"; | ||
123 | return "check find "+c.substring(0, p)+ modifier +c.substring(p); | ||
124 | } | ||
125 | |||
126 | @Override | ||
127 | public List<Integer> getVariablePositions() { | ||
128 | return Arrays.asList(sourcePosition, targetPosition); | ||
129 | } | ||
130 | |||
131 | @Override | ||
132 | public CallInformation getCallInformation() { | ||
133 | return information; | ||
134 | } | ||
135 | } | ||