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.java577
1 files changed, 577 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..133ef948
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java
@@ -0,0 +1,577 @@
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 try {
155 engine.delayUpdatePropagation(() -> {
156 domain.getCommandStack().execute(rc);
157 return null;
158 });
159 } catch (InvocationTargetException e) {
160 throw new RuntimeException(e);
161 }
162 forwardTime += System.nanoTime() - start;
163
164 Object newStateId = stateCoder.createStateCode();
165 updateActivationCodes();
166
167 if (designSpace != null) {
168 isNewState = !designSpace.isTraversed(newStateId);
169 designSpace.addState(previousState, transition, newStateId);
170 }
171
172 trajectory.addStep(transition, rule, newStateId, measureCosts);
173
174 if (handlers != null) {
175 for (IExploreEventHandler iExploreEventHandler : handlers) {
176 iExploreEventHandler.transitionFired(transition);
177 }
178 }
179
180 logger.debug("Executed activation: " + transition);/*
181 * + " from state: " + previousState + " to " + newStateId);
182 */
183
184 return true;
185 }
186
187 public boolean executeRandomActivationId() {
188 Collection<Object> transitions = getTransitionsFromCurrentState();
189 int size = transitions.size();
190 if (size == 0) {
191 return false;
192 }
193
194 int index = random.nextInt(size);
195 Iterator<Object> iterator = transitions.iterator();
196 for (int i = 0; i < index; ++i) {
197 iterator.next();
198 }
199 Object transition = iterator.next();
200
201 fireActivation(transition);
202 return true;
203 }
204
205 public int executeTrajectory(Object[] trajectoryToExecute) {
206 return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, false, true);
207 }
208
209 public int executeTrajectory(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex) {
210 return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, false, true);
211 }
212
213 public int executeTrajectoryByTrying(Object[] trajectoryToExecute) {
214 return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, true, true);
215 }
216
217 public int executeTrajectoryByTrying(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex) {
218 return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, true, true);
219 }
220
221 public int executeTrajectoryWithoutStateCoding(Object[] trajectoryToExecute) {
222 return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, false, false);
223 }
224
225 public int executeTrajectoryWithoutStateCoding(Object[] trajectoryToExecute, int fromIncludedIndex,
226 int toExcludedIndex) {
227 return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, false, false);
228 }
229
230 public int executeTrajectoryByTryingWithoutStateCoding(Object[] trajectoryToExecute) {
231 return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, true, false);
232 }
233
234 public int executeTrajectoryByTryingWithoutStateCoding(Object[] trajectoryToExecute, int fromIncludedIndex,
235 int toExcludedIndex) {
236 return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, true, false);
237 }
238
239 private int executeTrajectory(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex,
240 boolean tryAllActivations, boolean createStateCode) {
241 logger.debug("Executing trajectory.");
242 int unsuccesfulIndex = -1;
243 if (tryAllActivations) {
244 unsuccesfulIndex = 0;
245 }
246 for (int i = fromIncludedIndex; i < toExcludedIndex; i++) {
247 Object activationId = trajectoryToExecute[i];
248 final Activation<?> activation = getActivationById(activationId);
249
250 if (activation == null) {
251 logger.debug("Couldn't execute activation: " + activationId);
252 if (tryAllActivations) {
253 unsuccesfulIndex++;
254 continue;
255 } else {
256 unsuccesfulIndex = i;
257 logger.debug("Trajectory execution stopped at index " + i + "/" + trajectoryToExecute.length);
258 break;
259 }
260 }
261
262 BatchTransformationRule<?, ?> rule = getRuleByActivation(activation);
263
264 Map<String, Double> measureCosts = new HashMap<String, Double>();
265 if (activationFitnessProcessors != null && activationFitnessProcessors.containsKey(rule)) {
266 IPatternMatch match = (IPatternMatch) activation.getAtom();
267 ActivationFitnessProcessor processor = activationFitnessProcessors.get(rule);
268 double fitness = processor.process(match);
269 measureCosts.put(activationFitnessProcessorNames.get(rule), fitness);
270 }
271
272 ChangeCommand rc = new ChangeCommand(model) {
273 @Override
274 protected void doExecute() {
275 activation.fire(evmContext);
276 }
277 };
278
279 long start = System.nanoTime();
280 try {
281 engine.delayUpdatePropagation(() -> {
282 domain.getCommandStack().execute(rc);
283 return null;
284 });
285 } catch (InvocationTargetException e) {
286 throw new RuntimeException(e);
287 }
288 forwardTime += System.nanoTime() - start;
289
290 Object newStateId = null;
291 if (createStateCode) {
292 newStateId = stateCoder.createStateCode();
293 }
294 updateActivationCodes();
295
296 trajectory.addStep(activationId, rule, newStateId, measureCosts);
297
298 logger.debug("Activation executed: " + activationId);
299 }
300 if (!createStateCode) {
301 trajectory.modifyLastStateCode(stateCoder.createStateCode());
302 }
303 logger.debug("Trajectory execution finished.");
304 return unsuccesfulIndex;
305
306 }
307
308 public Object getTransitionByActivation(Activation<?> activation) {
309 return activationCodes.getActivationId(activation);
310 }
311
312 public Activation<?> getActivationById(Object activationId) {
313 return activationCodes.getActivation(activationId);
314 }
315
316 public BatchTransformationRule<?, ?> getRuleByActivation(Activation<?> activation) {
317 return context.getGlobalContext().getSpecificationRuleMap().get(activation.getInstance().getSpecification());
318 }
319
320 public BatchTransformationRule<?, ?> getRuleByActivationId(Object activationId) {
321 return getRuleByActivation(getActivationById(activationId));
322 }
323
324 /**
325 * Returns true if the given state is not owned by this crawler.
326 *
327 **/
328 public boolean isNewModelStateAlreadyTraversed() {
329 return !isNewState;
330 }
331
332 public List<Object> getTrajectoryFromRoot() {
333 return trajectory.getTrajectory();
334 }
335
336 public Collection<Object> getTransitionsFromCurrentState() {
337 return activationCodes.getCurrentActivationCodes();
338 }
339
340 public Collection<Object> getUntraversedTransitionsFromCurrentState() {
341 if (designSpace == null) {
342 throw new DSEException("Unsupported without a design space");
343 }
344 Object currentState = trajectory.getCurrentStateId();
345 Collection<Object> traversedIds = designSpace.getActivationIds(currentState);
346
347 List<Object> untraversedTransitions = new ArrayList<>();
348 for (Object activationId : activationCodes.getCurrentActivationCodes()) {
349 if (!traversedIds.contains(activationId)) {
350 untraversedTransitions.add(activationId);
351 }
352 }
353
354 return untraversedTransitions;
355 }
356
357 public boolean undoLastTransformation() {
358
359 if (!trajectory.canStepBack()) {
360 return false;
361 }
362
363 long start = System.nanoTime();
364 try {
365 engine.delayUpdatePropagation(() -> {
366 domain.getCommandStack().undo();
367 return null;
368 });
369 } catch (InvocationTargetException e) {
370 throw new RuntimeException(e);
371 }
372 backtrackingTime += System.nanoTime() - start;
373 updateActivationCodes();
374
375 Object lastActivationId = trajectory.getLastActivationId();
376
377 trajectory.backtrack();
378
379 if (handlers != null) {
380 for (IExploreEventHandler iExploreEventHandler : handlers) {
381 iExploreEventHandler.undo(lastActivationId);
382 }
383 }
384
385 logger.debug("Backtrack.");
386
387 return true;
388 }
389
390 public void backtrackXTimes(int steps) {
391 long start = System.nanoTime();
392 try {
393 engine.delayUpdatePropagation(() -> {
394 for (int i = steps; i > 0; i--) {
395 domain.getCommandStack().undo();
396 trajectory.backtrack();
397 }
398 return null;
399 });
400 } catch (InvocationTargetException e) {
401 throw new RuntimeException(e);
402 }
403 backtrackingTime += System.nanoTime() - start;
404 updateActivationCodes();
405 logger.debug("Backtracked " + steps + " times.");
406 }
407
408 public int backtrackUntilLastCommonActivation(Object[] newTrajectory) {
409 long start = System.nanoTime();
410 Iterator<Object> currentTrajectoryIterator = trajectory.getTrajectory().iterator();
411 if (!currentTrajectoryIterator.hasNext()) {
412 return 0;
413 }
414 int indexOfLastCommonActivation = 0;
415 for (Object activationCode : newTrajectory) {
416 if (currentTrajectoryIterator.hasNext()) {
417 Object activationCodeFromCurrent = currentTrajectoryIterator.next();
418 if (activationCodeFromCurrent.equals(activationCode)) {
419 indexOfLastCommonActivation++;
420 } else {
421 break;
422 }
423 } else {
424 // current trajectory is smaller
425 break;
426 }
427 }
428 int numberOfBacktracks = trajectory.getDepth() - indexOfLastCommonActivation;
429 if (numberOfBacktracks > 0) {
430 try {
431 engine.delayUpdatePropagation(() -> {
432 for (int i = numberOfBacktracks; i > 0; i--) {
433 domain.getCommandStack().undo();
434 trajectory.backtrack();
435 }
436 return null;
437 });
438 } catch (InvocationTargetException e) {
439 throw new RuntimeException(e);
440 }
441 }
442 backtrackingTime += System.nanoTime() - start;
443 updateActivationCodes();
444 logger.debug("Backtracked " + numberOfBacktracks + " times.");
445 return indexOfLastCommonActivation;
446 }
447
448 public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory) {
449 executeTrajectoryWithMinimalBacktrack(trajectory, trajectory.length);
450 }
451
452 public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory, int toExcludedIndex) {
453 int fromIndex = backtrackUntilLastCommonActivation(trajectory);
454 executeTrajectory(trajectory, fromIndex, toExcludedIndex, false, true);
455 }
456
457 public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory) {
458 executeTrajectoryWithMinimalBacktrackWithoutStateCoding(trajectory, trajectory.length);
459 }
460
461 public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory, int toExcludedIndex) {
462 int fromIndex = backtrackUntilLastCommonActivation(trajectory);
463 executeTrajectory(trajectory, fromIndex, toExcludedIndex, false, false);
464 Object stateCode = stateCoder.createStateCode();
465 this.trajectory.modifyLastStateCode(stateCode);
466 }
467
468 public void undoUntilRoot() {
469 long start = System.nanoTime();
470 try {
471 engine.delayUpdatePropagation(() -> {
472 while (trajectory.canStepBack()) {
473 domain.getCommandStack().undo();
474 trajectory.backtrack();
475 }
476 return null;
477 });
478 } catch (InvocationTargetException e) {
479 throw new RuntimeException(e);
480 }
481 backtrackingTime += System.nanoTime() - start;
482 updateActivationCodes();
483 logger.debug("Backtracked to root.");
484 }
485
486 private Object generateMatchCode(IPatternMatch match) {
487 return stateCoder.createActivationCode(match);
488 }
489
490 public Object getCurrentState() {
491 return trajectory.getCurrentStateId();
492 }
493
494 public SolutionTrajectory createSolutionTrajectroy() {
495 return trajectory.createSolutionTrajectory(context.getGlobalContext().getStateCoderFactory(), this);
496 }
497
498 public TrajectoryInfo getTrajectoryInfo() {
499 return trajectory;
500 }
501
502 public void setDesignSpace(IDesignSpace designSpace) {
503 this.designSpace = designSpace;
504 }
505
506 public IDesignSpace getDesignSpace() {
507 return designSpace;
508 }
509
510 public void registerExploreEventHandler(IExploreEventHandler handler) {
511 if (handler == null) {
512 return;
513 }
514 if (handlers == null) {
515 handlers = new ArrayList<IExploreEventHandler>();
516 }
517 handlers.add(handler);
518 }
519
520 public void deregisterExploreEventHandler(IExploreEventHandler handler) {
521 if (handler == null) {
522 return;
523 }
524 if (handlers != null) {
525 handlers.remove(handler);
526 }
527 }
528
529 public void registerActivationCostProcessor(String name, BatchTransformationRule<?, ?> rule,
530 ActivationFitnessProcessor activationFitnessProcessor) {
531 if (activationFitnessProcessors == null || activationFitnessProcessorNames == null) {
532 activationFitnessProcessors = new HashMap<BatchTransformationRule<?, ?>, ActivationFitnessProcessor>();
533 activationFitnessProcessorNames = new HashMap<BatchTransformationRule<?, ?>, String>();
534 }
535 activationFitnessProcessors.put(rule, activationFitnessProcessor);
536 activationFitnessProcessorNames.put(rule, name);
537 }
538
539 public boolean isCurentStateInTrajectory() {
540 Object currentStateId = trajectory.getCurrentStateId();
541 List<Object> stateTrajectory = trajectory.getStateTrajectory();
542 int size = stateTrajectory.size();
543 for (int i = 0; i < size - 1; i++) {
544 Object stateId = stateTrajectory.get(i);
545 if (currentStateId.equals(stateId)) {
546 return true;
547 }
548 }
549 return false;
550 }
551
552 public IStateCoder getStateCoder() {
553 return stateCoder;
554 }
555
556 private void updateActivationCodes() {
557 activationCodes.updateActivationCodes();
558 }
559
560 public long getForwardTime() {
561 return forwardTime;
562 }
563
564 public long getBacktrackingTime() {
565 return backtrackingTime;
566 }
567
568 @Override
569 public void forwardWorked(long nanos) {
570 forwardTime += nanos;
571 }
572
573 @Override
574 public void backtrackWorked(long nanos) {
575 backtrackingTime += nanos;
576 }
577}