diff options
author | Kristóf Marussy <marussy@mit.bme.hu> | 2020-11-02 02:02:40 +0100 |
---|---|---|
committer | Kristóf Marussy <marussy@mit.bme.hu> | 2020-11-02 02:02:40 +0100 |
commit | f06427cd7375551582461f91b3458339a8227f9b (patch) | |
tree | 97bc6ec85f4c384e5080a6611b492caf460b6ce9 /Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend | |
parent | Must unit propagation (diff) | |
download | VIATRA-Generator-f06427cd7375551582461f91b3458339a8227f9b.tar.gz VIATRA-Generator-f06427cd7375551582461f91b3458339a8227f9b.tar.zst VIATRA-Generator-f06427cd7375551582461f91b3458339a8227f9b.zip |
Optimizing generator with linear objective functions
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 | 112 |
1 files changed, 105 insertions, 7 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 index c0b5008c..e00f76ff 100644 --- 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 | |||
@@ -1,5 +1,9 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Bounds | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.DirectionalThresholdObjective | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.IObjectiveBoundsProvider | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold | ||
3 | import java.util.HashMap | 7 | import java.util.HashMap |
4 | import java.util.Map | 8 | import java.util.Map |
5 | import org.eclipse.viatra.dse.api.DSEException | 9 | import org.eclipse.viatra.dse.api.DSEException |
@@ -18,24 +22,32 @@ import org.eclipse.xtend.lib.annotations.Accessors | |||
18 | * Will also automatically fill any missing numerical values in the saved solutions | 22 | * Will also automatically fill any missing numerical values in the saved solutions |
19 | * using the supplied {@link NumericSolver}. | 23 | * using the supplied {@link NumericSolver}. |
20 | */ | 24 | */ |
21 | class ViatraReasonerSolutionSaver implements ISolutionSaver { | 25 | class ViatraReasonerSolutionSaver implements ISolutionSaver, IObjectiveBoundsProvider { |
26 | static val TOLERANCE = 1e-10 | ||
27 | |||
22 | @Accessors val SolutionCopier solutionCopier | 28 | @Accessors val SolutionCopier solutionCopier |
23 | val NumericSolver numericSolver | ||
24 | @Accessors val DiversityChecker diversityChecker | 29 | @Accessors val DiversityChecker diversityChecker |
30 | val IObjective[][] leveledExtremalObjectives | ||
25 | val boolean hasExtremalObjectives | 31 | val boolean hasExtremalObjectives |
26 | val int numberOfRequiredSolutions | 32 | val int numberOfRequiredSolutions |
27 | val ObjectiveComparatorHelper comparatorHelper | 33 | val ObjectiveComparatorHelper comparatorHelper |
28 | val Map<SolutionTrajectory, Fitness> trajectories = new HashMap | 34 | val Map<SolutionTrajectory, Fitness> trajectories = new HashMap |
29 | 35 | ||
30 | @Accessors(PUBLIC_SETTER) var Map<Object, Solution> solutionsCollection | 36 | @Accessors var NumericSolver numericSolver |
37 | @Accessors var Map<Object, Solution> solutionsCollection | ||
31 | 38 | ||
32 | new(IObjective[][] leveledExtremalObjectives, int numberOfRequiredSolutions, DiversityChecker diversityChecker, NumericSolver numericSolver) { | 39 | new(IObjective[][] leveledExtremalObjectives, int numberOfRequiredSolutions, DiversityChecker diversityChecker) { |
33 | this.diversityChecker = diversityChecker | 40 | this.diversityChecker = diversityChecker |
34 | comparatorHelper = new ObjectiveComparatorHelper(leveledExtremalObjectives) | 41 | comparatorHelper = new ObjectiveComparatorHelper(leveledExtremalObjectives) |
42 | this.leveledExtremalObjectives = leveledExtremalObjectives | ||
35 | hasExtremalObjectives = leveledExtremalObjectives.exists[!empty] | 43 | hasExtremalObjectives = leveledExtremalObjectives.exists[!empty] |
36 | this.numberOfRequiredSolutions = numberOfRequiredSolutions | 44 | this.numberOfRequiredSolutions = numberOfRequiredSolutions |
37 | this.solutionCopier = new SolutionCopier(numericSolver) | 45 | this.solutionCopier = new SolutionCopier |
46 | } | ||
47 | |||
48 | def setNumericSolver(NumericSolver numericSolver) { | ||
38 | this.numericSolver = numericSolver | 49 | this.numericSolver = numericSolver |
50 | solutionCopier.numericSolver = numericSolver | ||
39 | } | 51 | } |
40 | 52 | ||
41 | override saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | 53 | override saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { |
@@ -51,6 +63,7 @@ class ViatraReasonerSolutionSaver implements ISolutionSaver { | |||
51 | if (!shouldSaveSolution(fitness, context)) { | 63 | if (!shouldSaveSolution(fitness, context)) { |
52 | return false | 64 | return false |
53 | } | 65 | } |
66 | println("Found: " + fitness) | ||
54 | val dominatedTrajectories = newArrayList | 67 | val dominatedTrajectories = newArrayList |
55 | for (entry : trajectories.entrySet) { | 68 | for (entry : trajectories.entrySet) { |
56 | val isLastFitnessBetter = comparatorHelper.compare(fitness, entry.value) | 69 | val isLastFitnessBetter = comparatorHelper.compare(fitness, entry.value) |
@@ -99,7 +112,7 @@ class ViatraReasonerSolutionSaver implements ISolutionSaver { | |||
99 | } | 112 | } |
100 | 113 | ||
101 | private def shouldSaveSolution(Fitness fitness, ThreadContext context) { | 114 | private def shouldSaveSolution(Fitness fitness, ThreadContext context) { |
102 | return fitness.satisifiesHardObjectives && numericSolver.currentSatisfiable | 115 | fitness.satisifiesHardObjectives && (numericSolver === null || numericSolver.currentSatisfiable) |
103 | } | 116 | } |
104 | 117 | ||
105 | private def basicSaveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory, | 118 | private def basicSaveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory, |
@@ -145,8 +158,93 @@ class ViatraReasonerSolutionSaver implements ISolutionSaver { | |||
145 | } | 158 | } |
146 | solutionsCollection.size < numberOfRequiredSolutions | 159 | solutionsCollection.size < numberOfRequiredSolutions |
147 | } | 160 | } |
148 | 161 | ||
149 | def getTotalCopierRuntime() { | 162 | def getTotalCopierRuntime() { |
150 | solutionCopier.totalCopierRuntime | 163 | solutionCopier.totalCopierRuntime |
151 | } | 164 | } |
165 | |||
166 | override computeRequiredBounds(IObjective objective, Bounds bounds) { | ||
167 | if (!hasExtremalObjectives) { | ||
168 | return | ||
169 | } | ||
170 | if (objective instanceof DirectionalThresholdObjective) { | ||
171 | switch (threshold : objective.threshold) { | ||
172 | case ObjectiveThreshold.NO_THRESHOLD: { | ||
173 | // No threshold to set. | ||
174 | } | ||
175 | ObjectiveThreshold.Exclusive: { | ||
176 | switch (kind : objective.kind) { | ||
177 | case HIGHER_IS_BETTER: | ||
178 | bounds.tightenLowerBound(Math.floor(threshold.threshold + 1) as int) | ||
179 | case LOWER_IS_BETTER: | ||
180 | bounds.tightenUpperBound(Math.ceil(threshold.threshold - 1) as int) | ||
181 | default: | ||
182 | throw new IllegalArgumentException("Unknown objective kind" + kind) | ||
183 | } | ||
184 | if (threshold.clampToThreshold) { | ||
185 | return | ||
186 | } | ||
187 | } | ||
188 | ObjectiveThreshold.Inclusive: { | ||
189 | switch (kind : objective.kind) { | ||
190 | case HIGHER_IS_BETTER: | ||
191 | bounds.tightenLowerBound(Math.ceil(threshold.threshold) as int) | ||
192 | case LOWER_IS_BETTER: | ||
193 | bounds.tightenUpperBound(Math.floor(threshold.threshold) as int) | ||
194 | default: | ||
195 | throw new IllegalArgumentException("Unknown objective kind" + kind) | ||
196 | } | ||
197 | if (threshold.clampToThreshold) { | ||
198 | return | ||
199 | } | ||
200 | } | ||
201 | default: | ||
202 | throw new IllegalArgumentException("Unknown threshold: " + threshold) | ||
203 | } | ||
204 | for (level : leveledExtremalObjectives) { | ||
205 | switch (level.size) { | ||
206 | case 0: { | ||
207 | // Nothing to do, wait for the next level. | ||
208 | } | ||
209 | case 1: { | ||
210 | val primaryObjective = level.get(0) | ||
211 | if (primaryObjective != objective) { | ||
212 | // There are no worst-case bounds for secondary objectives. | ||
213 | return | ||
214 | } | ||
215 | } | ||
216 | default: | ||
217 | // There are no worst-case bounds for Pareto front calculation. | ||
218 | return | ||
219 | } | ||
220 | } | ||
221 | val fitnessIterator = trajectories.values.iterator | ||
222 | if (!fitnessIterator.hasNext) { | ||
223 | return | ||
224 | } | ||
225 | val fitness = fitnessIterator.next.get(objective.name) | ||
226 | while (fitnessIterator.hasNext) { | ||
227 | val otherFitness = fitnessIterator.next.get(objective.name) | ||
228 | if (Math.abs(fitness - otherFitness) > TOLERANCE) { | ||
229 | throw new IllegalStateException("Inconsistent fitness: " + objective.name) | ||
230 | } | ||
231 | } | ||
232 | switch (kind : objective.kind) { | ||
233 | case HIGHER_IS_BETTER: | ||
234 | if (needsMoreSolutionsWithSameFitness) { | ||
235 | bounds.tightenLowerBound(Math.floor(fitness) as int) | ||
236 | } else { | ||
237 | bounds.tightenLowerBound(Math.floor(fitness + 1) as int) | ||
238 | } | ||
239 | case LOWER_IS_BETTER: | ||
240 | if (needsMoreSolutionsWithSameFitness) { | ||
241 | bounds.tightenUpperBound(Math.ceil(fitness) as int) | ||
242 | } else { | ||
243 | bounds.tightenUpperBound(Math.ceil(fitness - 1) as int) | ||
244 | } | ||
245 | default: | ||
246 | throw new IllegalArgumentException("Unknown objective kind" + kind) | ||
247 | } | ||
248 | } | ||
249 | } | ||
152 | } | 250 | } |