aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-08-19 03:29:34 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-08-19 03:29:34 +0200
commit22b3b72ff9b978de50a2823739940b34f9fe8dfa (patch)
tree74695bdae60181e47303031ad91e1e707a98a287
parentchore: mark modified VIATRA files (diff)
downloadrefinery-22b3b72ff9b978de50a2823739940b34f9fe8dfa.tar.gz
refinery-22b3b72ff9b978de50a2823739940b34f9fe8dfa.tar.zst
refinery-22b3b72ff9b978de50a2823739940b34f9fe8dfa.zip
refactor: apply local search fixes to VIATRA
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java4
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendOperationExecutor.java76
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendPositivePatternCall.java117
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/GenericTypeExtend.java137
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchBackendFactory.java60
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchResultProvider.java28
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalOperationCompiler.java70
-rw-r--r--subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/ExtendOperationExecutor.java47
-rw-r--r--subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/compiler/GenericOperationCompiler.java23
9 files changed, 39 insertions, 523 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java
index c8aa067c..cfdc43ba 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java
@@ -15,11 +15,11 @@ import tools.refinery.store.query.rewriter.DuplicateDnfRemover;
15import tools.refinery.store.query.rewriter.InputParameterResolver; 15import tools.refinery.store.query.rewriter.InputParameterResolver;
16import tools.refinery.store.query.viatra.ViatraModelQueryBuilder; 16import tools.refinery.store.query.viatra.ViatraModelQueryBuilder;
17import tools.refinery.store.query.viatra.internal.localsearch.FlatCostFunction; 17import tools.refinery.store.query.viatra.internal.localsearch.FlatCostFunction;
18import tools.refinery.store.query.viatra.internal.localsearch.RelationalLocalSearchBackendFactory;
19import tools.refinery.store.query.viatra.internal.matcher.RawPatternMatcher; 18import tools.refinery.store.query.viatra.internal.matcher.RawPatternMatcher;
20import tools.refinery.store.query.viatra.internal.pquery.Dnf2PQuery; 19import tools.refinery.store.query.viatra.internal.pquery.Dnf2PQuery;
21import tools.refinery.viatra.runtime.api.IQuerySpecification; 20import tools.refinery.viatra.runtime.api.IQuerySpecification;
22import tools.refinery.viatra.runtime.api.ViatraQueryEngineOptions; 21import tools.refinery.viatra.runtime.api.ViatraQueryEngineOptions;
22import tools.refinery.viatra.runtime.localsearch.matcher.integration.LocalSearchGenericBackendFactory;
23import tools.refinery.viatra.runtime.localsearch.matcher.integration.LocalSearchHintOptions; 23import tools.refinery.viatra.runtime.localsearch.matcher.integration.LocalSearchHintOptions;
24import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactory; 24import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactory;
25import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint; 25import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint;
@@ -43,7 +43,7 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder<Via
43 engineOptionsBuilder = new ViatraQueryEngineOptions.Builder() 43 engineOptionsBuilder = new ViatraQueryEngineOptions.Builder()
44 .withDefaultBackend(ReteBackendFactory.INSTANCE) 44 .withDefaultBackend(ReteBackendFactory.INSTANCE)
45 .withDefaultCachingBackend(ReteBackendFactory.INSTANCE) 45 .withDefaultCachingBackend(ReteBackendFactory.INSTANCE)
46 .withDefaultSearchBackend(RelationalLocalSearchBackendFactory.INSTANCE); 46 .withDefaultSearchBackend(LocalSearchGenericBackendFactory.INSTANCE);
47 rewriter = new CompositeRewriter(); 47 rewriter = new CompositeRewriter();
48 rewriter.addFirst(new DuplicateDnfRemover()); 48 rewriter.addFirst(new DuplicateDnfRemover());
49 rewriter.addFirst(new InputParameterResolver()); 49 rewriter.addFirst(new InputParameterResolver());
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendOperationExecutor.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendOperationExecutor.java
deleted file mode 100644
index fc75198c..00000000
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendOperationExecutor.java
+++ /dev/null
@@ -1,76 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2013, Zoltan Ujhelyi, Akos Horvath, Istvan Rath and Daniel Varro
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-v20.html.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.query.viatra.internal.localsearch;
10
11import tools.refinery.viatra.runtime.localsearch.MatchingFrame;
12import tools.refinery.viatra.runtime.localsearch.matcher.ISearchContext;
13import tools.refinery.viatra.runtime.localsearch.operations.ISearchOperation.ISearchOperationExecutor;
14
15import java.util.Iterator;
16
17/**
18 * An operation that can be used to enumerate all possible values for a single position based on a constraint
19 * @author Zoltan Ujhelyi, Akos Horvath
20 * @since 2.0
21 */
22abstract class ExtendOperationExecutor<T> implements ISearchOperationExecutor {
23
24 private Iterator<? extends T> it;
25
26 /**
27 * Returns an iterator with the possible options from the current state
28 * @since 2.0
29 */
30 @SuppressWarnings("squid:S1452")
31 protected abstract Iterator<? extends T> getIterator(MatchingFrame frame, ISearchContext context);
32 /**
33 * Updates the frame with the next element of the iterator. Called during {@link #execute(MatchingFrame, ISearchContext)}.
34 *
35 * @return true if the update is successful or false otherwise; in case of false is returned, the next element should be taken from the iterator.
36 * @since 2.0
37 */
38 protected abstract boolean fillInValue(T newValue, MatchingFrame frame, ISearchContext context);
39
40 /**
41 * Restores the frame to the state before {@link #fillInValue(Object, MatchingFrame, ISearchContext)}. Called during
42 * {@link #onBacktrack(MatchingFrame, ISearchContext)}.
43 *
44 * @since 2.0
45 */
46 protected abstract void cleanup(MatchingFrame frame, ISearchContext context);
47
48 @Override
49 public void onInitialize(MatchingFrame frame, ISearchContext context) {
50 it = getIterator(frame, context);
51 }
52
53 @Override
54 public void onBacktrack(MatchingFrame frame, ISearchContext context) {
55 it = null;
56
57 }
58
59 /**
60 * Fixed version of {@link tools.refinery.viatra.runtime.localsearch.operations.ExtendOperationExecutor#execute}
61 * that handles failed unification of variables correctly.
62 * @param frame The matching frame to extend.
63 * @param context The search context.
64 * @return {@code true} if an extension was found, {@code false} otherwise.
65 */
66 @Override
67 public boolean execute(MatchingFrame frame, ISearchContext context) {
68 while (it.hasNext()) {
69 var newValue = it.next();
70 if (fillInValue(newValue, frame, context)) {
71 return true;
72 }
73 }
74 return false;
75 }
76}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendPositivePatternCall.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendPositivePatternCall.java
deleted file mode 100644
index b8b6b159..00000000
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendPositivePatternCall.java
+++ /dev/null
@@ -1,117 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Grill Balázs, IncQueryLabs
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-v20.html.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.query.viatra.internal.localsearch;
10
11import tools.refinery.viatra.runtime.localsearch.MatchingFrame;
12import tools.refinery.viatra.runtime.localsearch.matcher.ISearchContext;
13import tools.refinery.viatra.runtime.localsearch.operations.IPatternMatcherOperation;
14import tools.refinery.viatra.runtime.localsearch.operations.ISearchOperation;
15import tools.refinery.viatra.runtime.localsearch.operations.util.CallInformation;
16import tools.refinery.viatra.runtime.matchers.backend.IQueryResultProvider;
17import tools.refinery.viatra.runtime.matchers.tuple.Tuple;
18import tools.refinery.viatra.runtime.matchers.tuple.TupleMask;
19import tools.refinery.viatra.runtime.matchers.tuple.VolatileModifiableMaskedTuple;
20
21import java.util.Iterator;
22import java.util.List;
23import java.util.function.Function;
24
25/**
26 * @author Grill Balázs
27 * @since 1.4
28 *
29 */
30public class ExtendPositivePatternCall implements ISearchOperation, IPatternMatcherOperation {
31
32 private class Executor extends ExtendOperationExecutor<Tuple> {
33 private final VolatileModifiableMaskedTuple maskedTuple;
34
35 public Executor() {
36 maskedTuple = new VolatileModifiableMaskedTuple(information.getThinFrameMask());
37 }
38
39 @Override
40 protected Iterator<? extends Tuple> getIterator(MatchingFrame frame, ISearchContext context) {
41 maskedTuple.updateTuple(frame);
42 IQueryResultProvider matcher = context.getMatcher(information.getCallWithAdornment());
43 return matcher.getAllMatches(information.getParameterMask(), maskedTuple).iterator();
44 }
45
46 /**
47 * @since 2.0
48 */
49 @Override
50 protected boolean fillInValue(Tuple result, MatchingFrame frame, ISearchContext context) {
51 TupleMask mask = information.getFullFrameMask();
52 // The first loop clears out the elements from a possible previous iteration
53 for(int i : information.getFreeParameterIndices()) {
54 mask.set(frame, i, null);
55 }
56 for(int i : information.getFreeParameterIndices()) {
57 Object oldValue = mask.getValue(frame, i);
58 Object valueToFill = result.get(i);
59 if (oldValue != null && !oldValue.equals(valueToFill)){
60 // If the inverse map contains more than one values for the same key, it means that these arguments are unified by the caller.
61 // In this case if the callee assigns different values the frame shall be dropped
62 return false;
63 }
64 mask.set(frame, i, valueToFill);
65 }
66 return true;
67 }
68
69 @Override
70 protected void cleanup(MatchingFrame frame, ISearchContext context) {
71 TupleMask mask = information.getFullFrameMask();
72 for(int i : information.getFreeParameterIndices()){
73 mask.set(frame, i, null);
74 }
75
76 }
77
78 @Override
79 public ISearchOperation getOperation() {
80 return ExtendPositivePatternCall.this;
81 }
82 }
83
84 private final CallInformation information;
85
86 /**
87 * @since 1.7
88 */
89 public ExtendPositivePatternCall(CallInformation information) {
90 this.information = information;
91 }
92
93 @Override
94 public ISearchOperationExecutor createExecutor() {
95 return new Executor();
96 }
97
98 @Override
99 public List<Integer> getVariablePositions() {
100 return information.getVariablePositions();
101 }
102
103 @Override
104 public String toString() {
105 return toString(Object::toString);
106 }
107
108 @Override
109 public String toString(@SuppressWarnings("squid:S4276") Function<Integer, String> variableMapping) {
110 return "extend find " + information.toString(variableMapping);
111 }
112
113 @Override
114 public CallInformation getCallInformation() {
115 return information;
116 }
117}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/GenericTypeExtend.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/GenericTypeExtend.java
deleted file mode 100644
index 0ee69b88..00000000
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/GenericTypeExtend.java
+++ /dev/null
@@ -1,137 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd.
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-v20.html.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.query.viatra.internal.localsearch;
10
11import tools.refinery.viatra.runtime.localsearch.MatchingFrame;
12import tools.refinery.viatra.runtime.localsearch.matcher.ISearchContext;
13import tools.refinery.viatra.runtime.localsearch.operations.IIteratingSearchOperation;
14import tools.refinery.viatra.runtime.localsearch.operations.ISearchOperation;
15import tools.refinery.viatra.runtime.matchers.context.IInputKey;
16import tools.refinery.viatra.runtime.matchers.tuple.Tuple;
17import tools.refinery.viatra.runtime.matchers.tuple.TupleMask;
18import tools.refinery.viatra.runtime.matchers.tuple.VolatileMaskedTuple;
19import tools.refinery.viatra.runtime.matchers.util.Preconditions;
20
21import java.util.*;
22import java.util.function.Function;
23import java.util.stream.Collectors;
24
25/**
26 * @author Zoltan Ujhelyi
27 * @since 1.7
28 */
29public class GenericTypeExtend implements IIteratingSearchOperation {
30 private class Executor extends ExtendOperationExecutor<Tuple> {
31 private final VolatileMaskedTuple maskedTuple;
32
33 public Executor() {
34 this.maskedTuple = new VolatileMaskedTuple(callMask);
35 }
36
37 @Override
38 protected Iterator<? extends Tuple> getIterator(MatchingFrame frame, ISearchContext context) {
39 maskedTuple.updateTuple(frame);
40 return context.getRuntimeContext().enumerateTuples(type, indexerMask, maskedTuple).iterator();
41 }
42
43 @Override
44 protected boolean fillInValue(Tuple newTuple, MatchingFrame frame, ISearchContext context) {
45 for (Integer position : unboundVariableIndices) {
46 frame.setValue(position, null);
47 }
48 for (int i = 0; i < positions.length; i++) {
49 Object newValue = newTuple.get(i);
50 Object oldValue = frame.getValue(positions[i]);
51 if (oldValue != null && !Objects.equals(oldValue, newValue)) {
52 // If positions tuple maps more than one values for the same element (e.g. loop), it means that
53 // these arguments are to unified by the caller. In this case if the callee assigns different values
54 // the frame shall be considered a failed match
55 return false;
56 }
57 frame.setValue(positions[i], newValue);
58 }
59 return true;
60 }
61
62 @Override
63 protected void cleanup(MatchingFrame frame, ISearchContext context) {
64 for (Integer position : unboundVariableIndices) {
65 frame.setValue(position, null);
66 }
67 }
68
69 @Override
70 public ISearchOperation getOperation() {
71 return GenericTypeExtend.this;
72 }
73 }
74
75 private final IInputKey type;
76 private final int[] positions;
77 private final List<Integer> positionList;
78 private final Set<Integer> unboundVariableIndices;
79 private final TupleMask indexerMask;
80 private final TupleMask callMask;
81
82 /**
83 *
84 * @param type
85 * the type to execute the extend operation on
86 * @param positions
87 * the parameter positions that represent the variables of the input key
88 * @param unboundVariableIndices
89 * the set of positions that are bound at the start of the operation
90 */
91 public GenericTypeExtend(IInputKey type, int[] positions, TupleMask callMask, TupleMask indexerMask, Set<Integer> unboundVariableIndices) {
92 Preconditions.checkArgument(positions.length == type.getArity(),
93 "The type %s requires %d parameters, but %d positions are provided", type.getPrettyPrintableName(),
94 type.getArity(), positions.length);
95 List<Integer> modifiablePositionList = new ArrayList<>();
96 for (int position : positions) {
97 modifiablePositionList.add(position);
98 }
99 this.positionList = Collections.unmodifiableList(modifiablePositionList);
100 this.positions = positions;
101 this.type = type;
102
103 this.unboundVariableIndices = unboundVariableIndices;
104 this.indexerMask = indexerMask;
105 this.callMask = callMask;
106 }
107
108 @Override
109 public IInputKey getIteratedInputKey() {
110 return type;
111 }
112
113 @Override
114 public ISearchOperationExecutor createExecutor() {
115 return new Executor();
116 }
117
118 @Override
119 public List<Integer> getVariablePositions() {
120 return positionList;
121 }
122
123 @Override
124 public String toString() {
125 return toString(Object::toString);
126 }
127
128 @Override
129 public String toString(@SuppressWarnings("squid:S4276") Function<Integer, String> variableMapping) {
130 return "extend " + type.getPrettyPrintableName() + "("
131 + positionList.stream()
132 .map(input -> String.format("%s%s", unboundVariableIndices.contains(input) ? "-" : "+", variableMapping.apply(input)))
133 .collect(Collectors.joining(", "))
134 + ")";
135 }
136
137}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchBackendFactory.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchBackendFactory.java
deleted file mode 100644
index 7d5401c6..00000000
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchBackendFactory.java
+++ /dev/null
@@ -1,60 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.localsearch;
7
8import tools.refinery.viatra.runtime.localsearch.matcher.integration.AbstractLocalSearchResultProvider;
9import tools.refinery.viatra.runtime.localsearch.matcher.integration.LocalSearchBackend;
10import tools.refinery.viatra.runtime.localsearch.matcher.integration.LocalSearchHints;
11import tools.refinery.viatra.runtime.localsearch.plan.IPlanProvider;
12import tools.refinery.viatra.runtime.localsearch.plan.SimplePlanProvider;
13import tools.refinery.viatra.runtime.matchers.backend.IMatcherCapability;
14import tools.refinery.viatra.runtime.matchers.backend.IQueryBackend;
15import tools.refinery.viatra.runtime.matchers.backend.IQueryBackendFactory;
16import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint;
17import tools.refinery.viatra.runtime.matchers.context.IQueryBackendContext;
18import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery;
19
20public class RelationalLocalSearchBackendFactory implements IQueryBackendFactory {
21 public static final RelationalLocalSearchBackendFactory INSTANCE = new RelationalLocalSearchBackendFactory();
22
23 private RelationalLocalSearchBackendFactory() {
24 }
25
26 @Override
27 public IQueryBackend create(IQueryBackendContext context) {
28 return new LocalSearchBackend(context) {
29 // Create a new {@link IPlanProvider}, because the original {@link LocalSearchBackend#planProvider} is not
30 // accessible.
31 private final IPlanProvider planProvider = new SimplePlanProvider(context.getLogger());
32
33 @Override
34 protected AbstractLocalSearchResultProvider initializeResultProvider(PQuery query,
35 QueryEvaluationHint hints) {
36 return new RelationalLocalSearchResultProvider(this, context, query, planProvider, hints);
37 }
38
39 @Override
40 public IQueryBackendFactory getFactory() {
41 return RelationalLocalSearchBackendFactory.this;
42 }
43 };
44 }
45
46 @Override
47 public Class<? extends IQueryBackend> getBackendClass() {
48 return LocalSearchBackend.class;
49 }
50
51 @Override
52 public IMatcherCapability calculateRequiredCapability(PQuery pQuery, QueryEvaluationHint queryEvaluationHint) {
53 return LocalSearchHints.parse(queryEvaluationHint);
54 }
55
56 @Override
57 public boolean isCaching() {
58 return false;
59 }
60}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchResultProvider.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchResultProvider.java
deleted file mode 100644
index 37d06864..00000000
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchResultProvider.java
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.localsearch;
7
8import tools.refinery.viatra.runtime.localsearch.matcher.integration.AbstractLocalSearchResultProvider;
9import tools.refinery.viatra.runtime.localsearch.matcher.integration.LocalSearchBackend;
10import tools.refinery.viatra.runtime.localsearch.matcher.integration.LocalSearchHints;
11import tools.refinery.viatra.runtime.localsearch.plan.IPlanProvider;
12import tools.refinery.viatra.runtime.localsearch.planner.compiler.IOperationCompiler;
13import tools.refinery.viatra.runtime.matchers.backend.QueryEvaluationHint;
14import tools.refinery.viatra.runtime.matchers.context.IQueryBackendContext;
15import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery;
16
17class RelationalLocalSearchResultProvider extends AbstractLocalSearchResultProvider {
18 public RelationalLocalSearchResultProvider(LocalSearchBackend backend, IQueryBackendContext context, PQuery query,
19 IPlanProvider planProvider, QueryEvaluationHint userHints) {
20 super(backend, context, query, planProvider, userHints);
21 }
22
23 @Override
24 protected IOperationCompiler getOperationCompiler(IQueryBackendContext backendContext,
25 LocalSearchHints configuration) {
26 return new RelationalOperationCompiler(runtimeContext);
27 }
28}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalOperationCompiler.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalOperationCompiler.java
deleted file mode 100644
index 37f264ae..00000000
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalOperationCompiler.java
+++ /dev/null
@@ -1,70 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.localsearch;
7
8import tools.refinery.viatra.runtime.localsearch.operations.generic.GenericTypeExtendSingleValue;
9import tools.refinery.viatra.runtime.localsearch.operations.util.CallInformation;
10import tools.refinery.viatra.runtime.localsearch.planner.compiler.GenericOperationCompiler;
11import tools.refinery.viatra.runtime.matchers.context.IInputKey;
12import tools.refinery.viatra.runtime.matchers.context.IQueryRuntimeContext;
13import tools.refinery.viatra.runtime.matchers.psystem.PVariable;
14import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.PositivePatternCall;
15import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.TypeConstraint;
16import tools.refinery.viatra.runtime.matchers.tuple.Tuple;
17import tools.refinery.viatra.runtime.matchers.tuple.TupleMask;
18
19import java.util.*;
20
21public class RelationalOperationCompiler extends GenericOperationCompiler {
22 public RelationalOperationCompiler(IQueryRuntimeContext runtimeContext) {
23 super(runtimeContext);
24 }
25
26 @Override
27 protected void createExtend(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) {
28 IInputKey inputKey = typeConstraint.getSupplierKey();
29 Tuple tuple = typeConstraint.getVariablesTuple();
30
31 int[] positions = new int[tuple.getSize()];
32 List<Integer> boundVariableIndices = new ArrayList<>();
33 List<Integer> boundVariables = new ArrayList<>();
34 Set<Integer> unboundVariables = new HashSet<>();
35 for (int i = 0; i < tuple.getSize(); i++) {
36 PVariable variable = (PVariable) tuple.get(i);
37 Integer position = variableMapping.get(variable);
38 positions[i] = position;
39 if (variableBindings.get(typeConstraint).contains(position)) {
40 boundVariableIndices.add(i);
41 boundVariables.add(position);
42 } else {
43 unboundVariables.add(position);
44 }
45 }
46 TupleMask indexerMask = TupleMask.fromSelectedIndices(inputKey.getArity(), boundVariableIndices);
47 TupleMask callMask = TupleMask.fromSelectedIndices(variableMapping.size(), boundVariables);
48 // If multiple tuple elements from the indexer should be bound to the same variable, we must use a
49 // {@link GenericTypeExtend} check whether the tuple elements have the same value.
50 if (unboundVariables.size() == 1 && indexerMask.getSize() + 1 == indexerMask.getSourceWidth()) {
51 operations.add(new GenericTypeExtendSingleValue(inputKey, positions, callMask, indexerMask,
52 unboundVariables.iterator().next()));
53 } else {
54 // Use a fixed version of
55 // {@code tools.refinery.viatra.runtime.localsearch.operations.generic.GenericTypeExtend} that handles
56 // failed unification of variables correctly.
57 operations.add(new GenericTypeExtend(inputKey, positions, callMask, indexerMask, unboundVariables));
58 }
59 }
60
61 @Override
62 protected void createExtend(PositivePatternCall pCall, Map<PVariable, Integer> variableMapping) {
63 CallInformation information = CallInformation.create(pCall, variableMapping, variableBindings.get(pCall));
64 // Use a fixed version of
65 // {@code tools.refinery.viatra.runtime.localsearch.operations.extend.ExtendPositivePatternCall} that handles
66 // failed unification of variables correctly.
67 operations.add(new ExtendPositivePatternCall(information));
68 dependencies.add(information.getCallWithAdornment());
69 }
70}
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/ExtendOperationExecutor.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/ExtendOperationExecutor.java
index 01179118..a72c30dd 100644
--- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/ExtendOperationExecutor.java
+++ b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/ExtendOperationExecutor.java
@@ -1,19 +1,20 @@
1/******************************************************************************* 1/*******************************************************************************
2 * Copyright (c) 2010-2013, Zoltan Ujhelyi, Akos Horvath, Istvan Rath and Daniel Varro 2 * Copyright (c) 2010-2013, Zoltan Ujhelyi, Akos Horvath, Istvan Rath and Daniel Varro
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
3 * This program and the accompanying materials are made available under the 4 * 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 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html. 6 * http://www.eclipse.org/legal/epl-v20.html.
6 * 7 *
7 * SPDX-License-Identifier: EPL-2.0 8 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/ 9 *******************************************************************************/
9package tools.refinery.viatra.runtime.localsearch.operations; 10package tools.refinery.viatra.runtime.localsearch.operations;
10 11
11import java.util.Iterator;
12
13import tools.refinery.viatra.runtime.localsearch.MatchingFrame; 12import tools.refinery.viatra.runtime.localsearch.MatchingFrame;
14import tools.refinery.viatra.runtime.localsearch.matcher.ISearchContext; 13import tools.refinery.viatra.runtime.localsearch.matcher.ISearchContext;
15import tools.refinery.viatra.runtime.localsearch.operations.ISearchOperation.ISearchOperationExecutor; 14import tools.refinery.viatra.runtime.localsearch.operations.ISearchOperation.ISearchOperationExecutor;
16 15
16import java.util.Iterator;
17
17/** 18/**
18 * An operation that can be used to enumerate all possible values for a single position based on a constraint 19 * An operation that can be used to enumerate all possible values for a single position based on a constraint
19 * @author Zoltan Ujhelyi, Akos Horvath 20 * @author Zoltan Ujhelyi, Akos Horvath
@@ -31,42 +32,46 @@ public abstract class ExtendOperationExecutor<T> implements ISearchOperationExec
31 protected abstract Iterator<? extends T> getIterator(MatchingFrame frame, ISearchContext context); 32 protected abstract Iterator<? extends T> getIterator(MatchingFrame frame, ISearchContext context);
32 /** 33 /**
33 * Updates the frame with the next element of the iterator. Called during {@link #execute(MatchingFrame, ISearchContext)}. 34 * Updates the frame with the next element of the iterator. Called during {@link #execute(MatchingFrame, ISearchContext)}.
34 * 35 *
35 * @return true if the update is successful or false otherwise; in case of false is returned, the next element should be taken from the iterator. 36 * @return true if the update is successful or false otherwise; in case of false is returned, the next element should be taken from the iterator.
36 * @since 2.0 37 * @since 2.0
37 */ 38 */
38 protected abstract boolean fillInValue(T newValue, MatchingFrame frame, ISearchContext context); 39 protected abstract boolean fillInValue(T newValue, MatchingFrame frame, ISearchContext context);
39 40
40 /** 41 /**
41 * Restores the frame to the state before {@link #fillInValue(Object, MatchingFrame, ISearchContext)}. Called during 42 * Restores the frame to the state before {@link #fillInValue(Object, MatchingFrame, ISearchContext)}. Called during
42 * {@link #onBacktrack(MatchingFrame, ISearchContext)}. 43 * {@link #onBacktrack(MatchingFrame, ISearchContext)}.
43 * 44 *
44 * @since 2.0 45 * @since 2.0
45 */ 46 */
46 protected abstract void cleanup(MatchingFrame frame, ISearchContext context); 47 protected abstract void cleanup(MatchingFrame frame, ISearchContext context);
47 48
48 @Override 49 @Override
49 public void onInitialize(MatchingFrame frame, ISearchContext context) { 50 public void onInitialize(MatchingFrame frame, ISearchContext context) {
50 it = getIterator(frame, context); 51 it = getIterator(frame, context);
51 } 52 }
52 53
53 @Override 54 @Override
54 public void onBacktrack(MatchingFrame frame, ISearchContext context) { 55 public void onBacktrack(MatchingFrame frame, ISearchContext context) {
55 it = null; 56 it = null;
56 57
57 } 58 }
58 59
59 @Override 60 /**
60 public boolean execute(MatchingFrame frame, ISearchContext context) { 61 * Fixed version that handles failed unification of variables correctly.
61 if (it.hasNext()){ 62 * @param frame The matching frame to extend.
62 T newValue = it.next(); 63 * @param context The search context.
63 while(!fillInValue(newValue, frame, context) && it.hasNext()){ 64 * @return {@code true} if an extension was found, {@code false} otherwise.
64 newValue = it.next(); 65 */
65 } 66 @Override
66 return true; 67 public boolean execute(MatchingFrame frame, ISearchContext context) {
67 } else { 68 while (it.hasNext()) {
68 return false; 69 var newValue = it.next();
69 } 70 if (fillInValue(newValue, frame, context)) {
70 } 71 return true;
71 72 }
73 }
74 return false;
75 }
76
72} 77}
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/compiler/GenericOperationCompiler.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/compiler/GenericOperationCompiler.java
index 606048b7..d86982e9 100644
--- a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/compiler/GenericOperationCompiler.java
+++ b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/compiler/GenericOperationCompiler.java
@@ -1,19 +1,14 @@
1/******************************************************************************* 1/*******************************************************************************
2 * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd. 2 * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd.
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
3 * This program and the accompanying materials are made available under the 4 * 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 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html. 6 * http://www.eclipse.org/legal/epl-v20.html.
6 * 7 *
7 * SPDX-License-Identifier: EPL-2.0 8 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/ 9 *******************************************************************************/
9package tools.refinery.viatra.runtime.localsearch.planner.compiler; 10package tools.refinery.viatra.runtime.localsearch.planner.compiler;
10 11
11import java.util.ArrayList;
12import java.util.HashSet;
13import java.util.List;
14import java.util.Map;
15import java.util.Set;
16
17import tools.refinery.viatra.runtime.localsearch.operations.generic.GenericTypeCheck; 12import tools.refinery.viatra.runtime.localsearch.operations.generic.GenericTypeCheck;
18import tools.refinery.viatra.runtime.localsearch.operations.generic.GenericTypeExtend; 13import tools.refinery.viatra.runtime.localsearch.operations.generic.GenericTypeExtend;
19import tools.refinery.viatra.runtime.localsearch.operations.generic.GenericTypeExtendSingleValue; 14import tools.refinery.viatra.runtime.localsearch.operations.generic.GenericTypeExtendSingleValue;
@@ -25,6 +20,8 @@ import tools.refinery.viatra.runtime.matchers.psystem.basicenumerables.TypeConst
25import tools.refinery.viatra.runtime.matchers.tuple.Tuple; 20import tools.refinery.viatra.runtime.matchers.tuple.Tuple;
26import tools.refinery.viatra.runtime.matchers.tuple.TupleMask; 21import tools.refinery.viatra.runtime.matchers.tuple.TupleMask;
27 22
23import java.util.*;
24
28/** 25/**
29 * @author Zoltan Ujhelyi 26 * @author Zoltan Ujhelyi
30 * @since 1.7 27 * @since 1.7
@@ -46,9 +43,9 @@ public class GenericOperationCompiler extends AbstractOperationCompiler {
46 positions[i] = variableMapping.get(variable); 43 positions[i] = variableMapping.get(variable);
47 } 44 }
48 operations.add(new GenericTypeCheck(inputKey, positions, TupleMask.fromSelectedIndices(variableMapping.size(), positions))); 45 operations.add(new GenericTypeCheck(inputKey, positions, TupleMask.fromSelectedIndices(variableMapping.size(), positions)));
49 46
50 } 47 }
51 48
52 @Override 49 @Override
53 protected void createCheck(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) { 50 protected void createCheck(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) {
54 IInputKey inputKey = typeConstraint.getSupplierKey(); 51 IInputKey inputKey = typeConstraint.getSupplierKey();
@@ -60,7 +57,7 @@ public class GenericOperationCompiler extends AbstractOperationCompiler {
60 } 57 }
61 operations.add(new GenericTypeCheck(inputKey, positions, TupleMask.fromSelectedIndices(variableMapping.size(), positions))); 58 operations.add(new GenericTypeCheck(inputKey, positions, TupleMask.fromSelectedIndices(variableMapping.size(), positions)));
62 } 59 }
63 60
64 @Override 61 @Override
65 protected void createUnaryTypeCheck(IInputKey inputKey, int position) { 62 protected void createUnaryTypeCheck(IInputKey inputKey, int position) {
66 int[] positions = new int[] {position}; 63 int[] positions = new int[] {position};
@@ -71,7 +68,7 @@ public class GenericOperationCompiler extends AbstractOperationCompiler {
71 protected void createExtend(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) { 68 protected void createExtend(TypeConstraint typeConstraint, Map<PVariable, Integer> variableMapping) {
72 IInputKey inputKey = typeConstraint.getSupplierKey(); 69 IInputKey inputKey = typeConstraint.getSupplierKey();
73 Tuple tuple = typeConstraint.getVariablesTuple(); 70 Tuple tuple = typeConstraint.getVariablesTuple();
74 71
75 int[] positions = new int[tuple.getSize()]; 72 int[] positions = new int[tuple.getSize()];
76 List<Integer> boundVariableIndices = new ArrayList<>(); 73 List<Integer> boundVariableIndices = new ArrayList<>();
77 List<Integer> boundVariables = new ArrayList<>(); 74 List<Integer> boundVariables = new ArrayList<>();
@@ -89,7 +86,9 @@ public class GenericOperationCompiler extends AbstractOperationCompiler {
89 } 86 }
90 TupleMask indexerMask = TupleMask.fromSelectedIndices(inputKey.getArity(), boundVariableIndices); 87 TupleMask indexerMask = TupleMask.fromSelectedIndices(inputKey.getArity(), boundVariableIndices);
91 TupleMask callMask = TupleMask.fromSelectedIndices(variableMapping.size(), boundVariables); 88 TupleMask callMask = TupleMask.fromSelectedIndices(variableMapping.size(), boundVariables);
92 if (unboundVariables.size() == 1) { 89 // If multiple tuple elements from the indexer should be bound to the same variable, we must use a
90 // {@link GenericTypeExtend} check whether the tuple elements have the same value.
91 if (unboundVariables.size() == 1 && indexerMask.getSize() + 1 == indexerMask.getSourceWidth()) {
93 operations.add(new GenericTypeExtendSingleValue(inputKey, positions, callMask, indexerMask, unboundVariables.iterator().next())); 92 operations.add(new GenericTypeExtendSingleValue(inputKey, positions, callMask, indexerMask, unboundVariables.iterator().next()));
94 } else { 93 } else {
95 operations.add(new GenericTypeExtend(inputKey, positions, callMask, indexerMask, unboundVariables)); 94 operations.add(new GenericTypeExtend(inputKey, positions, callMask, indexerMask, unboundVariables));