aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/PlanState.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/PlanState.java')
-rw-r--r--subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/PlanState.java283
1 files changed, 283 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/PlanState.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/PlanState.java
new file mode 100644
index 00000000..e93b07bc
--- /dev/null
+++ b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/planner/PlanState.java
@@ -0,0 +1,283 @@
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 *******************************************************************************/
9package tools.refinery.viatra.runtime.localsearch.planner;
10
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.Collections;
14import java.util.Comparator;
15import java.util.HashSet;
16import java.util.List;
17import java.util.Map;
18import java.util.Set;
19
20import tools.refinery.viatra.runtime.localsearch.planner.util.OperationCostComparator;
21import tools.refinery.viatra.runtime.matchers.algorithms.OrderedIterableMerge;
22import tools.refinery.viatra.runtime.matchers.psystem.PBody;
23import tools.refinery.viatra.runtime.matchers.psystem.PConstraint;
24import tools.refinery.viatra.runtime.matchers.psystem.PVariable;
25
26/**
27 * This class represents the state of the plan during planning.
28 *
29 * <p> A PlanState represents a sequence of operations (operationsList) and caches the computed cost
30 * for this operation sequence. The list and the cost are initialized in the constructor.
31 * However, #categorizeChecks() also updates the operations list (by suffixing checks)
32 *
33 * @author Marton Bur
34 * @noreference This class is not intended to be referenced by clients.
35 */
36public class PlanState {
37
38 private final PBody pBody;
39 private final List<PConstraintInfo> operationsList;
40 private final Set<PVariable> boundVariables;
41 private final Collection<PVariable> deltaVariables; /* bound since ancestor plan */
42 private final Set<PConstraint> enforcedConstraints;
43
44 private double cummulativeProduct;
45 private double cost;
46
47 private static Comparator<PConstraintInfo> infoComparator = new OperationCostComparator();
48
49 /*
50 * For a short explanation of past, present and future operations,
51 * see class
52 */
53 private List<PConstraintInfo> presentExtends;
54
55 /**
56 * Creates an initial state
57 */
58 public PlanState(PBody pBody, Set<PVariable> boundVariables) {
59
60 this(pBody, new ArrayList<>(), boundVariables, boundVariables /* also the delta */,
61 0.0 /* initial cost */, 1.0 /*initial branch count */);
62 }
63
64 public PlanState cloneWithApplied(PConstraintInfo op) {
65 // Create operation list based on the current state
66 ArrayList<PConstraintInfo> newOperationsList =
67 // pre-reserve excess capacity for later addition of CHECK ops
68 new ArrayList<>(pBody.getConstraints().size());
69 newOperationsList.addAll(this.getOperations());
70 newOperationsList.add(op);
71
72 // Bind the variables of the op
73 Collection<PVariable> deltaVariables = op.getFreeVariables();
74 Set<PVariable> allBoundVariables =
75 // pre-reserve exact capacity as variables are known
76 // (will not be affected by adding CHECK ops later)
77 new HashSet<>(this.getBoundVariables().size() + deltaVariables.size());
78 allBoundVariables.addAll(this.getBoundVariables());
79 allBoundVariables.addAll(deltaVariables);
80
81 PlanState newState = new PlanState(getAssociatedPBody(), newOperationsList, allBoundVariables, deltaVariables,
82 cost, cummulativeProduct);
83 newState.accountNewOperation(op);
84 return newState;
85 }
86
87 private PlanState(PBody pBody, List<PConstraintInfo> operationsList,
88 Set<PVariable> boundVariables, Collection<PVariable> deltaVariables,
89 double cost, double cummulativeProduct)
90 {
91 this.pBody = pBody;
92 this.operationsList = operationsList;
93 this.boundVariables = boundVariables;
94 this.enforcedConstraints = new HashSet<>();
95 this.deltaVariables = deltaVariables;
96 this.cost = cost;
97 this.cummulativeProduct = cummulativeProduct;
98 }
99
100 // NOT included for EXTEND: bind all variables of op
101 private void accountNewOperation(PConstraintInfo constraintInfo) {
102 this.enforcedConstraints.add(constraintInfo.getConstraint());
103 accountCost(constraintInfo);
104 }
105
106 private void accountCost(PConstraintInfo constraintInfo) {
107 double constraintCost = constraintInfo.getCost();
108 double branchFactor = constraintCost;
109 if (constraintCost > 0){
110 cost += cummulativeProduct * constraintCost;
111 cummulativeProduct *= branchFactor;
112 }
113 }
114
115
116 public Set<PConstraint> getEnforcedConstraints() {
117 return enforcedConstraints;
118 }
119
120 /**
121 * Re-categorizes given extend operations into already applied or no longer applicable ones (discarded),
122 * immediately applicable ones (saved as presently viable extends),
123 * and not yet applicable ones (discarded).
124 *
125 * @param allPotentialExtendInfos all other extends that may be applicable
126 * to this plan state now or in the future;
127 * MUST consist of "extend" constraint applications only (at least one free variable)
128 */
129 public void updateExtends(Iterable<PConstraintInfo> allPotentialExtendInfos) {
130 presentExtends = new ArrayList<>();
131
132
133 // categorize future/present extend constraint infos
134 for (PConstraintInfo op : allPotentialExtendInfos) {
135 updateExtendInternal(op);
136 }
137 }
138
139 /**
140 * Re-categorizes given extend operations into already applied or no longer applicable ones (discarded),
141 * immediately applicable ones (saved as presently viable extends),
142 * and not yet applicable ones (discarded).
143 *
144 * @param extendOpsByBoundVariables all EXTEND operations indexed by affected <i>bound</i> variables
145 * MUST consist of "extend" constraint applications only (at least one free variable)
146 */
147 public void updateExtendsBasedOnDelta(
148 Iterable<PConstraintInfo> previousPresentExtends,
149 Map<PVariable, ? extends Collection<PConstraintInfo>> extendOpsByBoundVariables)
150 {
151 presentExtends = new ArrayList<>();
152 if (operationsList.isEmpty())
153 throw new IllegalStateException("Not applicable as starting step");
154
155 for (PConstraintInfo extend: previousPresentExtends) {
156 updateExtendInternal(extend);
157 }
158
159 Set<PConstraintInfo> affectedExtends = new HashSet<>();
160 for (PVariable variable : deltaVariables) {
161 // only those check ops may become applicable that have an affected variable in the delta
162 Collection<PConstraintInfo> extendsForVariable = extendOpsByBoundVariables.get(variable);
163 if (null != extendsForVariable) {
164 affectedExtends.addAll(extendsForVariable);
165 }
166 }
167 for (PConstraintInfo extend: affectedExtends) {
168 updateExtendInternal(extend);
169 }
170 }
171
172 private void updateExtendInternal(PConstraintInfo op) {
173 if(!enforcedConstraints.contains(op.getConstraint())) {
174 categorizeExtend(op);
175 }
176 }
177
178 /**
179 * Check operations that newly became applicable (see {@link #getDeltaVariables()})
180 * are appended to operations lists.
181 *
182 * <p> Will never discover degenerate checks (of PConstraints with zero variables),
183 * so must not use on initial state.
184 *
185 * @param allPotentialCheckInfos all CHECK operations
186 * MUST consist of "check" constraint applications only (no free variables)
187 * and must be iterable in decreasing order of cost
188 *
189 *
190 */
191 public void applyChecks(List<PConstraintInfo> allPotentialCheckInfos) {
192 applyChecksInternal(allPotentialCheckInfos);
193 }
194
195 /**
196 * Immediately applicable checks are appended to operations lists.
197 *
198 * @param checkOpsByVariables all CHECK operations indexed by affected variables
199 * MUST consist of "check" constraint applications only (no free variables)
200 * and each bucket must be iterable in decreasing order of cost
201 */
202 public void applyChecksBasedOnDelta(Map<PVariable, List<PConstraintInfo>> checkOpsByVariables) {
203 if (operationsList.isEmpty())
204 throw new IllegalStateException("Not applicable as starting step");
205
206 Iterable<PConstraintInfo> affectedChecks = Collections.emptyList();
207
208 for (PVariable variable : deltaVariables) {
209 // only those check ops may become applicable that have an affected variable in the delta
210 List<PConstraintInfo> checksForVariable = checkOpsByVariables.get(variable);
211 if (null != checksForVariable) {
212 affectedChecks = OrderedIterableMerge.mergeUniques(affectedChecks, checksForVariable, infoComparator);
213 }
214 }
215
216 // checks retain their order, no re-sorting needed
217 applyChecksInternal(affectedChecks);
218 }
219
220 private void applyChecksInternal(Iterable<PConstraintInfo> checks) {
221 for (PConstraintInfo checkInfo : checks) {
222 if (this.boundVariables.containsAll(checkInfo.getBoundVariables()) &&
223 !enforcedConstraints.contains(checkInfo.getConstraint()))
224 {
225 operationsList.add(checkInfo);
226 accountNewOperation(checkInfo);
227 }
228 }
229 }
230
231
232 private void categorizeExtend(PConstraintInfo constraintInfo) {
233 PConstraintCategory category = constraintInfo.getCategory(pBody, boundVariables);
234 if (category == PConstraintCategory.PRESENT) {
235 presentExtends.add(constraintInfo);
236 } else {
237 // do not categorize past/future operations
238 }
239 }
240
241
242 public PBody getAssociatedPBody() {
243 return pBody;
244 }
245
246 public List<PConstraintInfo> getOperations() {
247 return operationsList;
248 }
249
250 public Set<PVariable> getBoundVariables() {
251 return boundVariables;
252 }
253
254 /**
255 * @return the derived cost of the plan contained in the state
256 */
257 public double getCost() {
258 return cost;
259 }
260
261
262 /**
263 * @return cumulative branching factor
264 * @since 2.1
265 */
266 public double getCummulativeProduct() {
267 return cummulativeProduct;
268 }
269
270 public List<PConstraintInfo> getPresentExtends() {
271 return presentExtends;
272 }
273
274 /**
275 * Contains only those variables that are added by the newest extend
276 * (or the initially bound ones if no extend yet)
277 */
278 public Collection<PVariable> getDeltaVariables() {
279 return deltaVariables;
280 }
281
282
283}