aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend
diff options
context:
space:
mode:
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.xtend142
1 files changed, 142 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..74500cc2
--- /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,142 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2
3import java.util.HashMap
4import java.util.Map
5import org.eclipse.viatra.dse.api.DSEException
6import org.eclipse.viatra.dse.api.Solution
7import org.eclipse.viatra.dse.api.SolutionTrajectory
8import org.eclipse.viatra.dse.base.ThreadContext
9import org.eclipse.viatra.dse.objectives.Fitness
10import org.eclipse.viatra.dse.objectives.IObjective
11import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper
12import org.eclipse.viatra.dse.solutionstore.SolutionStore.ISolutionSaver
13import org.eclipse.xtend.lib.annotations.Accessors
14
15/**
16 * Based on {@link SolutionStore.BestSolutionSaver}.
17 */
18class ViatraReasonerSolutionSaver implements ISolutionSaver {
19 @Accessors val solutionCopier = new SolutionCopier
20 @Accessors val DiversityChecker diversityChecker
21 val boolean hasExtremalObjectives
22 val int numberOfRequiredSolutions
23 val ObjectiveComparatorHelper comparatorHelper
24 val Map<SolutionTrajectory, Fitness> trajectories = new HashMap
25
26 @Accessors(PUBLIC_SETTER) var Map<Object, Solution> solutionsCollection
27
28 new(IObjective[][] leveledExtremalObjectives, int numberOfRequiredSolutions, DiversityChecker diversityChecker) {
29 this.diversityChecker = diversityChecker
30 comparatorHelper = new ObjectiveComparatorHelper(leveledExtremalObjectives)
31 hasExtremalObjectives = leveledExtremalObjectives.exists[!empty]
32 this.numberOfRequiredSolutions = numberOfRequiredSolutions
33 }
34
35 override saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) {
36 if (hasExtremalObjectives) {
37 saveBestSolutionOnly(context, id, solutionTrajectory)
38 } else {
39 saveAnyDiverseSolution(context, id, solutionTrajectory)
40 }
41 }
42
43 private def saveBestSolutionOnly(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) {
44 val fitness = context.lastFitness
45 if (!shouldSaveSolution(fitness, context)) {
46 return false
47 }
48 val dominatedTrajectories = newArrayList
49 for (entry : trajectories.entrySet) {
50 val isLastFitnessBetter = comparatorHelper.compare(fitness, entry.value)
51 if (isLastFitnessBetter < 0) {
52 // Found a trajectory that dominates the current one, no need to save
53 return false
54 }
55 if (isLastFitnessBetter > 0) {
56 dominatedTrajectories += entry.key
57 }
58 }
59 if (dominatedTrajectories.size == 0 && !needsMoreSolutionsWithSameFitness) {
60 return false
61 }
62 if (!diversityChecker.newSolution(context, id, dominatedTrajectories.map[solution.stateCode])) {
63 return false
64 }
65 // We must save the new trajectory before removing dominated trajectories
66 // to avoid removing the current solution when it is reachable only via dominated trajectories.
67 val solutionSaved = basicSaveSolution(context, id, solutionTrajectory, fitness)
68 for (dominatedTrajectory : dominatedTrajectories) {
69 trajectories -= dominatedTrajectory
70 val dominatedSolution = dominatedTrajectory.solution
71 if (!dominatedSolution.trajectories.remove(dominatedTrajectory)) {
72 throw new DSEException(
73 "Dominated solution is not reachable from dominated trajectory. This should never happen!")
74 }
75 if (dominatedSolution.trajectories.empty) {
76 val dominatedSolutionId = dominatedSolution.stateCode
77 solutionCopier.markAsObsolete(dominatedSolutionId)
78 solutionsCollection -= dominatedSolutionId
79 }
80 }
81 solutionSaved
82 }
83
84 private def saveAnyDiverseSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) {
85 val fitness = context.lastFitness
86 if (!shouldSaveSolution(fitness, context)) {
87 return false
88 }
89 if (!diversityChecker.newSolution(context, id, emptyList)) {
90 return false
91 }
92 basicSaveSolution(context, id, solutionTrajectory, fitness)
93 }
94
95 private def shouldSaveSolution(Fitness fitness, ThreadContext context) {
96 return fitness.satisifiesHardObjectives
97 }
98
99 private def basicSaveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory,
100 Fitness fitness) {
101 var boolean solutionSaved = false
102 var dseSolution = solutionsCollection.get(id)
103 if (dseSolution === null) {
104 solutionCopier.copySolution(context, id)
105 dseSolution = new Solution(id, solutionTrajectory)
106 solutionsCollection.put(id, dseSolution)
107 solutionSaved = true
108 } else {
109 solutionSaved = dseSolution.trajectories.add(solutionTrajectory)
110 }
111 if (solutionSaved) {
112 solutionTrajectory.solution = dseSolution
113 trajectories.put(solutionTrajectory, fitness)
114 }
115 solutionSaved
116 }
117
118 def fitnessMayBeSaved(Fitness fitness) {
119 if (!hasExtremalObjectives) {
120 return true
121 }
122 var boolean mayDominate
123 for (existingFitness : trajectories.values) {
124 val isNewFitnessBetter = comparatorHelper.compare(fitness, existingFitness)
125 if (isNewFitnessBetter < 0) {
126 return false
127 }
128 if (isNewFitnessBetter > 0) {
129 mayDominate = true
130 }
131 }
132 mayDominate || needsMoreSolutionsWithSameFitness
133 }
134
135 private def boolean needsMoreSolutionsWithSameFitness() {
136 if (solutionsCollection === null) {
137 // The solutions collection will only be initialized upon saving the first solution.
138 return true
139 }
140 solutionsCollection.size < numberOfRequiredSolutions
141 }
142}