diff options
Diffstat (limited to 'Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend')
-rw-r--r-- | Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend new file mode 100644 index 00000000..5877778e --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend | |||
@@ -0,0 +1,99 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import java.util.HashMap | ||
4 | import java.util.Map | ||
5 | import org.eclipse.viatra.dse.api.DSEException | ||
6 | import org.eclipse.viatra.dse.api.Solution | ||
7 | import org.eclipse.viatra.dse.api.SolutionTrajectory | ||
8 | import org.eclipse.viatra.dse.base.ThreadContext | ||
9 | import org.eclipse.viatra.dse.objectives.Fitness | ||
10 | import org.eclipse.viatra.dse.objectives.IObjective | ||
11 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper | ||
12 | import org.eclipse.viatra.dse.solutionstore.SolutionStore.ISolutionSaver | ||
13 | import org.eclipse.xtend.lib.annotations.Accessors | ||
14 | |||
15 | /** | ||
16 | * Based on {@link org.eclipse.viatra.dse.solutionstore.SolutionStore.BestSolutionSaver}. | ||
17 | */ | ||
18 | class ViatraReasonerSolutionSaver implements ISolutionSaver { | ||
19 | @Accessors val solutionCopier = new SolutionCopier | ||
20 | val boolean hasExtremalObjectives | ||
21 | val ObjectiveComparatorHelper comparatorHelper | ||
22 | val Map<SolutionTrajectory, Fitness> trajectories = new HashMap | ||
23 | |||
24 | @Accessors(PUBLIC_SETTER) var Map<Object, Solution> solutionsCollection | ||
25 | |||
26 | new(IObjective[][] leveledExtremalObjectives) { | ||
27 | comparatorHelper = new ObjectiveComparatorHelper(leveledExtremalObjectives) | ||
28 | hasExtremalObjectives = leveledExtremalObjectives.exists[!empty] | ||
29 | } | ||
30 | |||
31 | override saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
32 | if (hasExtremalObjectives) { | ||
33 | saveBestSolutionOnly(context, id, solutionTrajectory) | ||
34 | } else { | ||
35 | basicSaveSolution(context, id, solutionTrajectory) | ||
36 | } | ||
37 | } | ||
38 | |||
39 | private def saveBestSolutionOnly(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
40 | val fitness = context.lastFitness | ||
41 | val dominatedTrajectories = newArrayList | ||
42 | for (entry : trajectories.entrySet) { | ||
43 | val isLastFitnessBetter = comparatorHelper.compare(fitness, entry.value) | ||
44 | if (isLastFitnessBetter < 0) { | ||
45 | // Found a trajectory that dominates the current one, no need to save | ||
46 | return false | ||
47 | } | ||
48 | if (isLastFitnessBetter > 0) { | ||
49 | dominatedTrajectories += entry.key | ||
50 | } | ||
51 | } | ||
52 | // We must save the new trajectory before removing dominated trajectories | ||
53 | // to avoid removing the current solution when it is reachable only via dominated trajectories. | ||
54 | val solutionSaved = basicSaveSolution(context, id, solutionTrajectory) | ||
55 | for (dominatedTrajectory : dominatedTrajectories) { | ||
56 | trajectories -= dominatedTrajectory | ||
57 | val dominatedSolution = dominatedTrajectory.solution | ||
58 | if (!dominatedSolution.trajectories.remove(dominatedTrajectory)) { | ||
59 | throw new DSEException( | ||
60 | "Dominated solution is not reachable from dominated trajectory. This should never happen!") | ||
61 | } | ||
62 | if (dominatedSolution.trajectories.empty) { | ||
63 | val dominatedSolutionId = dominatedSolution.stateCode | ||
64 | solutionCopier.markAsObsolete(dominatedSolutionId) | ||
65 | solutionsCollection -= dominatedSolutionId | ||
66 | } | ||
67 | } | ||
68 | solutionSaved | ||
69 | } | ||
70 | |||
71 | private def basicSaveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
72 | val fitness = context.lastFitness | ||
73 | var boolean solutionSaved = false | ||
74 | var dseSolution = solutionsCollection.get(id) | ||
75 | if (dseSolution === null) { | ||
76 | solutionCopier.copySolution(context, id) | ||
77 | dseSolution = new Solution(id, solutionTrajectory) | ||
78 | solutionsCollection.put(id, dseSolution) | ||
79 | solutionSaved = true | ||
80 | } else { | ||
81 | solutionSaved = dseSolution.trajectories.add(solutionTrajectory) | ||
82 | } | ||
83 | if (solutionSaved) { | ||
84 | solutionTrajectory.solution = dseSolution | ||
85 | trajectories.put(solutionTrajectory, fitness) | ||
86 | } | ||
87 | solutionSaved | ||
88 | } | ||
89 | |||
90 | def isFitnessDominated(Fitness fitness) { | ||
91 | for (existingFitness : trajectories.values) { | ||
92 | val isNewFitnessBetter = comparatorHelper.compare(fitness, existingFitness) | ||
93 | if (isNewFitnessBetter < 0) { | ||
94 | return true | ||
95 | } | ||
96 | } | ||
97 | false | ||
98 | } | ||
99 | } | ||