aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java')
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java563
1 files changed, 563 insertions, 0 deletions
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java
new file mode 100644
index 00000000..4c6b4097
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java
@@ -0,0 +1,563 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi 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 org.eclipse.viatra.dse.base;
10
11import java.lang.reflect.InvocationTargetException;
12import java.util.ArrayList;
13import java.util.Collection;
14import java.util.HashMap;
15import java.util.Iterator;
16import java.util.List;
17import java.util.Map;
18import java.util.Random;
19
20import org.apache.log4j.Logger;
21import org.eclipse.emf.common.notify.Notifier;
22import org.eclipse.emf.edit.command.ChangeCommand;
23import org.eclipse.emf.edit.domain.EditingDomain;
24import org.eclipse.viatra.dse.api.DSEException;
25import org.eclipse.viatra.dse.api.SolutionTrajectory;
26import org.eclipse.viatra.dse.designspace.api.IBacktrackListener;
27import org.eclipse.viatra.dse.designspace.api.IDesignSpace;
28import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo;
29import org.eclipse.viatra.dse.objectives.ActivationFitnessProcessor;
30import org.eclipse.viatra.dse.statecode.IStateCoder;
31import org.eclipse.viatra.dse.visualizer.IExploreEventHandler;
32import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine;
33import org.eclipse.viatra.query.runtime.api.IPatternMatch;
34import org.eclipse.viatra.transformation.evm.api.Activation;
35import org.eclipse.viatra.transformation.evm.api.Context;
36import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet;
37import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
38
39public class DesignSpaceManager implements IBacktrackListener {
40
41 private final IStateCoder stateCoder;
42 private final EditingDomain domain;
43 private Notifier model;
44
45 private IDesignSpace designSpace;
46
47 private final TrajectoryInfo trajectory;
48
49 // the occurence vector callback
50 private List<IExploreEventHandler> handlers;
51
52 // Dummy context for evm
53 private final Context evmContext = Context.create();
54
55 private Logger logger = Logger.getLogger(this.getClass());
56
57 private boolean isNewState = false;
58 private Map<BatchTransformationRule<?, ?>, ActivationFitnessProcessor> activationFitnessProcessors;
59 private Map<BatchTransformationRule<?, ?>, String> activationFitnessProcessorNames;
60 private ThreadContext context;
61
62 private ActivationCodesConflictSet activationCodes;
63 private ChangeableConflictSet conflictSet;
64
65 private AdvancedViatraQueryEngine engine;
66
67 private Random random = new Random();
68
69 private long forwardTime = 0;
70 private long backtrackingTime = 0;
71
72 public DesignSpaceManager(ThreadContext context) {
73
74 this.context = context;
75 model = context.getModel();
76 designSpace = context.getGlobalContext().getDesignSpace();
77 domain = context.getEditingDomain();
78
79 conflictSet = context.getConflictResolver().getLastCreatedConflictSet();
80
81 stateCoder = context.getStateCoder();
82 Object initialStateId = stateCoder.createStateCode();
83 designSpace.addState(null, null, initialStateId);
84
85 activationCodes = context.getActivationCodesConflictSet();
86
87 engine = (AdvancedViatraQueryEngine) context.getQueryEngine();
88
89 this.trajectory = new TrajectoryInfo(initialStateId);
90
91 logger.debug("DesignSpaceManager initialized with initial model: " + initialStateId);
92 }
93
94 public void fireActivation(final Object transition) {
95 if (fireActivationSilent(transition)) {
96 return;
97 }
98
99 StringBuilder sb = new StringBuilder();
100 sb.append(
101 "A retrieved Transition SHOULD have a matching Activation. Possible causes: the state serializer is faulty; the algorithm choosed a wrong Transition.");
102 sb.append("\nSought transition: ");
103 sb.append(transition);
104 Object currentStateId = getCurrentState();
105 sb.append("\nCurrent known state: ");
106 sb.append(currentStateId);
107 Object actualStateId = stateCoder.createStateCode();
108 sb.append("\nActual state: ");
109 sb.append((actualStateId.equals(currentStateId) ? "same as current" : actualStateId));
110 sb.append("\n");
111 sb.append(trajectory);
112 sb.append("\nAvailable transitions:");
113 for (Activation<?> act : conflictSet.getNextActivations()) {
114 IPatternMatch match = (IPatternMatch) act.getAtom();
115 Object code = generateMatchCode(match);
116 sb.append("\n\t");
117 sb.append(code);
118 }
119
120 throw new DSEException(sb.toString());
121 }
122
123 public boolean tryFireActivation(final Object transition) {
124 return fireActivationSilent(transition);
125 }
126
127 private boolean fireActivationSilent(final Object transition) {
128 final Activation<?> activation = getActivationById(transition);
129
130 if (activation == null) {
131 return false;
132 }
133
134 BatchTransformationRule<?, ?> rule = getRuleByActivation(activation);
135
136 Map<String, Double> measureCosts = new HashMap<String, Double>();
137 if (activationFitnessProcessors != null && activationFitnessProcessors.containsKey(rule)) {
138 IPatternMatch match = (IPatternMatch) activation.getAtom();
139 ActivationFitnessProcessor processor = activationFitnessProcessors.get(rule);
140 double fitness = processor.process(match);
141 measureCosts.put(activationFitnessProcessorNames.get(rule), fitness);
142 }
143
144 ChangeCommand rc = new ChangeCommand(model) {
145 @Override
146 protected void doExecute() {
147 activation.fire(evmContext);
148 }
149 };
150
151 Object previousState = trajectory.getCurrentStateId();
152
153 long start = System.nanoTime();
154 domain.getCommandStack().execute(rc);
155 forwardTime += System.nanoTime() - start;
156
157 Object newStateId = stateCoder.createStateCode();
158 updateActivationCodes();
159
160 if (designSpace != null) {
161 isNewState = !designSpace.isTraversed(newStateId);
162 designSpace.addState(previousState, transition, newStateId);
163 }
164
165 trajectory.addStep(transition, rule, newStateId, measureCosts);
166
167 if (handlers != null) {
168 for (IExploreEventHandler iExploreEventHandler : handlers) {
169 iExploreEventHandler.transitionFired(transition);
170 }
171 }
172
173 logger.debug("Executed activation: " + transition);/*
174 * + " from state: " + previousState + " to " + newStateId);
175 */
176
177 return true;
178 }
179
180 public boolean executeRandomActivationId() {
181 Collection<Object> transitions = getTransitionsFromCurrentState();
182 int size = transitions.size();
183 if (size == 0) {
184 return false;
185 }
186
187 int index = random.nextInt(size);
188 Iterator<Object> iterator = transitions.iterator();
189 for (int i = 0; i < index; ++i) {
190 iterator.next();
191 }
192 Object transition = iterator.next();
193
194 fireActivation(transition);
195 return true;
196 }
197
198 public int executeTrajectory(Object[] trajectoryToExecute) {
199 return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, false, true);
200 }
201
202 public int executeTrajectory(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex) {
203 return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, false, true);
204 }
205
206 public int executeTrajectoryByTrying(Object[] trajectoryToExecute) {
207 return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, true, true);
208 }
209
210 public int executeTrajectoryByTrying(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex) {
211 return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, true, true);
212 }
213
214 public int executeTrajectoryWithoutStateCoding(Object[] trajectoryToExecute) {
215 return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, false, false);
216 }
217
218 public int executeTrajectoryWithoutStateCoding(Object[] trajectoryToExecute, int fromIncludedIndex,
219 int toExcludedIndex) {
220 return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, false, false);
221 }
222
223 public int executeTrajectoryByTryingWithoutStateCoding(Object[] trajectoryToExecute) {
224 return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, true, false);
225 }
226
227 public int executeTrajectoryByTryingWithoutStateCoding(Object[] trajectoryToExecute, int fromIncludedIndex,
228 int toExcludedIndex) {
229 return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, true, false);
230 }
231
232 private int executeTrajectory(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex,
233 boolean tryAllActivations, boolean createStateCode) {
234 logger.debug("Executing trajectory.");
235 int unsuccesfulIndex = -1;
236 if (tryAllActivations) {
237 unsuccesfulIndex = 0;
238 }
239 for (int i = fromIncludedIndex; i < toExcludedIndex; i++) {
240 Object activationId = trajectoryToExecute[i];
241 final Activation<?> activation = getActivationById(activationId);
242
243 if (activation == null) {
244 logger.debug("Couldn't execute activation: " + activationId);
245 if (tryAllActivations) {
246 unsuccesfulIndex++;
247 continue;
248 } else {
249 unsuccesfulIndex = i;
250 logger.debug("Trajectory execution stopped at index " + i + "/" + trajectoryToExecute.length);
251 break;
252 }
253 }
254
255 BatchTransformationRule<?, ?> rule = getRuleByActivation(activation);
256
257 Map<String, Double> measureCosts = new HashMap<String, Double>();
258 if (activationFitnessProcessors != null && activationFitnessProcessors.containsKey(rule)) {
259 IPatternMatch match = (IPatternMatch) activation.getAtom();
260 ActivationFitnessProcessor processor = activationFitnessProcessors.get(rule);
261 double fitness = processor.process(match);
262 measureCosts.put(activationFitnessProcessorNames.get(rule), fitness);
263 }
264
265 ChangeCommand rc = new ChangeCommand(model) {
266 @Override
267 protected void doExecute() {
268 activation.fire(evmContext);
269 }
270 };
271
272 long start = System.nanoTime();
273 domain.getCommandStack().execute(rc);
274 forwardTime += System.nanoTime() - start;
275
276 Object newStateId = null;
277 if (createStateCode) {
278 newStateId = stateCoder.createStateCode();
279 }
280 updateActivationCodes();
281
282 trajectory.addStep(activationId, rule, newStateId, measureCosts);
283
284 logger.debug("Activation executed: " + activationId);
285 }
286 if (!createStateCode) {
287 trajectory.modifyLastStateCode(stateCoder.createStateCode());
288 }
289 logger.debug("Trajectory execution finished.");
290 return unsuccesfulIndex;
291
292 }
293
294 public Object getTransitionByActivation(Activation<?> activation) {
295 return activationCodes.getActivationId(activation);
296 }
297
298 public Activation<?> getActivationById(Object activationId) {
299 return activationCodes.getActivation(activationId);
300 }
301
302 public BatchTransformationRule<?, ?> getRuleByActivation(Activation<?> activation) {
303 return context.getGlobalContext().getSpecificationRuleMap().get(activation.getInstance().getSpecification());
304 }
305
306 public BatchTransformationRule<?, ?> getRuleByActivationId(Object activationId) {
307 return getRuleByActivation(getActivationById(activationId));
308 }
309
310 /**
311 * Returns true if the given state is not owned by this crawler.
312 *
313 **/
314 public boolean isNewModelStateAlreadyTraversed() {
315 return !isNewState;
316 }
317
318 public List<Object> getTrajectoryFromRoot() {
319 return trajectory.getTrajectory();
320 }
321
322 public Collection<Object> getTransitionsFromCurrentState() {
323 return activationCodes.getCurrentActivationCodes();
324 }
325
326 public Collection<Object> getUntraversedTransitionsFromCurrentState() {
327 if (designSpace == null) {
328 throw new DSEException("Unsupported without a design space");
329 }
330 Object currentState = trajectory.getCurrentStateId();
331 Collection<Object> traversedIds = designSpace.getActivationIds(currentState);
332
333 List<Object> untraversedTransitions = new ArrayList<>();
334 for (Object activationId : activationCodes.getCurrentActivationCodes()) {
335 if (!traversedIds.contains(activationId)) {
336 untraversedTransitions.add(activationId);
337 }
338 }
339
340 return untraversedTransitions;
341 }
342
343 public boolean undoLastTransformation() {
344
345 if (!trajectory.canStepBack()) {
346 return false;
347 }
348
349 long start = System.nanoTime();
350 try {
351 engine.delayUpdatePropagation(() -> {
352 domain.getCommandStack().undo();
353 return null;
354 });
355 } catch (InvocationTargetException e) {
356 throw new RuntimeException(e);
357 }
358 updateActivationCodes();
359
360 Object lastActivationId = trajectory.getLastActivationId();
361
362 trajectory.backtrack();
363
364 if (handlers != null) {
365 for (IExploreEventHandler iExploreEventHandler : handlers) {
366 iExploreEventHandler.undo(lastActivationId);
367 }
368 }
369
370 logger.debug("Backtrack.");
371 backtrackingTime += System.nanoTime() - start;
372
373 return true;
374 }
375
376 public void backtrackXTimes(int steps) {
377 long start = System.nanoTime();
378 try {
379 engine.delayUpdatePropagation(() -> {
380 for (int i = steps; i > 0; i--) {
381 domain.getCommandStack().undo();
382 trajectory.backtrack();
383 }
384 return null;
385 });
386 } catch (InvocationTargetException e) {
387 throw new RuntimeException(e);
388 }
389 backtrackingTime += System.nanoTime() - start;
390 updateActivationCodes();
391 logger.debug("Backtracked " + steps + " times.");
392 }
393
394 public int backtrackUntilLastCommonActivation(Object[] newTrajectory) {
395 long start = System.nanoTime();
396 Iterator<Object> currentTrajectoryIterator = trajectory.getTrajectory().iterator();
397 if (!currentTrajectoryIterator.hasNext()) {
398 return 0;
399 }
400 int indexOfLastCommonActivation = 0;
401 for (Object activationCode : newTrajectory) {
402 if (currentTrajectoryIterator.hasNext()) {
403 Object activationCodeFromCurrent = currentTrajectoryIterator.next();
404 if (activationCodeFromCurrent.equals(activationCode)) {
405 indexOfLastCommonActivation++;
406 } else {
407 break;
408 }
409 } else {
410 // current trajectory is smaller
411 break;
412 }
413 }
414 int numberOfBacktracks = trajectory.getDepth() - indexOfLastCommonActivation;
415 if (numberOfBacktracks > 0) {
416 try {
417 engine.delayUpdatePropagation(() -> {
418 for (int i = numberOfBacktracks; i > 0; i--) {
419 domain.getCommandStack().undo();
420 trajectory.backtrack();
421 }
422 return null;
423 });
424 } catch (InvocationTargetException e) {
425 throw new RuntimeException(e);
426 }
427 }
428 backtrackingTime += System.nanoTime() - start;
429 updateActivationCodes();
430 logger.debug("Backtracked " + numberOfBacktracks + " times.");
431 return indexOfLastCommonActivation;
432 }
433
434 public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory) {
435 executeTrajectoryWithMinimalBacktrack(trajectory, trajectory.length);
436 }
437
438 public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory, int toExcludedIndex) {
439 int fromIndex = backtrackUntilLastCommonActivation(trajectory);
440 executeTrajectory(trajectory, fromIndex, toExcludedIndex, false, true);
441 }
442
443 public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory) {
444 executeTrajectoryWithMinimalBacktrackWithoutStateCoding(trajectory, trajectory.length);
445 }
446
447 public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory, int toExcludedIndex) {
448 int fromIndex = backtrackUntilLastCommonActivation(trajectory);
449 executeTrajectory(trajectory, fromIndex, toExcludedIndex, false, false);
450 Object stateCode = stateCoder.createStateCode();
451 this.trajectory.modifyLastStateCode(stateCode);
452 }
453
454 public void undoUntilRoot() {
455 long start = System.nanoTime();
456 try {
457 engine.delayUpdatePropagation(() -> {
458 while (trajectory.canStepBack()) {
459 domain.getCommandStack().undo();
460 trajectory.backtrack();
461 }
462 return null;
463 });
464 } catch (InvocationTargetException e) {
465 throw new RuntimeException(e);
466 }
467 backtrackingTime += System.nanoTime() - start;
468 updateActivationCodes();
469 logger.debug("Backtracked to root.");
470 }
471
472 private Object generateMatchCode(IPatternMatch match) {
473 return stateCoder.createActivationCode(match);
474 }
475
476 public Object getCurrentState() {
477 return trajectory.getCurrentStateId();
478 }
479
480 public SolutionTrajectory createSolutionTrajectroy() {
481 return trajectory.createSolutionTrajectory(context.getGlobalContext().getStateCoderFactory(), this);
482 }
483
484 public TrajectoryInfo getTrajectoryInfo() {
485 return trajectory;
486 }
487
488 public void setDesignSpace(IDesignSpace designSpace) {
489 this.designSpace = designSpace;
490 }
491
492 public IDesignSpace getDesignSpace() {
493 return designSpace;
494 }
495
496 public void registerExploreEventHandler(IExploreEventHandler handler) {
497 if (handler == null) {
498 return;
499 }
500 if (handlers == null) {
501 handlers = new ArrayList<IExploreEventHandler>();
502 }
503 handlers.add(handler);
504 }
505
506 public void deregisterExploreEventHandler(IExploreEventHandler handler) {
507 if (handler == null) {
508 return;
509 }
510 if (handlers != null) {
511 handlers.remove(handler);
512 }
513 }
514
515 public void registerActivationCostProcessor(String name, BatchTransformationRule<?, ?> rule,
516 ActivationFitnessProcessor activationFitnessProcessor) {
517 if (activationFitnessProcessors == null || activationFitnessProcessorNames == null) {
518 activationFitnessProcessors = new HashMap<BatchTransformationRule<?, ?>, ActivationFitnessProcessor>();
519 activationFitnessProcessorNames = new HashMap<BatchTransformationRule<?, ?>, String>();
520 }
521 activationFitnessProcessors.put(rule, activationFitnessProcessor);
522 activationFitnessProcessorNames.put(rule, name);
523 }
524
525 public boolean isCurentStateInTrajectory() {
526 Object currentStateId = trajectory.getCurrentStateId();
527 List<Object> stateTrajectory = trajectory.getStateTrajectory();
528 int size = stateTrajectory.size();
529 for (int i = 0; i < size - 1; i++) {
530 Object stateId = stateTrajectory.get(i);
531 if (currentStateId.equals(stateId)) {
532 return true;
533 }
534 }
535 return false;
536 }
537
538 public IStateCoder getStateCoder() {
539 return stateCoder;
540 }
541
542 private void updateActivationCodes() {
543 activationCodes.updateActivationCodes();
544 }
545
546 public long getForwardTime() {
547 return forwardTime;
548 }
549
550 public long getBacktrackingTime() {
551 return backtrackingTime;
552 }
553
554 @Override
555 public void forwardWorked(long nanos) {
556 forwardTime += nanos;
557 }
558
559 @Override
560 public void backtrackWorked(long nanos) {
561 backtrackingTime += nanos;
562 }
563}