aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra
diff options
context:
space:
mode:
Diffstat (limited to 'Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra')
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSEException.java47
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSETransformationRule.java51
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DesignSpaceExplorer.java622
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Objectives.java153
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Solution.java60
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/SolutionTrajectory.java345
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Strategies.java123
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.java228
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.java220
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.java188
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.java208
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.java142
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.java163
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.java44
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory.java13
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ActivationCodesConflictSet.java213
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java577
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictResolver.java35
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictSet.java83
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseEvmRuleBase.java21
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseIdPoolHelper.java68
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ExplorerThread.java88
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java374
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/IDseStrategyContext.java117
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/SingletonSetConflictResolver.java53
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ThreadContext.java542
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/DesignSpace.java106
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IBacktrackListener.java7
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IDesignSpace.java27
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.java154
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/multithreading/DSEThreadPool.java58
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.java15
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Comparators.java31
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Fitness.java29
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IGlobalConstraint.java58
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IObjective.java110
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.java114
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.java217
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/TrajectoryFitness.java84
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardObjective.java52
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/BaseObjective.java150
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java137
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.java316
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.java89
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstraint.java116
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueryType.java14
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardObjective.java52
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObjective.java59
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjective.java148
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.java40
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.java18
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider.java37
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.java28
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHandler.java55
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java311
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoder.java82
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoderFactory.java29
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProvider.java45
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.java25
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.java60
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFactory.java18
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependency.java33
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.java44
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.java15
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNode.java100
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNodeType.java17
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoder.java215
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.java40
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java250
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactory.java38
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/EMFHelper.java424
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/Hasher.java86
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.java63
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.java56
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.java39
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IExploreEventHandler.java40
76 files changed, 9129 insertions, 0 deletions
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSEException.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSEException.java
new file mode 100644
index 00000000..f0da19ed
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSEException.java
@@ -0,0 +1,47 @@
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.api;
10
11/**
12 * Represents a general runtime exception that happened during the execution of the design space exploration process.
13 * Problems that cause this exception are not recoverable within the scope of the design space exploration process.
14 */
15public class DSEException extends RuntimeException {
16
17 private static final long serialVersionUID = -8312212010574763824L;
18
19 /**
20 * @see RuntimeException#RuntimeException()
21 */
22 public DSEException() {
23 super();
24 }
25
26 /**
27 * @see RuntimeException#RuntimeException(String)
28 */
29 public DSEException(String message) {
30 super(message);
31 }
32
33 /**
34 * @see RuntimeException#RuntimeException(String, Throwable)
35 */
36 public DSEException(String message, Throwable cause) {
37 super(message, cause);
38 }
39
40 /**
41 * @see RuntimeException#RuntimeException(Throwable)
42 */
43 public DSEException(Throwable cause) {
44 super(cause);
45 }
46
47}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSETransformationRule.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSETransformationRule.java
new file mode 100644
index 00000000..8c3511ae
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSETransformationRule.java
@@ -0,0 +1,51 @@
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.api;
10
11import java.util.Objects;
12import java.util.function.Consumer;
13
14import org.eclipse.viatra.query.runtime.api.IPatternMatch;
15import org.eclipse.viatra.query.runtime.api.IQuerySpecification;
16import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher;
17import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
18
19/**
20 * An instance of this class is a specification of a graph transformation rule on a given metamodel. Such a rule
21 * consists of a left hand side (LHS), which is specified by an {@link IQuerySpecification} and a right hand side (RHS),
22 * which is specified by an {@link Consumer}.
23 *
24 * @author Andras Szabolcs Nagy
25 *
26 * @param <Match>
27 * A VIATRA Query pattern match - left hand side of the rule
28 * @param <Matcher>
29 * A VIATRA Query pattern matcher - left hand side of the rule
30 * @deprecated
31 */
32@Deprecated
33public class DSETransformationRule<Match extends IPatternMatch, Matcher extends ViatraQueryMatcher<Match>> extends
34 BatchTransformationRule<Match, Matcher> {
35
36 public DSETransformationRule(String name, IQuerySpecification<Matcher> querySpec,
37 Consumer<Match> action) {
38 super(name, querySpec, BatchTransformationRule.STATELESS_RULE_LIFECYCLE, action);
39
40 Objects.requireNonNull(name);
41 Objects.requireNonNull(querySpec);
42 Objects.requireNonNull(action);
43
44 }
45
46 public DSETransformationRule(IQuerySpecification<Matcher> querySpec,
47 Consumer<Match> action) {
48 this(querySpec.getFullyQualifiedName(), querySpec, action);
49 }
50
51}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DesignSpaceExplorer.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DesignSpaceExplorer.java
new file mode 100644
index 00000000..9cd6e68a
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DesignSpaceExplorer.java
@@ -0,0 +1,622 @@
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.api;
10
11import java.util.Collection;
12import java.util.HashSet;
13import java.util.Set;
14import java.util.Timer;
15import java.util.TimerTask;
16import java.util.concurrent.atomic.AtomicBoolean;
17
18import org.apache.log4j.BasicConfigurator;
19import org.apache.log4j.Level;
20import org.apache.log4j.Logger;
21import org.eclipse.emf.common.notify.Notifier;
22import org.eclipse.emf.ecore.EObject;
23import org.eclipse.emf.ecore.EPackage;
24import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
25import org.eclipse.viatra.dse.base.DesignSpaceManager;
26import org.eclipse.viatra.dse.base.GlobalContext;
27import org.eclipse.viatra.dse.designspace.api.DesignSpace;
28import org.eclipse.viatra.dse.designspace.api.IDesignSpace;
29import org.eclipse.viatra.dse.objectives.IGlobalConstraint;
30import org.eclipse.viatra.dse.objectives.IObjective;
31import org.eclipse.viatra.dse.solutionstore.ISolutionNameProvider;
32import org.eclipse.viatra.dse.solutionstore.IdBasedSolutionNameProvider;
33import org.eclipse.viatra.dse.solutionstore.SolutionStore;
34import org.eclipse.viatra.dse.statecode.IStateCoder;
35import org.eclipse.viatra.dse.statecode.IStateCoderFactory;
36import org.eclipse.viatra.dse.statecoding.simple.SimpleStateCoderFactory;
37import org.eclipse.viatra.dse.visualizer.IDesignSpaceVisualizer;
38import org.eclipse.viatra.query.runtime.matchers.util.Preconditions;
39import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver;
40import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
41
42/**
43 * <p>
44 * The {@link DesignSpaceExplorer} is the main API of the <b>Design Space Exploration</b> engine.
45 * </p>
46 *
47 * <p>
48 * To parameterize the algorithm one must use the following methods after instantiating:
49 * <ul>
50 * <li>{@link #setInitialModel(EObject)} or it's overloads to set the starting model.</li>
51 * <li>{@link #addTransformationRule(BatchTransformationRule)} to define the transformations.</li> <li
52 * {@link #addObjective(IObjective)} to define the objective functions. Use the {@link Objectives} helper class for
53 * instantiating built-in, configurable objectives.</li>
54 * <li>{@link #startExploration(IStrategy)} or it's overloads to start an exploration with the given exploration
55 * strategy. Use the {@link Strategies} helper class for instantiating built-in, configurable exploration strategies.
56 * </li>
57 * </ul>
58 * </p>
59 *
60 * <p>
61 * <b>Designs Space Exploration</b> is the process of finding a sequence (or sequences) of predefined transformation
62 * rules ("transitions") that, if applied in order on the starting model, results in a new model state that fulfills the
63 * hard (or goal) constraints and is near optimal with respect to the objectives.
64 * </p>
65 *
66 * <p>
67 * An extension to this paradigm is the introduction of global constraints, which guarantees, that no sequence will be
68 * returned, which if executed, results in an intermediate model state that violates the specified global constraints,
69 * including the final state. You can add constraints by invoking {@link #addGlobalConstraint(IGlobalConstraint)}.
70 * </p>
71 *
72 * @author Andras Szabolcs Nagy & Miklos Foldenyi
73 *
74 */
75public class DesignSpaceExplorer {
76
77 private Notifier model;
78
79 private GlobalContext globalContext = new GlobalContext();
80
81 private final Logger logger = Logger.getLogger(this.getClass());
82
83 private Set<EPackage> metaModelPackages = new HashSet<EPackage>();
84
85 private static final String MODEL_NOT_YET_GIVEN = "The starting model is not given yet. Please call the setInitialModel method first.";
86
87 private boolean deepCopyModel;
88
89 /**
90 * <p>
91 * Creates a {@link DesignSpaceExplorer} object that is able to execute a design space exploration process.
92 * </p>
93 *
94 * <p>
95 * By default the state coder used is the generic (not meta-model specific) {@link GraphHash}. You can provide your
96 * custom state coder by implementing the {@link IStateCoderFactory} and {@link IStateCoder} interfaces, and passing
97 * the former to the {@link #setStateCoderFactory(IStateCoderFactory)} method.
98 *
99 */
100 public DesignSpaceExplorer() {
101 setDesignspace(new DesignSpace());
102 }
103
104 /**
105 * Adds a metamodel in the form of {@link EPackage}, which is needed for certain guidance.
106 *
107 * @param metaModelPackage
108 */
109 public void addMetaModelPackage(EPackage metaModelPackage) {
110 metaModelPackages.add(metaModelPackage);
111 }
112
113 /**
114 * Defines the initial model of the exploration, and whether it is supposed to be used to execute the DSE process or
115 * it should be cloned. Please note, that in multithreaded mode any subsequent threads will be working on cloned
116 * models.
117 *
118 * @param model
119 * The root object of the EMF model.
120 * @param deepCopyModel
121 * If it is set to true, the exploration will run on a cloned model.
122 */
123 public void setInitialModel(Notifier model, boolean deepCopyModel) {
124 this.model = model;
125 this.deepCopyModel = deepCopyModel;
126 }
127
128 /**
129 * Defines the initial model of the exploration. The model will be cloned, which is desired in most cases as the
130 * given model won't be changed.
131 *
132 * @param model
133 * The root object of the EMF model.
134 */
135 public void setInitialModel(Notifier model) {
136 setInitialModel(model, true);
137 }
138
139 /**
140 * Defines the initial model of the exploration. The given model won't be cloned, thus the exploration will modify
141 * it.
142 *
143 * @param model
144 * The root object of the EMF model. It won't be cloned.
145 */
146 public void setInitialModelUncloned(Notifier model) {
147 setInitialModel(model, false);
148 }
149
150 /**
151 * Adds a {@link BatchTransformationRule}.
152 *
153 * @param rule
154 * The transformationRule.
155 */
156 public void addTransformationRule(BatchTransformationRule<?, ?> rule) {
157 Preconditions.checkArgument(rule != null);
158 for (BatchTransformationRule<?, ?> rule2 : globalContext.getTransformations()) {
159 if (rule.getPrecondition().equals(rule2.getPrecondition())) {
160 throw new DSEException(
161 "Two transformation rule ("
162 + rule.getName()
163 + "; "
164 + rule2.getName()
165 + ") uses the same LHS VIATRA Query pattern ("
166 + rule.getPrecondition().getFullyQualifiedName()
167 + "), which may lead to hash collision."
168 + " Please wrap the pattern with an other pattern with the 'find' keyword (or duplicate the code), and use that for one of the rules LHS.");
169 }
170 }
171
172 globalContext.getTransformations().add(rule);
173 }
174
175 /**
176 * Adds a global constraint to the exploration process. Please see the {@link IGlobalConstraint} interface and its
177 * implementations for details.
178 *
179 * @param constraint
180 * The global constraint.
181 * @see IGlobalConstraint
182 */
183 public void addGlobalConstraint(IGlobalConstraint constraint) {
184 globalContext.getGlobalConstraints().add(constraint);
185 }
186
187 /**
188 * Adds an objective the the exploration process. Please see the {@link IObjective} interface and its
189 * implementations for details.
190 *
191 * @param objective
192 * The objective.
193 * @see IObjective
194 */
195 public void addObjective(IObjective objective) {
196 for (IObjective o : globalContext.getObjectives()) {
197 if (o.getName().equals(objective.getName())) {
198 throw new DSEException("Two objectives with the same name cannot be registered:" + o.getName());
199 }
200 }
201 globalContext.getObjectives().add(objective);
202 }
203
204 /**
205 * Sets a {@link IStateCoderFactory} for which will be used for creating {@link IStateCoder}s. The default
206 * implementation is the {@link SimpleStateCoderFactory}, which works well in most of the cases.
207 *
208 * @param stateCoderFactory
209 * The factory.
210 */
211 public final void setStateCoderFactory(IStateCoderFactory stateCoderFactory) {
212 globalContext.setStateCoderFactory(stateCoderFactory);
213 }
214
215 /**
216 * Defines the maximum processing threads that the design space exploration can use. Note, that this is only
217 * limiting the threads doing the actual calculation. By default this value will be set to the number of logical
218 * processors (including HyperThreading) in the computer, reported by {@link Runtime#availableProcessors()}.
219 *
220 * @param maxNumberOfThreads
221 * The number of maximum processing threads available to the design space exploration process.
222 */
223 public void setMaxNumberOfThreads(int maxNumberOfThreads) {
224 globalContext.getThreadPool().setMaximumPoolSize(maxNumberOfThreads);
225 }
226
227 /**
228 * Sets the {@link IDesignSpace} implementation that is to be used during the design space exploration process. By
229 * default, the {@link DesignSpace} implementation is used.
230 *
231 * @param designspace
232 * The {@link IDesignSpace} implementation.
233 */
234 public final void setDesignspace(IDesignSpace designspace) {
235 globalContext.setDesignSpace(designspace);
236 }
237
238 /**
239 * Sets the solution store for strategies. Please see the {@link SolutionStore} for how to configure it.
240 *
241 * @param solutionStore
242 * The parameterized {@link SolutionStore} implementation.
243 */
244 public void setSolutionStore(SolutionStore solutionStore) {
245 globalContext.setSolutionStore(solutionStore);
246 }
247
248 /**
249 * Starts the design space exploration. It returns only when the strategy decides to stop the execution.
250 *
251 * @param strategy
252 * The strategy of the exploration.
253 */
254 public void startExploration(IStrategy strategy) {
255 startExploration(strategy, true, -1);
256 }
257
258 /**
259 * Starts the design space exploration asynchronously. Completion of the process can be verified by calling
260 * {@link DesignSpaceExplorer#isDone()}.
261 *
262 * @param strategy
263 * The strategy of the exploration.
264 */
265 public void startExplorationAsync(IStrategy strategy) {
266 startExploration(strategy, false, -1);
267 }
268
269 /**
270 * Starts the design space exploration with a timeout. It returns only when the strategy decides to stop the
271 * execution or the given timeout is elapsed.
272 *
273 * @param strategy
274 * The strategy of the exploration.
275 * @param timeout
276 * The number of milliseconds before the exploration is forced to stop.
277 * @return Returns true if the exploration stopped by the timeout.
278 */
279 public boolean startExplorationWithTimeout(IStrategy strategy, long timeout) {
280 return startExploration(strategy, true, timeout);
281 }
282
283 /**
284 * Starts the design space exploration asynchronously with a timeout. Completion of the process can be verified by
285 * calling {@link DesignSpaceExplorer#isDone()}.
286 *
287 * @param strategy
288 * The strategy of the exploration.
289 * @param timeout
290 * The number of milliseconds before the exploration is forced to stop.
291 * @return Returns true if the exploration stopped by the timeout.
292 */
293 public boolean startExplorationAsyncWithTimeout(IStrategy strategy, long timeout) {
294 return startExploration(strategy, false, timeout);
295 }
296
297 /**
298 * Starts the design space exploration. If {@code waitForTermination} is true, then it returns only when the
299 * strategy decides to stop the execution or there was a timeout, otherwise when the exploration process is started
300 * it returns immediately. In this case, process completion can be verified by calling
301 * {@link DesignSpaceExplorer#isDone()}.
302 *
303 * @param strategy
304 * The strategy of the exploration.
305 * @param waitForTermination
306 * True if the method must wait for the engine to stop, i.e. whether to start synchronously.
307 * @param timeout
308 * The number of milliseconds before the exploration is forced to stop.
309 * @return Returns true if the exploration stopped by the timeout.
310 */
311 public boolean startExploration(IStrategy strategy, boolean waitForTermination, final long timeout) {
312 initExploration(strategy);
313
314 Timer timer = new Timer();
315 final AtomicBoolean wasTimeout = new AtomicBoolean(false);
316
317 if (timeout > 0) {
318 TimerTask timerTask = new TimerTask() {
319 @Override
320 public void run() {
321 logger.info("Timeout, stopping threads...");
322 globalContext.stopAllThreads();
323 wasTimeout.set(true);
324 }
325 };
326 timer.schedule(timerTask, timeout);
327 }
328
329 if (waitForTermination) {
330 waitForTerminaition();
331 timer.cancel();
332 } else {
333 logger.info("Design space exploration started asynchronously.");
334 }
335
336 return wasTimeout.get();
337
338 }
339
340 private void initExploration(IStrategy strategy) {
341 Preconditions.checkArgument(model != null, MODEL_NOT_YET_GIVEN);
342 Preconditions.checkArgument(strategy != null, "A strategy must be given. Use the Strategies helper class.");
343 Preconditions.checkState(!globalContext.getTransformations().isEmpty(),
344 "At least one transformation rule must be added to start the exploration.");
345
346 if (globalContext.getStateCoderFactory() == null) {
347 if (getMetaModelPackages() == null || getMetaModelPackages().isEmpty()) {
348 throw new DSEException("Cannot initialize state coder."
349 + " Please specifiy the EPackages your model uses with addMetaModelPackage(EPackage)");
350 }
351 globalContext.setStateCoderFactory(new SimpleStateCoderFactory(getMetaModelPackages()));
352 }
353
354 logger.info("DesignSpaceExplorer started exploration.");
355
356 if (deepCopyModel) {
357 globalContext.startFirstThread(strategy, model);
358 } else {
359 globalContext.startFirstThreadWithoutModelClone(strategy, model);
360 }
361 }
362
363 /**
364 * Returns all of the found {@link Solution}s, trajectories. Call it after
365 * {@link DesignSpaceExplorer#startExploration()}. Calling this while the process is running returns the solutions
366 * that have been found <b>so far</b>. The returned {@link Solution} objects may change internal state after they
367 * have been returned, if a shorter trajectory has been found to the referred state.
368 *
369 * @return The found solutions.
370 */
371 public Collection<Solution> getSolutions() {
372 return globalContext.getSolutionStore().getSolutions();
373 }
374
375 /**
376 * Returns an arbitrary solution trajectory or null if the exploration failed to find any.
377 *
378 * @return An arbitrary solution trajectory.
379 */
380 public SolutionTrajectory getArbitrarySolution() {
381 Collection<Solution> solutions = getSolutions();
382 if (solutions.isEmpty()) {
383 return null;
384 }
385 return solutions.iterator().next().getArbitraryTrajectory();
386 }
387
388 /**
389 * Returns the number of distinct states the exploration process has visited so far.
390 *
391 * @return the number of distinct states.
392 */
393 public long getNumberOfStates() {
394 return globalContext.getDesignSpace().getNumberOfStates();
395 }
396
397 /**
398 * Returns the number of distinct transitions the exploration process has discovered (but not necessarily traversed)
399 * so far.
400 *
401 * @return the number of distinct transitions.
402 */
403 public long getNumberOfTransitions() {
404 return globalContext.getDesignSpace().getNumberOfTransitions();
405 }
406
407 /**
408 * Returns the {@link EPackage}s, which were registered with the
409 * {@link DesignSpaceExplorer#addMetaModelPackage(EPackage)} method.
410 *
411 * @return The set of meta model packages.
412 */
413 public Set<EPackage> getMetaModelPackages() {
414 return metaModelPackages;
415 }
416
417 /**
418 * Returns true if the {@link IExplorerThread strategy} decided to stop, and all the threads finished their work.
419 *
420 * @return true if the process has finished, false otherwise.
421 */
422 public boolean isDone() {
423 return globalContext.isDone();
424 }
425
426 /**
427 * Returns the {@link GlobalContext} which holds the configurations such as rule, objectives, etc.
428 *
429 * @return The global context.
430 */
431 public GlobalContext getGlobalContext() {
432 return globalContext;
433 }
434
435 /**
436 * Registers a design space visualizer. Please see the corresponding interface {@link IDesignSpaceVisualizer}.
437 *
438 * @see IDesignSpaceVisualizer
439 *
440 * @param visualizer
441 */
442 public void addDesignSpaceVisulaizer(IDesignSpaceVisualizer visualizer) {
443 globalContext.registerDesignSpaceVisualizer(visualizer);
444 }
445
446 /**
447 * Creates a string containing the state codes of all the found solutions and the found trajectories to these
448 * solutions with fitness values.
449 *
450 * @return A pretty string with the solutions.
451 */
452 public String toStringSolutions() {
453 StringBuilder sb = new StringBuilder();
454 Collection<Solution> solutions = getSolutions();
455 sb.append("Number of solutions: ");
456 sb.append(solutions.size());
457 sb.append("\n");
458 for (Solution solution : solutions) {
459 sb.append("Solution: ");
460 sb.append(solution.getStateCode());
461 sb.append("\n");
462 for (SolutionTrajectory trajectory : solution.getTrajectories()) {
463 sb.append(" ");
464 sb.append(trajectory.toPrettyString());
465 sb.append("\n");
466 }
467 }
468 return sb.toString();
469 }
470
471 /**
472 * A conflict resolver can filter rule activations the DSE engine will see. The primary use of this is symmetry
473 * reduction. This function is subject to change for better API.
474 *
475 * @param conflictResolver
476 */
477 public void setConflictResolver(ConflictResolver conflictResolver) {
478 globalContext.setConflictResolver(conflictResolver);
479 }
480
481 /**
482 * Enumeration for different use cases of logging, including:
483 * <ul>
484 * <li>OFF - no error messages.</li>
485 * <li>WARN - only error and warn messages.</li>
486 * <li>BASIC - logs basic information on how the exploration is going.</li>
487 * <li>VERBOSE_STRATEGY - logs everything the exploration strategy is prepared for.</li>
488 * <li>VERBOSE_FULL - logs every transformation.</li>
489 * </ul>
490 *
491 * @author Andras Szabolcs Nagy
492 *
493 */
494 public enum DseLoggingLevel {
495 OFF, WARN, BASIC, VERBOSE_STRATEGY, VERBOSE_FULL
496 }
497
498 /**
499 * Changes the level of logging. See {@link DseLoggingLevel} for details.
500 *
501 * @param dseLoggingLevel
502 */
503 public static void turnOnLogging(DseLoggingLevel dseLoggingLevel) {
504 switch (dseLoggingLevel) {
505 case OFF:
506 Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.OFF);
507 Logger.getLogger(IStrategy.class).setLevel(Level.OFF);
508 Logger.getLogger(DesignSpaceManager.class).setLevel(Level.OFF);
509 break;
510 case WARN:
511 Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.WARN);
512 Logger.getLogger(IStrategy.class).setLevel(Level.WARN);
513 Logger.getLogger(DesignSpaceManager.class).setLevel(Level.WARN);
514 break;
515 case BASIC:
516 Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.INFO);
517 Logger.getLogger(IStrategy.class).setLevel(Level.INFO);
518 Logger.getLogger(DesignSpaceManager.class).setLevel(Level.WARN);
519 break;
520 case VERBOSE_STRATEGY:
521 Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.DEBUG);
522 Logger.getLogger(IStrategy.class).setLevel(Level.DEBUG);
523 Logger.getLogger(DesignSpaceManager.class).setLevel(Level.WARN);
524 break;
525 case VERBOSE_FULL:
526 Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.DEBUG);
527 Logger.getLogger(IStrategy.class).setLevel(Level.DEBUG);
528 Logger.getLogger(DesignSpaceManager.class).setLevel(Level.DEBUG);
529 break;
530 default:
531 throw new DSEException("Not supported logging level.");
532 }
533 }
534
535 /**
536 * Changes the level of logging. See {@link DseLoggingLevel} for details.
537 *
538 * Also configures a basic console appender for log4j.
539 *
540 * @param dseLoggingLevel
541 */
542 public static void turnOnLoggingWithBasicConfig(DseLoggingLevel dseLoggingLevel) {
543 BasicConfigurator.configure();
544 Logger.getRootLogger().setLevel(Level.WARN);
545 turnOnLogging(dseLoggingLevel);
546 }
547
548 /**
549 * Stops the exploration and waits for termination. It has no effect if the exploration is already terminated or not
550 * even started.
551 */
552 public void stopExploration() {
553 if (globalContext.isDone()) {
554 logger.info("Cannot stop exploration - design space exploration has already finished.");
555 } else if (globalContext.isNotStarted()) {
556 logger.info("Cannot stop exploration - design space exploration has not been started.");
557 } else {
558 globalContext.stopAllThreads();
559 waitForTerminaition();
560 }
561 }
562
563 /**
564 * Stops the exploration asynchronously. It has no effect if the exploration is already terminated or not even
565 * started.
566 */
567 public void stopExplorationAsync() {
568 if (globalContext.isDone()) {
569 logger.info("Cannot stop exploration - design space exploration has already finished.");
570 } else if (globalContext.isNotStarted()) {
571 logger.info("Cannot stop exploration - design space exploration has not been started.");
572 } else {
573 globalContext.stopAllThreads();
574 }
575 }
576
577 /**
578 * Waits for termination.
579 */
580 public void waitForTerminaition() {
581 globalContext.waitForTermination();
582 }
583
584 /**
585 * Serializes all the found solutions by transforming the given initial model.
586 * </p>Files will be named <code>solution[id].xmi</code>.
587 * @param model The initial model.
588 */
589 public void saveModels(Notifier model) {
590 this.saveModels(model, "solution", "xmi");
591 }
592
593 /**
594 * Serializes all the found solutions by transforming the given initial model.
595 * </p>Files will be named <code>solution[id].[extension]</code>.
596 * @param model The initial model.
597 * @param extension The extension of the omitted file.
598 */
599 public void saveModels(Notifier model, String extension) {
600 this.saveModels(model, "solution", extension);
601 }
602
603 /**
604 * Serializes all the found solutions by transforming the given initial model.
605 * </p>Files will be named <code>[fileNamePrefix][id].[extension]</code>.
606 * @param model The initial model.
607 * @param fileNamePrefix The prefix (optionally including a file path) of the omitted file.
608 * @param extension The extension of the omitted file.
609 */
610 public void saveModels(Notifier model, String fileNamePrefix, String extension) {
611 globalContext.getSolutionStore().saveModels(model, new IdBasedSolutionNameProvider(fileNamePrefix, extension));
612 }
613
614 /**
615 * Serializes all the found solutions by transforming the given initial model.
616 * </p>Files will be named using the {@link ISolutionNameProvider}.
617 * @param model The initial model.
618 */
619 public void saveModels(Notifier model, ISolutionNameProvider solutionNameProvider) {
620 globalContext.getSolutionStore().saveModels(model, solutionNameProvider);
621 }
622}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Objectives.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Objectives.java
new file mode 100644
index 00000000..3b375fac
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Objectives.java
@@ -0,0 +1,153 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.api;
10
11import org.eclipse.viatra.dse.objectives.impl.CompositeObjective;
12import org.eclipse.viatra.dse.objectives.impl.ConstraintsObjective;
13import org.eclipse.viatra.dse.objectives.impl.AlwaysSatisfiedDummyHardObjective;
14import org.eclipse.viatra.dse.objectives.impl.DepthHardObjective;
15import org.eclipse.viatra.dse.objectives.impl.NeverSatisfiedDummyHardObjective;
16import org.eclipse.viatra.dse.objectives.impl.NoRuleActivationsHardObjective;
17import org.eclipse.viatra.dse.objectives.impl.TrajectoryCostSoftObjective;
18
19/**
20 *
21 * Helper class for creating built-in objectives.
22 *
23 * @author Andras Szabolcs Nagy
24 *
25 */
26public class Objectives {
27
28 private Objectives() {
29 }
30
31 /**
32 * This objective uses VIATRA Queries to calculate fitness and/or goal constraints. Use methods on the returned
33 * objective to configure it.
34 *
35 * @param name
36 * @return The objective.
37 * @see ConstraintsObjective
38 */
39 public static ConstraintsObjective createConstraintsObjective(String name) {
40 return new ConstraintsObjective(name);
41 }
42
43 /**
44 * This objective calculates fitness on the trajectory by adding either fix costs to the rules, or by calculating
45 * custom fitness on activation of rules.
46 *
47 * @param name
48 * @return The objective.
49 * @see TrajectoryCostSoftObjective
50 */
51 public static TrajectoryCostSoftObjective createTrajcetoryCostObjective(String name) {
52 return new TrajectoryCostSoftObjective(name);
53 }
54
55 /**
56 * This objective adds a goal constraint that a solution state should not have any activations.
57 *
58 * @return The objective.
59 * @see NoRuleActivationsHardObjective
60 */
61 public static NoRuleActivationsHardObjective createNoRuleActivationsHardConstraint() {
62 return new NoRuleActivationsHardObjective();
63 }
64
65 /**
66 * This objective adds a goal constraint that a solution state should not have any activations.
67 *
68 * @param name
69 * @return The objective.
70 * @see NoRuleActivationsHardObjective
71 */
72 public static NoRuleActivationsHardObjective createNoRuleActivationsHardConstraint(String name) {
73 return new NoRuleActivationsHardObjective(name);
74 }
75
76 /**
77 * This objective can combine the calculated fitness value of other objectives. Weights are supported.
78 *
79 * @param name
80 * @return The objective.
81 * @see NoRuleActivationsHardObjective
82 */
83 public static CompositeObjective createCompositeObjective(String name) {
84 return new CompositeObjective(name);
85 }
86
87 /**
88 * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid
89 * solution.
90 *
91 * @return The objective.
92 * @see AlwaysSatisfiedDummyHardObjective
93 */
94 public static AlwaysSatisfiedDummyHardObjective createAlwaysSatisfiedDummyHardObjective() {
95 return new AlwaysSatisfiedDummyHardObjective();
96 }
97
98 /**
99 * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid
100 * solution.
101 *
102 * @param name
103 * @return The objective.
104 * @see AlwaysSatisfiedDummyHardObjective
105 */
106 public static AlwaysSatisfiedDummyHardObjective createDummyHardObjective(String name) {
107 return new AlwaysSatisfiedDummyHardObjective(name);
108 }
109
110 /**
111 * This hard objective is never fulfilled. Use it if all states should be regarded as an invalid solution.
112 *
113 * @return The objective.
114 * @see AlwaysSatisfiedDummyHardObjective
115 */
116 public static NeverSatisfiedDummyHardObjective createNeverSatisfiedDummyHardObjective() {
117 return new NeverSatisfiedDummyHardObjective();
118 }
119
120 /**
121 * This hard objective is never fulfilled. Use it if all states should be regarded as an invalid solution.
122 *
123 * @return The objective.
124 * @see AlwaysSatisfiedDummyHardObjective
125 */
126 public static NeverSatisfiedDummyHardObjective createNeverSatisfiedDummyHardObjective(String name) {
127 return new NeverSatisfiedDummyHardObjective(name);
128 }
129
130 /**
131 * This hard objective is fulfilled if the length of the trajectory is in the specified interval (inclusive). Use
132 * {@link DepthHardObjective#withMinDepth(int)} and {@link DepthHardObjective#withMaxDepth(int)} to configure.
133 *
134 * @return The objective.
135 * @see DepthHardObjective
136 */
137 public static DepthHardObjective createDepthHardObjective() {
138 return new DepthHardObjective();
139 }
140
141 /**
142 * This hard objective is fulfilled if the length of the trajectory is in the specified interval (inclusive). Use
143 * {@link DepthHardObjective#withMinDepth(int)} and {@link DepthHardObjective#withMaxDepth(int)} to configure.
144 *
145 * @param name
146 * @return The objective.
147 * @see DepthHardObjective
148 */
149 public static DepthHardObjective createDepthHardObjective(String name) {
150 return new DepthHardObjective(name);
151 }
152
153}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Solution.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Solution.java
new file mode 100644
index 00000000..b776db7a
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Solution.java
@@ -0,0 +1,60 @@
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.api;
10
11import java.util.Collection;
12import java.util.HashSet;
13import java.util.Iterator;
14import java.util.Set;
15
16public class Solution {
17
18 private Set<SolutionTrajectory> trajectories;
19 private final Object stateId;
20
21 public Solution(Object stateId, SolutionTrajectory trajectory) {
22 this.stateId = stateId;
23 trajectories = new HashSet<>();
24 trajectories.add(trajectory);
25 }
26
27 public void addTrajectory(SolutionTrajectory trajectory) {
28 trajectories.add(trajectory);
29 }
30
31 public SolutionTrajectory getArbitraryTrajectory() {
32 return trajectories.iterator().next();
33 }
34
35 public SolutionTrajectory getShortestTrajectory() {
36 Iterator<SolutionTrajectory> iterator = trajectories.iterator();
37 SolutionTrajectory shortestTrajecotry = iterator.next();
38 int minSize = shortestTrajecotry.getTrajectoryLength();
39
40 while (iterator.hasNext()) {
41 SolutionTrajectory traj = iterator.next();
42 int size = traj.getTrajectoryLength();
43 if (size < minSize) {
44 shortestTrajecotry = traj;
45 minSize = size;
46 }
47 }
48
49 return shortestTrajecotry;
50 }
51
52 public Collection<SolutionTrajectory> getTrajectories() {
53 return trajectories;
54 }
55
56 public Object getStateCode() {
57 return stateId;
58 }
59
60}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/SolutionTrajectory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/SolutionTrajectory.java
new file mode 100644
index 00000000..500dd7d2
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/SolutionTrajectory.java
@@ -0,0 +1,345 @@
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.api;
10
11import java.lang.reflect.InvocationTargetException;
12import java.util.HashSet;
13import java.util.List;
14import java.util.Objects;
15import java.util.function.Consumer;
16
17import org.eclipse.emf.common.notify.Notifier;
18import org.eclipse.emf.edit.command.ChangeCommand;
19import org.eclipse.emf.edit.domain.EditingDomain;
20import org.eclipse.viatra.dse.base.DseIdPoolHelper;
21import org.eclipse.viatra.dse.designspace.api.IBacktrackListener;
22import org.eclipse.viatra.dse.objectives.Fitness;
23import org.eclipse.viatra.dse.statecode.IStateCoder;
24import org.eclipse.viatra.dse.statecode.IStateCoderFactory;
25import org.eclipse.viatra.dse.util.EMFHelper;
26import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine;
27import org.eclipse.viatra.query.runtime.api.IPatternMatch;
28import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
29import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher;
30import org.eclipse.viatra.query.runtime.emf.EMFScope;
31import org.eclipse.viatra.query.runtime.matchers.ViatraQueryRuntimeException;
32import org.eclipse.viatra.query.runtime.matchers.util.Preconditions;
33import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
34
35import com.google.common.util.concurrent.UncheckedExecutionException;
36
37/**
38 * A SolutionTrajectory represents a trajectory (i.e. sequence of transformation
39 * rule applications), which can transform the initial model to a desired state.
40 * An instance of this class holds the the actual rule sequence and the
41 * corresponding activation codes. Furthermore it can be used to perform the
42 * transformation on a given model (if possible).
43 * <p>
44 * It is also possible to undo the transformation if initialized with an editing
45 * domain.
46 * <p>
47 * The instance of this class can be reused for different models.
48 *
49 * @author Andras Szabolcs Nagy
50 *
51 */
52public class SolutionTrajectory {
53
54 private final List<Object> activationCodes;
55 private final List<BatchTransformationRule<?, ?>> transformationRules;
56 private final IStateCoderFactory stateCoderFactory;
57 private Fitness fitness;
58 private Solution solution;
59
60 private ViatraQueryEngine engine;
61 private Notifier model;
62 private EditingDomain editingDomain;
63 private IStateCoder stateCoder;
64 private IBacktrackListener listener;
65
66 private int currentIndex;
67
68 public SolutionTrajectory(final List<Object> activationCodes,
69 final List<BatchTransformationRule<?, ?>> transformationRules, final IStateCoderFactory stateCoderFactory,
70 final IBacktrackListener backtrackListener) {
71 Objects.requireNonNull(transformationRules, "Parameter transformationRules cannot be null!");
72 Objects.requireNonNull(stateCoderFactory, "Parameter stateCoderFactory cannot be null!");
73 Objects.requireNonNull(activationCodes, "Parameter activations cannot be null!");
74 Preconditions.checkState(transformationRules.size() == activationCodes.size(),
75 "The two List parameters must be the same in size.");
76
77 this.activationCodes = activationCodes;
78 this.transformationRules = transformationRules;
79 this.stateCoderFactory = stateCoderFactory;
80 this.listener = backtrackListener;
81 currentIndex = 0;
82 }
83
84 /**
85 * Initialize this SolutionTrajectory for transforming the model along the
86 * trajectory.
87 *
88 * @param model The model.
89 * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize.
90 */
91 public void setModel(Notifier model) {
92 editingDomain = null;
93 EMFScope scope = new EMFScope(model);
94 this.engine = ViatraQueryEngine.on(scope);
95 this.model = model;
96 stateCoder = stateCoderFactory.createStateCoder();
97 stateCoder.init(model);
98 currentIndex = 0;
99 DseIdPoolHelper.INSTANCE.disposeByThread();
100 DseIdPoolHelper.INSTANCE.registerRules(rule -> {
101 int id = 0;
102 for (BatchTransformationRule<?, ?> r : transformationRules.subList(0, currentIndex)) {
103 if (r.equals(rule)) {
104 id++;
105 }
106 }
107 return id;
108 }, new HashSet<BatchTransformationRule<?, ?>>(transformationRules));
109 }
110
111 /**
112 * Initialize this SolutionTrajectory for transforming the given model along the
113 * trajectory.
114 * <p>
115 * The transformation will be reversible by creating an {@link EditingDomain} on
116 * the model.
117 *
118 * @param modelRoot The root of the model.
119 * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize.
120 */
121 public void setModelWithEditingDomain(Notifier modelRoot) {
122 setModel(modelRoot);
123 editingDomain = EMFHelper.createEditingDomain(model);
124 }
125
126 /**
127 * Transforms the given model along the trajectory.
128 *
129 * @param modelRoot The root of the model.
130 * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize.
131 */
132 public void doTransformation(Notifier modelRoot) {
133 setModel(modelRoot);
134 doTransformation();
135 }
136
137 /**
138 * Transforms the given model along the trajectory.
139 * <p>
140 * The transformation will be reversible by creating an {@link EditingDomain} on
141 * the model.
142 *
143 * @param modelRoot The root of the model.
144 * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize.
145 */
146 public void doTransformationUndoable(Notifier modelRoot) {
147 setModelWithEditingDomain(modelRoot);
148 doTransformation();
149 }
150
151 /**
152 * Transforms the given model along the trajectory. To initialize the model call
153 * the {@link SolutionTrajectory#setModel(Notifier)} method.
154 *
155 * @throws Exception If the activation to fire is not found.
156 * Possible problems: wrong model, bad state
157 * serializer.
158 * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize.
159 */
160 public void doTransformation() {
161 while (doNextTransformation())
162 ;
163 }
164
165 /**
166 * Transforms the given model by one step to the solution (makes one step in the
167 * trajectory). To initialize the model call the
168 * {@link SolutionTrajectory#setModel(Notifier)} method.
169 *
170 * @throws ViatraQueryRuntimeException
171 */
172 public boolean doNextTransformation() {
173 if (currentIndex >= activationCodes.size()) {
174 return false;
175 } else {
176 doNextTransformation(currentIndex);
177 currentIndex++;
178 return true;
179 }
180 }
181
182 @SuppressWarnings("unchecked")
183 private void doNextTransformation(int index) {
184 Objects.requireNonNull(model, "The model cannot be null! Use the setModel method.");
185
186 // cast for the ".process(match)" method.
187 BatchTransformationRule<?, ?> tr = transformationRules.get(index);
188 Object activationCode = activationCodes.get(index);
189
190 ViatraQueryMatcher<?> matcher = tr.getPrecondition().getMatcher(engine);
191
192 boolean isActivationFound = false;
193 for (final IPatternMatch match : matcher.getAllMatches()) {
194 Object matchHash = stateCoder.createActivationCode(match);
195 if (matchHash.equals(activationCode)) {
196 @SuppressWarnings("rawtypes")
197 final Consumer action = tr.getAction();
198
199 if (editingDomain == null) {
200 action.accept(match);
201 } else {
202 ChangeCommand cc = new ChangeCommand(model) {
203 @Override
204 protected void doExecute() {
205 action.accept(match);
206 }
207 };
208 long start = System.nanoTime();
209 try {
210 ((AdvancedViatraQueryEngine) engine).delayUpdatePropagation(() -> {
211 editingDomain.getCommandStack().execute(cc);
212 return null;
213 });
214 } catch (InvocationTargetException e) {
215 throw new RuntimeException(e);
216 }
217 listener.forwardWorked(System.nanoTime() - start);
218 }
219
220 isActivationFound = true;
221 break;
222 }
223 }
224 if (!isActivationFound) {
225 throw new UncheckedExecutionException(
226 "Activation was not found for transformation! Possible cause: wrong model, bad state coder. index: "
227 + index + " Activation code: " + activationCode,
228 null);
229 }
230 }
231
232 /**
233 * Call this method to undo the last transformation.
234 *
235 * @return True, if it was successful.
236 */
237 public boolean undoLastTransformation() {
238 Objects.requireNonNull(editingDomain, "To be able to undo the transformation initialize with editing domain.");
239 long start = System.nanoTime();
240 boolean result;
241
242 if (currentIndex > 0) {
243 try {
244 ((AdvancedViatraQueryEngine) engine).delayUpdatePropagation(() -> {
245 editingDomain.getCommandStack().undo();
246 return null;
247 });
248 } catch (InvocationTargetException e) {
249 throw new RuntimeException(e);
250 }
251 currentIndex--;
252 result = true;
253 }
254 result = false;
255 listener.backtrackWorked(System.nanoTime() - start);
256 return result;
257 }
258
259 /**
260 * Call this method to undo the transformation.
261 */
262 public void undoTransformation() {
263 while (undoLastTransformation())
264 ;
265 }
266
267 public List<Object> getActivationCodes() {
268 return activationCodes;
269 }
270
271 public List<BatchTransformationRule<?, ?>> getTransformationRules() {
272 return transformationRules;
273 }
274
275 public IStateCoderFactory getStateCoderFactory() {
276 return stateCoderFactory;
277 }
278
279 public ViatraQueryEngine getEngine() {
280 return engine;
281 }
282
283 public Notifier getModel() {
284 return model;
285 }
286
287 public IStateCoder getStateCoder() {
288 return stateCoder;
289 }
290
291 public int getCurrentIndex() {
292 return currentIndex;
293 }
294
295 public int getTrajectoryLength() {
296 return activationCodes.size();
297 }
298
299 public Fitness getFitness() {
300 return fitness;
301 }
302
303 public void setFitness(Fitness fitness) {
304 this.fitness = fitness;
305 }
306
307 public String toPrettyString() {
308 StringBuilder sb = new StringBuilder();
309 sb.append("Fitness: ");
310 sb.append(fitness.toString());
311 sb.append(" | Trajectory (");
312 sb.append(activationCodes.size());
313 sb.append("): ");
314 for (Object object : activationCodes) {
315 sb.append(object.toString());
316 sb.append(" | ");
317 }
318 return sb.toString();
319 }
320
321 @Override
322 public int hashCode() {
323 return activationCodes.hashCode();
324 }
325
326 @Override
327 public boolean equals(Object obj) {
328 if (this == obj) {
329 return true;
330 }
331 if (obj instanceof SolutionTrajectory) {
332 SolutionTrajectory that = (SolutionTrajectory) obj;
333 return activationCodes.equals(that.activationCodes);
334 }
335 return false;
336 }
337
338 public Solution getSolution() {
339 return solution;
340 }
341
342 public void setSolution(Solution solution) {
343 this.solution = solution;
344 }
345}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Strategies.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Strategies.java
new file mode 100644
index 00000000..ed7a90da
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Strategies.java
@@ -0,0 +1,123 @@
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.api;
10
11import org.eclipse.viatra.dse.api.strategy.impl.BestFirstStrategy;
12import org.eclipse.viatra.dse.api.strategy.impl.BreadthFirstStrategy;
13import org.eclipse.viatra.dse.api.strategy.impl.DepthFirstStrategy;
14import org.eclipse.viatra.dse.api.strategy.impl.FixedPriorityStrategy;
15import org.eclipse.viatra.dse.api.strategy.impl.HillClimbingStrategy;
16import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
17
18/**
19 * Helper class for instantiating strategies. To implement a new strategy use the {@link IStrategy} interface.
20 *
21 * @author Andras Szabolcs Nagy
22 *
23 */
24public final class Strategies {
25
26 private Strategies() {
27 }
28
29 /**
30 * Creates a depth-first search exploration strategy without a depth limit.
31 *
32 * @return The strategy.
33 * @see DepthFirstStrategy
34 */
35 public static DepthFirstStrategy createDfsStrategy() {
36 return new DepthFirstStrategy();
37 }
38
39 /**
40 * Creates a depth-first search exploration strategy with a depth limit. A negative depth limit means no
41 * depth limit, zero means that it will check the initial state.
42 *
43 * @param depthLimit
44 * @return The strategy.
45 * @see DepthFirstStrategy
46 */
47 public static DepthFirstStrategy createDfsStrategy(int depthLimit) {
48 return new DepthFirstStrategy(depthLimit);
49 }
50
51 /**
52 * Creates a fixed priority exploration strategy without a depth limit. It is a depth-first search exploration
53 * strategy but from a current state it only explores the activations with the highest priority. Priorities can be
54 * defined on the strategy itself.
55 *
56 * @return The strategy.
57 * @see FixedPriorityStrategy
58 */
59 public static FixedPriorityStrategy createFixedPriorityStrategy() {
60 return createFixedPriorityStrategy(-1);
61 }
62
63 /**
64 * Creates a fixed priority exploration strategy with a depth limit, where a zero or negative depth limit means no
65 * depth limit. It is a depth-first search exploration strategy but from a current state it only explores the
66 * activations with the highest priority. Priorities can be defined on the strategy itself.
67 *
68 * @param depthLimit
69 * @return The strategy.
70 * @see FixedPriorityStrategy
71 */
72 public static FixedPriorityStrategy createFixedPriorityStrategy(int depthLimit) {
73 return new FixedPriorityStrategy().withDepthLimit(depthLimit);
74 }
75
76 /**
77 * Creates a breadth-first search exploration strategy without a depth limit.
78 *
79 * @return The strategy.
80 * @see BreadthFirstStrategy
81 */
82 public static BreadthFirstStrategy createBfsStrategy() {
83 return new BreadthFirstStrategy();
84 }
85
86 /**
87 * Creates a breadth-first search exploration strategy with a depth limit. A zero or negative depth limit means no
88 * depth limit.
89 *
90 * @param depthLimit
91 * @return The strategy.
92 * @see BreadthFirstStrategy
93 */
94 public static BreadthFirstStrategy createBfsStrategy(int depthLimit) {
95 return new BreadthFirstStrategy(depthLimit);
96 }
97
98 /**
99 * Creates a hill climbing exploration strategy. By default, it explores all neighborhood states and chooses the
100 * best one to continue with until all neighborhood states are dominated by the current state. Other options are
101 * available on the strategy.
102 *
103 * @return The strategy.
104 * @see HillClimbingStrategy
105 */
106 public static HillClimbingStrategy creatHillClimbingStrategy() {
107 return new HillClimbingStrategy();
108 }
109
110 /**
111 * See {@link BestFirstStrategy}.
112 */
113 public static BestFirstStrategy createBestFirstStrategy() {
114 return new BestFirstStrategy();
115 }
116
117 /**
118 * See {@link BestFirstStrategy}.
119 */
120 public static BestFirstStrategy createBestFirstStrategy(int depthLimit) {
121 return new BestFirstStrategy(depthLimit);
122 }
123}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.java
new file mode 100644
index 00000000..fe5604a1
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.java
@@ -0,0 +1,228 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.api.strategy.impl;
10
11import java.util.Arrays;
12import java.util.Collection;
13import java.util.Iterator;
14import java.util.PriorityQueue;
15
16import org.apache.log4j.Logger;
17import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
18import org.eclipse.viatra.dse.base.ThreadContext;
19import org.eclipse.viatra.dse.objectives.Fitness;
20import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper;
21import org.eclipse.viatra.dse.solutionstore.SolutionStore;
22
23/**
24 * This exploration strategy eventually explorers the whole design space but goes in the most promising directions
25 * first, based on the {@link Fitness}.
26 *
27 * There are a few parameter to tune such as
28 * <ul>
29 * <li>maximum depth</li>
30 * <li>continue the exploration from a state that satisfies the hard objectives (the default that it will
31 * backtrack),</li>
32 * <li>whether to continue the exploration from the newly explored state if it is at least equally good than the
33 * previous one or only if it is better (default is "at least equally good").</li>
34 * </ul>
35 *
36 * @author Andras Szabolcs Nagy
37 *
38 */
39public class BestFirstStrategy implements IStrategy {
40
41 private ThreadContext context;
42 private SolutionStore solutionStore;
43
44 private int maxDepth;
45 private boolean isInterrupted = false;
46 private boolean backTrackIfSolution = true;
47 private boolean onlyBetterFirst = false;
48
49 private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore;
50 private Logger logger = Logger.getLogger(IStrategy.class);
51
52 private static class TrajectoryWithFitness {
53
54 public Object[] trajectory;
55 public Fitness fitness;
56
57 public TrajectoryWithFitness(Object[] trajectory, Fitness fitness) {
58 super();
59 this.trajectory = trajectory;
60 this.fitness = fitness;
61 }
62
63 @Override
64 public String toString() {
65 return Arrays.toString(trajectory) + fitness.toString();
66 }
67
68 }
69
70 /**
71 * Creates a new best-first search algorithm without depth limit.
72 */
73 public BestFirstStrategy() {
74 this(-1);
75 }
76
77 /**
78 * Creates a new best-first search algorithm with depth limit.
79 *
80 * @param maxDepth
81 * A negative <code>maxDepth</code> means no depth limit, zero means the checking of the initial state.
82 */
83 public BestFirstStrategy(int maxDepth) {
84 if (maxDepth < 0) {
85 this.maxDepth = Integer.MAX_VALUE;
86 } else {
87 this.maxDepth = maxDepth;
88 }
89 }
90
91 public BestFirstStrategy continueIfHardObjectivesFulfilled() {
92 backTrackIfSolution = false;
93 return this;
94 }
95
96 public BestFirstStrategy goOnOnlyIfFitnessIsBetter() {
97 onlyBetterFirst = true;
98 return this;
99 }
100
101 @Override
102 public void initStrategy(ThreadContext context) {
103 this.context = context;
104 this.solutionStore = context.getGlobalContext().getSolutionStore();
105 final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper();
106
107 trajectoiresToExplore = new PriorityQueue<TrajectoryWithFitness>(11,
108 (o1, o2) -> objectiveComparatorHelper.compare(o2.fitness, o1.fitness));
109 }
110
111 @Override
112 public void explore() {
113 final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper();
114
115 boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints();
116 if (!globalConstraintsAreSatisfied) {
117 logger.info("Global contraint is not satisifed in the first state. Terminate.");
118 return;
119 }
120
121 final Fitness firstFittness = context.calculateFitness();
122 if (firstFittness.isSatisifiesHardObjectives()) {
123 context.newSolution();
124 logger.info("First state is a solution. Terminate.");
125 return;
126 }
127
128 if (maxDepth == 0) {
129 return;
130 }
131
132 final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]);
133 TrajectoryWithFitness currentTrajectoryWithFittness = new TrajectoryWithFitness(firstTrajectory, firstFittness);
134 trajectoiresToExplore.add(currentTrajectoryWithFittness);
135
136 mainLoop: while (!isInterrupted) {
137
138 if (currentTrajectoryWithFittness == null) {
139 if (trajectoiresToExplore.isEmpty()) {
140 logger.debug("State space is fully traversed.");
141 return;
142 } else {
143 currentTrajectoryWithFittness = trajectoiresToExplore.element();
144 if (logger.isDebugEnabled()) {
145 logger.debug("New trajectory is chosen: " + currentTrajectoryWithFittness);
146 }
147 context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFittness.trajectory);
148 }
149 }
150
151 Collection<Object> activationIds = context.getUntraversedActivationIds();
152 Iterator<Object> iterator = activationIds.iterator();
153
154 while (!isInterrupted && iterator.hasNext()) {
155 final Object nextActivation = iterator.next();
156 if (!iterator.hasNext()) {
157 logger.debug("Last untraversed activation of the state.");
158 trajectoiresToExplore.remove(currentTrajectoryWithFittness);
159 }
160
161 if (logger.isDebugEnabled()) {
162 logger.debug("Executing new activation: " + nextActivation);
163 }
164 context.executeAcitvationId(nextActivation);
165 if (context.isCurrentStateAlreadyTraversed()) {
166 logger.info("The new state is already visited.");
167 context.backtrack();
168 } else if (!context.checkGlobalConstraints()) {
169 logger.debug("Global contraint is not satisifed.");
170 context.backtrack();
171 } else {
172 final Fitness nextFitness = context.calculateFitness();
173 if (nextFitness.isSatisifiesHardObjectives()) {
174 solutionStore.newSolution(context);
175 logger.debug("Found a solution.");
176 if (backTrackIfSolution) {
177 context.backtrack();
178 continue;
179 }
180 }
181 if (context.getDepth() >= maxDepth) {
182 logger.debug("Reached max depth.");
183 context.backtrack();
184 continue;
185 }
186
187 TrajectoryWithFitness nextTrajectoryWithFittness = new TrajectoryWithFitness(
188 context.getTrajectory().toArray(), nextFitness);
189 trajectoiresToExplore.add(nextTrajectoryWithFittness);
190
191 int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFittness.fitness,
192 nextTrajectoryWithFittness.fitness);
193 if (compare < 0) {
194 logger.debug("Better fitness, moving on: " + nextFitness);
195 currentTrajectoryWithFittness = nextTrajectoryWithFittness;
196 continue mainLoop;
197 } else if (compare == 0) {
198 if (onlyBetterFirst) {
199 logger.debug("Equally good fitness, backtrack: " + nextFitness);
200 context.backtrack();
201 continue;
202 } else {
203 logger.debug("Equally good fitness, moving on: " + nextFitness);
204 currentTrajectoryWithFittness = nextTrajectoryWithFittness;
205 continue mainLoop;
206 }
207 } else {
208 logger.debug("Worse fitness.");
209 currentTrajectoryWithFittness = null;
210 continue mainLoop;
211 }
212 }
213 }
214
215 logger.debug("State is fully traversed.");
216 trajectoiresToExplore.remove(currentTrajectoryWithFittness);
217 currentTrajectoryWithFittness = null;
218
219 }
220 logger.info("Interrupted.");
221 }
222
223 @Override
224 public void interruptStrategy() {
225 isInterrupted = true;
226 }
227
228}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.java
new file mode 100644
index 00000000..6b7d9817
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.java
@@ -0,0 +1,220 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.api.strategy.impl;
10
11import java.util.Collection;
12import java.util.Iterator;
13import java.util.concurrent.BrokenBarrierException;
14import java.util.concurrent.ConcurrentLinkedQueue;
15import java.util.concurrent.CyclicBarrier;
16import java.util.concurrent.atomic.AtomicBoolean;
17
18import org.apache.log4j.Logger;
19import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
20import org.eclipse.viatra.dse.base.GlobalContext;
21import org.eclipse.viatra.dse.base.ThreadContext;
22import org.eclipse.viatra.dse.objectives.Fitness;
23import org.eclipse.viatra.dse.solutionstore.SolutionStore;
24
25/**
26 * A breadth-first search algorithm implementation, that
27 * <ul>
28 * <li>can work with multiple threads,</li>
29 * <li>indeterministic,</li>
30 * <li>saves all states (trajectories) as solutions that fulfill all the hard objectives,</li>
31 * <li>can have a depth limit,</li>
32 * <li>will backtrack when a model satisfies the hard objectives (after saving it as a solution) and will not explore
33 * beyond that state.</li>
34 * </ul>
35 *
36 * @author Andras Szabolcs Nagy
37 *
38 */
39public class BreadthFirstStrategy implements IStrategy {
40
41 private static final class BfsSharedObject {
42 private final ConcurrentLinkedQueue<Object[]> trajectoryQueue1 = new ConcurrentLinkedQueue<>();
43 private final ConcurrentLinkedQueue<Object[]> trajectoryQueue2 = new ConcurrentLinkedQueue<>();
44
45 private final AtomicBoolean pushToQueue1 = new AtomicBoolean(false);
46 private final AtomicBoolean designSpaceTraversed = new AtomicBoolean(false);
47
48 public final CyclicBarrier barrier;
49
50 public BfsSharedObject(int numberOfThreads) {
51 barrier = new CyclicBarrier(numberOfThreads, () -> {
52 boolean oldValue = pushToQueue1.get();
53 pushToQueue1.set(!oldValue);
54 if (trajectoryQueue1.isEmpty() && trajectoryQueue2.isEmpty()) {
55 designSpaceTraversed.set(true);
56 }
57 });
58 }
59
60 public Object[] poll() {
61 if (pushToQueue1.get()) {
62 return trajectoryQueue2.poll();
63 } else {
64 return trajectoryQueue1.poll();
65 }
66 }
67
68 public void push(Object[] trajectory) {
69 if (pushToQueue1.get()) {
70 trajectoryQueue1.add(trajectory);
71 } else {
72 trajectoryQueue2.add(trajectory);
73 }
74 }
75
76 public boolean isDesignSpaceTraversed() {
77 return designSpaceTraversed.get();
78 }
79 }
80
81 private int maxDepth = 0;
82 private BfsSharedObject shared;
83 private boolean isInterrupted = false;
84 private ThreadContext context;
85 private Logger logger = Logger.getLogger(IStrategy.class);
86 private SolutionStore solutionStore;
87 private boolean isFirstThread = false;
88
89 /**
90 * Creates a new breadth-first search algorithm without depth limit.
91 */
92 public BreadthFirstStrategy() {
93 this.maxDepth = Integer.MAX_VALUE;
94 }
95
96 /**
97 * Creates a new breadth-first search algorithm with depth limit.
98 *
99 * @param maxDepth
100 * A negative <code>maxDepth</code> means no depth limit, zero means the checking of the initial state.
101 */
102 public BreadthFirstStrategy(int maxDepth) {
103 if (maxDepth < 0) {
104 this.maxDepth = Integer.MAX_VALUE;
105 } else {
106 this.maxDepth = maxDepth;
107 }
108 }
109
110 @Override
111 public void initStrategy(ThreadContext context) {
112 this.context = context;
113 this.solutionStore = context.getGlobalContext().getSolutionStore();
114
115 GlobalContext globalContext = context.getGlobalContext();
116 if (globalContext.getSharedObject() == null) {
117 isFirstThread = true;
118 shared = new BfsSharedObject(globalContext.getThreadPool().getMaximumPoolSize());
119 globalContext.setSharedObject(shared);
120 logger.info("Breadth-first exploration strategy is inited.");
121 } else {
122 shared = (BfsSharedObject) globalContext.getSharedObject();
123 }
124 }
125
126 @Override
127 public void explore() {
128
129 if (isFirstThread) {
130
131 boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints();
132 if (!globalConstraintsAreSatisfied) {
133 logger.info("Global contraint is not satisifed in the first state. Terminate.");
134 return;
135 }
136
137 Fitness fitness = context.calculateFitness();
138 if (fitness.isSatisifiesHardObjectives()) {
139 context.newSolution();
140 logger.info("First state is a solution. Terminate.");
141 return;
142 }
143
144 Object[] currentTrajectory = context.getTrajectory().toArray(new Object[0]);
145
146 shared.push(currentTrajectory);
147
148 startThreads();
149 } else {
150 try {
151 shared.barrier.await();
152 } catch (InterruptedException | BrokenBarrierException e) {
153 }
154 }
155
156 mainLoop: while (!isInterrupted && !shared.isDesignSpaceTraversed()) {
157
158 Object[] next = shared.poll();
159 while (next == null) {
160 try {
161 logger.debug("Reached barrier.");
162 shared.barrier.await();
163 } catch (InterruptedException | BrokenBarrierException e1) {
164 }
165 if (isInterrupted || shared.isDesignSpaceTraversed()) {
166 break mainLoop;
167 }
168 next = shared.poll();
169 }
170
171 context.backtrackUntilRoot();
172
173 context.executeTrajectory(next);
174
175 Collection<Object> activationIds = context.getCurrentActivationIds();
176 int i = activationIds.size() - 1;
177
178 while (!isInterrupted && i >= 0) {
179
180 Iterator<Object> iterator = activationIds.iterator();
181 int index = i--;
182 while (iterator.hasNext() && index > 0) {
183 index--;
184 iterator.next();
185 }
186 Object activationIdToTry = iterator.next();
187
188 context.executeAcitvationId(activationIdToTry);
189
190 if (context.isCurrentStateAlreadyTraversed()) {
191 logger.info("The new state is already visited.");
192 } else if (!context.checkGlobalConstraints()) {
193 logger.debug("Global contraint is not satisifed.");
194 } else if (context.calculateFitness().isSatisifiesHardObjectives()) {
195 solutionStore.newSolution(context);
196 logger.debug("Found a solution.");
197 } else if (context.getDepth() >= maxDepth) {
198 logger.debug("Reached max depth.");
199 } else {
200 Object[] currentTrajectory = context.getTrajectory().toArray(new Object[0]);
201 shared.push(currentTrajectory);
202 }
203
204 context.backtrack();
205 }
206
207 }
208 }
209
210 private void startThreads() {
211 context.startAllThreads(() -> new BreadthFirstStrategy(maxDepth));
212 }
213
214 @Override
215 public void interruptStrategy() {
216 isInterrupted = true;
217 shared.barrier.reset();
218 }
219
220}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.java
new file mode 100644
index 00000000..22a4a683
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.java
@@ -0,0 +1,188 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.api.strategy.impl;
10
11import java.util.Collection;
12import java.util.Iterator;
13import java.util.Random;
14import java.util.concurrent.atomic.AtomicBoolean;
15
16import org.apache.log4j.Logger;
17import org.eclipse.viatra.dse.api.DSEException;
18import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
19import org.eclipse.viatra.dse.base.ThreadContext;
20import org.eclipse.viatra.dse.objectives.Fitness;
21
22/**
23 * A depth-first search algorithm implementation, that
24 * <ul>
25 * <li>can work with multiple threads,</li>
26 * <li>randomly traverses the search space,</li>
27 * <li>saves all states (trajectories) as solutions that fulfill all the hard objectives,</li>
28 * <li>can have a depth limit,</li>
29 * <li>will backtrack when a model satisfies the hard objectives (after saving it as a solution), which can be modified
30 * by calling {@link #continueIfHardObjectivesFulfilled()}</li>
31 * </ul>
32 *
33 * @author Andras Szabolcs Nagy
34 *
35 */
36public class DepthFirstStrategy implements IStrategy {
37
38 private int maxDepth;
39 private AtomicBoolean isInterrupted = new AtomicBoolean(false);
40 private ThreadContext context;
41
42 private Logger logger = Logger.getLogger(IStrategy.class);
43
44 private Random random = new Random();
45 private boolean backTrackIfSolution = true;
46
47 /**
48 * Creates a new depth-first search algorithm without depth limit.
49 */
50 public DepthFirstStrategy() {
51 this.maxDepth = Integer.MAX_VALUE;
52 }
53
54 /**
55 * Creates a new depth-first search algorithm with depth limit.
56 *
57 * @param maxDepth
58 * A negative <code>maxDepth</code> means no depth limit, zero means the checking of the initial state.
59 */
60 public DepthFirstStrategy(int maxDepth) {
61 if (maxDepth < 0) {
62 this.maxDepth = Integer.MAX_VALUE;
63 } else {
64 this.maxDepth = maxDepth;
65 }
66 }
67
68 /**
69 * If called, the algorithm will not backtrack after the hard objectives are fulfilled, instead it goes deeper in
70 * the search space.
71 */
72 public DepthFirstStrategy continueIfHardObjectivesFulfilled() {
73 backTrackIfSolution = false;
74 return this;
75 }
76
77 @Override
78 public void initStrategy(ThreadContext context) {
79 this.context = context;
80
81 if (context.getSharedObject() == null) {
82 context.setSharedObject(new Object());
83 logger.info("Depth-first exploration strategy is initied.");
84 startThreads();
85 }
86
87 }
88
89 private void startThreads() {
90 context.startAllThreads(() -> new DepthFirstStrategy(maxDepth));
91 }
92
93 @Override
94 public void explore() {
95
96 mainloop: do {
97
98 boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints();
99 if (!globalConstraintsAreSatisfied) {
100 boolean isSuccessfulUndo = context.backtrack();
101 if (!isSuccessfulUndo) {
102 logger.info("Global contraint is not satisifed and cannot backtrack.");
103 break;
104 } else {
105 logger.debug("Global contraint is not satisifed, backtrack.");
106 continue;
107 }
108 }
109
110 Fitness fitness = context.calculateFitness();
111 if (fitness.isSatisifiesHardObjectives()) {
112 context.newSolution();
113 if (backTrackIfSolution) {
114 boolean isSuccessfulUndo = context.backtrack();
115 if (!isSuccessfulUndo) {
116 logger.info("Found a solution but cannot backtrack.");
117 break;
118 } else {
119 logger.debug("Found a solution, backtrack.");
120 continue;
121 }
122 }
123 }
124
125 if (context.getDepth() >= maxDepth) {
126 boolean isSuccessfulUndo = context.backtrack();
127 if (!isSuccessfulUndo) {
128 logger.info("Reached max depth but cannot bactrack.");
129 break;
130 } else {
131 logger.debug("Reached max depth, bactrack.");
132 continue;
133 }
134 }
135
136 if (isInterrupted.get()) {
137 logger.info("Interrupted, stop exploration.");
138 break;
139 }
140
141 Object activationId = null;
142 Collection<Object> activationIds;
143
144 do {
145 activationIds = context.getUntraversedActivationIds();
146 if (activationIds.isEmpty()) {
147 boolean isSuccessfulUndo = context.backtrack();
148 if (!isSuccessfulUndo) {
149 logger.info("No more transitions from current state and cannot backtrack.");
150 break mainloop;
151 } else {
152 logger.debug("No more transitions from current state, backtrack.");
153 continue;
154 }
155 }
156 } while (activationIds.isEmpty());
157
158 int index = random.nextInt(activationIds.size());
159
160 Iterator<Object> iterator = activationIds.iterator();
161 while (index-- > 0) {
162 iterator.next();
163 }
164 activationId = iterator.next();
165
166 context.executeAcitvationId(activationId);
167
168 boolean loopInTrajectory = context.isCurrentStateInTrajectory();
169 if (loopInTrajectory) {
170 boolean isSuccessfulUndo = context.backtrack();
171 if (!isSuccessfulUndo) {
172 throw new DSEException("The new state is present in the trajectoy but cannot bactkrack. Should never happen!");
173 } else {
174 logger.info("The new state is already visited in the trajectory, backtrack.");
175 }
176 }
177
178 } while (true);
179
180 logger.info("Terminated.");
181 }
182
183 @Override
184 public void interruptStrategy() {
185 isInterrupted.set(true);
186 }
187
188}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.java
new file mode 100644
index 00000000..4ccda4ce
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.java
@@ -0,0 +1,208 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.api.strategy.impl;
10
11import java.util.Collection;
12import java.util.HashMap;
13import java.util.List;
14import java.util.Map;
15import java.util.Random;
16import java.util.concurrent.atomic.AtomicBoolean;
17
18import org.apache.log4j.Logger;
19import org.eclipse.viatra.dse.api.DSEException;
20import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
21import org.eclipse.viatra.dse.base.ThreadContext;
22import org.eclipse.viatra.dse.objectives.Fitness;
23import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
24
25import com.google.common.collect.Lists;
26
27/**
28 * Works as {@link DepthFirstStrategy} but:
29 * <ul>
30 * <li>works only with single thread,</li>
31 * <li>in a given state, it only traverses the activations with locally the highest priority.</li>
32 * </ul>
33 *
34 * @author Andras Szabolcs Nagy
35 *
36 */
37public class FixedPriorityStrategy implements IStrategy {
38
39 private int maxDepth = Integer.MAX_VALUE;
40 private AtomicBoolean isInterrupted = new AtomicBoolean(false);
41 private ThreadContext context;
42
43 private Logger logger = Logger.getLogger(IStrategy.class);
44 private Map<BatchTransformationRule<?, ?>, Integer> priorities = new HashMap<BatchTransformationRule<?, ?>, Integer>();
45
46 private Random random = new Random();
47 private Map<Object, List<Object>> bestPriorityInState = new HashMap<>();
48
49 /**
50 * Adds a depth limit to the strategy.
51 *
52 * @param depthLimit
53 * The depth limit.
54 * @return The actual instance to enable a builder pattern like usage.
55 */
56 public FixedPriorityStrategy withDepthLimit(int maxDepth) {
57 if (maxDepth < 0) {
58 this.maxDepth = Integer.MAX_VALUE;
59 } else {
60 this.maxDepth = maxDepth;
61 }
62 return this;
63 }
64
65 /**
66 * Assigns a priority to a rule. Unassigned rule will have a priority of 0.
67 *
68 * @param rule
69 * The transformation rule.
70 * @param priority
71 * The priority of the rule. Higher is better.
72 * @return The actual instance to enable a builder pattern like usage.
73 */
74 public FixedPriorityStrategy withRulePriority(BatchTransformationRule<?, ?> rule, int priority) {
75 priorities.put(rule, priority);
76 return this;
77 }
78
79 public Map<BatchTransformationRule<?, ?>, Integer> getPriorities() {
80 return priorities;
81 }
82
83 @Override
84 public void initStrategy(ThreadContext context) {
85 this.context = context;
86
87 logger.info("Fixed priority exploration strategy is initied.");
88 }
89
90 @Override
91 public void explore() {
92
93 mainloop: do {
94
95 boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints();
96 if (!globalConstraintsAreSatisfied) {
97 boolean isSuccessfulUndo = context.backtrack();
98 if (!isSuccessfulUndo) {
99 logger.info("Global contraint is not satisifed and cannot backtrack.");
100 break;
101 } else {
102 logger.debug("Global contraint is not satisifed, backtrack.");
103 continue;
104 }
105 }
106
107 Fitness fitness = context.calculateFitness();
108 if (fitness.isSatisifiesHardObjectives()) {
109 context.newSolution();
110 boolean isSuccessfulUndo = context.backtrack();
111 if (!isSuccessfulUndo) {
112 logger.info("Found a solution but cannot backtrack.");
113 break;
114 } else {
115 logger.debug("Found a solution, backtrack.");
116 continue;
117 }
118 }
119
120 if (context.getDepth() >= maxDepth) {
121 boolean isSuccessfulUndo = context.backtrack();
122 if (!isSuccessfulUndo) {
123 logger.info("Reached max depth but cannot bactrack.");
124 break;
125 } else {
126 logger.debug("Reached max depth, bactrack.");
127 continue;
128 }
129 }
130
131 if (isInterrupted.get()) {
132 logger.info("Interrupted, stop exploration.");
133 break;
134 }
135
136 List<Object> transitions;
137
138 do {
139
140 transitions = bestPriorityInState.get(context.getCurrentStateId());
141
142 if (transitions == null) {
143 Integer bestPriority = getBestPriority(context.getCurrentActivationIds());
144 transitions = Lists.newArrayList();
145 for (Object iTransition : context.getCurrentActivationIds()) {
146 Integer integer = priorities.get(context.getRuleByActivationId(iTransition));
147 if (integer == null) {
148 integer = Integer.valueOf(0);
149 }
150 if (integer.equals(bestPriority)) {
151 transitions.add(iTransition);
152 }
153 }
154 bestPriorityInState.put(context.getCurrentStateId(), transitions);
155 }
156
157 if (transitions.isEmpty()) {
158 boolean isSuccessfulUndo = context.backtrack();
159 if (!isSuccessfulUndo) {
160 logger.info("No more transitions from current state and cannot backtrack.");
161 break mainloop;
162 } else {
163 logger.debug("No more transitions from current state, backtrack.");
164 continue;
165 }
166 }
167 } while (transitions.isEmpty());
168
169 int index = random.nextInt(transitions.size());
170 Object transition = transitions.remove(index);
171
172 context.executeAcitvationId(transition);
173
174 boolean loopInTrajectory = context.isCurrentStateInTrajectory();
175 if (loopInTrajectory) {
176 boolean isSuccessfulUndo = context.backtrack();
177 if (!isSuccessfulUndo) {
178 throw new DSEException(
179 "The new state is present in the trajectoy but cannot bactkrack. Should never happen!");
180 } else {
181 logger.info("The new state is already visited in the trajectory, backtrack.");
182 }
183 }
184
185 } while (true);
186
187 logger.info("Terminated.");
188 }
189
190 @Override
191 public void interruptStrategy() {
192 isInterrupted.set(true);
193 }
194
195 private Integer getBestPriority(Collection<? extends Object> transitions) {
196 Integer bestPriority = Integer.MIN_VALUE;
197 for (Object iTransition : transitions) {
198 Integer priority = priorities.get(context.getRuleByActivationId(iTransition));
199 if (priority == null) {
200 priority = Integer.valueOf(0);
201 }
202 if (priority > bestPriority) {
203 bestPriority = priority;
204 }
205 }
206 return bestPriority;
207 }
208}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.java
new file mode 100644
index 00000000..0ccb0668
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.java
@@ -0,0 +1,142 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.api.strategy.impl;
10
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.Random;
14import java.util.concurrent.atomic.AtomicBoolean;
15
16import org.apache.log4j.Logger;
17import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
18import org.eclipse.viatra.dse.base.ThreadContext;
19import org.eclipse.viatra.dse.objectives.Fitness;
20import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper;
21import org.eclipse.viatra.dse.objectives.TrajectoryFitness;
22
23public class HillClimbingStrategy implements IStrategy {
24
25 private AtomicBoolean isInterrupted = new AtomicBoolean(false);
26 private ThreadContext context;
27
28 private Logger logger = Logger.getLogger(IStrategy.class);
29
30 private Random random = new Random();
31 private double percentOfOpenedStates;
32 private ObjectiveComparatorHelper objectiveComparatorHelper;
33
34 public HillClimbingStrategy() {
35 this(2);
36 }
37
38 public HillClimbingStrategy(double percentOfOpenedStates) {
39 this.percentOfOpenedStates = percentOfOpenedStates;
40 }
41
42 @Override
43 public void initStrategy(ThreadContext context) {
44 this.context = context;
45 objectiveComparatorHelper = context.getObjectiveComparatorHelper();
46 logger.info("Hill climbing exploration strategy is initied.");
47 }
48
49 @Override
50 public void explore() {
51
52 boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints();
53 if (!globalConstraintsAreSatisfied) {
54 boolean isSuccessfulUndo = context.backtrack();
55 if (!isSuccessfulUndo) {
56 logger.info("Global contraint is not satisifed and cannot backtrack.");
57 return;
58 }
59 }
60
61 mainloop: do {
62
63 Fitness previousFitness = context.calculateFitness();
64
65 logger.debug("Current depth: " + context.getDepth() + " Fitness: " + previousFitness);
66
67 Collection<Object> transitionsFromCurrentState = context.getCurrentActivationIds();
68
69 while (transitionsFromCurrentState.isEmpty()) {
70 logger.debug("No transitions from current state: considered as a solution.");
71 saveSolutionAndBacktrack();
72 continue mainloop;
73 }
74
75 ArrayList<Object> transitionsToTry = new ArrayList<>(transitionsFromCurrentState.size());
76 for (Object transition : transitionsFromCurrentState) {
77 transitionsToTry.add(transition);
78 }
79 double numberOfTransitionsToTry = transitionsToTry.size() * percentOfOpenedStates;
80
81 for (; numberOfTransitionsToTry > 0 && !transitionsToTry.isEmpty(); numberOfTransitionsToTry--) {
82 int index = random.nextInt(transitionsToTry.size());
83 Object transition = transitionsToTry.remove(index);
84
85 context.executeAcitvationId(transition);
86
87 if (!context.checkGlobalConstraints()) {
88 logger.debug("Global contraint is not satisifed, backtrack.");
89 context.backtrack();
90 continue;
91 }
92 if (context.isCurrentStateInTrajectory()) {
93 logger.debug("Current state is in trajectory, backtrack.");
94 context.backtrack();
95 continue;
96 }
97
98 Fitness fitness = context.calculateFitness();
99 objectiveComparatorHelper.addTrajectoryFitness(
100 new TrajectoryFitness(context.getTrajectoryInfo().getLastActivationId(), fitness));
101 context.backtrack();
102 }
103
104 if (objectiveComparatorHelper.getTrajectoryFitnesses().isEmpty()) {
105 logger.debug("No viable transitions from current state: considered as a solution.");
106 saveSolutionAndBacktrack();
107 continue;
108 }
109
110 TrajectoryFitness randomBestFitness = objectiveComparatorHelper.getRandomBest();
111 objectiveComparatorHelper.clearTrajectoryFitnesses();
112
113 int compare = objectiveComparatorHelper.compare(previousFitness, randomBestFitness.fitness);
114
115 if (compare > 0) {
116 saveSolutionAndBacktrack();
117 continue;
118 } else {
119 previousFitness = randomBestFitness.fitness;
120 Object transition = randomBestFitness.trajectory[randomBestFitness.trajectory.length - 1];
121 context.executeAcitvationId(transition);
122 }
123
124 } while (!isInterrupted.get());
125
126 logger.info("Terminated.");
127 }
128
129 private void saveSolutionAndBacktrack() {
130 context.calculateFitness();
131 context.newSolution();
132 logger.debug("Found solution: " + context.getTrajectoryInfo().toString());
133 logger.debug("Backtrack for more solutions, if needed.");
134 context.backtrackUntilRoot();
135 }
136
137 @Override
138 public void interruptStrategy() {
139 isInterrupted.set(true);
140 }
141
142}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.java
new file mode 100644
index 00000000..af8fb8cc
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.java
@@ -0,0 +1,163 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.api.strategy.impl;
10
11import java.util.Collection;
12import java.util.Iterator;
13import java.util.Random;
14import java.util.concurrent.atomic.AtomicBoolean;
15import java.util.concurrent.atomic.AtomicInteger;
16
17import org.apache.log4j.Logger;
18import org.eclipse.viatra.dse.api.DSEException;
19import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
20import org.eclipse.viatra.dse.base.GlobalContext;
21import org.eclipse.viatra.dse.base.ThreadContext;
22import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo;
23import org.eclipse.viatra.dse.objectives.Fitness;
24
25public class RandomSearchStrategy implements IStrategy {
26
27 private static class SharedData {
28 public final AtomicInteger triesLeft;
29 public final int minDepth;
30 public final int maxDepth;
31
32 public SharedData(int minDepth, int maxDepth, int numberOfTries) {
33 this.minDepth = minDepth;
34 this.maxDepth = maxDepth;
35 this.triesLeft = new AtomicInteger(numberOfTries);
36 }
37 }
38
39 private int maxDepth = -1;
40 private Random rnd = new Random();
41 private SharedData shared;
42 private TrajectoryInfo trajectoryInfo;
43 int nth;
44 private ThreadContext context;
45 private AtomicBoolean isInterrupted = new AtomicBoolean(false);
46 private Logger logger = Logger.getLogger(IStrategy.class);
47
48 public RandomSearchStrategy(int minDepth, int maxDepth, int numberOfTries) {
49 shared = new SharedData(minDepth, maxDepth, numberOfTries);
50 }
51
52 private RandomSearchStrategy() {
53 }
54
55 @Override
56 public void initStrategy(ThreadContext context) {
57 this.context = context;
58 trajectoryInfo = context.getTrajectoryInfo();
59 GlobalContext gc = context.getGlobalContext();
60
61 Object sharedObject = gc.getSharedObject();
62 if (sharedObject == null) {
63 gc.setSharedObject(shared);
64 logger.info("Random exploration strategy is initied.");
65 startThreads();
66 } else {
67 shared = (SharedData) sharedObject;
68 }
69
70 maxDepth = rnd.nextInt(shared.maxDepth - shared.minDepth) + shared.minDepth;
71
72 }
73
74 @Override
75 public void explore() {
76
77 do {
78
79 boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints();
80 if (!globalConstraintsAreSatisfied) {
81 boolean isSuccessfulUndo = context.backtrack();
82 if (!isSuccessfulUndo) {
83 logger.info("Global contraint is not satisifed and cannot backtrack.");
84 break;
85 } else {
86 logger.debug("Global contraint is not satisifed, backtrack.");
87 continue;
88 }
89 }
90
91 Fitness fitness = context.calculateFitness();
92 if (fitness.isSatisifiesHardObjectives()) {
93 context.newSolution();
94 boolean isSuccessfulUndo = context.backtrack();
95 if (!isSuccessfulUndo) {
96 logger.info("Found a solution but cannot backtrack.");
97 break;
98 } else {
99 logger.debug("Found a solution, backtrack.");
100 continue;
101 }
102 }
103
104 if (trajectoryInfo.getDepth() < maxDepth) {
105
106 Collection<Object> transitions = context.getCurrentActivationIds();
107 int index = rnd.nextInt(transitions.size());
108 Object transition = getByIndex(transitions, index);
109 context.executeAcitvationId(transition);
110
111 } else {
112
113 nth = shared.triesLeft.getAndDecrement();
114 logger.debug(nth + " tries left");
115 if (nth > 0) {
116
117 context.backtrackUntilRoot();
118 maxDepth = rnd.nextInt(shared.maxDepth - shared.minDepth) + shared.minDepth;
119
120 } else {
121 break;
122 }
123 }
124
125 boolean loopInTrajectory = context.isCurrentStateInTrajectory();
126 if (loopInTrajectory) {
127 boolean isSuccessfulUndo = context.backtrack();
128 if (!isSuccessfulUndo) {
129 throw new DSEException(
130 "The new state is present in the trajectoy but cannot bactkrack. Should never happen!");
131 } else {
132 logger.info("The new state is already visited in the trajectory, backtrack.");
133 }
134 }
135
136 } while (isInterrupted.get());
137
138 logger.info("Terminated.");
139 }
140
141 @Override
142 public void interruptStrategy() {
143 isInterrupted.set(true);
144 }
145
146 private void startThreads() {
147 context.startAllThreads(RandomSearchStrategy::new);
148 }
149
150 private static Object getByIndex(Collection<Object> availableTransitions, int index) {
151 int i = 0;
152 Iterator<Object> iterator = availableTransitions.iterator();
153 while (iterator.hasNext()) {
154 Object transition = iterator.next();
155 if (i == index) {
156 return transition;
157 } else {
158 ++i;
159 }
160 }
161 throw new IndexOutOfBoundsException("size: " + availableTransitions.size() + ", index: " + index);
162 }
163}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.java
new file mode 100644
index 00000000..8c164396
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.java
@@ -0,0 +1,44 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.api.strategy.interfaces;
10
11import org.eclipse.viatra.dse.base.ThreadContext;
12import org.eclipse.viatra.dse.solutionstore.SolutionStore;
13
14/**
15 * This high level interface is responsible for defining basic operations of an exploration strategy.
16 *
17 * @author Andras Szabolcs Nagy
18 *
19 */
20public interface IStrategy {
21
22 /**
23 * Initializes the strategy with a specific {@link ThreadContext}.
24 *
25 * @param context
26 * The context.
27 */
28 void initStrategy(ThreadContext context);
29
30 /**
31 * This method explores the design space as the implementation specifies. It will be called only once, hence the
32 * exploration loop is run by the implementation. The termination condition is also specified by the implementation
33 * and when it returns the exploration thread will be disposed.
34 */
35 void explore();
36
37 /**
38 * The implementation of this interface should be ready to be interrupted. If this method is called, the
39 * {@link IStrategy#explore()} method should return ASAP.
40 *
41 * This method is also called by the {@link SolutionStore} class if enough solutions are found.
42 */
43 void interruptStrategy();
44}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory.java
new file mode 100644
index 00000000..b3352d13
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory.java
@@ -0,0 +1,13 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.api.strategy.interfaces;
10
11public interface IStrategyFactory {
12 IStrategy createStrategy();
13}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ActivationCodesConflictSet.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ActivationCodesConflictSet.java
new file mode 100644
index 00000000..d3990c23
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ActivationCodesConflictSet.java
@@ -0,0 +1,213 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.util.Collection;
12import java.util.HashMap;
13import java.util.HashSet;
14import java.util.Map;
15import java.util.Objects;
16import java.util.Set;
17
18import org.eclipse.viatra.dse.statecode.IStateCoder;
19import org.eclipse.viatra.query.runtime.api.IPatternMatch;
20import org.eclipse.viatra.transformation.evm.api.Activation;
21import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet;
22import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver;
23import org.eclipse.viatra.transformation.evm.api.resolver.ConflictSet;
24
25public class ActivationCodesConflictSet implements ChangeableConflictSet {
26
27 private static class ActivationCodesMultiBiMap {
28 public Map<Activation<?>, Object> activationsToCodes = new HashMap<>();
29 public Map<Object, Set<Activation<?>>> codesToActivations = new HashMap<>();
30
31 public void addActivation(Activation<?> activation, Object activationCode) {
32 activationsToCodes.put(activation, activationCode);
33 codesToActivations.computeIfAbsent(activationCode, k -> new HashSet<>()).add(activation);
34 }
35
36 public void removeActivaion(Activation<?> activation) {
37 Object activationCode = activationsToCodes.remove(activation);
38 Set<Activation<?>> activations = codesToActivations.get(activationCode);
39 if (activations != null) {
40 activations.remove(activation);
41 }
42 }
43
44 public void clear() {
45 activationsToCodes.clear();
46 codesToActivations.clear();
47 }
48 }
49
50 protected ActivationCodesMultiBiMap activationCodes;
51 protected IStateCoder stateCoder;
52
53 protected Set<Activation<?>> newActivations = new HashSet<>();
54 protected Set<Activation<?>> removedActivations = new HashSet<>();
55// private Logger logger = Logger.getLogger(getClass());
56
57 private boolean isIncremental = false;
58 private ConflictSet nextActivationsConflictSet;
59
60 public void setIncremental(boolean isIncremental) {
61 this.isIncremental = isIncremental;
62 }
63
64 public ActivationCodesConflictSet(ConflictSet nextActivationsConflictSet, IStateCoder stateCoder) {
65 Objects.requireNonNull(nextActivationsConflictSet);
66 this.nextActivationsConflictSet = nextActivationsConflictSet;
67 this.stateCoder = stateCoder;
68 activationCodes = new ActivationCodesMultiBiMap();
69 }
70
71 private Object createActivationCode(Activation<?> activation) {
72 return stateCoder.createActivationCode((IPatternMatch) activation.getAtom());
73 }
74
75 @Override
76 public boolean removeActivation(Activation<?> activation) {
77 if (isIncremental) {
78//*
79 removedActivations.add(activation);
80 newActivations.remove(activation);
81/*/
82 if(!removedActivations.add(activation)) {
83 logger.debug("Abnormal: already marked to remove: " + activation);
84 } else {
85 logger.debug("marked to remove: " + activation);
86 }
87 if(newActivations.remove(activation)) {
88 logger.debug("Abnormal: removed from new activations: " + activation);
89 }
90//*/
91 }
92 return false;
93 }
94
95 @Override
96 public boolean addActivation(Activation<?> activation) {
97 if (isIncremental) {
98//*
99 newActivations.add(activation);
100 removedActivations.remove(activation);
101 /*/
102 if (activation.isEnabled()) {
103 if (!newActivations.add(activation)) {
104 logger.debug("Abnormal: already added as new: " + activation);
105 } else {
106 logger.debug("activation added: " + activation);
107 }
108 }
109 if(removedActivations.remove(activation)) {
110 logger.debug("Abnormal: was already marked to remove: " + activation);
111 }
112//*/
113 }
114 return false;
115 }
116
117 public Object getActivationId(Activation<?> activation) {
118 return activationCodes.activationsToCodes.get(activation);
119 }
120
121 public Activation<?> getActivation(Object activationId) {
122 Set<Activation<?>> activationsSet = activationCodes.codesToActivations.get(activationId);
123 if (activationsSet == null || activationsSet.isEmpty()) {
124 return null;
125 } else {
126 return activationsSet.iterator().next();
127 }
128 }
129
130 public void updateActivationCodes() {
131// logger.debug("Updating activation codes.");
132
133 if (isIncremental) {
134 for (Activation<?> activation : removedActivations) {
135 activationCodes.removeActivaion(activation);
136// logger.debug("removed activation: " + activationId);
137 }
138
139 for (Activation<?> activation : newActivations) {
140 if (activation.getState().isInactive()) {
141 continue;
142 }
143 Object activationCode = createActivationCode(activation);
144 activationCodes.addActivation(activation, activationCode);
145// logger.debug("new activation: " + activationId);
146// Activation<?> similarActivation = activationIds.inverse().get(activationId);
147// if (similarActivation != null) {
148// logger.debug("Activation " + toStringAct(activation) + " is already present with id: " + activationId);
149// if (similarActivation.isEnabled()) {
150// logger.warn("Duplicate activation code: " + activationId);
151// } else {
152// logger.debug("Force put: " + activationId);
153// }
154// continue;
155// }
156// activationIds.put(activation, activationId);
157 }
158 removedActivations.clear();
159 newActivations.clear();
160 } else {
161 activationCodes.clear();
162 for (Activation<?> activation : nextActivationsConflictSet.getNextActivations()) {
163 Object activationCode = createActivationCode(activation);
164 activationCodes.addActivation(activation, activationCode);
165 }
166 }
167
168
169 }
170
171 protected void reinitWithActivations(ConflictSet nextActivationsConflictSet) {
172 this.nextActivationsConflictSet = nextActivationsConflictSet;
173 activationCodes.clear();
174 for (Activation<?> activation : nextActivationsConflictSet.getNextActivations()) {
175 Object activationCode = createActivationCode(activation);
176 activationCodes.addActivation(activation, activationCode);
177 }
178 }
179
180 @Override
181 public Activation<?> getNextActivation() {
182 throw new UnsupportedOperationException();
183 }
184
185 @Override
186 public Set<Activation<?>> getNextActivations() {
187 throw new UnsupportedOperationException();
188 }
189
190 @Override
191 public Set<Activation<?>> getConflictingActivations() {
192 throw new UnsupportedOperationException();
193 }
194
195 @Override
196 public ConflictResolver getConflictResolver() {
197 throw new UnsupportedOperationException();
198 }
199
200 @Override
201 public String toString() {
202 StringBuilder sb = new StringBuilder();
203 for (Object activationCode : activationCodes.activationsToCodes.values()) {
204 sb.append(activationCode);
205 sb.append(" | ");
206 }
207 return sb.toString();
208 }
209
210 public Collection<Object> getCurrentActivationCodes() {
211 return activationCodes.activationsToCodes.values();
212 }
213}
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}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictResolver.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictResolver.java
new file mode 100644
index 00000000..35504b56
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictResolver.java
@@ -0,0 +1,35 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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 org.eclipse.viatra.dse.statecode.IStateCoder;
12import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet;
13import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver;
14
15public class DseConflictResolver implements ConflictResolver {
16
17 private ConflictResolver activationOrderingconflictResolver;
18 private IStateCoder stateCoder;
19 private DseConflictSet lastCreatedConflictSet;
20
21 public DseConflictResolver(ConflictResolver activationOrderingConflictResolver, IStateCoder stateCoder) {
22 this.activationOrderingconflictResolver = activationOrderingConflictResolver;
23 this.stateCoder = stateCoder;
24 }
25
26 @Override
27 public ChangeableConflictSet createConflictSet() {
28 lastCreatedConflictSet = new DseConflictSet(this, activationOrderingconflictResolver, stateCoder);
29 return lastCreatedConflictSet;
30 }
31
32 public DseConflictSet getLastCreatedConflictSet() {
33 return lastCreatedConflictSet;
34 }
35}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictSet.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictSet.java
new file mode 100644
index 00000000..cba595f4
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictSet.java
@@ -0,0 +1,83 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.util.Set;
12
13import org.eclipse.viatra.dse.statecode.IStateCoder;
14import org.eclipse.viatra.transformation.evm.api.Activation;
15import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet;
16import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver;
17
18public class DseConflictSet implements ChangeableConflictSet {
19
20 private ActivationCodesConflictSet activationCodesConflictSet;
21 private ChangeableConflictSet activationOrderingConflictSet;
22 private ChangeableConflictSet prevActivationOrderingConflictSet;
23 private ConflictResolver resolver;
24
25 public DseConflictSet(ConflictResolver resolver, ConflictResolver activationOrderingConflictResolver,
26 IStateCoder stateCoder) {
27 this.resolver = resolver;
28 activationOrderingConflictSet = activationOrderingConflictResolver.createConflictSet();
29 activationCodesConflictSet = new ActivationCodesConflictSet(activationOrderingConflictSet, stateCoder);
30 }
31
32 @Override
33 public Activation<?> getNextActivation() {
34 return activationOrderingConflictSet.getNextActivation();
35 }
36
37 @Override
38 public Set<Activation<?>> getNextActivations() {
39 return activationOrderingConflictSet.getNextActivations();
40 }
41
42 @Override
43 public Set<Activation<?>> getConflictingActivations() {
44 return activationOrderingConflictSet.getConflictingActivations();
45 }
46
47 @Override
48 public ConflictResolver getConflictResolver() {
49 return resolver;
50 }
51
52 @Override
53 public boolean addActivation(Activation<?> activation) {
54 activationCodesConflictSet.addActivation(activation);
55 return activationOrderingConflictSet.addActivation(activation);
56 }
57
58 @Override
59 public boolean removeActivation(Activation<?> activation) {
60 activationCodesConflictSet.removeActivation(activation);
61 return activationOrderingConflictSet.removeActivation(activation);
62 }
63
64 public ActivationCodesConflictSet getActivationCodesConflictSet() {
65 return activationCodesConflictSet;
66 }
67
68 public void changeActivationOrderingConflictSet(ChangeableConflictSet newActivationOrderingConflictSet) {
69 for (Activation<?> activation : activationOrderingConflictSet.getConflictingActivations()) {
70 newActivationOrderingConflictSet.addActivation(activation);
71 }
72 activationCodesConflictSet.reinitWithActivations(newActivationOrderingConflictSet);
73 ChangeableConflictSet tmp = activationOrderingConflictSet;
74 activationOrderingConflictSet = newActivationOrderingConflictSet;
75 prevActivationOrderingConflictSet = tmp;
76 }
77
78 public void changeActivationOrderingConflictSetBack() {
79 ChangeableConflictSet newActivationOrderingConflictSet =
80 prevActivationOrderingConflictSet.getConflictResolver().createConflictSet();
81 changeActivationOrderingConflictSet(newActivationOrderingConflictSet);
82 }
83}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseEvmRuleBase.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseEvmRuleBase.java
new file mode 100644
index 00000000..838c1d1b
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseEvmRuleBase.java
@@ -0,0 +1,21 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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 org.eclipse.viatra.transformation.evm.api.Agenda;
12import org.eclipse.viatra.transformation.evm.api.RuleBase;
13import org.eclipse.viatra.transformation.evm.api.event.EventRealm;
14
15public class DseEvmRuleBase extends RuleBase {
16
17 public DseEvmRuleBase(EventRealm eventRealm, Agenda agenda) {
18 super(eventRealm, agenda);
19 }
20
21}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseIdPoolHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseIdPoolHelper.java
new file mode 100644
index 00000000..f6fee7be
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseIdPoolHelper.java
@@ -0,0 +1,68 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.util.Collection;
12import java.util.HashMap;
13import java.util.concurrent.ConcurrentHashMap;
14
15import org.eclipse.viatra.dse.api.DSEException;
16import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
17
18public enum DseIdPoolHelper {
19
20 INSTANCE;
21
22 public static interface IGetRuleExecutions {
23 int getRuleExecutions(BatchTransformationRule<?, ?> rule);
24 }
25
26 public static class IdProvider {
27
28 private final BatchTransformationRule<?, ?> rule;
29 private IGetRuleExecutions getRuleExecutions;
30
31 public IdProvider(IGetRuleExecutions getRuleExecutions, BatchTransformationRule<?, ?> rule) {
32 this.getRuleExecutions = getRuleExecutions;
33 this.rule = rule;
34 }
35
36 public int getId() {
37 return getRuleExecutions.getRuleExecutions(rule);
38 }
39
40 }
41
42 private ConcurrentHashMap<Thread, HashMap<BatchTransformationRule<?, ?>, IdProvider>> idProviders = new ConcurrentHashMap<>();
43
44 public int getId(BatchTransformationRule<?, ?> rule) {
45 Thread currentThread = Thread.currentThread();
46 HashMap<BatchTransformationRule<?, ?>, IdProvider> ruleMap = idProviders.get(currentThread);
47 if (ruleMap == null) {
48 throw new DSEException("There is no registered id provider");
49 }
50 IdProvider idProvider = ruleMap.get(rule);
51 return idProvider.getId();
52 }
53
54 public void registerRules(IGetRuleExecutions getRuleExecutions, Collection<BatchTransformationRule<?, ?>> rules) {
55 Thread currentThread = Thread.currentThread();
56 HashMap<BatchTransformationRule<?, ?>, IdProvider> ruleMap = new HashMap<>();
57 for (BatchTransformationRule<?, ?> rule : rules) {
58 IdProvider idProvider = new IdProvider(getRuleExecutions, rule);
59 ruleMap.put(rule, idProvider);
60 }
61 idProviders.put(currentThread, ruleMap);
62 }
63
64 public void disposeByThread() {
65 Thread currentThread = Thread.currentThread();
66 idProviders.remove(currentThread);
67 }
68}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ExplorerThread.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ExplorerThread.java
new file mode 100644
index 00000000..f2231e5c
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ExplorerThread.java
@@ -0,0 +1,88 @@
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 org.apache.log4j.Logger;
12import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
13import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
14import org.eclipse.viatra.transformation.evm.api.RuleEngine;
15
16/**
17 * This class implements the {@link Runnable} interface, to able to run an exploration strategy in a separate thread. It
18 * is also responsible to initialize the exploration, start the exploration (call the {@link IStrategy#explore()}
19 * method), catch any exception during exploration and to shutdown the thread correctly.
20 *
21 * @author Földenyi Miklos & Nagy Andras Szabolcs
22 *
23 */
24public class ExplorerThread implements Runnable {
25
26 private final ThreadContext threadContext;
27
28 private IStrategy strategy;
29
30 public ExplorerThread(final ThreadContext context) {
31 this.threadContext = context;
32 strategy = threadContext.getStrategy();
33 }
34
35 /**
36 * Signals the {@link IStrategy} instance that execution should be stopped. By contract, the strategy is to
37 * stop execution at the next stage of execution where stopping and exiting is appropriate.
38 */
39 public void stopRunning() {
40 strategy.interruptStrategy();
41 }
42
43 /**
44 * Starts the design space exploration. Returns only when the {@link IStrategy#explore()} method returns.
45 */
46 public void run() {
47 GlobalContext globalContext = threadContext.getGlobalContext();
48 try {
49
50 threadContext.init();
51
52 strategy.initStrategy(threadContext);
53
54 strategy.explore();
55
56 threadContext.backtrackUntilRoot();
57
58 } catch (Throwable e) {
59 Logger.getLogger(IStrategy.class).error("Thread stopped unexpectedly!", e);
60 globalContext.registerException(e);
61 } finally {
62 globalContext.strategyFinished(this);
63 dispose();
64 }
65 }
66
67 /**
68 * Disposes of this strategy. Recursively calls dispose on the underlying {@link RuleEngine} and
69 * {@link ViatraQueryEngine}. Calling this is only required if the design space exploration was launched in thread, as
70 * the underlying engines get collected on the stop of the running {@link Thread}.
71 */
72 public void dispose() {
73 threadContext.getRuleEngine().dispose();
74 DseIdPoolHelper.INSTANCE.disposeByThread();
75 }
76
77 /**
78 * Returns the associated {@link ThreadContext} that houses all the thread specific data about the exploration
79 * process, and is also the gateway to the {@link GlobalContext} which stores data relevant to the design space
80 * exploration process as a whole.
81 *
82 * @return the relevant {@link ThreadContext}.
83 */
84 public ThreadContext getThreadContext() {
85 return threadContext;
86 }
87
88}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java
new file mode 100644
index 00000000..7325ead3
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java
@@ -0,0 +1,374 @@
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.util.ArrayList;
12import java.util.Collection;
13import java.util.HashMap;
14import java.util.HashSet;
15import java.util.List;
16import java.util.Map;
17import java.util.Set;
18import java.util.concurrent.ConcurrentLinkedQueue;
19import java.util.concurrent.atomic.AtomicBoolean;
20
21import org.apache.log4j.Logger;
22import org.eclipse.emf.common.notify.Notifier;
23import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
24import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategyFactory;
25import org.eclipse.viatra.dse.designspace.api.IDesignSpace;
26import org.eclipse.viatra.dse.multithreading.DSEThreadPool;
27import org.eclipse.viatra.dse.objectives.IGlobalConstraint;
28import org.eclipse.viatra.dse.objectives.IObjective;
29import org.eclipse.viatra.dse.objectives.LeveledObjectivesHelper;
30import org.eclipse.viatra.dse.solutionstore.SolutionStore;
31import org.eclipse.viatra.dse.statecode.IStateCoderFactory;
32import org.eclipse.viatra.dse.util.EMFHelper;
33import org.eclipse.viatra.dse.visualizer.IDesignSpaceVisualizer;
34import org.eclipse.viatra.transformation.evm.api.RuleSpecification;
35import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver;
36import org.eclipse.viatra.transformation.evm.specific.ConflictResolvers;
37import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
38
39import com.google.common.base.Preconditions;
40import com.google.common.collect.ImmutableList;
41
42/**
43 * Creates new contexts for strategies. It is needed because of the multithreading.
44 *
45 * @author Andras Szabolcs Nagy
46 *
47 */
48public class GlobalContext {
49
50 // **** fields and methods for multi threading *****//
51 // *************************************************//
52
53 public enum ExplorationProcessState {
54 NOT_STARTED,
55 RUNNING,
56 STOPPING,
57 COMPLETED
58 }
59
60 private ConcurrentLinkedQueue<Throwable> exceptions = new ConcurrentLinkedQueue<Throwable>();
61
62 private volatile ExplorationProcessState state = ExplorationProcessState.NOT_STARTED;
63 private final Set<ExplorerThread> runningThreads = new HashSet<ExplorerThread>();
64 private DSEThreadPool threadPool = new DSEThreadPool();
65 private int numberOfStartedThreads = 0;
66 private IDesignSpace designSpace;
67
68 private AtomicBoolean firstThreadContextInited = new AtomicBoolean(false);
69 private AtomicBoolean firstThreadContextIniting = new AtomicBoolean(false);
70
71 private Map<RuleSpecification<?>, BatchTransformationRule<?,?>> specificationRuleMap;
72
73 private Object terminationSnycObject = new Object();
74
75 private Logger logger = Logger.getLogger(IStrategy.class);
76
77 private boolean isAlreadyInited;
78
79 public void waitForTermination() {
80 synchronized (terminationSnycObject) {
81 while (!isDone()) {
82 try {
83 terminationSnycObject.wait();
84 } catch (InterruptedException e) {
85 }
86 }
87 }
88 }
89
90 /**
91 * Starts a new thread to explore the design space.
92 *
93 * @param originalThreadContext The context of the thread which starts the new thread.
94 * @param model The model to start from.
95 * @param cloneModel It should be true in most cases.
96 * @param strategy The strategy, the thread will use.
97 * @return The {@link ExplorerThread}
98 */
99 private synchronized ExplorerThread tryStartNewThread(ThreadContext originalThreadContext, Notifier model,
100 IStrategy strategy) {
101
102 if(!isAlreadyInited) {
103 isAlreadyInited = true;
104 init();
105 }
106
107 if (state != ExplorationProcessState.COMPLETED && state != ExplorationProcessState.STOPPING
108 && threadPool.canStartNewThread()) {
109
110 ThreadContext newThreadContext = new ThreadContext(this, strategy, model);
111
112 // TODO : clone undo list? slave strategy can't go further back...
113 ExplorerThread explorerThread = new ExplorerThread(newThreadContext);
114 newThreadContext.setExplorerThread(explorerThread);
115
116 boolean isSuccessful = threadPool.tryStartNewStrategy(explorerThread);
117
118 if (isSuccessful) {
119 runningThreads.add(explorerThread);
120
121 state = ExplorationProcessState.RUNNING;
122 ++numberOfStartedThreads;
123
124 logger.info("New thread started, active threads: " + runningThreads.size());
125
126 return explorerThread;
127 }
128 }
129 return null;
130 }
131
132 public synchronized ExplorerThread tryStartNewThread(ThreadContext originalThreadContext, IStrategy strategy) {
133 return tryStartNewThread(originalThreadContext, EMFHelper.clone(originalThreadContext.getModel()), strategy);
134 }
135
136 public synchronized ExplorerThread tryStartNewThreadWithoutModelClone(ThreadContext originalThreadContext,
137 IStrategy strategy) {
138 return tryStartNewThread(originalThreadContext, originalThreadContext.getModel(), strategy);
139 }
140
141 public synchronized ExplorerThread startFirstThread(IStrategy strategy, Notifier model) {
142 Preconditions.checkState(!isAlreadyInited, "First thread is already started.");
143 return tryStartNewThread(null, EMFHelper.clone(model), strategy);
144 }
145
146 public synchronized ExplorerThread startFirstThreadWithoutModelClone(IStrategy strategy, Notifier model) {
147 Preconditions.checkState(!isAlreadyInited, "First thread is already started.");
148 return tryStartNewThread(null, model, strategy);
149 }
150
151 public synchronized void startAllThreads(ThreadContext originalThreadContext, IStrategyFactory strategyFactory) {
152 while (canStartNewThread()) {
153 tryStartNewThread(originalThreadContext, strategyFactory.createStrategy());
154 }
155 }
156
157 /**
158 * Starts a new thread to explore the design space.
159 *
160 * @param strategyBase
161 * The {@link Strategy}.
162 * @param tedToClone
163 * The model to clone. Hint: context.getTed()
164 */
165
166 public synchronized void strategyFinished(ExplorerThread strategy) {
167 runningThreads.remove(strategy);
168
169 logger.info("Thread finished, active threads: " + runningThreads.size());
170
171 // is the first part necessary?
172 if (runningThreads.isEmpty()) {
173 state = ExplorationProcessState.COMPLETED;
174 threadPool.shutdown();
175
176 // if the main thread (which started the exploration)
177 // is waiting for the solution, than wake it up
178 synchronized (terminationSnycObject) {
179 terminationSnycObject.notify();
180 logger.info("Exploration terminated.");
181 }
182
183 }
184 }
185
186 public synchronized boolean isDone() {
187 return state == ExplorationProcessState.COMPLETED && runningThreads.isEmpty();
188 }
189
190 public synchronized boolean isNotStarted() {
191 return state == ExplorationProcessState.NOT_STARTED;
192 }
193
194 public boolean canStartNewThread() {
195 return (state == ExplorationProcessState.NOT_STARTED || state == ExplorationProcessState.RUNNING)
196 && threadPool.canStartNewThread();
197 }
198
199 public synchronized void stopAllThreads() {
200 if (state == ExplorationProcessState.RUNNING) {
201 state = ExplorationProcessState.STOPPING;
202 logger.info("Stopping all threads.");
203 for (ExplorerThread strategy : runningThreads) {
204 strategy.stopRunning();
205 }
206 }
207 }
208
209 public void registerException(Throwable e) {
210 exceptions.add(e);
211 }
212
213 // ******* fields and methods for exploration *******//
214 // **************************************************//
215
216 private List<IObjective> objectives = new ArrayList<IObjective>();
217 private IObjective[][] leveledObjectives;
218 private List<IGlobalConstraint> globalConstraints = new ArrayList<IGlobalConstraint>();
219 private Set<BatchTransformationRule<?, ?>> transformations = new HashSet<BatchTransformationRule<?, ?>>();
220 private IStateCoderFactory stateCoderFactory;
221 private SolutionStore solutionStore = new SolutionStore(1);
222 private Object sharedObject;
223 private List<IDesignSpaceVisualizer> visualizers;
224
225 private ConflictResolver conflictResolver = ConflictResolvers.createArbitraryResolver();
226
227 private void init() {
228 leveledObjectives = new LeveledObjectivesHelper(objectives).initLeveledObjectives();
229
230 specificationRuleMap = new HashMap<>();
231 for (BatchTransformationRule<?,?> rule : transformations) {
232 specificationRuleMap.put(rule.getRuleSpecification(), rule);
233 }
234 }
235
236 public List<IDesignSpaceVisualizer> getVisualizers() {
237 return ImmutableList.copyOf(visualizers);
238 }
239
240 public void registerDesignSpaceVisualizer(IDesignSpaceVisualizer visualizer) {
241 if (visualizer == null) {
242 return;
243 }
244 if (visualizers == null) {
245 visualizers = new ArrayList<IDesignSpaceVisualizer>();
246 }
247 visualizers.add(visualizer);
248 }
249
250 public void deregisterDesignSpaceVisualizer(IDesignSpaceVisualizer visualizer) {
251 if (visualizer == null) {
252 return;
253 }
254 if (visualizers != null) {
255 visualizers.remove(visualizer);
256 }
257 }
258
259 public boolean isDesignSpaceVisualizerRegistered(IDesignSpaceVisualizer visualizer) {
260 if (visualizers != null) {
261 return visualizers.contains(visualizer);
262 }
263 return false;
264 }
265
266 public void initVisualizersForThread(ThreadContext threadContext) {
267 if (visualizers != null && !visualizers.isEmpty()) {
268 for (IDesignSpaceVisualizer visualizer : visualizers) {
269 visualizer.init(threadContext);
270 threadContext.getDesignSpaceManager().registerExploreEventHandler(visualizer);
271 }
272 }
273 }
274
275 public boolean isExceptionHappendInOtherThread() {
276 return !exceptions.isEmpty();
277 }
278
279 public Collection<Throwable> getExceptions() {
280 return exceptions;
281 }
282
283 public IStateCoderFactory getStateCoderFactory() {
284 return stateCoderFactory;
285 }
286
287 public void setStateCoderFactory(IStateCoderFactory stateCoderFactory) {
288 this.stateCoderFactory = stateCoderFactory;
289 }
290
291 public Set<BatchTransformationRule<?, ?>> getTransformations() {
292 return transformations;
293 }
294
295 public void setTransformations(Set<BatchTransformationRule<?, ?>> transformations) {
296 this.transformations = transformations;
297 }
298
299 public DSEThreadPool getThreadPool() {
300 return threadPool;
301 }
302
303 public IDesignSpace getDesignSpace() {
304 return designSpace;
305 }
306
307 public void setDesignSpace(IDesignSpace designSpace) {
308 this.designSpace = designSpace;
309 }
310
311 public int getNumberOfStartedThreads() {
312 return numberOfStartedThreads;
313 }
314
315 public Object getSharedObject() {
316 return sharedObject;
317 }
318
319 public void setSharedObject(Object sharedObject) {
320 this.sharedObject = sharedObject;
321 }
322
323 public ExplorationProcessState getState() {
324 return state;
325 }
326
327 public List<IObjective> getObjectives() {
328 return objectives;
329 }
330
331 public void setObjectives(List<IObjective> objectives) {
332 this.objectives = objectives;
333 }
334
335 public List<IGlobalConstraint> getGlobalConstraints() {
336 return globalConstraints;
337 }
338
339 public void setGlobalConstraints(List<IGlobalConstraint> globalConstraints) {
340 this.globalConstraints = globalConstraints;
341 }
342
343 AtomicBoolean getFirstThreadContextInited() {
344 return firstThreadContextInited;
345 }
346
347 AtomicBoolean getFirstThreadContextIniting() {
348 return firstThreadContextIniting;
349 }
350
351 public IObjective[][] getLeveledObjectives() {
352 return leveledObjectives;
353 }
354
355 public void setSolutionStore(SolutionStore solutionStore) {
356 this.solutionStore = solutionStore;
357 }
358
359 public SolutionStore getSolutionStore() {
360 return solutionStore;
361 }
362
363 public Map<RuleSpecification<?>, BatchTransformationRule<?, ?>> getSpecificationRuleMap() {
364 return specificationRuleMap;
365 }
366
367 public void setConflictResolver(ConflictResolver conflictResolver) {
368 this.conflictResolver = conflictResolver;
369 }
370
371 public ConflictResolver getConflictResolver() {
372 return conflictResolver;
373 }
374}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/IDseStrategyContext.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/IDseStrategyContext.java
new file mode 100644
index 00000000..d630964f
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/IDseStrategyContext.java
@@ -0,0 +1,117 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.util.Collection;
12import java.util.List;
13import java.util.Set;
14
15import org.eclipse.emf.common.notify.Notifier;
16import org.eclipse.emf.edit.domain.EditingDomain;
17import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
18import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategyFactory;
19import org.eclipse.viatra.dse.designspace.api.IDesignSpace;
20import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo;
21import org.eclipse.viatra.dse.objectives.Fitness;
22import org.eclipse.viatra.dse.objectives.IGlobalConstraint;
23import org.eclipse.viatra.dse.objectives.IObjective;
24import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper;
25import org.eclipse.viatra.dse.solutionstore.SolutionStore;
26import org.eclipse.viatra.dse.statecode.IStateCoder;
27import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
28import org.eclipse.viatra.transformation.evm.api.Activation;
29import org.eclipse.viatra.transformation.evm.api.RuleEngine;
30import org.eclipse.viatra.transformation.evm.api.RuleSpecification;
31import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
32
33/**
34 * This interface is only to overview the required methods for exploration strategies. It is not used explicitly.
35 *
36 * @author Andras Szabolcs Nagy
37 *
38 */
39public interface IDseStrategyContext {
40
41 void init();
42
43 Notifier getModel();
44 EditingDomain getEditingDomain();
45 ViatraQueryEngine getQueryEngine();
46 RuleEngine getRuleEngine();
47 IStrategy getStrategy();
48 ExplorerThread getExplorerThread();
49 List<IObjective> getObjectives();
50 IObjective[][] getLeveledObjectives();
51 List<IGlobalConstraint> getGlobalConstraints();
52
53 SolutionStore getSolutionStore();
54 void newSolution();
55// TODO void newSolution(TrajectoryFitness trajectoryFitness);
56
57
58 ObjectiveComparatorHelper getObjectiveComparatorHelper();
59
60 GlobalContext getGlobalContext();
61 Set<BatchTransformationRule<?, ?>> getRules();
62 BatchTransformationRule<?, ?> getRuleByRuleSpecification(RuleSpecification<?> ruleSpecification);
63 ExplorerThread tryStartNewThread(IStrategy strategy); /*IDseStrategyContext originalContext*/
64 ExplorerThread tryStartNewThreadWithoutModelClone(IStrategy strategy);
65 void startAllThreads(IStrategyFactory strategyFactory);
66 Object getSharedObject();
67 void setSharedObject(Object sharedObject);
68
69
70 DesignSpaceManager getDesignSpaceManager();
71 IStateCoder getStateCoder();
72 IDesignSpace getDesignSpace();
73 TrajectoryInfo getTrajectoryInfo();
74 List<Object> getTrajectory();
75 List<Object> getTrajectoryCopied();
76 int getDepth();
77 Object getCurrentStateId();
78
79 Object getTransitionByActivation(Activation<?> activation);
80 Activation<?> getActivationById(Object activationId);
81 BatchTransformationRule<?, ?> getRuleByActivation(Activation<?> activation);
82 BatchTransformationRule<?, ?> getRuleByActivationId(Object activationId);
83
84 Collection<Object> getCurrentActivationIds();
85 Collection<Object> getUntraversedActivationIds();
86// TODO Object getArbitraryActivationId();
87// TODO Object getArbitraryUntraversedActivationId();
88
89 void executeAcitvationId(Object activationId);
90 boolean tryExecuteAcitvationId(Object activationId);
91 boolean executeRandomActivationId();
92 void executeTrajectory(Object[] activationIds);
93 void executeTrajectory(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex);
94 int executeTrajectoryByTrying(Object[] activationIds);
95 int executeTrajectoryByTrying(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex);
96 int executeTrajectoryWithoutStateCoding(Object[] activationIds);
97 int executeTrajectoryWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex);
98 int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds);
99 int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex);
100 void executeTrajectoryWithMinimalBacktrack(Object[] trajectory);
101 void executeTrajectoryWithMinimalBacktrack(Object[] trajectory, int toExcludedIndex);
102 void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory);
103 void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory, int toExcludedIndex);
104
105 boolean backtrack();
106 // TODO int backtrack(int times);
107 void backtrackUntilLastCommonActivation(Object[] trajectory);
108 void backtrackUntilRoot();
109
110 Fitness calculateFitness();
111 Fitness getLastFitness();
112 boolean checkGlobalConstraints();
113 boolean isCurrentStateAlreadyTraversed();
114 // this needs states stored:
115 boolean isCurrentStateInTrajectory();
116
117}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/SingletonSetConflictResolver.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/SingletonSetConflictResolver.java
new file mode 100644
index 00000000..8c0a715a
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/SingletonSetConflictResolver.java
@@ -0,0 +1,53 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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 org.eclipse.viatra.transformation.evm.api.RuleEngine;
12import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet;
13import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver;
14
15/**
16 *
17 * @author Andras Szabolcs Nagy
18 *
19 */
20public class SingletonSetConflictResolver implements ConflictResolver {
21
22 protected ChangeableConflictSet conflictSet;
23 protected ConflictResolver conflictResolver;
24 protected ConflictResolver prevConflictResolver;
25 protected RuleEngine ruleEngine;
26
27 public SingletonSetConflictResolver(ConflictResolver conflictResolver) {
28 this.conflictResolver = conflictResolver;
29 conflictSet = conflictResolver.createConflictSet();
30 }
31
32 @Override
33 public ChangeableConflictSet createConflictSet() {
34 return conflictSet;
35 }
36
37 public void changeConflictResolver(ConflictResolver conflictResolver) {
38 ConflictResolver tmp = this.conflictResolver;
39 this.conflictResolver = conflictResolver;
40 prevConflictResolver = tmp;
41 conflictSet = conflictResolver.createConflictSet();
42 ruleEngine.setConflictResolver(this);
43 }
44
45 public void changeConflictResolverBack() {
46 changeConflictResolver(prevConflictResolver);
47 }
48
49 public void setRuleEngine(RuleEngine ruleEngine) {
50 this.ruleEngine = ruleEngine;
51 ruleEngine.setConflictResolver(this);
52 }
53}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ThreadContext.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ThreadContext.java
new file mode 100644
index 00000000..b62442ce
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ThreadContext.java
@@ -0,0 +1,542 @@
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.util.ArrayList;
12import java.util.Collection;
13import java.util.List;
14import java.util.Set;
15import java.util.concurrent.atomic.AtomicBoolean;
16
17import org.apache.log4j.Logger;
18import org.eclipse.emf.common.notify.Notifier;
19import org.eclipse.emf.edit.domain.EditingDomain;
20import org.eclipse.viatra.dse.api.DSEException;
21import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
22import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategyFactory;
23import org.eclipse.viatra.dse.designspace.api.IDesignSpace;
24import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo;
25import org.eclipse.viatra.dse.objectives.Fitness;
26import org.eclipse.viatra.dse.objectives.IGlobalConstraint;
27import org.eclipse.viatra.dse.objectives.IObjective;
28import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper;
29import org.eclipse.viatra.dse.solutionstore.SolutionStore;
30import org.eclipse.viatra.dse.statecode.IStateCoder;
31import org.eclipse.viatra.dse.util.EMFHelper;
32import org.eclipse.viatra.query.runtime.api.IPatternMatch;
33import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
34import org.eclipse.viatra.query.runtime.emf.EMFScope;
35import org.eclipse.viatra.query.runtime.exception.ViatraQueryException;
36import org.eclipse.viatra.query.runtime.matchers.util.Preconditions;
37import org.eclipse.viatra.transformation.evm.api.Activation;
38import org.eclipse.viatra.transformation.evm.api.RuleEngine;
39import org.eclipse.viatra.transformation.evm.api.RuleSpecification;
40import org.eclipse.viatra.transformation.evm.api.event.EventFilter;
41import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet;
42import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver;
43import org.eclipse.viatra.transformation.evm.api.resolver.ConflictSet;
44import org.eclipse.viatra.transformation.evm.specific.RuleEngines;
45import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
46
47/**
48 * This class holds all the information that is related to a single processing thread of the DesignSpaceExploration
49 * process. For any attributes related to the Design Space Exploration process as a whole, see {@link GlobalContext}.
50 *
51 * @author Miklos Foldenyi
52 *
53 */
54public class ThreadContext implements IDseStrategyContext{
55
56 private final GlobalContext globalContext;
57 private final IStrategy strategy;
58 private ExplorerThread explorerThread;
59 private RuleEngine ruleEngine;
60 private ViatraQueryEngine queryEngine;
61 private EditingDomain domain;
62 private Notifier model;
63 private DesignSpaceManager designSpaceManager;
64 private List<IObjective> objectives;
65 private List<IGlobalConstraint> globalConstraints;
66 private Fitness lastFitness;
67 private ObjectiveComparatorHelper objectiveComparatorHelper;
68 private IStateCoder stateCoder;
69 private DseConflictResolver dseConflictResolver;
70 private DseConflictSet dseConflictSet;
71 private ActivationCodesConflictSet activationCodesConflictSet;
72
73 /**
74 * This value is true after the {@link ThreadContext} has been initialized in it's own thread.
75 */
76 private AtomicBoolean inited = new AtomicBoolean(false);
77
78 private boolean isFirstThread = false;
79 private IObjective[][] leveledObjectives;
80
81 private static class GetRuleExecutionsImpl implements DseIdPoolHelper.IGetRuleExecutions {
82
83 private List<BatchTransformationRule<?, ?>> executedRules;
84
85 public GetRuleExecutionsImpl(List<BatchTransformationRule<?, ?>> executedRulesView) {
86 this.executedRules = executedRulesView;
87 }
88
89 @Override
90 public int getRuleExecutions(BatchTransformationRule<?, ?> rule) {
91 int nextId = 0;
92 for (BatchTransformationRule<?, ?> r : executedRules) {
93 if (r.equals(rule)) {
94 nextId ++;
95 }
96 }
97 return nextId;
98 }
99
100 }
101
102 public DseConflictResolver getConflictResolver() {
103 return dseConflictResolver;
104 }
105
106 public ConflictSet getConflictSet() {
107 return dseConflictSet;
108 }
109
110 /**
111 * Creates a {@link ThreadContext} and sets it up to be initialized on the given {@link TransactionalEditingDomain}
112 *
113 * @param globalContext
114 * @param strategyBase
115 * @param domain
116 * @param trajectoryInfoToClone
117 * @param parentGuidance
118 */
119 public ThreadContext(final GlobalContext globalContext, IStrategy strategy, Notifier model) {
120 Preconditions.checkArgument(model != null, "Cannot initialize ThreadContext on a null model.");
121 this.globalContext = globalContext;
122 this.strategy = strategy;
123 this.model = model;
124 }
125
126 /**
127 * Initializes the {@link ThreadContext} by initializing the underlying {@link ViatraQueryEngine} and
128 * {@link RuleEngine}. {@link Guidance} initialization is also happening within this method.
129 *
130 * @throws DSEException
131 */
132 public void init() {
133
134 AtomicBoolean isFirst = globalContext.getFirstThreadContextIniting();
135 AtomicBoolean isFirstReady = globalContext.getFirstThreadContextInited();
136 if (!isFirstReady.get()) {
137 if (!isFirst.compareAndSet(false, true)) {
138 try {
139 do {
140 Thread.sleep(5);
141 } while (!isFirstReady.get());
142 } catch (InterruptedException e) {
143 }
144 } else {
145 isFirstThread = true;
146 }
147 }
148 // prohibit re-initialization
149 Preconditions.checkArgument(!inited.getAndSet(true), "This Thread context has been initialized already!");
150
151 try {
152 // initialize query engine
153 final EMFScope scope = new EMFScope(model);
154 queryEngine = ViatraQueryEngine.on(scope);
155
156
157 stateCoder = getGlobalContext().getStateCoderFactory().createStateCoder();
158 stateCoder.init(model);
159 stateCoder.createStateCode();
160
161 ConflictResolver activationOrderingCconflictResolver = globalContext.getConflictResolver();
162 dseConflictResolver = new DseConflictResolver(activationOrderingCconflictResolver, stateCoder);
163
164 ruleEngine = RuleEngines.createViatraQueryRuleEngine(queryEngine);
165 ruleEngine.setConflictResolver(dseConflictResolver);
166 for (BatchTransformationRule<?, ?> tr : globalContext.getTransformations()) {
167 ruleEngine.addRule(tr.getRuleSpecification(), (EventFilter<IPatternMatch>) tr.getFilter());
168 }
169 dseConflictSet = dseConflictResolver.getLastCreatedConflictSet();
170 activationCodesConflictSet = dseConflictSet.getActivationCodesConflictSet();
171 activationCodesConflictSet.updateActivationCodes();
172
173
174 } catch (ViatraQueryException e) {
175 throw new DSEException("Failed to create unmanaged ViatraQueryEngine on the model.", e);
176 }
177
178 if (isFirstThread) {
179
180 objectives = globalContext.getObjectives();
181 leveledObjectives = globalContext.getLeveledObjectives();
182 globalConstraints = globalContext.getGlobalConstraints();
183
184 } else {
185 objectives = new ArrayList<IObjective>();
186
187 IObjective[][] leveledObjectivesToCopy = globalContext.getLeveledObjectives();
188 leveledObjectives = new IObjective[leveledObjectivesToCopy.length][];
189 for (int i = 0; i < leveledObjectivesToCopy.length; i++) {
190 leveledObjectives[i] = new IObjective[leveledObjectivesToCopy[i].length];
191 for (int j = 0; j < leveledObjectivesToCopy[i].length; j++) {
192 leveledObjectives[i][j] = leveledObjectivesToCopy[i][j].createNew();
193 objectives.add(leveledObjectives[i][j]);
194 }
195 }
196
197 globalConstraints = new ArrayList<IGlobalConstraint>();
198 for (IGlobalConstraint globalConstraint : globalContext.getGlobalConstraints()) {
199 globalConstraints.add(globalConstraint.createNew());
200 }
201
202 }
203 // create the thread specific DesignSpaceManager
204 this.domain = EMFHelper.createEditingDomain(model);
205 designSpaceManager = new DesignSpaceManager(this);
206
207 boolean isThereHardObjective = false;
208 for (IObjective objective : objectives) {
209 objective.init(this);
210 if (objective.isHardObjective()) {
211 isThereHardObjective = true;
212 }
213 }
214 if (!isThereHardObjective) {
215 Logger.getLogger(IStrategy.class).warn(
216 "No hard objective is specified: all reachable state is a solution. Use a dummy hard objective to be explicit.");
217 }
218
219 for (IGlobalConstraint globalConstraint : globalConstraints) {
220 globalConstraint.init(this);
221 }
222
223 DseIdPoolHelper.INSTANCE.registerRules(new GetRuleExecutionsImpl(getDesignSpaceManager().getTrajectoryInfo().getRules()), getRules());
224
225 globalContext.initVisualizersForThread(this);
226
227 if (isFirstThread) {
228 isFirstReady.set(true);
229 }
230
231 }
232
233 public Fitness calculateFitness() {
234 Fitness result = new Fitness();
235
236 boolean satisifiesHardObjectives = true;
237
238 for (IObjective objective : objectives) {
239 Double fitness = objective.getFitness(this);
240 result.put(objective.getName(), fitness);
241 if (objective.isHardObjective() && !objective.satisifiesHardObjective(fitness)) {
242 satisifiesHardObjectives = false;
243 }
244 }
245
246 result.setSatisifiesHardObjectives(satisifiesHardObjectives);
247
248 lastFitness = result;
249
250 return result;
251 }
252
253 public boolean checkGlobalConstraints() {
254 for (IGlobalConstraint globalConstraint : globalContext.getGlobalConstraints()) {
255 if (!globalConstraint.checkGlobalConstraint(this)) {
256 return false;
257 }
258 }
259 return true;
260 }
261
262 public RuleEngine getRuleEngine() {
263 return ruleEngine;
264 }
265
266 public GlobalContext getGlobalContext() {
267 return globalContext;
268 }
269
270 public DesignSpaceManager getDesignSpaceManager() {
271 return designSpaceManager;
272 }
273
274 public EditingDomain getEditingDomain() {
275 return domain;
276 }
277
278 public Notifier getModel() {
279 return model;
280 }
281
282 public ViatraQueryEngine getQueryEngine() {
283 return queryEngine;
284 }
285
286 public IStrategy getStrategy() {
287 return strategy;
288 }
289
290 public ExplorerThread getExplorerThread() {
291 return explorerThread;
292 }
293
294 public void setExplorerThread(ExplorerThread explorerThread) {
295 this.explorerThread = explorerThread;
296 }
297
298 public Fitness getLastFitness() {
299 return lastFitness;
300 }
301
302 public ObjectiveComparatorHelper getObjectiveComparatorHelper() {
303 if (objectiveComparatorHelper == null) {
304 objectiveComparatorHelper = new ObjectiveComparatorHelper(leveledObjectives);
305 }
306 return objectiveComparatorHelper;
307 }
308
309 public IObjective[][] getLeveledObjectives() {
310 return leveledObjectives;
311 }
312
313 public List<IObjective> getObjectives() {
314 return objectives;
315 }
316
317 public List<IGlobalConstraint> getGlobalConstraints() {
318 return globalConstraints;
319 }
320
321 @Override
322 public SolutionStore getSolutionStore() {
323 return globalContext.getSolutionStore();
324 }
325
326 @Override
327 public void newSolution() {
328 globalContext.getSolutionStore().newSolution(this);
329 }
330
331 @Override
332 public Object getSharedObject() {
333 return globalContext.getSharedObject();
334 }
335
336 @Override
337 public void setSharedObject(Object sharedObject) {
338 globalContext.setSharedObject(sharedObject);
339 }
340
341 @Override
342 public Set<BatchTransformationRule<?, ?>> getRules() {
343 return globalContext.getTransformations();
344 }
345
346 @Override
347 public BatchTransformationRule<?, ?> getRuleByRuleSpecification(RuleSpecification<?> ruleSpecification) {
348 return globalContext.getSpecificationRuleMap().get(ruleSpecification);
349 }
350
351 @Override
352 public ExplorerThread tryStartNewThread(IStrategy strategy) {
353 return globalContext.tryStartNewThread(this, strategy);
354 }
355
356 @Override
357 public ExplorerThread tryStartNewThreadWithoutModelClone(IStrategy strategy) {
358 return globalContext.tryStartNewThreadWithoutModelClone(this, strategy);
359 }
360
361 @Override
362 public void startAllThreads(IStrategyFactory strategyFactory) {
363 globalContext.startAllThreads(this, strategyFactory);
364 }
365
366 @Override
367 public IStateCoder getStateCoder() {
368 return stateCoder;
369 }
370
371 @Override
372 public IDesignSpace getDesignSpace() {
373 return globalContext.getDesignSpace();
374 }
375
376 @Override
377 public TrajectoryInfo getTrajectoryInfo() {
378 return designSpaceManager.getTrajectoryInfo();
379 }
380
381 @Override
382 public List<Object> getTrajectory() {
383 return designSpaceManager.getTrajectoryInfo().getTrajectory();
384 }
385
386 @Override
387 public List<Object> getTrajectoryCopied() {
388 return new ArrayList<Object>(getTrajectory());
389 }
390
391 @Override
392 public int getDepth() {
393 return designSpaceManager.getTrajectoryInfo().getDepth();
394 }
395
396 @Override
397 public Object getCurrentStateId() {
398 return designSpaceManager.getTrajectoryInfo().getCurrentStateId();
399 }
400
401 @Override
402 public Object getTransitionByActivation(Activation<?> activation) {
403 return designSpaceManager.getTransitionByActivation(activation);
404 }
405
406 @Override
407 public Activation<?> getActivationById(Object activationId) {
408 return designSpaceManager.getActivationById(activationId);
409 }
410
411 @Override
412 public BatchTransformationRule<?, ?> getRuleByActivation(Activation<?> activation) {
413 return designSpaceManager.getRuleByActivation(activation);
414 }
415
416 @Override
417 public BatchTransformationRule<?, ?> getRuleByActivationId(Object activationId) {
418 return designSpaceManager.getRuleByActivationId(activationId);
419 }
420
421 @Override
422 public Collection<Object> getCurrentActivationIds() {
423 return designSpaceManager.getTransitionsFromCurrentState();
424 }
425
426 @Override
427 public Collection<Object> getUntraversedActivationIds() {
428 return designSpaceManager.getUntraversedTransitionsFromCurrentState();
429 }
430
431 @Override
432 public void executeAcitvationId(Object activationId) {
433 designSpaceManager.fireActivation(activationId);
434 }
435
436 @Override
437 public boolean tryExecuteAcitvationId(Object activationId) {
438 return designSpaceManager.tryFireActivation(activationId);
439 }
440
441 @Override
442 public boolean executeRandomActivationId() {
443 return designSpaceManager.executeRandomActivationId();
444 }
445
446 @Override
447 public void executeTrajectory(Object[] activationIds) {
448 designSpaceManager.executeTrajectory(activationIds);
449 }
450
451 @Override
452 public void executeTrajectory(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) {
453 designSpaceManager.executeTrajectory(activationIds, fromIncludedIndex, toExcludedIndex);
454 }
455
456 @Override
457 public int executeTrajectoryByTrying(Object[] activationIds) {
458 return designSpaceManager.executeTrajectoryByTrying(activationIds);
459 }
460
461 @Override
462 public int executeTrajectoryByTrying(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) {
463 return designSpaceManager.executeTrajectoryByTrying(activationIds, fromIncludedIndex, toExcludedIndex);
464 }
465
466 @Override
467 public int executeTrajectoryWithoutStateCoding(Object[] activationIds) {
468 return designSpaceManager.executeTrajectoryWithoutStateCoding(activationIds);
469 }
470
471 @Override
472 public int executeTrajectoryWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) {
473 return designSpaceManager.executeTrajectoryWithoutStateCoding(activationIds, fromIncludedIndex, toExcludedIndex);
474 }
475
476 @Override
477 public int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds) {
478 return designSpaceManager.executeTrajectoryByTryingWithoutStateCoding(activationIds);
479 }
480
481 @Override
482 public int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) {
483 return designSpaceManager.executeTrajectoryByTryingWithoutStateCoding(activationIds, fromIncludedIndex, toExcludedIndex);
484 }
485
486 @Override
487 public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory) {
488 designSpaceManager.executeTrajectoryWithMinimalBacktrack(trajectory);
489 }
490
491 @Override
492 public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory, int toExcludedIndex) {
493 designSpaceManager.executeTrajectoryWithMinimalBacktrack(trajectory, toExcludedIndex);
494 }
495
496 @Override
497 public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory) {
498 designSpaceManager.executeTrajectoryWithMinimalBacktrackWithoutStateCoding(trajectory);
499 }
500
501 @Override
502 public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory, int toExcludedIndex) {
503 designSpaceManager.executeTrajectoryWithMinimalBacktrackWithoutStateCoding(trajectory, toExcludedIndex);
504 }
505
506 @Override
507 public boolean backtrack() {
508 return designSpaceManager.undoLastTransformation();
509 }
510
511 @Override
512 public void backtrackUntilLastCommonActivation(Object[] trajectory) {
513 designSpaceManager.backtrackUntilLastCommonActivation(trajectory);
514 }
515
516 @Override
517 public void backtrackUntilRoot() {
518 designSpaceManager.undoUntilRoot();
519 }
520
521 @Override
522 public boolean isCurrentStateAlreadyTraversed() {
523 return designSpaceManager.isNewModelStateAlreadyTraversed();
524 }
525
526 @Override
527 public boolean isCurrentStateInTrajectory() {
528 return designSpaceManager.isCurentStateInTrajectory();
529 }
530
531 public ActivationCodesConflictSet getActivationCodesConflictSet() {
532 return activationCodesConflictSet;
533 }
534
535 public void changeActivationOrdering(ChangeableConflictSet activationOrderingConflictSet) {
536 this.dseConflictSet.changeActivationOrderingConflictSet(activationOrderingConflictSet);
537 }
538
539 public void changeActivationOrderingBack() {
540 this.dseConflictSet.changeActivationOrderingConflictSetBack();
541 }
542}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/DesignSpace.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/DesignSpace.java
new file mode 100644
index 00000000..bc0f08d4
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/DesignSpace.java
@@ -0,0 +1,106 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.designspace.api;
10
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.Collections;
14import java.util.HashMap;
15import java.util.HashSet;
16import java.util.List;
17import java.util.Map;
18import java.util.Random;
19import java.util.Set;
20
21public class DesignSpace implements IDesignSpace {
22
23 Set<Object> statesView;
24
25 Set<Object> rootStates;
26 Set<Object> rootStatesView;
27
28 Map<Object, List<Object>> statesAndActivations;
29
30 Random random = new Random();
31
32 public DesignSpace() {
33 rootStates = new HashSet<>();
34 rootStatesView = Collections.unmodifiableSet(rootStates);
35
36 statesAndActivations = new HashMap<>();
37 statesView = statesAndActivations.keySet();
38 }
39
40 @Override
41 public synchronized Collection<Object> getStates() {
42 return statesView;
43 }
44
45 @Override
46 public synchronized Collection<Object> getRoots() {
47 return rootStatesView;
48 }
49
50 @Override
51 public synchronized void addState(Object sourceStateId, Object firedActivationId, Object newStateId) {
52
53 List<Object> activationIds = statesAndActivations.get(newStateId);
54
55 if (activationIds == null) {
56 activationIds = new ArrayList<Object>();
57 statesAndActivations.put(newStateId, activationIds);
58
59 if (sourceStateId == null) {
60 rootStates.add(newStateId);
61 return;
62 }
63 }
64
65 activationIds = statesAndActivations.get(sourceStateId);
66
67 if (activationIds == null) {
68 activationIds = new ArrayList<Object>();
69 activationIds.add(firedActivationId);
70 statesAndActivations.put(sourceStateId, activationIds);
71 } else {
72 activationIds.add(firedActivationId);
73 }
74 }
75
76 public synchronized boolean isTraversed(Object stateId) {
77 return statesAndActivations.containsKey(stateId);
78 }
79
80 @Override
81 public synchronized Collection<Object> getActivationIds(Object stateId) {
82 return statesAndActivations.get(stateId);
83 }
84
85 @Override
86 public synchronized Object getRandomActivationId(Object stateId) {
87 List<Object> activations = statesAndActivations.get(stateId);
88 int index = random.nextInt(activations.size());
89 return activations.get(index);
90 }
91
92 @Override
93 public synchronized long getNumberOfStates() {
94 return statesAndActivations.size();
95 }
96
97 @Override
98 public synchronized long getNumberOfTransitions() {
99 int numberOfTransitions = 0;
100 for (List<Object> activations : statesAndActivations.values()) {
101 numberOfTransitions += activations.size();
102 }
103 return numberOfTransitions;
104 }
105
106}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IBacktrackListener.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IBacktrackListener.java
new file mode 100644
index 00000000..5c688276
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IBacktrackListener.java
@@ -0,0 +1,7 @@
1package org.eclipse.viatra.dse.designspace.api;
2
3public interface IBacktrackListener {
4 void forwardWorked(long nanos);
5
6 void backtrackWorked(long nanos);
7}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IDesignSpace.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IDesignSpace.java
new file mode 100644
index 00000000..a1d64bbf
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IDesignSpace.java
@@ -0,0 +1,27 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.designspace.api;
10
11import java.util.Collection;
12
13public interface IDesignSpace {
14
15 Collection<Object> getStates();
16 Collection<Object> getRoots();
17 void addState(Object sourceStateId, Object firedActivationId, Object newStateId);
18
19 boolean isTraversed(Object stateId);
20
21 Collection<Object> getActivationIds(Object stateId);
22 Object getRandomActivationId(Object stateId);
23
24 long getNumberOfStates();
25 long getNumberOfTransitions();
26
27}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.java
new file mode 100644
index 00000000..acd88416
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.java
@@ -0,0 +1,154 @@
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.designspace.api;
10
11import java.util.ArrayList;
12import java.util.Collections;
13import java.util.List;
14import java.util.Map;
15import java.util.Objects;
16
17import org.eclipse.viatra.dse.api.DSEException;
18import org.eclipse.viatra.dse.api.SolutionTrajectory;
19import org.eclipse.viatra.dse.base.DesignSpaceManager;
20import org.eclipse.viatra.dse.statecode.IStateCoderFactory;
21import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
22
23public class TrajectoryInfo {
24
25 private final List<Object> trajectory;
26 private final List<Object> trajectoryView;
27 private final List<BatchTransformationRule<?, ?>> rules;
28 private final List<BatchTransformationRule<?, ?>> rulesView;
29 private final List<Object> stateIds;
30 private final List<Object> stateIdsView;
31 private final List<Map<String, Double>> measuredCosts;
32
33 public TrajectoryInfo(Object initialStateId) {
34 Objects.requireNonNull(initialStateId);
35
36 stateIds = new ArrayList<>();
37 stateIds.add(initialStateId);
38
39 trajectory = new ArrayList<>();
40 rules = new ArrayList<>();
41 measuredCosts = new ArrayList<>();
42
43 trajectoryView = Collections.unmodifiableList(trajectory);
44 stateIdsView = Collections.unmodifiableList(stateIds);
45 rulesView = Collections.unmodifiableList(rules);
46 }
47
48 /**
49 * Copy constructor
50 *
51 * @since 0.17
52 */
53 public TrajectoryInfo(TrajectoryInfo other) {
54 this(other.stateIds, other.trajectory, other.rules, other.measuredCosts);
55 }
56
57 protected TrajectoryInfo(List<Object> stateIds, List<Object> trajectory, List<BatchTransformationRule<?, ?>> rules, List<Map<String, Double>> measuredCosts) {
58
59 this.stateIds = new ArrayList<>(stateIds);
60 this.trajectory = new ArrayList<>(trajectory);
61 this.rules = new ArrayList<>(rules);
62 trajectoryView = Collections.unmodifiableList(trajectory);
63 stateIdsView = Collections.unmodifiableList(stateIds);
64 rulesView = Collections.unmodifiableList(rules);
65 this.measuredCosts = new ArrayList<>(measuredCosts);
66 }
67
68 public void addStep(Object activationId, BatchTransformationRule<?, ?> rule, Object newStateId, Map<String, Double> measuredCosts) {
69 stateIds.add(newStateId);
70 trajectory.add(activationId);
71 rules.add(rule);
72 this.measuredCosts.add(measuredCosts);
73 }
74
75 public void backtrack() {
76 int size = trajectory.size();
77
78 if (size == 0) {
79 throw new DSEException("Cannot step back any further!");
80 }
81
82 trajectory.remove(size - 1);
83 rules.remove(size - 1);
84 stateIds.remove(size);
85 measuredCosts.remove(size - 1);
86 }
87
88 public Object getInitialStateId() {
89 return stateIds.get(0);
90 }
91
92 public Object getCurrentStateId() {
93 return stateIds.get(stateIds.size() - 1);
94 }
95
96 public Object getLastActivationId() {
97 return trajectory.get(trajectory.size() - 1);
98 }
99
100 public List<Object> getTrajectory() {
101 return trajectoryView;
102 }
103
104 public List<Object> getStateTrajectory() {
105 return stateIdsView;
106 }
107
108 public List<BatchTransformationRule<?, ?>> getRules() {
109 return rulesView;
110 }
111
112 public int getDepth() {
113 return trajectory.size();
114 }
115
116 public List<Map<String, Double>> getMeasuredCosts() {
117 return measuredCosts;
118 }
119
120 public SolutionTrajectory createSolutionTrajectory(final IStateCoderFactory stateCoderFactory, final IBacktrackListener listener) {
121
122 List<Object> activationIds = new ArrayList<>(trajectory);
123 List<BatchTransformationRule<?, ?>> copiedRules = new ArrayList<>(rules);
124
125 return new SolutionTrajectory(activationIds, copiedRules, stateCoderFactory, listener);
126 }
127
128 public boolean canStepBack() {
129 return !trajectory.isEmpty();
130 }
131
132 @Override
133 public String toString() {
134 StringBuilder sb = new StringBuilder("Trajectory:\n");
135 for (Object activationId : trajectory) {
136 sb.append(activationId);
137 sb.append("\n");
138 }
139 return sb.toString();
140 }
141
142 /**
143 * This method is only used by the {@link DesignSpaceManager}.
144 * @param stateCode
145 * @return false if the initial state code is the last one, otherwise true.
146 */
147 public boolean modifyLastStateCode(Object stateCode) {
148 if (stateIds.size() == 1) {
149 return false;
150 }
151 stateIds.set(stateIds.size() - 1, stateCode);
152 return true;
153 }
154}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/multithreading/DSEThreadPool.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/multithreading/DSEThreadPool.java
new file mode 100644
index 00000000..17e96a75
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/multithreading/DSEThreadPool.java
@@ -0,0 +1,58 @@
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.multithreading;
10
11import java.util.concurrent.RejectedExecutionException;
12import java.util.concurrent.SynchronousQueue;
13import java.util.concurrent.ThreadPoolExecutor;
14import java.util.concurrent.TimeUnit;
15
16import org.apache.log4j.Logger;
17import org.eclipse.viatra.dse.api.DesignSpaceExplorer;
18import org.eclipse.viatra.dse.base.ExplorerThread;
19
20/**
21 *
22 * @author Andras Szabolcs Nagy
23 *
24 */
25public class DSEThreadPool extends ThreadPoolExecutor {
26
27 private static final long THREAD_KEEP_ALIVE_IN_SECONDS = 60;
28
29 public DSEThreadPool() {
30 // Based on the Executors.newCachedThreadPool()
31 super(0, getProcNumber(), THREAD_KEEP_ALIVE_IN_SECONDS, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
32 }
33
34 // helper for constructor
35 private static int getProcNumber() {
36 return Runtime.getRuntime().availableProcessors();
37 }
38
39 public boolean tryStartNewStrategy(ExplorerThread strategy) {
40
41 if (!canStartNewThread()) {
42 return false;
43 }
44
45 try {
46 submit(strategy);
47 } catch (RejectedExecutionException e) {
48 Logger.getLogger(DesignSpaceExplorer.class).info("Couldn't start new thread.", e);
49 return false;
50 }
51
52 return true;
53 }
54
55 public boolean canStartNewThread() {
56 return getMaximumPoolSize() > getActiveCount();
57 }
58}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.java
new file mode 100644
index 00000000..c06d2916
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.java
@@ -0,0 +1,15 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, 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.objectives;
10
11import org.eclipse.viatra.query.runtime.api.IPatternMatch;
12
13public interface ActivationFitnessProcessor {
14 public double process(IPatternMatch match);
15} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Comparators.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Comparators.java
new file mode 100644
index 00000000..b1bd9349
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Comparators.java
@@ -0,0 +1,31 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, 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.objectives;
10
11import java.util.Comparator;
12
13/**
14 * This helper class holds comparators for objective implementations.
15 *
16 * @author Andras Szabolcs Nagy
17 *
18 */
19public class Comparators {
20
21 private Comparators() { /*Utility class constructor*/ }
22
23 public static final Comparator<Double> HIGHER_IS_BETTER = (o1, o2) -> o1.compareTo(o2);
24
25 public static final Comparator<Double> LOWER_IS_BETTER = (o1, o2) -> o2.compareTo(o1);
26
27 private static final Double ZERO = Double.valueOf(0);
28
29 public static final Comparator<Double> DIFFERENCE_TO_ZERO_IS_BETTER = (o1, o2) -> ZERO.compareTo(Math.abs(o1)-Math.abs(o2));
30
31}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Fitness.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Fitness.java
new file mode 100644
index 00000000..8beef3bd
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Fitness.java
@@ -0,0 +1,29 @@
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.objectives;
10
11import java.util.HashMap;
12
13public class Fitness extends HashMap<String, Double>{
14
15 private boolean satisifiesHardObjectives;
16
17 public boolean isSatisifiesHardObjectives() {
18 return satisifiesHardObjectives;
19 }
20
21 public void setSatisifiesHardObjectives(boolean satisifiesHardObjectives) {
22 this.satisifiesHardObjectives = satisifiesHardObjectives;
23 }
24
25 @Override
26 public String toString() {
27 return super.toString() + " hardObjectives=" + satisifiesHardObjectives;
28 }
29}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IGlobalConstraint.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IGlobalConstraint.java
new file mode 100644
index 00000000..2f7f0347
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IGlobalConstraint.java
@@ -0,0 +1,58 @@
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.objectives;
10
11import org.eclipse.viatra.dse.base.ThreadContext;
12
13/**
14 *
15 * Implementation of this interface represents a global constraint of the DSE problem, which can halt an exploration
16 * continuing from a state which dissatisfies the global constraint.
17 * <p>
18 * Certain global constraints can have inner state for the validation. In this case a new instance is necessary for
19 * every new thread, and the {@code createNew} method should not return the same instance more than once.
20 *
21 * @author Andras Szabolcs Nagy
22 *
23 */
24public interface IGlobalConstraint {
25
26 /**
27 * Returns the name of the global constraint.
28 *
29 * @return The name of the global constraint.
30 */
31 String getName();
32
33 /**
34 * Checks whether the current state satisfies the global constraint.
35 *
36 * @param context
37 * The {@link ThreadContext} which contains the necessary information.
38 * @return True if the state is valid and exploration can be continued from the actual state.
39 */
40 boolean checkGlobalConstraint(ThreadContext context);
41
42 /**
43 * Initializes the global constraint. It is called exactly once for every thread starts.
44 *
45 * @param context
46 * The {@link ThreadContext}.
47 */
48 void init(ThreadContext context);
49
50 /**
51 * Returns an instance of the {@link IGlobalConstraint}. If it returns the same instance, all the methods has to be
52 * thread save as they are called concurrently.
53 *
54 * @return An instance of the global constraint.
55 */
56 IGlobalConstraint createNew();
57
58}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IObjective.java
new file mode 100644
index 00000000..849dd4e8
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IObjective.java
@@ -0,0 +1,110 @@
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.objectives;
10
11import java.util.Comparator;
12
13import org.eclipse.viatra.dse.base.ThreadContext;
14
15/**
16 *
17 * Implementation of this interface represents a single objective of the DSE problem, which can assess a solution
18 * (trajectory) in a single number. It has a name and a comparator which orders two solution based on the calculated
19 * value.
20 * <p>
21 * Objectives can be either hard or soft objectives. Hard objectives can be satisfied or unsatisfied. If all of the hard
22 * objectives are satisfied on a single solution, then it is considered to be a valid (or goal) solution.
23 * <p>
24 * Certain objectives can have inner state for calculating the fitness value. In this case a new instance is necessary
25 * for every new thread, and the {@code createNew} method should not return the same instance more than once.
26 *
27 * @author Andras Szabolcs Nagy
28 *
29 */
30public interface IObjective {
31
32 /**
33 * Returns the name of the objective.
34 *
35 * @return The name of the objective.
36 */
37 String getName();
38
39 /**
40 * Sets the {@link Comparator} which is used to compare fitness (doubles). It determines whether the objective is to
41 * minimize or maximize (or minimize or maximize a delta from a given number).
42 *
43 * @param comparator The comparator.
44 */
45 void setComparator(Comparator<Double> comparator);
46
47 /**
48 * Returns a {@link Comparator} which is used to compare fitness (doubles). It determines whether the objective is
49 * to minimize or maximize (or minimize or maximize a delta from a given number).
50 *
51 * @return The comparator.
52 */
53 Comparator<Double> getComparator();
54
55 /**
56 * Calculates the value of the objective on a given solution (trajectory).
57 *
58 * @param context
59 * The {@link ThreadContext}
60 * @return The objective value in double.
61 */
62 Double getFitness(ThreadContext context);
63
64 /**
65 * Initializes the objective. It is called exactly once for every thread starts.
66 *
67 * @param context
68 * The {@link ThreadContext}.
69 */
70 void init(ThreadContext context);
71
72 /**
73 * Returns an instance of the {@link IObjective}. If it returns the same instance, all the methods has to be thread
74 * save as they are called concurrently.
75 *
76 * @return An instance of the objective.
77 */
78 IObjective createNew();
79
80 /**
81 * Returns true if the objective is a hard objective. In such a case the method
82 * {@link IObjective#satisifiesHardObjective(Double)} is called.
83 *
84 * @return True if the objective is a hard objective.
85 * @see IObjective#satisifiesHardObjective(Double)
86 * @see IObjective
87 */
88 boolean isHardObjective();
89
90 /**
91 * Determines if the given fitness value satisfies the hard objective.
92 *
93 * @param fitness
94 * The fitness value of a solution.
95 * @return True if it satisfies the hard objective or it is a soft constraint.
96 * @see IObjective
97 */
98 boolean satisifiesHardObjective(Double fitness);
99
100 /**
101 * Set the level of the objective.
102 */
103 void setLevel(int level);
104
105 /**
106 * Gets the level of the objective.
107 */
108 int getLevel();
109
110}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.java
new file mode 100644
index 00000000..2d81629b
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.java
@@ -0,0 +1,114 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.objectives;
10
11import java.util.ArrayList;
12import java.util.Arrays;
13import java.util.Comparator;
14import java.util.List;
15
16public class LeveledObjectivesHelper {
17
18 private List<IObjective> objectives = new ArrayList<IObjective>();
19 private IObjective[][] leveledObjectives;
20
21 public LeveledObjectivesHelper(List<IObjective> objectives) {
22 this.objectives = objectives;
23 }
24
25 public IObjective[][] initLeveledObjectives() {
26 if (objectives.isEmpty()) {
27 leveledObjectives = new IObjective[0][0];
28 return leveledObjectives;
29 }
30
31 int level = objectives.get(0).getLevel();
32 boolean oneLevelOnly = true;
33 for (IObjective objective : objectives) {
34 if (objective.getLevel() != level) {
35 oneLevelOnly = false;
36 break;
37 }
38 }
39
40 if (oneLevelOnly) {
41 leveledObjectives = new IObjective[1][objectives.size()];
42 for (int i = 0; i < objectives.size(); i++) {
43 leveledObjectives[0][i] = objectives.get(i);
44 }
45 return leveledObjectives;
46 }
47
48 IObjective[] objectivesArray = getSortedByLevelObjectives(objectives);
49
50 int numberOfLevels = getNumberOfObjectiveLevels(objectivesArray);
51
52 leveledObjectives = new IObjective[numberOfLevels][];
53
54 fillLeveledObjectives(objectivesArray);
55
56 return leveledObjectives;
57 }
58
59 private void fillLeveledObjectives(IObjective[] objectivesArray) {
60 int actLevel = objectivesArray[0].getLevel();
61 int levelIndex = 0;
62 int lastIndex = 0;
63 int corrigationForLastLevel = 0;
64 boolean oneObjectiveAtLastLevel = false;
65 for (int i = 0; i < objectivesArray.length; i++) {
66 if (i == objectivesArray.length - 1) {
67 corrigationForLastLevel = 1;
68 if (objectivesArray[i - 1].getLevel() != objectivesArray[i].getLevel()) {
69 oneObjectiveAtLastLevel = true;
70 corrigationForLastLevel = 0;
71 }
72 }
73 if (objectivesArray[i].getLevel() != actLevel || corrigationForLastLevel == 1 || oneObjectiveAtLastLevel) {
74 leveledObjectives[levelIndex] = new IObjective[i - lastIndex + corrigationForLastLevel];
75 for (int j = lastIndex; j < i + corrigationForLastLevel; j++) {
76 leveledObjectives[levelIndex][j - lastIndex] = objectivesArray[j];
77 }
78 if (oneObjectiveAtLastLevel) {
79 leveledObjectives[levelIndex + 1] = new IObjective[1];
80 leveledObjectives[levelIndex + 1][0] = objectivesArray[i];
81 }
82 actLevel = objectivesArray[i].getLevel();
83 levelIndex++;
84 lastIndex = i;
85 }
86 }
87 }
88
89 private int getNumberOfObjectiveLevels(IObjective[] objectivesArray) {
90
91 int actLevel = objectivesArray[0].getLevel();
92 int numberOfLevels = 1;
93
94 for (int i = 1; i < objectivesArray.length; i++) {
95 if (objectivesArray[i].getLevel() != actLevel) {
96 numberOfLevels++;
97 actLevel = objectivesArray[i].getLevel();
98 }
99 }
100
101 return numberOfLevels;
102 }
103
104 private IObjective[] getSortedByLevelObjectives(List<IObjective> objectives) {
105 IObjective[] objectivesArray = objectives.toArray(new IObjective[objectives.size()]);
106 Arrays.sort(objectivesArray, Comparator.comparingInt(IObjective::getLevel));
107 return objectivesArray;
108 }
109
110 public IObjective[][] getLeveledObjectives() {
111 return leveledObjectives;
112 }
113
114}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.java
new file mode 100644
index 00000000..39139bb0
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.java
@@ -0,0 +1,217 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, 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.objectives;
10
11import java.util.ArrayList;
12import java.util.Arrays;
13import java.util.HashMap;
14import java.util.List;
15import java.util.Map;
16import java.util.Random;
17
18import org.eclipse.viatra.query.runtime.matchers.util.Preconditions;
19
20/**
21 * This class is responsible to compare and sort fitness values. {@link TrajectoryFitness} instances can be added to an
22 * instance of this class, that it can sort them.
23 *
24 * @author András Szabolcs Nagy
25 */
26public class ObjectiveComparatorHelper {
27
28 private IObjective[][] leveledObjectives;
29 private List<TrajectoryFitness> trajectoryFitnesses = new ArrayList<TrajectoryFitness>();
30 private Random random = new Random();
31 private boolean computeCrowdingDistance = false;
32
33 public ObjectiveComparatorHelper(IObjective[][] leveledObjectives) {
34 this.leveledObjectives = leveledObjectives;
35 }
36
37 public void setComputeCrowdingDistance(boolean computeCrowdingDistance) {
38 this.computeCrowdingDistance = computeCrowdingDistance;
39 }
40
41 /**
42 * Compares two fitnesses based on hierarchical dominance. Returns -1 if the second parameter {@code o2} is a better
43 * solution ({@code o2} dominates {@code o1}), 1 if the first parameter {@code o1} is better ({@code o1} dominates
44 * {@code o2}) and returns 0 if they are non-dominating each other.
45 */
46 public int compare(Fitness o1, Fitness o2) {
47
48 levelsLoop: for (int i = 0; i < leveledObjectives.length; i++) {
49
50 boolean o1HasBetterFitness = false;
51 boolean o2HasBetterFitness = false;
52
53 for (IObjective objective : leveledObjectives[i]) {
54 String objectiveName = objective.getName();
55 int sgn = objective.getComparator().compare(o1.get(objectiveName), o2.get(objectiveName));
56
57 if (sgn < 0) {
58 o2HasBetterFitness = true;
59 }
60 if (sgn > 0) {
61 o1HasBetterFitness = true;
62 }
63 if (o1HasBetterFitness && o2HasBetterFitness) {
64 continue levelsLoop;
65 }
66 }
67 if (o2HasBetterFitness && !o1HasBetterFitness) {
68 return -1;
69 } else if (!o2HasBetterFitness && o1HasBetterFitness) {
70 return 1;
71 }
72 }
73
74 return 0;
75
76 }
77
78 /**
79 * Adds a {@link TrajectoryFitness} to an inner list to compare later.
80 *
81 * @param trajectoryFitness
82 */
83 public void addTrajectoryFitness(TrajectoryFitness trajectoryFitness) {
84 trajectoryFitnesses.add(trajectoryFitness);
85 }
86
87 /**
88 * Clears the inner {@link TrajectoryFitness} list.
89 */
90 public void clearTrajectoryFitnesses() {
91 trajectoryFitnesses.clear();
92 }
93
94 /**
95 * Returns the inner {@link TrajectoryFitness} list.
96 */
97 public List<TrajectoryFitness> getTrajectoryFitnesses() {
98 return trajectoryFitnesses;
99 }
100
101 /**
102 * Returns a random {@link TrajectoryFitness} from the pareto front.
103 */
104 public TrajectoryFitness getRandomBest() {
105 List<TrajectoryFitness> paretoFront = getParetoFront();
106 int randomIndex = random.nextInt(paretoFront.size());
107 return paretoFront.get(randomIndex);
108 }
109
110 /**
111 * Returns the pareto front of the previously added {@link TrajectoryFitness}.
112 */
113 public List<TrajectoryFitness> getParetoFront() {
114 return getFronts().get(0);
115 }
116
117 /**
118 * Returns the previously added {@link TrajectoryFitness} instances in fronts.
119 */
120 public List<? extends List<TrajectoryFitness>> getFronts() {
121 Preconditions.checkArgument(!trajectoryFitnesses.isEmpty(), "No trajectory fitnesses were added.");
122 List<ArrayList<TrajectoryFitness>> fronts = new ArrayList<ArrayList<TrajectoryFitness>>();
123
124 Map<TrajectoryFitness, ArrayList<TrajectoryFitness>> dominatedInstances = new HashMap<TrajectoryFitness, ArrayList<TrajectoryFitness>>();
125 Map<TrajectoryFitness, Integer> dominatingInstances = new HashMap<TrajectoryFitness, Integer>();
126
127 // calculate dominations
128 for (TrajectoryFitness TrajectoryFitnessP : trajectoryFitnesses) {
129 dominatedInstances.put(TrajectoryFitnessP, new ArrayList<TrajectoryFitness>());
130 dominatingInstances.put(TrajectoryFitnessP, 0);
131
132 for (TrajectoryFitness TrajectoryFitnessQ : trajectoryFitnesses) {
133 int dominates = compare(TrajectoryFitnessP.fitness, TrajectoryFitnessQ.fitness);
134 if (dominates > 0) {
135 dominatedInstances.get(TrajectoryFitnessP).add(TrajectoryFitnessQ);
136 } else if (dominates < 0) {
137 dominatingInstances.put(TrajectoryFitnessP, dominatingInstances.get(TrajectoryFitnessP) + 1);
138 }
139 }
140
141 if (dominatingInstances.get(TrajectoryFitnessP) == 0) {
142 // p belongs to the first front
143 TrajectoryFitnessP.rank = 1;
144 if (fronts.isEmpty()) {
145 ArrayList<TrajectoryFitness> firstDominationFront = new ArrayList<TrajectoryFitness>();
146 firstDominationFront.add(TrajectoryFitnessP);
147 fronts.add(firstDominationFront);
148 } else {
149 List<TrajectoryFitness> firstDominationFront = fronts.get(0);
150 firstDominationFront.add(TrajectoryFitnessP);
151 }
152 }
153 }
154
155 // create fronts
156 int i = 1;
157 while (fronts.size() == i) {
158 ArrayList<TrajectoryFitness> nextDominationFront = new ArrayList<TrajectoryFitness>();
159 for (TrajectoryFitness TrajectoryFitnessP : fronts.get(i - 1)) {
160 for (TrajectoryFitness TrajectoryFitnessQ : dominatedInstances.get(TrajectoryFitnessP)) {
161 dominatingInstances.put(TrajectoryFitnessQ, dominatingInstances.get(TrajectoryFitnessQ) - 1);
162 if (dominatingInstances.get(TrajectoryFitnessQ) == 0) {
163 TrajectoryFitnessQ.rank = i + 1;
164 nextDominationFront.add(TrajectoryFitnessQ);
165 }
166 }
167 }
168 i++;
169 if (!nextDominationFront.isEmpty()) {
170 if (computeCrowdingDistance) {
171 crowdingDistanceAssignment(nextDominationFront, leveledObjectives);
172 }
173 fronts.add(nextDominationFront);
174 }
175 }
176
177 return fronts;
178 }
179
180 /**
181 * Executes the crowding distance assignment for the specified front.
182 *
183 * @param front
184 */
185 public static void crowdingDistanceAssignment(List<TrajectoryFitness> front, IObjective[][] leveledObjectives) {
186
187 for (TrajectoryFitness InstanceData : front) {
188 // initialize crowding distance
189 InstanceData.crowdingDistance = 0;
190 }
191
192 for (final IObjective[] objectives : leveledObjectives) {
193 for (final IObjective objective : objectives) {
194
195 final String m = objective.getName();
196 TrajectoryFitness[] sortedFront = front.toArray(new TrajectoryFitness[0]);
197 // sort using m-th objective value
198 Arrays.sort(sortedFront, (o1, o2) -> objective.getComparator().compare(o1.fitness.get(m), o2.fitness.get(m)));
199 // so that boundary points are always selected
200 sortedFront[0].crowdingDistance = Double.POSITIVE_INFINITY;
201 sortedFront[sortedFront.length - 1].crowdingDistance = Double.POSITIVE_INFINITY;
202 // If minimal and maximal fitness value for this objective are
203 // equal, then do not change crowding distance
204 if (sortedFront[0].fitness.get(m) != sortedFront[sortedFront.length - 1].fitness.get(m)) {
205 for (int i = 1; i < sortedFront.length - 1; i++) {
206 double newCrowdingDistance = sortedFront[i].crowdingDistance;
207 newCrowdingDistance += (sortedFront[i + 1].fitness.get(m) - sortedFront[i - 1].fitness.get(m))
208 / (sortedFront[sortedFront.length - 1].fitness.get(m) - sortedFront[0].fitness.get(m));
209
210 sortedFront[i].crowdingDistance = newCrowdingDistance;
211 }
212 }
213 }
214 }
215 }
216
217}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/TrajectoryFitness.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/TrajectoryFitness.java
new file mode 100644
index 00000000..f783afac
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/TrajectoryFitness.java
@@ -0,0 +1,84 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, 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.objectives;
10
11import java.util.Arrays;
12import java.util.List;
13
14import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo;
15
16/**
17 * This class represents a trajectory and its fitness.
18 * @author Andras Szabolcs Nagy
19 *
20 */
21public class TrajectoryFitness {
22
23 public Object[] trajectory;
24 public Fitness fitness;
25
26 public int rank;
27 public double crowdingDistance;
28
29 private int hash;
30
31 public int survive;
32
33 /**
34 * Creates a {@link TrajectoryFitness} with the full trajectory.
35 * @param trajectory The trajectory.
36 * @param fitness The fitness.
37 */
38 public TrajectoryFitness(Object[] trajectory, Fitness fitness) {
39 this.fitness = fitness;
40 this.trajectory = trajectory;
41 }
42
43 /**
44 * Creates a {@link TrajectoryFitness} with the full trajectory.
45 * @param trajectoryInfo The trajectory.
46 * @param fitness The fitness.
47 */
48 public TrajectoryFitness(TrajectoryInfo trajectoryInfo, Fitness fitness) {
49 this.fitness = fitness;
50 List<Object> fullTraj = trajectoryInfo.getTrajectory();
51 trajectory = fullTraj.toArray(new Object[fullTraj.size()]);
52 }
53
54 /**
55 * Creates a {@link TrajectoryFitness} with the given activation id}
56 * @param transition The transition.
57 * @param fitness The fitness.
58 */
59 public TrajectoryFitness(Object transition, Fitness fitness) {
60 this.fitness = fitness;
61 trajectory = new Object[] {transition};
62 }
63
64 @Override
65 public boolean equals(Object obj) {
66 if (obj instanceof TrajectoryFitness) {
67 return Arrays.equals(trajectory, ((TrajectoryFitness) obj).trajectory);
68 }
69 return false;
70 }
71
72 @Override
73 public int hashCode() {
74 if (hash == 0 && trajectory.length > 0) {
75 hash = Arrays.hashCode(trajectory);
76 }
77 return hash;
78 }
79
80 @Override
81 public String toString() {
82 return Arrays.toString(trajectory) + fitness.toString();
83 }
84}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardObjective.java
new file mode 100644
index 00000000..9898a3b5
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardObjective.java
@@ -0,0 +1,52 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.objectives.impl;
10
11import org.eclipse.viatra.dse.base.ThreadContext;
12import org.eclipse.viatra.dse.objectives.IObjective;
13
14/**
15 * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid solution.
16 *
17 * @author Andras Szabolcs Nagy
18 *
19 */
20public class AlwaysSatisfiedDummyHardObjective extends BaseObjective {
21
22 private static final String DEFAULT_NAME = "AlwaysSatisfiedDummyHardObjective";
23
24 public AlwaysSatisfiedDummyHardObjective() {
25 super(DEFAULT_NAME);
26 }
27
28 public AlwaysSatisfiedDummyHardObjective(String name) {
29 super(name);
30 }
31
32 @Override
33 public Double getFitness(ThreadContext context) {
34 return 0d;
35 }
36
37 @Override
38 public boolean isHardObjective() {
39 return true;
40 }
41
42 @Override
43 public boolean satisifiesHardObjective(Double fitness) {
44 return true;
45 }
46
47 @Override
48 public IObjective createNew() {
49 return this;
50 }
51
52}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/BaseObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/BaseObjective.java
new file mode 100644
index 00000000..0a1de875
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/BaseObjective.java
@@ -0,0 +1,150 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, 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.objectives.impl;
10
11import java.util.Comparator;
12import java.util.Objects;
13
14import org.eclipse.viatra.dse.base.ThreadContext;
15import org.eclipse.viatra.dse.objectives.Comparators;
16import org.eclipse.viatra.dse.objectives.IObjective;
17
18/**
19 * This abstract class implements the basic functionality of an objective ({@link IObjective} namely its name,
20 * comparator, level and fitness hard constraint.
21 *
22 * @author Andras Szabolcs Nagy
23 *
24 */
25public abstract class BaseObjective implements IObjective {
26
27 protected final String name;
28 protected Comparator<Double> comparator = Comparators.HIGHER_IS_BETTER;
29 protected int level = 0;
30
31 protected double fitnessConstraint;
32 protected boolean isThereFitnessConstraint = false;
33 protected Comparator<Double> fitnessConstraintComparator;
34
35 public BaseObjective(String name) {
36 Objects.requireNonNull(name, "Name of the objective cannot be null.");
37 this.name = name;
38 }
39
40 @Override
41 public String getName() {
42 return name;
43 }
44
45 @Override
46 public void setComparator(Comparator<Double> comparator) {
47 this.comparator = comparator;
48 }
49
50 @Override
51 public Comparator<Double> getComparator() {
52 return comparator;
53 }
54
55 @Override
56 public void setLevel(int level) {
57 this.level = level;
58 }
59
60 @Override
61 public int getLevel() {
62 return level;
63 }
64
65 public BaseObjective withLevel(int level) {
66 setLevel(level);
67 return this;
68 }
69
70 public BaseObjective withComparator(Comparator<Double> comparator) {
71 setComparator(comparator);
72 return this;
73 }
74
75 /**
76 * Adds a hard constraint on the fitness value. For example, the fitness value must be better than 10 to accept the
77 * current state as a solution.
78 *
79 * @param fitnessConstraint
80 * Solutions should be better than this value.
81 * @param fitnessConstraintComparator
82 * {@link Comparator} to determine if the current state is better than the given value.
83 * @return The actual instance to enable builder pattern like usage.
84 */
85 public BaseObjective withHardConstraintOnFitness(double fitnessConstraint,
86 Comparator<Double> fitnessConstraintComparator) {
87 this.fitnessConstraint = fitnessConstraint;
88 this.fitnessConstraintComparator = fitnessConstraintComparator;
89 this.isThereFitnessConstraint = true;
90 return this;
91 }
92
93 /**
94 * Adds a hard constraint on the fitness value. For example, the fitness value must be better than 10 to accept the
95 * current state as a solution. The provided comparator will be used.
96 *
97 * @param fitnessConstraint
98 * Solutions should be better than this value.
99 * @return The actual instance to enable builder pattern like usage.
100 */
101 public BaseObjective withHardConstraintOnFitness(double fitnessConstraint) {
102 return withHardConstraintOnFitness(fitnessConstraint, null);
103 }
104
105 @Override
106 public void init(ThreadContext context) {
107 if (fitnessConstraintComparator == null) {
108 fitnessConstraintComparator = comparator;
109 }
110 }
111
112 @Override
113 public boolean isHardObjective() {
114 return isThereFitnessConstraint;
115 }
116
117 @Override
118 public boolean satisifiesHardObjective(Double fitness) {
119 if (isThereFitnessConstraint) {
120 int compare = fitnessConstraintComparator.compare(fitness, fitnessConstraint);
121 if (compare < 0) {
122 return false;
123 }
124 }
125 return true;
126 }
127
128 @Override
129 public int hashCode() {
130 return name.hashCode();
131 }
132
133 @Override
134 public boolean equals(Object obj) {
135 if (this == obj) {
136 return true;
137 }
138 if (obj instanceof BaseObjective) {
139 BaseObjective baseObjective = (BaseObjective) obj;
140 return name.equals(baseObjective.getName());
141 }
142 return false;
143 }
144
145 @Override
146 public String toString() {
147 return name;
148 }
149
150}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java
new file mode 100644
index 00000000..cc48d22e
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java
@@ -0,0 +1,137 @@
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.objectives.impl;
10
11import java.util.ArrayList;
12import java.util.List;
13import java.util.Objects;
14
15import org.eclipse.viatra.dse.base.ThreadContext;
16import org.eclipse.viatra.dse.objectives.IObjective;
17import org.eclipse.viatra.query.runtime.matchers.util.Preconditions;
18
19/**
20 * This objective collects a list of other objectives. It returns the weighted sum of the objectives.
21 *
22 * @author Andras Szabolcs Nagy
23 *
24 */
25public class CompositeObjective extends BaseObjective {
26
27 public static final String DEFAULT_NAME = "CompositeObjective";
28 protected List<IObjective> objectives;
29 protected List<Double> weights;
30 protected boolean hardObjective;
31
32 public CompositeObjective(String name, List<IObjective> objectives, List<Double> weights) {
33 super(name);
34 Objects.requireNonNull(objectives, "The list of objectives cannot be null.");
35 Objects.requireNonNull(weights, "The list of weights cannot be null.");
36 Preconditions.checkState(objectives.size() == weights.size(), "The size of the objectives and weights must match.");
37 this.objectives = objectives;
38 this.weights = weights;
39 }
40
41 public CompositeObjective(List<IObjective> objectives, List<Double> weights) {
42 this(DEFAULT_NAME, objectives, weights);
43 }
44
45 public CompositeObjective(String name) {
46 this(name, new ArrayList<IObjective>(), new ArrayList<Double>());
47 }
48
49 public CompositeObjective() {
50 this(DEFAULT_NAME, new ArrayList<IObjective>(), new ArrayList<Double>());
51 }
52
53 /**
54 * Adds a new objective.
55 *
56 * @param objective
57 * @return The actual instance to enable builder pattern like usage.
58 */
59 public CompositeObjective withObjective(IObjective objective) {
60 objectives.add(objective);
61 weights.add(1d);
62 return this;
63 }
64
65 /**
66 * Adds a new objective.
67 *
68 * @param objective
69 * @return The actual instance to enable builder pattern like usage.
70 */
71 public CompositeObjective withObjective(IObjective objective, double weight) {
72 objectives.add(objective);
73 weights.add(weight);
74 return this;
75 }
76
77 @Override
78 public Double getFitness(ThreadContext context) {
79
80 double result = 0;
81
82 for (int i = 0; i < objectives.size(); i++) {
83 IObjective objective = objectives.get(i);
84 Double weight = weights.get(i);
85 result += objective.getFitness(context) * weight;
86 }
87 return result;
88 }
89
90 @Override
91 public void init(ThreadContext context) {
92 super.init(context);
93 hardObjective = false;
94 for (IObjective objective : objectives) {
95 objective.init(context);
96 if (objective.isHardObjective()) {
97 hardObjective = true;
98 }
99 }
100 }
101
102 @Override
103 public IObjective createNew() {
104
105 List<IObjective> newObjectives = new ArrayList<IObjective>();
106
107 for (IObjective objective : objectives) {
108 newObjectives.add(objective.createNew());
109 }
110
111 CompositeObjective objective = new CompositeObjective(name, newObjectives, weights);
112 if (isThereFitnessConstraint) {
113 objective.withHardConstraintOnFitness(fitnessConstraint, fitnessConstraintComparator);
114 }
115
116 return objective.withComparator(comparator).withLevel(level);
117 }
118
119 @Override
120 public boolean isHardObjective() {
121 return hardObjective;
122 }
123
124 @Override
125 public boolean satisifiesHardObjective(Double fitness) {
126
127 boolean hardObjectiveSatisfied = true;
128
129 for (IObjective objective : objectives) {
130 hardObjectiveSatisfied = objective.satisifiesHardObjective(fitness) ? hardObjectiveSatisfied : false;
131 }
132
133 hardObjectiveSatisfied = super.satisifiesHardObjective(fitness) ? hardObjectiveSatisfied : false;
134
135 return hardObjectiveSatisfied;
136 }
137}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.java
new file mode 100644
index 00000000..77d416f5
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.java
@@ -0,0 +1,316 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.objectives.impl;
10
11import java.util.ArrayList;
12import java.util.List;
13import java.util.Objects;
14
15import org.eclipse.viatra.dse.api.DSEException;
16import org.eclipse.viatra.dse.base.ThreadContext;
17import org.eclipse.viatra.dse.objectives.IObjective;
18import org.eclipse.viatra.query.runtime.api.IPatternMatch;
19import org.eclipse.viatra.query.runtime.api.IQuerySpecification;
20import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
21import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher;
22import org.eclipse.viatra.query.runtime.exception.ViatraQueryException;
23
24/**
25 * This objective serves as soft and as hard objective at the same time by defining two lists of VIATRA Query
26 * specifications.
27 *
28 * As a soft objective, it collects a list of VIATRA Query specifications, which have predefined weights. Then the
29 * fitness value of an arbitrary solution is calculated in the following way:
30 * <p>
31 * <code>fitness = sum( pattern[i].countMatches() * weight[i] )</code>
32 * <p>
33 * As a hard objective it collects a separate list of VIATRA Query specifications. If every one of them has a match the
34 * hard constraint is considered to be fulfilled.
35 *
36 * @author Andras Szabolcs Nagy
37 * @see IObjective
38 *
39 */
40public class ConstraintsObjective extends BaseObjective {
41
42 public static final String DEFAULT_NAME = "ConstraintsObjective";
43
44 public static class QueryConstraint {
45 public final String name;
46 public final IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query;
47 public final Double weight;
48 public final ModelQueryType type;
49
50 public QueryConstraint(String name,
51 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query, Double weight,
52 ModelQueryType type) {
53 this.name = name;
54 this.query = query;
55 this.weight = weight;
56 this.type = type;
57 }
58
59 public QueryConstraint(String name,
60 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query, Double weight) {
61 this(name, query, weight, ModelQueryType.MUST_HAVE_MATCH);
62 }
63
64 public QueryConstraint(String name,
65 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query, ModelQueryType type) {
66 this(name, query, 0d, type);
67 }
68 }
69
70 protected List<QueryConstraint> softConstraints;
71 protected List<QueryConstraint> hardConstraints;
72
73 protected List<ViatraQueryMatcher<? extends IPatternMatch>> softMatchers;
74 protected List<ViatraQueryMatcher<? extends IPatternMatch>> hardMatchers;
75 protected List<Integer> softMatches;
76 protected List<Integer> hardMatches;
77
78 public ConstraintsObjective(String name, List<QueryConstraint> softConstraints,
79 List<QueryConstraint> hardConstraints) {
80 super(name);
81 Objects.requireNonNull(softConstraints, "The list of soft constraints cannot be null.");
82 Objects.requireNonNull(hardConstraints, "The list of hard constraints cannot be null.");
83
84 this.softConstraints = softConstraints;
85 this.hardConstraints = hardConstraints;
86 }
87
88 public ConstraintsObjective(String name, List<QueryConstraint> hardConstraints) {
89 this(name, new ArrayList<QueryConstraint>(), hardConstraints);
90 }
91
92 public ConstraintsObjective(List<QueryConstraint> hardConstraints) {
93 this(DEFAULT_NAME, new ArrayList<QueryConstraint>(), hardConstraints);
94 }
95
96 public ConstraintsObjective(String name) {
97 this(name, new ArrayList<QueryConstraint>(), new ArrayList<QueryConstraint>());
98 }
99
100 public ConstraintsObjective() {
101 this(DEFAULT_NAME, new ArrayList<QueryConstraint>(), new ArrayList<QueryConstraint>());
102 }
103
104 /**
105 * Adds a new soft constraint.
106 *
107 * @param name
108 * A name for the soft constraint.
109 * @param softConstraint
110 * A VIATRA Query pattern specification.
111 * @param weight
112 * The weight of the pattern.
113 * @return The actual instance to enable builder pattern like usage.
114 */
115 public ConstraintsObjective withSoftConstraint(String name,
116 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> softConstraint, double weight) {
117 softConstraints.add(new QueryConstraint(name, softConstraint, weight));
118 return this;
119 }
120
121 /**
122 * Adds a new soft constraint with the name of the query specification's fully qualified name.
123 *
124 * @param softConstraint
125 * A VIATRA Query pattern specification.
126 * @param weight
127 * The weight of the pattern.
128 * @return The actual instance to enable builder pattern like usage.
129 */
130 public ConstraintsObjective withSoftConstraint(
131 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> softConstraint, double weight) {
132 return withSoftConstraint(softConstraint.getFullyQualifiedName(), softConstraint, weight);
133 }
134
135 /**
136 * Adds a new hard constraint.
137 *
138 * @param name
139 * A name for the hard constraint.
140 * @param softConstraint
141 * A VIATRA Query pattern specification.
142 * @param type
143 * {@link ModelQueryType}, which determines whether the constraint should have at least one match or none
144 * at all.
145 * @return The actual instance to enable builder pattern like usage.
146 */
147 public ConstraintsObjective withHardConstraint(String name,
148 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint,
149 ModelQueryType type) {
150 hardConstraints.add(new QueryConstraint(name, hardConstraint, type));
151 return this;
152 }
153
154 /**
155 * Adds a new hard constraint with the default {@link ModelQueryType#MUST_HAVE_MATCH}.
156 *
157 * @param name
158 * A name for the hard constraint.
159 * @param softConstraint
160 * A VIATRA Query pattern specification.
161 * @return The actual instance to enable builder pattern like usage.
162 */
163 public ConstraintsObjective withHardConstraint(String name,
164 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint) {
165 hardConstraints.add(new QueryConstraint(name, hardConstraint, ModelQueryType.MUST_HAVE_MATCH));
166 return this;
167 }
168
169 /**
170 * Adds a new hard constraint with the name of the query specification's fully qualified name and the default
171 * {@link ModelQueryType#MUST_HAVE_MATCH}.
172 *
173 * @param softConstraint
174 * A VIATRA Query pattern specification.
175 * @return The actual instance to enable builder pattern like usage.
176 */
177 public ConstraintsObjective withHardConstraint(
178 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint) {
179 return withHardConstraint(hardConstraint.getFullyQualifiedName(), hardConstraint,
180 ModelQueryType.MUST_HAVE_MATCH);
181 }
182
183 /**
184 * Adds a new hard constraint with the name of the query specification's fully qualified name.
185 *
186 * @param softConstraint
187 * A VIATRA Query pattern specification.
188 * @param type
189 * {@link ModelQueryType}, which determines whether the constraint should have at least one match or none
190 * at all.
191 * @return The actual instance to enable builder pattern like usage.
192 */
193 public ConstraintsObjective withHardConstraint(
194 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint,
195 ModelQueryType type) {
196 return withHardConstraint(hardConstraint.getFullyQualifiedName(), hardConstraint, type);
197 }
198
199 @Override
200 public Double getFitness(ThreadContext context) {
201
202 if (softConstraints.isEmpty()) {
203 return 0d;
204 }
205
206 double result = 0;
207
208 for (int i = 0; i < softConstraints.size(); i++) {
209 int countMatches = softMatchers.get(i).countMatches();
210 result += countMatches * softConstraints.get(i).weight;
211 softMatches.set(i, Integer.valueOf(countMatches));
212 }
213
214 return result;
215 }
216
217 @Override
218 public void init(ThreadContext context) {
219
220 super.init(context);
221
222 softMatches = new ArrayList<Integer>(softConstraints.size());
223 softMatchers = new ArrayList<ViatraQueryMatcher<? extends IPatternMatch>>(softConstraints.size());
224 hardMatches = new ArrayList<Integer>(hardConstraints.size());
225 hardMatchers = new ArrayList<ViatraQueryMatcher<? extends IPatternMatch>>(hardConstraints.size());
226 for (int i = 0; i < softConstraints.size(); i++) {
227 softMatches.add(0);
228 }
229 for (int i = 0; i < hardConstraints.size(); i++) {
230 hardMatches.add(0);
231 }
232
233 try {
234 ViatraQueryEngine queryEngine = context.getQueryEngine();
235
236 for (QueryConstraint qc : softConstraints) {
237 softMatchers.add(qc.query.getMatcher(queryEngine));
238 }
239
240 for (QueryConstraint qc : hardConstraints) {
241 hardMatchers.add(qc.query.getMatcher(queryEngine));
242 }
243
244 } catch (ViatraQueryException e) {
245 throw new DSEException("Couldn't initialize the VIATRA Query matcher, see inner exception", e);
246 }
247 }
248
249 @Override
250 public IObjective createNew() {
251 new ArrayList<Double>(softConstraints.size());
252 ConstraintsObjective result = new ConstraintsObjective(name, softConstraints, hardConstraints);
253 if (isThereFitnessConstraint) {
254 result.withHardConstraintOnFitness(fitnessConstraint, fitnessConstraintComparator);
255 }
256 return result.withComparator(comparator).withLevel(level);
257 }
258
259 @Override
260 public boolean isHardObjective() {
261 return !hardConstraints.isEmpty() || super.isHardObjective();
262 }
263
264 @Override
265 public boolean satisifiesHardObjective(Double fitness) {
266
267 boolean result = true;
268
269 for (int i = 0; i < hardConstraints.size(); i++) {
270 ModelQueryType type = hardConstraints.get(i).type;
271 int countMatches = hardMatchers.get(i).countMatches();
272 hardMatches.set(i, Integer.valueOf(countMatches));
273 if ((type.equals(ModelQueryType.MUST_HAVE_MATCH) && countMatches <= 0)
274 || (type.equals(ModelQueryType.NO_MATCH) && countMatches > 0)) {
275 result = false;
276 }
277 }
278
279 result = super.satisifiesHardObjective(fitness) ? result : false;
280
281 return result;
282 }
283
284 public List<QueryConstraint> getSoftConstraints() {
285 return softConstraints;
286 }
287
288 public List<QueryConstraint> getHardConstraints() {
289 return hardConstraints;
290 }
291
292 public String getSoftName(int index) {
293 return softConstraints.get(index).name;
294 }
295
296 public String getHardName(int index) {
297 return hardConstraints.get(index).name;
298 }
299
300 public List<Integer> getSoftMatches() {
301 return softMatches;
302 }
303
304 public List<Integer> getHardMatches() {
305 return hardMatches;
306 }
307
308 public List<String> getSoftNames() {
309 List<String> softNames = new ArrayList<>(softConstraints.size());
310 for (QueryConstraint qc : softConstraints) {
311 softNames.add(qc.name);
312 }
313 return softNames;
314 }
315
316}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.java
new file mode 100644
index 00000000..b21da397
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.java
@@ -0,0 +1,89 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.objectives.impl;
10
11import org.eclipse.viatra.dse.base.ThreadContext;
12import org.eclipse.viatra.dse.objectives.IObjective;
13
14/**
15 * This hard objective is fulfilled if the trajectory is in the specified interval (inclusive).
16 *
17 * @author Andras Szabolcs Nagy
18 *
19 */
20public class DepthHardObjective extends BaseObjective {
21
22 private static final String DEFAULT_NAME = "DepthHardObjective";
23 protected int minDepth;
24 protected int maxDepth;
25 private ThreadContext context;
26
27 public DepthHardObjective() {
28 this(DEFAULT_NAME, 0, Integer.MAX_VALUE);
29 }
30
31 public DepthHardObjective(String name) {
32 this(name, 0, Integer.MAX_VALUE);
33 }
34
35 public DepthHardObjective(int minDepth) {
36 this(DEFAULT_NAME, minDepth, Integer.MAX_VALUE);
37 }
38
39 public DepthHardObjective(String name, int minDepth) {
40 this(name, minDepth, Integer.MAX_VALUE);
41 }
42
43 public DepthHardObjective(int minDepth, int maxDepth) {
44 this(DEFAULT_NAME, minDepth, maxDepth);
45 }
46
47 public DepthHardObjective(String name, int minDepth, int maxDepth) {
48 super(name);
49 this.minDepth = minDepth;
50 this.maxDepth = maxDepth;
51 }
52
53 public DepthHardObjective withMinDepth(int minDepth) {
54 this.minDepth = minDepth;
55 return this;
56 }
57
58 public DepthHardObjective withMaxDepth(int maxDepth) {
59 this.maxDepth = maxDepth;
60 return this;
61 }
62
63 @Override
64 public void init(ThreadContext context) {
65 super.init(context);
66 this.context = context;
67 }
68
69 @Override
70 public Double getFitness(ThreadContext context) {
71 return 0d;
72 }
73
74 @Override
75 public boolean isHardObjective() {
76 return true;
77 }
78
79 @Override
80 public boolean satisifiesHardObjective(Double fitness) {
81 return minDepth <= context.getDepth() && context.getDepth() <= maxDepth;
82 }
83
84 @Override
85 public IObjective createNew() {
86 return new DepthHardObjective(name, minDepth, maxDepth);
87 }
88
89}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstraint.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstraint.java
new file mode 100644
index 00000000..7616b4a2
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstraint.java
@@ -0,0 +1,116 @@
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.objectives.impl;
10
11import java.util.ArrayList;
12import java.util.List;
13import java.util.Objects;
14
15import org.eclipse.viatra.dse.api.DSEException;
16import org.eclipse.viatra.dse.base.ThreadContext;
17import org.eclipse.viatra.dse.objectives.IGlobalConstraint;
18import org.eclipse.viatra.query.runtime.api.IPatternMatch;
19import org.eclipse.viatra.query.runtime.api.IQuerySpecification;
20import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
21import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher;
22import org.eclipse.viatra.query.runtime.exception.ViatraQueryException;
23
24/**
25 * This global constraint collects a list of VIATRA Query pattern and checks if any of them has a match on along a trajectory.
26 * If any of the patterns has a match then it is unsatisfied and the exploration should backtrack.
27 *
28 * @author Andras Szabolcs Nagy
29 *
30 */
31public class ModelQueriesGlobalConstraint implements IGlobalConstraint {
32
33 public static final String GLOBAL_CONSTRAINT = "GlobalConstraint";
34 protected String name;
35 protected List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> constraints;
36 protected List<ViatraQueryMatcher<? extends IPatternMatch>> matchers = new ArrayList<ViatraQueryMatcher<? extends IPatternMatch>>();
37 protected ModelQueryType type = ModelQueryType.NO_MATCH;
38
39 public ModelQueriesGlobalConstraint(String name,
40 List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> constraints) {
41 Objects.requireNonNull(name, "Name of the global constraint cannot be null.");
42 Objects.requireNonNull(constraints, "The list of constraints cannot be null.");
43
44 this.name = name;
45 this.constraints = constraints;
46 }
47
48 public ModelQueriesGlobalConstraint(
49 List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> constraints) {
50 this(GLOBAL_CONSTRAINT, constraints);
51 }
52
53 public ModelQueriesGlobalConstraint(String name) {
54 this(name, new ArrayList<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>>());
55 }
56
57 public ModelQueriesGlobalConstraint() {
58 this(GLOBAL_CONSTRAINT,
59 new ArrayList<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>>());
60 }
61
62 /**
63 * Adds a new VIATRA Query pattern.
64 *
65 * @param constraint
66 * A VIATRA Query pattern.
67 * @return The actual instance to enable builder pattern like usage.
68 */
69 public ModelQueriesGlobalConstraint withConstraint(
70 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> constraint) {
71 constraints.add(constraint);
72 return this;
73 }
74
75 public ModelQueriesGlobalConstraint withType(ModelQueryType type) {
76 this.type = type;
77 return this;
78 }
79
80 @Override
81 public String getName() {
82 return name;
83 }
84
85 @Override
86 public boolean checkGlobalConstraint(ThreadContext context) {
87 for (ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) {
88 if ((type.equals(ModelQueryType.NO_MATCH) && matcher.countMatches() > 0)
89 || (type.equals(ModelQueryType.MUST_HAVE_MATCH) && matcher.countMatches() == 0)) {
90 return false;
91 }
92 }
93 return true;
94 }
95
96 @Override
97 public void init(ThreadContext context) {
98 try {
99 ViatraQueryEngine queryEngine = context.getQueryEngine();
100
101 for (IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification : constraints) {
102 ViatraQueryMatcher<? extends IPatternMatch> matcher = querySpecification.getMatcher(queryEngine);
103 matchers.add(matcher);
104 }
105
106 } catch (ViatraQueryException e) {
107 throw new DSEException("Couldn't get the VIATRA Query matcher, see inner exception", e);
108 }
109 }
110
111 @Override
112 public IGlobalConstraint createNew() {
113 return new ModelQueriesGlobalConstraint(name, constraints);
114 }
115
116}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueryType.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueryType.java
new file mode 100644
index 00000000..76390352
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueryType.java
@@ -0,0 +1,14 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, 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.objectives.impl;
10
11public enum ModelQueryType {
12 MUST_HAVE_MATCH,
13 NO_MATCH
14}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardObjective.java
new file mode 100644
index 00000000..27cf139c
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardObjective.java
@@ -0,0 +1,52 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.objectives.impl;
10
11import org.eclipse.viatra.dse.base.ThreadContext;
12import org.eclipse.viatra.dse.objectives.IObjective;
13
14/**
15 * This hard objective is never fulfilled. Use it if all states should be regarded as an invalid solution.
16 *
17 * @author Andras Szabolcs Nagy
18 *
19 */
20public class NeverSatisfiedDummyHardObjective extends BaseObjective {
21
22 private static final String DEFAULT_NAME = "NeverSatisfiedDummyHardObjective";
23
24 public NeverSatisfiedDummyHardObjective() {
25 super(DEFAULT_NAME);
26 }
27
28 public NeverSatisfiedDummyHardObjective(String name) {
29 super(name);
30 }
31
32 @Override
33 public Double getFitness(ThreadContext context) {
34 return 0d;
35 }
36
37 @Override
38 public boolean isHardObjective() {
39 return true;
40 }
41
42 @Override
43 public boolean satisifiesHardObjective(Double fitness) {
44 return false;
45 }
46
47 @Override
48 public IObjective createNew() {
49 return this;
50 }
51
52}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObjective.java
new file mode 100644
index 00000000..756d94ec
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObjective.java
@@ -0,0 +1,59 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.objectives.impl;
10
11import org.eclipse.viatra.dse.base.ThreadContext;
12import org.eclipse.viatra.dse.objectives.IObjective;
13
14/**
15 * This hard objective is satisfied if there are no rule activations from the current state (returning 1 in this case).
16 *
17 * @author Andras Szabolcs Nagy
18 *
19 */
20public class NoRuleActivationsHardObjective extends BaseObjective {
21
22 protected static final String DEFAULT_NAME = "NoMoreActivationHardObjective";
23 private ThreadContext context;
24
25 public NoRuleActivationsHardObjective(String name) {
26 super(name);
27 }
28
29 public NoRuleActivationsHardObjective() {
30 this(DEFAULT_NAME);
31 }
32
33 @Override
34 public Double getFitness(ThreadContext context) {
35 return 0d;
36 }
37
38 @Override
39 public void init(ThreadContext context) {
40 super.init(context);
41 this.context = context;
42 }
43
44 @Override
45 public IObjective createNew() {
46 return new NoRuleActivationsHardObjective(name);
47 }
48
49 @Override
50 public boolean isHardObjective() {
51 return true;
52 }
53
54 @Override
55 public boolean satisifiesHardObjective(Double fitness) {
56 return context.getConflictSet().getNextActivations().isEmpty();
57 }
58
59}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjective.java
new file mode 100644
index 00000000..25ff45ae
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjective.java
@@ -0,0 +1,148 @@
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.objectives.impl;
10
11import java.util.HashMap;
12import java.util.List;
13import java.util.Map;
14import java.util.Map.Entry;
15import java.util.Objects;
16
17import org.eclipse.viatra.dse.base.DesignSpaceManager;
18import org.eclipse.viatra.dse.base.ThreadContext;
19import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo;
20import org.eclipse.viatra.dse.objectives.ActivationFitnessProcessor;
21import org.eclipse.viatra.dse.objectives.Comparators;
22import org.eclipse.viatra.dse.objectives.IObjective;
23import org.eclipse.viatra.query.runtime.matchers.util.Preconditions;
24import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
25
26/**
27 * This soft objective calculates a fitness value based on the length of the trajectory. Costs to the rules can be
28 * assigned.
29 *
30 * @author Andras Szabolcs Nagy
31 *
32 */
33public class TrajectoryCostSoftObjective extends BaseObjective {
34
35 public static final String DEFAULT_NAME = "TrajectoryCostObjective";
36 protected Map<BatchTransformationRule<?, ?>, Double> fixCosts;
37 protected Map<BatchTransformationRule<?, ?>, ActivationFitnessProcessor> activationCostProcessors;
38 protected double trajectoryLengthWeight = 0.0;
39 protected boolean calculateTrajectoryLengthWeight;
40
41 public TrajectoryCostSoftObjective(String name) {
42 super(name);
43 comparator = Comparators.LOWER_IS_BETTER;
44 }
45
46 public TrajectoryCostSoftObjective() {
47 this(DEFAULT_NAME);
48 }
49
50 /**
51 * Sets the cost of a rule.
52 *
53 * @param rule
54 * @param cost
55 * @return The actual instance to enable builder pattern like usage.
56 */
57 public TrajectoryCostSoftObjective withRuleCost(BatchTransformationRule<?, ?> rule, double cost) {
58 Objects.requireNonNull(rule);
59 if (fixCosts == null) {
60 fixCosts = new HashMap<BatchTransformationRule<?, ?>, Double>();
61 }
62 Preconditions.checkArgument(!fixCosts.containsKey(rule));
63 fixCosts.put(rule, cost);
64 return this;
65 }
66
67 /**
68 * Sets an activation processor for a rule.
69 *
70 * @param rule
71 * @param activationCostProcessor
72 * @return The actual instance to enable builder pattern like usage.
73 */
74 public TrajectoryCostSoftObjective withActivationCost(BatchTransformationRule<?, ?> rule,
75 ActivationFitnessProcessor activationCostProcessor) {
76 Objects.requireNonNull(rule);
77 Objects.requireNonNull(activationCostProcessor);
78 if (activationCostProcessors == null) {
79 activationCostProcessors = new HashMap<BatchTransformationRule<?, ?>, ActivationFitnessProcessor>();
80 }
81 Preconditions.checkArgument(!activationCostProcessors.containsKey(rule));
82 activationCostProcessors.put(rule, activationCostProcessor);
83 return this;
84 }
85
86 /**
87 * The length of the trajectory multiplied with given parameter will be added to the fitness value.
88 *
89 * @param trajectoryLengthWeight
90 * The weight of a transformation rule application.
91 * @return The actual instance to enable builder pattern like usage.
92 */
93 public TrajectoryCostSoftObjective withTrajectoryLengthWeight(double trajectoryLengthWeight) {
94 this.trajectoryLengthWeight = trajectoryLengthWeight;
95 this.calculateTrajectoryLengthWeight = true;
96 return this;
97 }
98
99 @Override
100 public Double getFitness(ThreadContext context) {
101
102 DesignSpaceManager dsm = context.getDesignSpaceManager();
103 TrajectoryInfo trajectoryInfo = dsm.getTrajectoryInfo();
104 List<Object> trajectory = trajectoryInfo.getTrajectory();
105 List<BatchTransformationRule<?, ?>> rules = trajectoryInfo.getRules();
106
107 double result = 0;
108
109 for (int i = 0; i < trajectory.size(); i++) {
110 BatchTransformationRule<?, ?> rule = rules.get(i);
111
112 Double cost = fixCosts.get(rule);
113 if (cost != null) {
114 result += cost;
115 }
116
117 Map<String, Double> costs = trajectoryInfo.getMeasuredCosts().get(i);
118 if (costs != null) {
119 cost = costs.get(name);
120 if (cost != null) {
121 result += cost;
122 }
123 }
124 }
125
126 if (calculateTrajectoryLengthWeight) {
127 result += trajectory.size() * trajectoryLengthWeight;
128 }
129
130 return result;
131 }
132
133 @Override
134 public void init(ThreadContext context) {
135 super.init(context);
136 DesignSpaceManager dsm = context.getDesignSpaceManager();
137 if (activationCostProcessors != null) {
138 for (Entry<BatchTransformationRule<?, ?>, ActivationFitnessProcessor> entry : activationCostProcessors.entrySet()) {
139 dsm.registerActivationCostProcessor(name, entry.getKey(), entry.getValue());
140 }
141 }
142 }
143
144 @Override
145 public IObjective createNew() {
146 return this;
147 }
148}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.java
new file mode 100644
index 00000000..8d74e856
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.java
@@ -0,0 +1,40 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.solutionstore;
10
11import org.eclipse.viatra.dse.api.SolutionTrajectory;
12import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
13import org.eclipse.viatra.dse.base.ThreadContext;
14import org.eclipse.viatra.dse.solutionstore.SolutionStore.ISolutionSaver;
15
16/**
17 * Contains callback methods which are called when a solution is found by the exploration {@link IStrategy}.
18 *
19 * @author Andras Szabolcs Nagy
20 *
21 */
22public interface ISolutionFoundHandler {
23
24 /**
25 * Called when a solution is saved by the {@link ISolutionSaver}. Later, this solution can be omitted from the final
26 * set of solutions.
27 *
28 * @param context
29 * @param trajectory
30 */
31 void solutionFound(ThreadContext context, SolutionTrajectory trajectory);
32
33 /**
34 * Called when the exploration found a solution but it was not saved because of certain conditions.
35 *
36 * @param context
37 * @param trajectory
38 */
39 void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory);
40} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.java
new file mode 100644
index 00000000..36e6b5b7
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.java
@@ -0,0 +1,18 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.solutionstore;
10
11/**
12 * Provides file name when a model is searialzed.
13 * @author Andras Szabolcs Nagy
14 *
15 */
16public interface ISolutionNameProvider {
17 String getName();
18} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider.java
new file mode 100644
index 00000000..43460015
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider.java
@@ -0,0 +1,37 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.solutionstore;
10
11/**
12 * Provides file name with a String <code>[prefix][id].[extension]</code> pattern.
13 * @author Andras Szabolcs Nagy
14 *
15 */
16public class IdBasedSolutionNameProvider implements ISolutionNameProvider {
17
18 private int id = 1;
19 private String prefix;
20 private String extension;
21
22 public IdBasedSolutionNameProvider(String prefix, String extension) {
23 this.extension = extension;
24 this.prefix = prefix;
25
26 }
27
28 @Override
29 public String getName() {
30 StringBuilder sb = new StringBuilder(prefix);
31 sb.append(id++);
32 sb.append('.');
33 sb.append(extension);
34 return sb.toString();
35 }
36
37} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.java
new file mode 100644
index 00000000..118f0c75
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.java
@@ -0,0 +1,28 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.solutionstore;
10
11import org.apache.log4j.Logger;
12import org.eclipse.viatra.dse.api.SolutionTrajectory;
13import org.eclipse.viatra.dse.base.ThreadContext;
14
15public class LogSolutionHandler implements ISolutionFoundHandler {
16
17 Logger logger = Logger.getLogger(LogSolutionHandler.class);
18
19 @Override
20 public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) {
21 logger.info("Solution registered: " + trajectory.toPrettyString());
22 }
23
24 @Override
25 public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) {
26 logger.debug("Not good enough solution: " + trajectory.toPrettyString());
27 }
28} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHandler.java
new file mode 100644
index 00000000..bbbe60de
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHandler.java
@@ -0,0 +1,55 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.solutionstore;
10
11import java.util.HashSet;
12
13import org.eclipse.emf.common.notify.Notifier;
14import org.eclipse.viatra.dse.api.SolutionTrajectory;
15import org.eclipse.viatra.dse.base.ThreadContext;
16import org.eclipse.viatra.dse.util.EMFHelper;
17
18public class ModelSaverSolutionFoundHandler implements ISolutionFoundHandler {
19
20 private HashSet<Object> savedSolutions = new HashSet<Object>();
21 private ISolutionNameProvider solutionNameProvider;
22
23 public ModelSaverSolutionFoundHandler() {
24 solutionNameProvider = new IdBasedSolutionNameProvider("solution", "xmi");
25 }
26
27 public ModelSaverSolutionFoundHandler(String extension) {
28 solutionNameProvider = new IdBasedSolutionNameProvider("solution", extension);
29 }
30
31 public ModelSaverSolutionFoundHandler(String prefix, String extension) {
32 solutionNameProvider = new IdBasedSolutionNameProvider(prefix, extension);
33 }
34
35 public ModelSaverSolutionFoundHandler(ISolutionNameProvider solutionNameProvider) {
36 this.solutionNameProvider = solutionNameProvider;
37 }
38
39 @Override
40 public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) {
41 }
42
43 @Override
44 public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) {
45 Object stateCode = trajectory.getSolution().getStateCode();
46
47 if (savedSolutions.contains(stateCode)) {
48 return;
49 }
50
51 savedSolutions.add(stateCode);
52 Notifier clonedModel = EMFHelper.clone(context.getModel());
53 EMFHelper.saveModel(clonedModel, solutionNameProvider.getName());
54 }
55} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java
new file mode 100644
index 00000000..578ae277
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java
@@ -0,0 +1,311 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2016, Andras Szabolcs Nagy, 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.solutionstore;
10
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.HashMap;
14import java.util.List;
15import java.util.Map;
16import java.util.Map.Entry;
17import java.util.concurrent.atomic.AtomicBoolean;
18import java.util.concurrent.atomic.AtomicInteger;
19
20import org.apache.log4j.Level;
21import org.apache.log4j.Logger;
22import org.eclipse.emf.common.notify.Notifier;
23import org.eclipse.viatra.dse.api.DSEException;
24import org.eclipse.viatra.dse.api.Solution;
25import org.eclipse.viatra.dse.api.SolutionTrajectory;
26import org.eclipse.viatra.dse.base.DesignSpaceManager;
27import org.eclipse.viatra.dse.base.ThreadContext;
28import org.eclipse.viatra.dse.objectives.Fitness;
29import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper;
30import org.eclipse.viatra.dse.statecode.IStateCoderFactory;
31import org.eclipse.viatra.dse.util.EMFHelper;
32import org.eclipse.viatra.query.runtime.exception.ViatraQueryException;
33
34/**
35 *
36 * @author Andras Szabolcs Nagy
37 *
38 */
39public class SolutionStore {
40
41 public interface ISolutionSaver {
42 void setSolutionsCollection(Map<Object, Solution> solutions);
43 boolean saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory);
44 }
45
46 public interface IEnoughSolutions extends ISolutionFoundHandler {
47 boolean enoughSolutions();
48 }
49
50 public static class ANumberOfEnoughSolutions implements IEnoughSolutions {
51
52 private final AtomicInteger foundSolutions;
53 private final AtomicBoolean foundEnoughSolutions;
54
55 public ANumberOfEnoughSolutions(int number) {
56 foundSolutions = new AtomicInteger(number);
57 foundEnoughSolutions = new AtomicBoolean(false);
58 }
59
60 @Override
61 public boolean enoughSolutions() {
62 return foundEnoughSolutions.get();
63 }
64
65 @Override
66 public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) {
67 int solutionsToFind = foundSolutions.decrementAndGet();
68 if (solutionsToFind == 0) {
69 foundEnoughSolutions.set(true);
70 }
71 }
72
73 @Override
74 public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) {
75 }
76 }
77
78 public static class SimpleSolutionSaver implements ISolutionSaver {
79
80 private Map<Object, Solution> solutions;
81
82 @Override
83 public void setSolutionsCollection(Map<Object, Solution> solutions) {
84 this.solutions = solutions;
85 }
86
87 @Override
88 public boolean saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) {
89 Solution solution = solutions.get(id);
90 if (solution != null) {
91 if (solution.getTrajectories().contains(solutionTrajectory)) {
92 return false;
93 } else {
94 solution.addTrajectory(solutionTrajectory);
95 solutionTrajectory.setSolution(solution);
96 }
97 } else {
98 solution = new Solution(id, solutionTrajectory);
99 solutions.put(id, solution);
100 solutionTrajectory.setSolution(solution);
101 }
102 return true;
103 }
104 }
105
106 public static class BestSolutionSaver implements ISolutionSaver {
107
108 private Map<Object, Solution> solutions;
109 private Map<SolutionTrajectory, Fitness> trajectories = new HashMap<>();
110
111 @Override
112 public void setSolutionsCollection(Map<Object, Solution> solutions) {
113 this.solutions = solutions;
114 }
115
116 @Override
117 public boolean saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) {
118
119 Fitness lastFitness = context.getLastFitness();
120 ObjectiveComparatorHelper comparatorHelper = context.getObjectiveComparatorHelper();
121
122 List<SolutionTrajectory> dominatedTrajectories = new ArrayList<>();
123
124 for (Entry<SolutionTrajectory, Fitness> entry : trajectories.entrySet()) {
125 int isLastFitnessBetter = comparatorHelper.compare(lastFitness, entry.getValue());
126 if (isLastFitnessBetter < 0) {
127 return false;
128 }
129 if (isLastFitnessBetter > 0) {
130 dominatedTrajectories.add(entry.getKey());
131 }
132 }
133
134 boolean solutionSaved = false;
135
136 Solution solution = solutions.get(id);
137 if (solution != null) {
138 if (!solution.getTrajectories().contains(solutionTrajectory)) {
139 solution.addTrajectory(solutionTrajectory);
140 solutionTrajectory.setSolution(solution);
141 solutionSaved = true;
142 trajectories.put(solutionTrajectory, lastFitness);
143 }
144 } else {
145 solution = new Solution(id, solutionTrajectory);
146 solutions.put(id, solution);
147 solutionTrajectory.setSolution(solution);
148 solutionSaved = true;
149 trajectories.put(solutionTrajectory, lastFitness);
150 }
151
152 for (SolutionTrajectory st : dominatedTrajectories) {
153 trajectories.remove(st);
154 Solution s = st.getSolution();
155 if (!s.getTrajectories().remove(st)) {
156 throw new DSEException("Should not happen.");
157 }
158 if (s.getTrajectories().isEmpty()) {
159 Object stateCode = s.getStateCode();
160 solutions.remove(stateCode);
161 }
162 }
163
164 return solutionSaved;
165 }
166
167 }
168
169 protected boolean acceptOnlyGoalSolutions = true;
170 protected final Map<Object, Solution> solutions = new HashMap<Object, Solution>();
171 protected ISolutionSaver solutionSaver = new SimpleSolutionSaver();
172 protected List<ISolutionFoundHandler> solutionFoundHandlers = new ArrayList<ISolutionFoundHandler>(1);
173
174 protected final IEnoughSolutions enoughSolutions;
175
176 public SolutionStore() {
177 this(new IEnoughSolutions() {
178 @Override
179 public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) {
180 }
181
182 @Override
183 public boolean enoughSolutions() {
184 return false;
185 }
186
187 @Override
188 public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) {
189 }
190 });
191 }
192
193 public SolutionStore(int numOfSolutionsToFind) {
194 this(new ANumberOfEnoughSolutions(numOfSolutionsToFind));
195 }
196
197 public SolutionStore(IEnoughSolutions enoughSolutionsImpl) {
198 enoughSolutions = enoughSolutionsImpl;
199 }
200
201 public synchronized void newSolution(ThreadContext context) {
202 solutionSaver.setSolutionsCollection(solutions);
203 Fitness fitness = context.getLastFitness();
204 DesignSpaceManager dsm = context.getDesignSpaceManager();
205 Object id = dsm.getCurrentState();
206 IStateCoderFactory stateCoderFactory = context.getGlobalContext().getStateCoderFactory();
207 SolutionTrajectory solutionTrajectory = dsm.getTrajectoryInfo().createSolutionTrajectory(stateCoderFactory, context.getDesignSpaceManager());
208 solutionTrajectory.setFitness(fitness);
209
210 if (acceptOnlyGoalSolutions && !fitness.isSatisifiesHardObjectives()) {
211 unsavedSolutionCallbacks(context, solutionTrajectory);
212 return;
213 }
214
215 boolean solutionSaved = solutionSaver.saveSolution(context, id, solutionTrajectory);
216
217 if (solutionSaved) {
218 enoughSolutions.solutionFound(context, solutionTrajectory);
219
220 savedSolutionCallbacks(context, solutionTrajectory);
221
222 if (enoughSolutions.enoughSolutions()) {
223 context.getGlobalContext().stopAllThreads();
224 }
225 } else {
226 unsavedSolutionCallbacks(context, solutionTrajectory);
227 }
228 }
229
230 private void unsavedSolutionCallbacks(ThreadContext context, SolutionTrajectory solutionTrajectory) {
231 for (ISolutionFoundHandler handler : solutionFoundHandlers) {
232 handler.solutionTriedToSave(context, solutionTrajectory);
233 }
234 }
235
236 private void savedSolutionCallbacks(ThreadContext context, SolutionTrajectory solutionTrajectory) {
237 for (ISolutionFoundHandler handler : solutionFoundHandlers) {
238 handler.solutionFound(context, solutionTrajectory);
239 }
240 }
241
242 public synchronized Collection<Solution> getSolutions() {
243 return solutions.values();
244 }
245
246 public synchronized void registerSolutionFoundHandler(ISolutionFoundHandler handler) {
247 if (solutionFoundHandlers == null) {
248 solutionFoundHandlers = new ArrayList<ISolutionFoundHandler>(1);
249 }
250 solutionFoundHandlers.add(handler);
251 }
252
253 public SolutionStore logSolutionsWhenFound() {
254 registerSolutionFoundHandler(new LogSolutionHandler());
255 Logger.getLogger(LogSolutionHandler.class).setLevel(Level.INFO);
256 return this;
257 }
258
259 public SolutionStore saveModelWhenFound() {
260 registerSolutionFoundHandler(new ModelSaverSolutionFoundHandler());
261 return this;
262 }
263
264 public SolutionStore saveModelWhenFound(String extension) {
265 registerSolutionFoundHandler(new ModelSaverSolutionFoundHandler(extension));
266 return this;
267 }
268
269 public SolutionStore saveModelWhenFound(String prefix, String extension) {
270 registerSolutionFoundHandler(new ModelSaverSolutionFoundHandler(prefix, extension));
271 return this;
272 }
273
274 public SolutionStore saveModelWhenFound(ISolutionNameProvider solutionNameProvider) {
275 registerSolutionFoundHandler(new ModelSaverSolutionFoundHandler(solutionNameProvider));
276 return this;
277 }
278
279 public SolutionStore acceptGoalSolutionsOnly() {
280 acceptOnlyGoalSolutions = true;
281 return this;
282 }
283
284 public SolutionStore acceptAnySolutions() {
285 acceptOnlyGoalSolutions = false;
286 return this;
287 }
288
289 public SolutionStore withSolutionSaver(ISolutionSaver solutionSaver) {
290 this.solutionSaver = solutionSaver;
291 return this;
292 }
293
294 public SolutionStore storeBestSolutionsOnly() {
295 this.solutionSaver = new BestSolutionSaver();
296 return this;
297 }
298
299 public void saveModels(Notifier model, ISolutionNameProvider solutionNameProvider) {
300 try {
301 for (Solution solution : solutions.values()) {
302 SolutionTrajectory trajectory = solution.getArbitraryTrajectory();
303 trajectory.doTransformationUndoable(model);
304 EMFHelper.saveModel(model, solutionNameProvider.getName());
305 trajectory.undoTransformation();
306 }
307 } catch (ViatraQueryException e) {
308 Logger.getLogger(SolutionStore.class).error("Exception happened during model saving.", e);
309 }
310 }
311}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoder.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoder.java
new file mode 100644
index 00000000..f163f1a5
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoder.java
@@ -0,0 +1,82 @@
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.statecode;
10
11import org.eclipse.emf.common.notify.Notifier;
12import org.eclipse.viatra.query.runtime.api.IPatternMatch;
13
14/**
15 * <p>
16 * To be able to efficiently explore a design space, a state that has been explored before through an other trajectory
17 * needs to be recognized and ignored accordingly.
18 * </p>
19 *
20 * <p>
21 * This is done by generating a pseudo-unique value (object) that is only depended on the relevant parts of the model's
22 * internal state, that is, the values of two states can only be equal if the states themselves can be considered equal.
23 * </p>
24 *
25 * <p>
26 * The processing engine however assumes, that any two states that share this pseudo-unique value has the same
27 * characteristics, meaning they have the same amount and type of outgoing transitions available, and firing the
28 * appropriate transitions from both states also result in states that share their pseudo-unique identifier. If this
29 * condition is not satisfied, the exploration process's result will be non-deterministic, and in consequence, solutions
30 * can be lost.
31 * </p>
32 *
33 * <p>
34 * In addition to providing pseudo-unique identifiers to model states, the state coder must provide pseud-unique
35 * identifiers to the outgoing transitions as well, but they only need to be unique on the scope of the particular
36 * state, not globally. Global addressing thus can be achieved by considering the pseudo-unique identifier of the state
37 * and the pseudo-unique identifier of the transition together if needed.
38 * </p>
39 *
40 * <p>
41 * Both identifiers can be arbitrary objects, and equality is checked by calling {@link Object#equals(Object)} on the
42 * two identifiers.
43 * </p>
44 *
45 * <p>
46 * For any particular implementation an {@link IStateCoderFactory} implementation must also be supplied that handles the
47 * creation of {@link IStateCoder} instances.
48 * </p>
49 *
50 * <p>
51 * Usually it is unnecessary to represent everything from the model in a state code, only the parts which are modified
52 * by the transformation rules.
53 * </p>
54 *
55 * @author Miklos Foldenyi, Andras Szabolcs Nagy
56 *
57 */
58public interface IStateCoder {
59
60 /**
61 * Initializes the state coder on the given model.
62 *
63 * @param notifier
64 */
65 void init(Notifier notifier);
66
67 /**
68 * Returns a pseudo-unique identifier that describes the underlying model's current internal state.
69 *
70 * @return an arbitrary {@link Object} that can be used as the identifier.
71 */
72 Object createStateCode();
73
74 /**
75 * Returns a pseudo-unique identifier that describes the given {@link IPatternMatch} in the context of the
76 * underlying model's current internal state.
77 *
78 * @return an arbitrary {@link Object} that can be used as the identifier in the given state.
79 */
80 Object createActivationCode(IPatternMatch match);
81
82}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoderFactory.java
new file mode 100644
index 00000000..cf8bdf8d
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoderFactory.java
@@ -0,0 +1,29 @@
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.statecode;
10
11/**
12 * Interface for a factory class that creates instances of {@link IStateCoder} objects. This is required because state
13 * coders have to be created on-demand if the design space exploration process decides that a new thread is to be
14 * spawned. Since each thread requires it's own working model instance and a state coder is linked to the underlying
15 * model, a new {@link IStateCoder} needs to be created per processing thread.
16 *
17 * @author Miklos Foldenyi, Andras Szabolcs Nagy
18 *
19 */
20public interface IStateCoderFactory {
21
22 /**
23 * Creates a new {@link IStateCoder} instance specific to this {@link IStateCoderFactory}.
24 *
25 * @return the new {@link IStateCoder} instance specific to this working model.
26 */
27 IStateCoder createStateCoder();
28
29}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProvider.java
new file mode 100644
index 00000000..afcba7b6
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProvider.java
@@ -0,0 +1,45 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11import java.util.Collection;
12
13import org.eclipse.emf.common.notify.Notifier;
14import org.eclipse.emf.ecore.EClass;
15import org.eclipse.emf.ecore.EObject;
16
17/**
18 * Implementation of this interface is responsible to provide {@link EObject}s of a given {@link EClass} for
19 * {@link TheStateCoder}
20 *
21 * @author Andras Szabolcs Nagy
22 *
23 */
24public interface IObjectsProvider {
25
26 /**
27 * Initialize the {@link IObjectsProvider} on a given model and {@link StatecodingDependencyGraph}.
28 *
29 * @param notifier
30 * The root of the model.
31 * @param statecodingDependencyGraph
32 * The state coding dependency graph.
33 */
34 void init(Notifier notifier, StatecodingDependencyGraph statecodingDependencyGraph);
35
36 /**
37 * Returns the instances of an {@link EClass} in a model.
38 *
39 * @param eClass
40 * The class of the objects.
41 * @return The collection of the instances.
42 */
43 Collection<EObject> getEObjects(EClass eClass);
44
45}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.java
new file mode 100644
index 00000000..931eb1a2
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.java
@@ -0,0 +1,25 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11/**
12 * Interface for creating {@link IObjectsProvider} instances.
13 *
14 * @author Andras Szabolcs Nagy
15 */
16public interface IObjectsProviderFactory {
17
18 /**
19 * Creates an {@link IObjectsProvider} implementation.
20 *
21 * @return The newly created {@link IObjectsProvider}.
22 */
23 IObjectsProvider createObjectsProvider();
24
25}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.java
new file mode 100644
index 00000000..e38d45d3
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.java
@@ -0,0 +1,60 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11import java.util.Collection;
12import java.util.HashSet;
13import java.util.Set;
14
15import org.apache.log4j.Logger;
16import org.eclipse.emf.common.notify.Notifier;
17import org.eclipse.emf.ecore.EClass;
18import org.eclipse.emf.ecore.EObject;
19import org.eclipse.viatra.dse.api.DSEException;
20import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
21import org.eclipse.viatra.query.runtime.base.api.IndexingLevel;
22import org.eclipse.viatra.query.runtime.base.api.NavigationHelper;
23import org.eclipse.viatra.query.runtime.emf.EMFScope;
24import org.eclipse.viatra.query.runtime.exception.ViatraQueryException;
25
26public class IncrementalObjectProvider implements IObjectsProvider {
27
28 private Logger logger = Logger.getLogger(getClass());
29 private NavigationHelper baseIndex;
30
31 @Override
32 public void init(Notifier notifier, StatecodingDependencyGraph statecodingDependencyGraph) {
33
34 try {
35 EMFScope scope = new EMFScope(notifier);
36 ViatraQueryEngine queryEngine = ViatraQueryEngine.on(scope);
37
38 Set<EClass> classes = new HashSet<EClass>();
39// Set<EReference> references = new HashSet<EReference>();
40 for (StatecodingNode node : statecodingDependencyGraph.getNodes()) {
41 classes.add(node.getClazz());
42// for (StatecodingDependency dependency : node.getStatecodingDependencies()) {
43// // TODO inverse reference
44// references.add(dependency.eReference);
45// }
46 }
47 baseIndex = EMFScope.extractUnderlyingEMFIndex(queryEngine);
48 baseIndex.registerEClasses(classes, IndexingLevel.FULL);
49 } catch (ViatraQueryException e) {
50 logger.error("Failed to initialize VIATRA Query engine on the given notifier", e);
51 throw new DSEException("Failed to initialize VIATRA Query engine on the given notifier");
52 }
53 }
54
55 @Override
56 public Collection<EObject> getEObjects(EClass eClass) {
57 return baseIndex.getAllInstances(eClass);
58 }
59
60}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFactory.java
new file mode 100644
index 00000000..97011436
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFactory.java
@@ -0,0 +1,18 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11public class IncrementalObjectProviderFactory implements IObjectsProviderFactory {
12
13 @Override
14 public IncrementalObjectProvider createObjectsProvider() {
15 return new IncrementalObjectProvider();
16 }
17
18}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependency.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependency.java
new file mode 100644
index 00000000..67b1982d
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependency.java
@@ -0,0 +1,33 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11import org.eclipse.emf.ecore.EReference;
12
13public class StatecodingDependency {
14
15 protected EReference eReference;
16 protected StatecodingNode node;
17 protected boolean isContained;
18 protected StatecodingDependencyType type;
19
20 public StatecodingDependency(EReference eReference, StatecodingNode node, boolean isContained,
21 StatecodingDependencyType type) {
22 super();
23 this.eReference = eReference;
24 this.node = node;
25 this.isContained = isContained;
26 this.type = type;
27 }
28
29 public StatecodingDependency(EReference eReference, StatecodingNode node) {
30 this(eReference, node, false, StatecodingDependencyType.NORMAL);
31 }
32
33} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.java
new file mode 100644
index 00000000..6f7255a3
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.java
@@ -0,0 +1,44 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11import java.util.ArrayList;
12import java.util.List;
13
14import org.eclipse.emf.ecore.EClass;
15
16public class StatecodingDependencyGraph {
17
18 private List<StatecodingNode> nodes = new ArrayList<StatecodingNode>();
19
20 public StatecodingNode createNode(EClass clazz) {
21 StatecodingNode node = new StatecodingNode(clazz);
22 node.setGraph(this);
23 addNode(node);
24 return node;
25 }
26
27 public void addNode(StatecodingNode node) {
28 nodes.add(node);
29 }
30
31 public StatecodingNode getNodeByClass(EClass eClass) {
32 for (StatecodingNode node : nodes) {
33 if (node.getClazz().equals(eClass)) {
34 return node;
35 }
36 }
37 return null;
38 }
39
40 public List<StatecodingNode> getNodes() {
41 return nodes;
42 }
43
44}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.java
new file mode 100644
index 00000000..bdd4677d
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.java
@@ -0,0 +1,15 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11public enum StatecodingDependencyType {
12
13 NORMAL,
14 INVERSE
15}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNode.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNode.java
new file mode 100644
index 00000000..91fc28cf
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNode.java
@@ -0,0 +1,100 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11import java.util.ArrayList;
12import java.util.Comparator;
13import java.util.List;
14import java.util.Set;
15import java.util.TreeSet;
16
17import org.eclipse.emf.ecore.EAttribute;
18import org.eclipse.emf.ecore.EClass;
19import org.eclipse.emf.ecore.EReference;
20
21public class StatecodingNode {
22
23 private StatecodingDependencyGraph graph;
24
25 private final EClass clazz;
26 private Set<EAttribute> attributes = new TreeSet<EAttribute>(Comparator.comparing(EAttribute::getName));
27 private List<StatecodingDependency> dependencies = new ArrayList<StatecodingDependency>();
28 private boolean stateCodeIsId = false;
29 private StatecodingNodeType statecodingNodeType = StatecodingNodeType.CREATE_AND_DELETE;
30
31 public StatecodingNode(EClass clazz) {
32 this.clazz = clazz;
33 }
34
35 public StatecodingNode withAttribute(EAttribute attribute) {
36 attributes.add(attribute);
37 return this;
38 }
39
40 public StatecodingNode withType(StatecodingNodeType type) {
41 statecodingNodeType = type;
42 return this;
43 }
44
45 public StatecodingNode withUniqueness() {
46 stateCodeIsId = true;
47 return this;
48 }
49
50 public StatecodingNode withDependency(EReference reference, StatecodingNode node) {
51 dependencies.add(new StatecodingDependency(reference, node));
52 return this;
53 }
54
55 public StatecodingNode withInverseDependency(EReference reference, StatecodingNode node) {
56 dependencies.add(new StatecodingDependency(reference, node, false, StatecodingDependencyType.INVERSE));
57 return this;
58 }
59
60 public void addDependency(StatecodingDependency statecodingDependency) {
61 dependencies.add(statecodingDependency);
62 }
63
64 public EClass getClazz() {
65 return clazz;
66 }
67
68 public boolean isStateCodeIsId() {
69 return stateCodeIsId;
70 }
71
72 public void setStateCodeIsId(boolean stateCodeIsId) {
73 this.stateCodeIsId = stateCodeIsId;
74 }
75
76 public StatecodingNodeType getStatecodingNodeType() {
77 return statecodingNodeType;
78 }
79
80 public void setStatecodingNodeType(StatecodingNodeType statecodingNodeType) {
81 this.statecodingNodeType = statecodingNodeType;
82 }
83
84 public Set<EAttribute> getAttributes() {
85 return attributes;
86 }
87
88 public List<StatecodingDependency> getStatecodingDependencies() {
89 return dependencies;
90 }
91
92 public StatecodingDependencyGraph getGraph() {
93 return graph;
94 }
95
96 public void setGraph(StatecodingDependencyGraph graph) {
97 this.graph = graph;
98 }
99
100}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNodeType.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNodeType.java
new file mode 100644
index 00000000..c902a7a6
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNodeType.java
@@ -0,0 +1,17 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11public enum StatecodingNodeType {
12
13 FIXED,
14 ONLY_CREATE,
15 ONLY_DELETE,
16 CREATE_AND_DELETE
17}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoder.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoder.java
new file mode 100644
index 00000000..4601ff08
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoder.java
@@ -0,0 +1,215 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11import java.util.Arrays;
12import java.util.Collection;
13import java.util.List;
14import java.util.Set;
15
16import org.eclipse.emf.common.notify.Notifier;
17import org.eclipse.emf.common.util.EList;
18import org.eclipse.emf.ecore.EAttribute;
19import org.eclipse.emf.ecore.EObject;
20import org.eclipse.viatra.dse.api.DSEException;
21import org.eclipse.viatra.dse.statecode.IStateCoder;
22import org.eclipse.viatra.query.runtime.api.IPatternMatch;
23
24public class TheStateCoder implements IStateCoder {
25
26 private StatecodingDependencyGraph sdg;
27 private IObjectsProvider objectProvider;
28
29 public TheStateCoder(StatecodingDependencyGraph sdg, IObjectsProvider objectProvider) {
30 this.sdg = sdg;
31 this.objectProvider = objectProvider;
32 }
33
34 @Override
35 public void init(Notifier notifier) {
36 // TODO checks
37 // TODO node sorting based on traversal - in factory
38
39 // this.notifier = notifier;
40 // try {
41 // EMFScope scope = new EMFScope(notifier);
42 // queryEngine = ViatraQueryEngine.on(scope);
43 // } catch (ViatraQueryException e1) {
44 // logger.error("Failed to initialize VIATRA Query engine on the given notifier", e1);
45 // throw new DSEException("Failed to initialize VIATRA Query engine on the given notifier");
46 // }
47
48 objectProvider.init(notifier, sdg);
49 }
50
51 @Override
52 public String createStateCode() {
53
54 StringBuilder sb = new StringBuilder();
55
56 // TODO sort
57 for (StatecodingNode node : sdg.getNodes()) {
58 sb.append(node.getClazz().getName());
59 sb.append(':');
60 sb.append(addStateCode(node));
61 sb.append('|');
62 }
63 sb.deleteCharAt(sb.length() - 1);
64
65 return sb.toString();
66
67 }
68
69 @Override
70 public Object createActivationCode(IPatternMatch match) {
71 // TODO root object
72 // TODO parameterless?
73
74 int i = 0;
75 StringBuilder sb = new StringBuilder();
76 Object object;
77 do {
78 object = match.get(i++);
79 if (object != null) {
80 if (object instanceof EObject) {
81 EObject eObject = (EObject) object;
82 sb.append(addStateCode(sdg.getNodeByClass(eObject.eClass()), eObject));
83 } else {
84 // TODO toString or not to toString
85 }
86 }
87 } while (object != null);
88
89 return sb.toString();
90 }
91
92 public String addStateCode(StatecodingNode node, EObject eObject) {
93 StringBuilder sb = new StringBuilder();
94
95 Set<EAttribute> attributes = node.getAttributes();
96 if (!attributes.isEmpty()) {
97 for (EAttribute eAttribute : attributes) {
98 // attributes are sorted
99 // TODO handle collection
100 sb.append(eObject.eGet(eAttribute));
101 sb.append(';');
102 }
103 sb.deleteCharAt(sb.length() - 1);
104 }
105
106 List<StatecodingDependency> dependencies = node.getStatecodingDependencies();
107 int dependenciesSize = dependencies.size();
108 if (dependenciesSize > 0) {
109 String[] codeParts = new String[dependenciesSize];
110 int i = 0;
111 for (StatecodingDependency dependency : dependencies) {
112 String code = addStateCodeFromDependency(dependency, eObject);
113 codeParts[i++] = code;
114 }
115 Arrays.sort(codeParts);
116
117 sb.append("(");
118 sb.append(codeParts[0]);
119 for (i = 1; i < codeParts.length; i++) {
120 sb.append(';');
121 sb.append(codeParts[i]);
122 }
123 sb.append(")");
124 }
125 return sb.toString();
126 }
127
128 public String addStateCode(StatecodingNode node) {
129 Collection<EObject> eObjects = objectProvider.getEObjects(node.getClazz());
130 int size = eObjects.size();
131
132 if (size > 0) {
133 String[] codeParts = new String[size];
134 int i = 0;
135 for (EObject eObject : eObjects) {
136 String code = addStateCode(node, eObject);
137 codeParts[i++] = code;
138 }
139 Arrays.sort(codeParts);
140
141 StringBuilder sb = new StringBuilder();
142 sb.append(codeParts[0]);
143 for (i = 1; i < codeParts.length; i++) {
144 sb.append(';');
145 sb.append(codeParts[i]);
146 }
147 return sb.toString();
148 }
149
150 return "";
151 }
152
153 public String addStateCodeFromDependency(StatecodingDependency sd, EObject eObject) {
154
155 if (sd.type.equals(StatecodingDependencyType.NORMAL)) {
156
157 Object eReferred = eObject.eGet(sd.eReference);
158 if (eReferred == null) {
159 return "";
160 } else if (eReferred instanceof EList<?>) {
161 EList<?> refferedList = (EList<?>) eReferred;
162 // TODO test
163 if (!refferedList.isEmpty()) {
164
165 String[] codeParts = new String[refferedList.size()];
166 int i = 0;
167 for (Object referredEObject : refferedList) {
168 String code = addStateCode(sd.node, (EObject) referredEObject);
169 codeParts[i++] = code;
170 }
171 Arrays.sort(codeParts);
172
173 StringBuilder sb = new StringBuilder();
174 sb.append('[');
175 sb.append(codeParts[0]);
176 for (i = 1; i < codeParts.length; i++) {
177 sb.append(';');
178 sb.append(codeParts[i]);
179 }
180 sb.append(']');
181 return sb.toString();
182
183 }
184 } else if (eReferred instanceof EObject) {
185 return addStateCode(sd.node, (EObject) eReferred);
186 } else {
187 throw new DSEException("The EObject " + eObject.toString() + " does not have a feature "
188 + eReferred.toString() + ".");
189 }
190
191 } else {
192 for (EObject dependentEObject : objectProvider.getEObjects(sd.node.getClazz())) {
193 Object eReferred = dependentEObject.eGet(sd.eReference);
194 if (eReferred == null) {
195 continue;
196 } else if (eReferred instanceof EList<?>) {
197 // TODO this is slow, use VIATRA Query
198 for (Object referredEObject : ((EList<?>) eReferred)) {
199 if (referredEObject.equals(eObject)) {
200 return addStateCode(sd.node, (EObject) dependentEObject);
201 }
202 }
203 } else if (eReferred.equals(eObject)) {
204 // Probably never happens?
205 return addStateCode(sd.node, (EObject) dependentEObject);
206 } else {
207 throw new DSEException("The EObject " + eObject.toString() + " does not have a feature "
208 + eReferred.toString() + ".");
209 }
210 }
211 }
212
213 return "";
214 }
215}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.java
new file mode 100644
index 00000000..eeb6e48f
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.java
@@ -0,0 +1,40 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding;
10
11import org.eclipse.viatra.dse.statecode.IStateCoder;
12import org.eclipse.viatra.dse.statecode.IStateCoderFactory;
13
14public class TheStateCoderFactory implements IStateCoderFactory {
15
16 private StatecodingDependencyGraph sdg;
17 private IObjectsProviderFactory objectProviderFactory;
18
19 public TheStateCoderFactory(StatecodingDependencyGraph sdg) {
20 this(sdg, new IncrementalObjectProviderFactory());
21 }
22
23 public TheStateCoderFactory(StatecodingDependencyGraph sdg, IObjectsProviderFactory objectProviderFactory) {
24 this.sdg = sdg;
25 this.objectProviderFactory = objectProviderFactory;
26
27 // TODO cyclic dependency? - exception
28
29 // TODO make plan for traversal
30
31 // TODO If the type is FIXED and all dependency is FIXED then do not create state code for it (them)
32 // This is not true :( e.g. matchmaking - they are fixed, but the references must be encoded
33 }
34
35 @Override
36 public IStateCoder createStateCoder() {
37 return new TheStateCoder(sdg, objectProviderFactory.createObjectsProvider());
38 }
39
40}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java
new file mode 100644
index 00000000..0f0759ae
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java
@@ -0,0 +1,250 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding.simple;
10
11import java.util.Arrays;
12import java.util.Collection;
13import java.util.HashMap;
14import java.util.HashSet;
15import java.util.List;
16import java.util.Map;
17import java.util.Set;
18
19import org.eclipse.emf.common.notify.Notifier;
20import org.eclipse.emf.ecore.EAttribute;
21import org.eclipse.emf.ecore.EClass;
22import org.eclipse.emf.ecore.EObject;
23import org.eclipse.emf.ecore.EReference;
24import org.eclipse.emf.ecore.EStructuralFeature;
25import org.eclipse.emf.ecore.EStructuralFeature.Setting;
26import org.eclipse.viatra.dse.api.DSEException;
27import org.eclipse.viatra.dse.statecode.IStateCoder;
28import org.eclipse.viatra.dse.util.EMFHelper.MetaModelElements;
29import org.eclipse.viatra.dse.util.ValueComparableEObjectStringMap;
30import org.eclipse.viatra.query.runtime.api.IPatternMatch;
31import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
32import org.eclipse.viatra.query.runtime.base.api.FeatureListener;
33import org.eclipse.viatra.query.runtime.base.api.IndexingLevel;
34import org.eclipse.viatra.query.runtime.base.api.InstanceListener;
35import org.eclipse.viatra.query.runtime.base.api.NavigationHelper;
36import org.eclipse.viatra.query.runtime.emf.EMFBaseIndexWrapper;
37import org.eclipse.viatra.query.runtime.emf.EMFScope;
38import org.eclipse.viatra.query.runtime.exception.ViatraQueryException;
39
40/**
41 *
42 * @author Andras Szabolcs Nagy
43 *
44 */
45public class SimpleStateCoder implements IStateCoder {
46
47 private Set<EClass> classes;
48 private Set<EStructuralFeature> features;
49 private NavigationHelper navigationHelper;
50
51 private Map<EClass, Map<EObject, String>> objectCodes;
52 private int maxDepth;
53
54 private Set<EObject> changedOrNewEObjects = new HashSet<EObject>();
55 private Set<EObject> deletedClasses = new HashSet<EObject>();
56
57 public SimpleStateCoder(MetaModelElements metaModelElements) {
58 this.maxDepth = 1;
59
60 classes = metaModelElements.classes;
61 features = new HashSet<EStructuralFeature>(metaModelElements.attributes);
62 features.addAll(metaModelElements.references);
63 }
64
65 @Override
66 public void init(Notifier notifier) {
67 try {
68 EMFScope scope = new EMFScope(notifier);
69 ViatraQueryEngine queryEngine = ViatraQueryEngine.on(scope);
70 EMFBaseIndexWrapper baseIndex = (EMFBaseIndexWrapper) queryEngine.getBaseIndex();
71 navigationHelper = baseIndex.getNavigationHelper();
72 navigationHelper.registerObservedTypes(classes, null, features, IndexingLevel.FULL);
73 } catch (ViatraQueryException e) {
74 throw new DSEException(e);
75 }
76
77 objectCodes = new HashMap<EClass, Map<EObject, String>>();
78 for (EClass eClass : classes) {
79 Map<EObject, String> codes = new ValueComparableEObjectStringMap();
80
81 objectCodes.put(eClass, codes);
82
83 for (EObject eObject : navigationHelper.getDirectInstances(eClass)) {
84 codes.put(eObject, createObjectCodeWithDepth(eObject, maxDepth));
85 }
86 }
87
88 navigationHelper.addFeatureListener(features, new FeatureListener() {
89
90 @Override
91 public void featureInserted(EObject host, EStructuralFeature feature, Object value) {
92 changedOrNewEObjects.add(host);
93 }
94
95 @Override
96 public void featureDeleted(EObject host, EStructuralFeature feature, Object value) {
97 changedOrNewEObjects.add(host);
98 if (value instanceof EObject) {
99 changedOrNewEObjects.add((EObject) value);
100 }
101 }
102 });
103
104 navigationHelper.addInstanceListener(classes, new InstanceListener() {
105
106 @Override
107 public void instanceInserted(EClass clazz, EObject instance) {
108 changedOrNewEObjects.add(instance);
109 }
110
111 @Override
112 public void instanceDeleted(EClass clazz, EObject instance) {
113 deletedClasses.add(instance);
114 }
115 });
116 }
117
118 private String createObjectCodeWithDepth(EObject eObject, int depth) {
119
120 StringBuilder sb = new StringBuilder();
121
122 Collection<EAttribute> attributes = eObject.eClass().getEAllAttributes();
123 for (EAttribute eAttribute : attributes) {
124 Object value = eObject.eGet(eAttribute);
125 sb.append(value);
126 sb.append(',');
127 }
128 if (!attributes.isEmpty()) {
129 sb.deleteCharAt(sb.length() - 1);
130 }
131 if (depth > 0) {
132 sb.append('-');
133 Collection<EReference> eReferences = eObject.eClass().getEAllReferences();
134 for (EReference eReference : eReferences) {
135 Object value = eObject.eGet(eReference);
136 if (value == null) {
137 sb.append("null,");
138 } else if (value instanceof EObject) {
139 sb.append(createObjectCodeWithDepth((EObject) value, depth - 1));
140 sb.append(',');
141 } else {
142 List<EObject> referencedEObjects = (List<EObject>) value;
143 if (!referencedEObjects.isEmpty()) {
144
145 String[] codes = new String[referencedEObjects.size()];
146 int index = 0;
147 for (EObject referencedEObject : referencedEObjects) {
148 codes[index++] = createObjectCodeWithDepth(referencedEObject, depth - 1);
149 }
150 Arrays.sort(codes);
151 sb.append('(');
152 for (String code : codes) {
153 sb.append(code);
154 }
155 sb.append("),");
156 }
157 }
158 }
159 sb.deleteCharAt(sb.length() - 1);
160 }
161 return sb.toString();
162 }
163
164 @Override
165 public Object createStateCode() {
166
167 refreshObjectCodes();
168
169 StringBuilder sb = new StringBuilder();
170
171 for (EClass eClass : classes) {
172
173 Set<EObject> instances = navigationHelper.getDirectInstances(eClass);
174
175 if (!instances.isEmpty()) {
176
177 sb.append(eClass.getName());
178 sb.append(':');
179
180 String[] codesToSort = new String[instances.size()];
181 int index = 0;
182 Map<EObject, String> codes = objectCodes.get(eClass);
183 for (EObject eObject : instances) {
184 codesToSort[index++] = codes.get(eObject);
185 }
186 Arrays.sort(codesToSort);
187 for (String string : codesToSort) {
188 sb.append(string);
189 sb.append(';');
190 }
191 sb.deleteCharAt(sb.length() - 1);
192 sb.append('|');
193 }
194 }
195 if (sb.length() != 0) {
196 sb.deleteCharAt(sb.length() - 1);
197 }
198 return sb.toString();
199 }
200
201 private void refreshObjectCodes() {
202 for (EObject eObject : deletedClasses) {
203 EClass eClass = eObject.eClass();
204 objectCodes.get(eClass).remove(eObject);
205 }
206 deletedClasses.clear();
207
208 Set<EObject> objectsToRecode = new HashSet<EObject>();
209 for (EObject eObject : changedOrNewEObjects) {
210 objectsToRecode.add(eObject);
211 for (Setting setting : navigationHelper.getInverseReferences(eObject)) {
212 objectsToRecode.add(setting.getEObject());
213 }
214 }
215
216 for (EObject eObject : objectsToRecode) {
217 EClass eClass = eObject.eClass();
218 objectCodes.get(eClass).put(eObject, createObjectCodeWithDepth(eObject, maxDepth));
219 }
220 changedOrNewEObjects.clear();
221 }
222
223 @Override
224 public Object createActivationCode(IPatternMatch match) {
225
226 StringBuilder sb = new StringBuilder();
227 String[] tokens = match.specification().getFullyQualifiedName().split("\\.");
228 sb.append(tokens[tokens.length - 1]);
229 sb.append(':');
230 Object param;
231 for (int i = 0; (param = match.get(i)) != null; i++) {
232 EObject eObject = (EObject) param;
233
234 Collection<EAttribute> attributes = eObject.eClass().getEAllAttributes();
235 for (EAttribute eAttribute : attributes) {
236 Object value = eObject.eGet(eAttribute);
237 sb.append(value);
238 sb.append(',');
239 }
240 if (!attributes.isEmpty()) {
241 sb.deleteCharAt(sb.length() - 1);
242 }
243
244 sb.append('|');
245 }
246 sb.deleteCharAt(sb.length() - 1);
247 return sb.toString().intern();
248 }
249
250}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactory.java
new file mode 100644
index 00000000..d776e8a8
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactory.java
@@ -0,0 +1,38 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding.simple;
10
11import java.util.Collection;
12import java.util.HashSet;
13
14import org.eclipse.emf.ecore.EPackage;
15import org.eclipse.viatra.dse.statecode.IStateCoder;
16import org.eclipse.viatra.dse.statecode.IStateCoderFactory;
17import org.eclipse.viatra.dse.util.EMFHelper;
18import org.eclipse.viatra.dse.util.EMFHelper.MetaModelElements;
19
20/**
21 *
22 * @author Andras Szabolcs Nagy
23 *
24 */
25public class SimpleStateCoderFactory implements IStateCoderFactory {
26
27 private MetaModelElements metaModelElements;
28
29 public SimpleStateCoderFactory(Collection<EPackage> metaModelPackages) {
30 metaModelElements = EMFHelper.getAllMetaModelElements(new HashSet<EPackage>(metaModelPackages));
31 }
32
33 @Override
34 public IStateCoder createStateCoder() {
35 return new SimpleStateCoder(metaModelElements);
36 }
37
38}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/EMFHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/EMFHelper.java
new file mode 100644
index 00000000..14b3acfb
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/EMFHelper.java
@@ -0,0 +1,424 @@
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.util;
10
11import java.io.IOException;
12import java.util.Collections;
13import java.util.Comparator;
14import java.util.HashMap;
15import java.util.HashSet;
16import java.util.List;
17import java.util.Map;
18import java.util.Objects;
19import java.util.Set;
20import java.util.TreeSet;
21
22import org.apache.log4j.Logger;
23import org.eclipse.emf.common.command.BasicCommandStack;
24import org.eclipse.emf.common.notify.Notifier;
25import org.eclipse.emf.common.util.EList;
26import org.eclipse.emf.common.util.URI;
27import org.eclipse.emf.ecore.EAttribute;
28import org.eclipse.emf.ecore.EClass;
29import org.eclipse.emf.ecore.EClassifier;
30import org.eclipse.emf.ecore.ENamedElement;
31import org.eclipse.emf.ecore.EObject;
32import org.eclipse.emf.ecore.EPackage;
33import org.eclipse.emf.ecore.EReference;
34import org.eclipse.emf.ecore.resource.Resource;
35import org.eclipse.emf.ecore.resource.ResourceSet;
36import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
37import org.eclipse.emf.ecore.util.EcoreUtil.Copier;
38import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
39import org.eclipse.emf.edit.command.AddCommand;
40import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
41import org.eclipse.emf.edit.domain.EditingDomain;
42import org.eclipse.viatra.query.runtime.matchers.util.Preconditions;
43
44/**
45 * This class contains static helper methods.
46 * @author Andras Szabolcs Nagy
47 */
48public final class EMFHelper {
49
50 private static final Logger logger = Logger.getLogger(EMFHelper.class);
51
52 private EMFHelper() {
53 }
54
55 public static class EmfHelperException extends RuntimeException {
56 private static final long serialVersionUID = 7635796550669616626L;
57
58 public EmfHelperException(String string) {
59 super(string);
60 }
61 public EmfHelperException(String string, Throwable e) {
62 super(string, e);
63 }
64 }
65
66 /**
67 * Gets the {@link EditingDomain} of either an {@link EObject}, {@link Resource} or {@link ResourceSet}.
68 * @param notifier The {@link Notifier}.
69 * @return The EditingDomain.
70 */
71 public static EditingDomain getEditingDomain(Notifier notifier) {
72 Objects.requireNonNull(notifier);
73 if (notifier instanceof EObject) {
74 EObject eObject = (EObject) notifier;
75 return AdapterFactoryEditingDomain.getEditingDomainFor(eObject);
76 } else if (notifier instanceof Resource) {
77 Resource resource = (Resource) notifier;
78 EList<EObject> contents = resource.getContents();
79 if (contents.isEmpty()) {
80 return null;
81 }
82 return AdapterFactoryEditingDomain.getEditingDomainFor(contents.get(0));
83 } else if (notifier instanceof ResourceSet) {
84 ResourceSet resourceSet = (ResourceSet) notifier;
85 if (resourceSet.getResources().isEmpty()) {
86 return null;
87 }
88 return getEditingDomain(resourceSet.getResources().get(0));
89 }
90
91 return null;
92 }
93
94 /**
95 * Creates (or gets if already exists) an {@link EditingDomain} over the given {@link Notifier},
96 * either an {@link EObject}, {@link Resource} or {@link ResourceSet}.
97 * @param notifier The {@link Notifier}.
98 * @return The EditingDomain.
99 */
100 public static EditingDomain createEditingDomain(Notifier notifier) {
101
102 EditingDomain domain = getEditingDomain(notifier);
103 if (domain != null) {
104 return domain;
105 }
106
107 registerExtensionForXmiSerializer("dummyext");
108
109 if (notifier instanceof EObject) {
110 EObject eObject = (EObject) notifier;
111
112 domain = new AdapterFactoryEditingDomain(null, new BasicCommandStack());
113 Resource resource = domain.getResourceSet().createResource(URI.createFileURI("dummy.dummyext"));
114 domain.getCommandStack().execute(new AddCommand(domain, resource.getContents(), eObject));
115
116 return domain;
117
118 } else if (notifier instanceof Resource) {
119 Resource resource = (Resource) notifier;
120
121 ResourceSet resourceSet = resource.getResourceSet();
122 if (resourceSet != null) {
123 return new AdapterFactoryEditingDomain(null, new BasicCommandStack(), resourceSet);
124 } else {
125 domain = new AdapterFactoryEditingDomain(null, new BasicCommandStack(), (ResourceSet) null);
126 resourceSet = domain.getResourceSet();
127 domain.getCommandStack().execute(new AddCommand(domain, resourceSet.getResources(), resource));
128 return domain;
129 }
130
131 } else if (notifier instanceof ResourceSet) {
132 return new AdapterFactoryEditingDomain(null, new BasicCommandStack(), (ResourceSet) notifier);
133 } else {
134 throw new EmfHelperException("Not supported argument type.");
135 }
136 }
137
138 /**
139 * Saves the EMF model (EObject or Resource) into the given file. An {@link XMIResourceFactoryImpl} will be
140 * registered if not already.
141 *
142 * Doesn't throw exception but logs an error if the save was unsuccessful.
143 *
144 * @param model Can be an {@link EObject} or a {@link Resource}.
145 * @param fileName
146 */
147 public static void saveModel(Notifier model, String fileName) {
148
149 Objects.requireNonNull(model);
150 Preconditions.checkArgument(fileName != null && !fileName.isEmpty(), "File name is null or empty.");
151
152 int extensionIndex = fileName.lastIndexOf('.');
153
154 Preconditions.checkState(extensionIndex > -1 && extensionIndex != fileName.length() - 1, "Bad file extension.");
155
156 String ext = fileName.substring(extensionIndex + 1);
157
158 registerExtensionForXmiSerializer(ext);
159
160 URI uri = URI.createFileURI(fileName);
161 Resource resource;
162
163 if (model instanceof ResourceSet) {
164 throw new EmfHelperException("Unsupported type: ResourceSet");
165 } else if (model instanceof Resource) {
166 resource = (Resource) model;
167 } else if (model instanceof EObject) {
168 EObject root = (EObject) model;
169 ResourceSet resSet = new ResourceSetImpl();
170 resource = resSet.createResource(uri);
171 resource.getContents().add(root);
172 } else {
173 throw new EmfHelperException("Unkown type: " + model.getClass());
174 }
175
176 resource.setURI(uri);
177 saveResource(resource);
178 }
179
180 private static void saveResource(Resource resource) {
181 try {
182 resource.save(Collections.emptyMap());
183 } catch (IOException e) {
184 logger.error(e);
185 }
186 }
187
188 /**
189 * Loads a model as a {@link Resource}. In headless mode, don't forget to call XYZPackage.eINSTANCE.
190 */
191 public static Resource loadModel(String fileName) throws IOException {
192 Preconditions.checkArgument(fileName != null && !fileName.isEmpty(), "File name is null or empty.");
193 int extensionIndex = fileName.lastIndexOf('.');
194 Preconditions.checkState(extensionIndex > -1 && extensionIndex != fileName.length() - 1, "Bad file extension.");
195
196 String ext = fileName.substring(extensionIndex + 1);
197 registerExtensionForXmiSerializer(ext);
198
199 ResourceSetImpl rSet = new ResourceSetImpl();
200 URI fileUri = URI.createFileURI(fileName);
201 Resource resource = rSet.createResource(fileUri);
202
203 resource.load(null);
204 return resource;
205 }
206
207 /**
208 * Retrieves the root EObject from a Resource or ResourceSet.
209 * <ul>
210 * <li>Returns null if there is no content.</li>
211 * <li>Returns the notifier itself if it is an EObject.</li>
212 * <li>Logs a warn if there are multiple roots.</li>
213 * </ul>
214 *
215 * @param notifier
216 * @return The root EObject or null.
217 */
218 public static EObject getRootEObject(Notifier notifier) {
219 if (notifier instanceof EObject) {
220 return (EObject) notifier;
221 } else if (notifier instanceof Resource) {
222 Resource resource = (Resource) notifier;
223 List<EObject> contents = resource.getContents();
224 if (contents.size() > 1) {
225 logger.warn("Resource has more than one root.");
226 }
227 if (contents.isEmpty()) {
228 return null;
229 } else {
230 return contents.get(0);
231 }
232 } else if (notifier instanceof ResourceSet) {
233 ResourceSet resourceSet = (ResourceSet) notifier;
234 List<Resource> resources = resourceSet.getResources();
235 if (resources.size() > 1) {
236 logger.warn("ResourceSet has more than one resources.");
237 }
238 if (resources.isEmpty()) {
239 return null;
240 } else {
241 return getRootEObject(resources.get(0));
242 }
243 } else {
244 throw new EmfHelperException("Unkown type: " + notifier.getClass());
245 }
246 }
247
248 /**
249 * Registers an {@link XMIResourceFactoryImpl} for the given extension.
250 * @param ext The extension as a String.
251 */
252 public static void registerExtensionForXmiSerializer(String ext) {
253 Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
254 Map<String, Object> m = reg.getExtensionToFactoryMap();
255 m.computeIfAbsent(ext, e -> new XMIResourceFactoryImpl());
256 }
257
258 /**
259 * Clones the given model. Either an {@link EObject}, {@link Resource} or {@link ResourceSet}.
260 * @param notifier The root container of the model.
261 * @return The cloned model.
262 */
263 public static Notifier clone(Notifier notifier) {
264 Copier copier = new Copier();
265 Notifier clonedModel = clone(notifier, copier, null);
266 copier.copyReferences();
267 return clonedModel;
268 }
269
270 private static Notifier clone(Notifier notifier, Copier copier, ResourceSet resourceSetToCloneTo) {
271 Objects.requireNonNull(copier);
272
273 if (notifier instanceof EObject) {
274 EObject eObject = (EObject) notifier;
275 return copier.copy(eObject);
276 } else if (notifier instanceof Resource) {
277 Resource resource = (Resource) notifier;
278 ResourceSet rSetTemp = resourceSetToCloneTo;
279 if (resourceSetToCloneTo == null) {
280 rSetTemp = new ResourceSetImpl();
281 }
282 Resource clonedResource = rSetTemp.createResource(URI.createFileURI("dummy.dummyext"));
283
284 for (EObject eObject : resource.getContents()) {
285 EObject clonedEObject = copier.copy(eObject);
286 clonedResource.getContents().add(clonedEObject);
287 }
288
289 return clonedResource;
290 } else if (notifier instanceof ResourceSet) {
291 ResourceSet resourceSet = (ResourceSet) notifier;
292 ResourceSetImpl clonedResourceSet = new ResourceSetImpl();
293
294 for (Resource resource : resourceSet.getResources()) {
295 clone(resource, copier, clonedResourceSet);
296 }
297
298 return clonedResourceSet;
299 } else {
300 throw new EmfHelperException("Not supported argument type.");
301 }
302 }
303
304 public static class ENamedElementComparator implements Comparator<ENamedElement> {
305 @Override
306 public int compare(ENamedElement eClass1, ENamedElement eClass2) {
307 return eClass1.getName().compareTo(eClass2.getName());
308 }
309 }
310
311 /**
312 * This class is used to store
313 * <ul>
314 * <li>{@link EClass}es,</li>
315 * <li>{@link EAttribute}s,</li>
316 * <li>{@link EReference}s,</li>
317 * <li>EAttributes by EClasses,</li>
318 * <li>EReferences by EClasses</li>
319 * </ul>
320 * for a given set of {@link EPackage}s.
321 *
322 */
323 public static class MetaModelElements {
324 public Set<EPackage> metaModelPackages;
325 public Set<EClass> classes;
326 public Set<EAttribute> attributes;
327 public Set<EReference> references;
328 public Map<EClass, Set<EAttribute>> attributesOfClass;
329 public Map<EClass, Set<EReference>> referencesOfClass;
330 }
331
332 /**
333 * Traverses the full metamodel on the given {@link EPackage}s and returns all the classes, attributes and
334 * references it contains.
335 *
336 * @param metaModelPackages
337 * The set of {@link EPackage}s.
338 * @return A {@link MetaModelElements} instance containing the metamodel elements.
339 */
340 public static MetaModelElements getAllMetaModelElements(Set<EPackage> metaModelPackages) {
341 return getMetaModelElements(metaModelPackages, true, true, true);
342 }
343
344 /**
345 * Return a {@link MetaModelElements} instance populated with its {@link MetaModelElements#classes}.
346 *
347 * @param metaModelPackages
348 * The set of {@link EPackage}s.
349 * @return AA {@link MetaModelElements} instance.
350 */
351 public static MetaModelElements getClasses(Set<EPackage> metaModelPackages) {
352 return getMetaModelElements(metaModelPackages, true, false, false);
353 }
354
355 /**
356 * Return a {@link MetaModelElements} instance populated with its {@link MetaModelElements#references} and
357 * {@link MetaModelElements#referencesOfClass}.
358 *
359 * @param metaModelPackages
360 * The set of {@link EPackage}s.
361 * @return AA {@link MetaModelElements} instance.
362 */
363 public static MetaModelElements getReferences(Set<EPackage> metaModelPackages) {
364 return getMetaModelElements(metaModelPackages, false, true, false);
365 }
366
367 /**
368 * Return a {@link MetaModelElements} instance populated with its {@link MetaModelElements#attributes} and
369 * {@link MetaModelElements#attributesOfClass}.
370 *
371 * @param metaModelPackages
372 * The set of {@link EPackage}s.
373 * @return AA {@link MetaModelElements} instance.
374 */
375 public static MetaModelElements getAttrbiutes(Set<EPackage> metaModelPackages) {
376 return getMetaModelElements(metaModelPackages, false, false, true);
377 }
378
379 private static MetaModelElements getMetaModelElements(Set<EPackage> metaModelPackages, boolean getClasses,
380 boolean getReferences, boolean getAttrbiutes) {
381
382 Comparator<ENamedElement> comparator = new ENamedElementComparator();
383
384 MetaModelElements result = new MetaModelElements();
385 result.metaModelPackages = metaModelPackages;
386 if (getClasses) {
387 result.classes = new TreeSet<EClass>(comparator);
388 }
389 if (getReferences) {
390 result.references = new HashSet<EReference>();
391 result.referencesOfClass = new HashMap<EClass, Set<EReference>>();
392 }
393 if (getAttrbiutes) {
394 result.attributes = new HashSet<EAttribute>();
395 result.attributesOfClass = new HashMap<EClass, Set<EAttribute>>();
396 }
397 for (EPackage ePackage : metaModelPackages) {
398 for (EClassifier eClassifier : ePackage.getEClassifiers()) {
399 if (eClassifier instanceof EClass) {
400 EClass eClass = ((EClass) eClassifier);
401 if (getClasses) {
402 result.classes.add(eClass);
403 }
404 if (getReferences) {
405 result.referencesOfClass.put(eClass, new TreeSet<EReference>(comparator));
406 for (EReference eReference : eClass.getEAllReferences()) {
407 result.references.add(eReference);
408 result.referencesOfClass.get(eClass).add(eReference);
409 }
410 }
411 if (getAttrbiutes) {
412 result.attributesOfClass.put(eClass, new TreeSet<EAttribute>(comparator));
413 for (EAttribute eAttribute : eClass.getEAllAttributes()) {
414 result.attributes.add(eAttribute);
415 result.attributesOfClass.get(eClass).add(eAttribute);
416 }
417 }
418 }
419 }
420 }
421 return result;
422 }
423
424}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/Hasher.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/Hasher.java
new file mode 100644
index 00000000..0c5d7eba
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/Hasher.java
@@ -0,0 +1,86 @@
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.util;
10
11import java.math.BigInteger;
12import java.security.MessageDigest;
13import java.security.NoSuchAlgorithmException;
14
15import org.eclipse.viatra.dse.api.DSEException;
16
17/**
18 * Utility class that encapsulates a {@link MessageDigest} instance to aid calculating hash values more easily, and to
19 * reuse a {@link MessageDigest} instance.
20 *
21 */
22public final class Hasher {
23 private MessageDigest md;
24
25 private static final int HEX = 16;
26
27 private Hasher(MessageDigest md) {
28 this.md = md;
29 }
30
31 /**
32 * Calculates and returns a hash value.
33 *
34 * @param data
35 * the data to be hashed in a {@link String}.
36 * @return the hash value in some {@link String} representation.
37 */
38 public String hash(String data) {
39 md.update(data.getBytes(), 0, data.length());
40 return new String(md.digest());
41 }
42
43 @SuppressWarnings("unused")
44 private String alternateHashBest(String data) {
45 md.update(data.getBytes(), 0, data.length());
46 return new String(md.digest());
47 }
48
49 @SuppressWarnings("unused")
50 private String alternateHashSecondBest(String data) {
51 md.update(data.getBytes(), 0, data.length());
52 return new BigInteger(1, md.digest()).toString(HEX);
53 }
54
55 @SuppressWarnings("unused")
56 private String alternateHashThirdBest(String data) {
57 md.update(data.getBytes(), 0, data.length());
58 byte[] array = md.digest();
59 StringBuilder sb = new StringBuilder();
60 for (int i = 0; i < array.length; i++) {
61 sb.append(Integer.toHexString((int) array[i]));
62 }
63 return sb.toString();
64 }
65
66 /**
67 * Returns a {@link Hasher} with an internal {@link MessageDigest} that is based on the protocol named
68 * {@code protocoll}.
69 *
70 * @param protocoll
71 * the name of the hash algorythm.
72 * @return the initialized {@link Hasher}
73 *
74 * @throws DSEException
75 * on initialization failure.
76 */
77 public static Hasher getHasher(String protocoll) {
78 try {
79 return new Hasher(MessageDigest.getInstance(protocoll));
80 } catch (NoSuchAlgorithmException e) {
81 throw new DSEException(e);
82 }
83 }
84
85 public static final String SHA1_PROTOCOLL = "SHA-1";
86}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.java
new file mode 100644
index 00000000..49af05d1
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.java
@@ -0,0 +1,63 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.util;
10
11import java.util.Comparator;
12import java.util.HashMap;
13import java.util.Map;
14import java.util.TreeMap;
15
16import org.eclipse.emf.ecore.EObject;
17
18import com.google.common.base.Functions;
19import com.google.common.collect.Ordering;
20
21/**
22 *
23 * This custom {@link TreeMap} implementation enables to store {@link EObject}-{@link String} pairs sorted by values
24 * (strings). It works as expected if the map is modified in any way, hence the map will still be sorted by values on
25 * the new set of entries.
26 *
27 * It is allowed to have two entries with the same EObject key (and also with same values).
28 *
29 * The short coming of the class is that EObjects are compared to each other by their
30 * {@link System#identityHashCode(Object)}, which may lead to unexpected errors.
31 *
32 * @author Andras Szabolcs Nagy
33 *
34 */
35public class ValueComparableEObjectStringMap extends TreeMap<EObject, String> {
36
37 private static final class EObjectComparator implements Comparator<EObject> {
38 @Override
39 public int compare(EObject o1, EObject o2) {
40 return Integer.valueOf(System.identityHashCode(o1)).compareTo(Integer.valueOf(System.identityHashCode(o2)));
41 }
42 }
43
44 private final Map<EObject, String> innerMap;
45
46 public ValueComparableEObjectStringMap() {
47 this(new HashMap<EObject, String>());
48 }
49
50 private ValueComparableEObjectStringMap(Map<EObject, String> innerMap) {
51 super(Ordering.natural().onResultOf(Functions.forMap(innerMap)).compound(new EObjectComparator()));
52 this.innerMap = innerMap;
53 }
54
55 @Override
56 public String put(EObject keyEObject, String stringValue) {
57 if (innerMap.containsKey(keyEObject)) {
58 remove(keyEObject);
59 }
60 innerMap.put(keyEObject, stringValue);
61 return super.put(keyEObject, stringValue);
62 }
63}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.java
new file mode 100644
index 00000000..bb8000d5
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.java
@@ -0,0 +1,56 @@
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.visualizer;
10
11public class DesignSpaceVisualizerOptions {
12
13 public boolean showExplorationTrace = true;
14 public boolean showStateCodes = true;
15 public boolean showTransitionCodes = true;
16
17 public DesignSpaceVisualizerOptions withOutExploraionTrace() {
18 showExplorationTrace = false;
19 return this;
20 }
21
22 public DesignSpaceVisualizerOptions withOutstateCodes() {
23 showStateCodes = false;
24 return this;
25 }
26
27 public DesignSpaceVisualizerOptions withOutTransitionCodes() {
28 showTransitionCodes = false;
29 return this;
30 }
31
32 public boolean isShowExplorationTrace() {
33 return showExplorationTrace;
34 }
35
36 public void setShowExplorationTrace(boolean showExplorationTrace) {
37 this.showExplorationTrace = showExplorationTrace;
38 }
39
40 public boolean isShowStateCodes() {
41 return showStateCodes;
42 }
43
44 public void setShowStateCodes(boolean showStateCodes) {
45 this.showStateCodes = showStateCodes;
46 }
47
48 public boolean isShowTransitionCodes() {
49 return showTransitionCodes;
50 }
51
52 public void setShowTransitionCodes(boolean showTransitionCodes) {
53 this.showTransitionCodes = showTransitionCodes;
54 }
55
56}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.java
new file mode 100644
index 00000000..da598b91
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.java
@@ -0,0 +1,39 @@
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.visualizer;
10
11import org.eclipse.viatra.dse.api.DesignSpaceExplorer;
12import org.eclipse.viatra.dse.base.ThreadContext;
13
14/**
15 *
16 * An implementation of this interface is notified about the traversal of the design space from every traversing thread,
17 * if registered to the {@link DesignSpaceExplorer}. Its purpose is to able to visualize the design space (a directed
18 * graph with IDs of the nodes and transitions) and to able to visualize the order of the exploration (the trace of a
19 * thread).
20 *
21 * @author Andras Szabolcs Nagy
22 *
23 */
24public interface IDesignSpaceVisualizer extends IExploreEventHandler {
25
26 /**
27 * Initializes the instance with a starting thread's context. Can be called multiple times and concurrently.
28 *
29 * @see DesignSpaceVisualizerOptions
30 * @param context
31 */
32 void init(ThreadContext context);
33
34 /**
35 * Saves the captured data.
36 */
37 void save();
38
39}
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IExploreEventHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IExploreEventHandler.java
new file mode 100644
index 00000000..9f902f31
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IExploreEventHandler.java
@@ -0,0 +1,40 @@
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.visualizer;
10
11import org.eclipse.viatra.dse.base.DesignSpaceManager;
12
13/**
14 * An implementation of this interface is notified about every move in the design space (firing a rule activation or
15 * undoing it) of a single thread, if registered to the corresponding {@link DesignSpaceManager}. Its methods are called
16 * synchronously, therefore the implementation can have an impact on the performance. Also note, if the same instance is
17 * registered to multiple threads ({@link DesignSpaceManager}), it has to be thread safe.
18 *
19 * @author Andras Szabolcs Nagy
20 *
21 */
22public interface IExploreEventHandler {
23
24 /**
25 * Called by the {@link DesignSpaceManager}, after a rule activation (transition) is fired. Multiple calls with the
26 * same transition can occur.
27 *
28 * @param transition The fired transition.
29 */
30 void transitionFired(Object transition);
31
32 /**
33 * Called by the {@link DesignSpaceManager}, after undoing the previously fired rule activation (transition).
34 * Multiple calls with the same transition can occur.
35 *
36 * @param transition The undone transition.
37 */
38 void undo(Object transition);
39
40}