aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java
diff options
context:
space:
mode:
Diffstat (limited to 'Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java')
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java311
1 files changed, 311 insertions, 0 deletions
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}