diff options
author | 20001LastOrder <boqi.chen@mail.mcgill.ca> | 2020-11-04 01:16:22 -0500 |
---|---|---|
committer | 20001LastOrder <boqi.chen@mail.mcgill.ca> | 2020-11-04 01:16:22 -0500 |
commit | 93243cb3faf1ccd733081fcf380559ac03c9ad35 (patch) | |
tree | 421f9f174eb77c387b5acaa05f01e64a62cab3a7 /Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java | |
parent | add realistic solver (diff) | |
parent | Optimizing generator with linear objective functions (diff) | |
download | VIATRA-Generator-93243cb3faf1ccd733081fcf380559ac03c9ad35.tar.gz VIATRA-Generator-93243cb3faf1ccd733081fcf380559ac03c9ad35.tar.zst VIATRA-Generator-93243cb3faf1ccd733081fcf380559ac03c9ad35.zip |
merge with current master, comment numerical solver related logging
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.java | 311 |
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 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.solutionstore; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collection; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.List; | ||
15 | import java.util.Map; | ||
16 | import java.util.Map.Entry; | ||
17 | import java.util.concurrent.atomic.AtomicBoolean; | ||
18 | import java.util.concurrent.atomic.AtomicInteger; | ||
19 | |||
20 | import org.apache.log4j.Level; | ||
21 | import org.apache.log4j.Logger; | ||
22 | import org.eclipse.emf.common.notify.Notifier; | ||
23 | import org.eclipse.viatra.dse.api.DSEException; | ||
24 | import org.eclipse.viatra.dse.api.Solution; | ||
25 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
26 | import org.eclipse.viatra.dse.base.DesignSpaceManager; | ||
27 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
28 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
29 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | ||
30 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
31 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
32 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
33 | |||
34 | /** | ||
35 | * | ||
36 | * @author Andras Szabolcs Nagy | ||
37 | * | ||
38 | */ | ||
39 | public 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 | } | ||