diff options
author | Kristóf Marussy <kris7topher@gmail.com> | 2019-04-09 23:11:20 +0200 |
---|---|---|
committer | Kristóf Marussy <kris7topher@gmail.com> | 2019-04-09 23:11:20 +0200 |
commit | ec11efe9e0c3863be32e740b28e124499ad653f9 (patch) | |
tree | 7e4c5b1c6d501aa3ac53e66546a1625f91d11572 /Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src | |
parent | Fix solution store for optimization (diff) | |
download | VIATRA-Generator-ec11efe9e0c3863be32e740b28e124499ad653f9.tar.gz VIATRA-Generator-ec11efe9e0c3863be32e740b28e124499ad653f9.tar.zst VIATRA-Generator-ec11efe9e0c3863be32e740b28e124499ad653f9.zip |
Make diversity checking work with optimization
Proof of concept implementation, mixing diversity checking and optimization
may not be very effective in practice
Diffstat (limited to 'Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src')
5 files changed, 216 insertions, 146 deletions
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend index c022beac..edcca676 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend | |||
@@ -19,6 +19,7 @@ import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.par | |||
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.IdentifierBasedStateCoderFactory | 19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.IdentifierBasedStateCoderFactory |
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedStateCoderFactory | 20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedStateCoderFactory |
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.BestFirstStrategyForModelGeneration | 21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.BestFirstStrategyForModelGeneration |
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.DiversityChecker | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.LoggerSolutionFoundHandler | 23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.LoggerSolutionFoundHandler |
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ModelGenerationCompositeObjective | 24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ModelGenerationCompositeObjective |
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PartialModelAsLogicInterpretation | 25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PartialModelAsLogicInterpretation |
@@ -122,7 +123,9 @@ class ViatraReasoner extends LogicReasoner { | |||
122 | new SolutionStore() | 123 | new SolutionStore() |
123 | } | 124 | } |
124 | solutionStore.registerSolutionFoundHandler(new LoggerSolutionFoundHandler(viatraConfig)) | 125 | solutionStore.registerSolutionFoundHandler(new LoggerSolutionFoundHandler(viatraConfig)) |
125 | val solutionSaver = new ViatraReasonerSolutionSaver(newArrayList(extremalObjectives), numberOfRequiredSolutions) | 126 | val diversityChecker = DiversityChecker.of(viatraConfig.diversityRequirement) |
127 | val solutionSaver = new ViatraReasonerSolutionSaver(newArrayList(extremalObjectives), numberOfRequiredSolutions, | ||
128 | diversityChecker) | ||
126 | val solutionCopier = solutionSaver.solutionCopier | 129 | val solutionCopier = solutionSaver.solutionCopier |
127 | solutionStore.withSolutionSaver(solutionSaver) | 130 | solutionStore.withSolutionSaver(solutionSaver) |
128 | dse.solutionStore = solutionStore | 131 | dse.solutionStore = solutionStore |
@@ -197,14 +200,14 @@ class ViatraReasoner extends LogicReasoner { | |||
197 | it.name = "SolutionCopyTime" | 200 | it.name = "SolutionCopyTime" |
198 | it.value = (solutionCopier.getTotalCopierRuntime / 1000000) as int | 201 | it.value = (solutionCopier.getTotalCopierRuntime / 1000000) as int |
199 | ] | 202 | ] |
200 | if (strategy.solutionStoreWithDiversityDescriptor.isActive) { | 203 | if (diversityChecker.isActive) { |
201 | it.entries += createIntStatisticEntry => [ | 204 | it.entries += createIntStatisticEntry => [ |
202 | it.name = "SolutionDiversityCheckTime" | 205 | it.name = "SolutionDiversityCheckTime" |
203 | it.value = (strategy.solutionStoreWithDiversityDescriptor.sumRuntime / 1000000) as int | 206 | it.value = (diversityChecker.totalRuntime / 1000000) as int |
204 | ] | 207 | ] |
205 | it.entries += createRealStatisticEntry => [ | 208 | it.entries += createRealStatisticEntry => [ |
206 | it.name = "SolutionDiversitySuccessRate" | 209 | it.name = "SolutionDiversitySuccessRate" |
207 | it.value = strategy.solutionStoreWithDiversityDescriptor.successRate | 210 | it.value = diversityChecker.successRate |
208 | ] | 211 | ] |
209 | } | 212 | } |
210 | ] | 213 | ] |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java index 1234d54b..6ff867d7 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java | |||
@@ -75,7 +75,6 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
75 | // Running | 75 | // Running |
76 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; | 76 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; |
77 | private SolutionStore solutionStore; | 77 | private SolutionStore solutionStore; |
78 | private SolutionStoreWithDiversityDescriptor solutionStoreWithDiversityDescriptor; | ||
79 | private volatile boolean isInterrupted = false; | 78 | private volatile boolean isInterrupted = false; |
80 | private ModelResult modelResultByInternalSolver = null; | 79 | private ModelResult modelResultByInternalSolver = null; |
81 | private Random random = new Random(); | 80 | private Random random = new Random(); |
@@ -96,9 +95,6 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
96 | this.method = method; | 95 | this.method = method; |
97 | } | 96 | } |
98 | 97 | ||
99 | public SolutionStoreWithDiversityDescriptor getSolutionStoreWithDiversityDescriptor() { | ||
100 | return solutionStoreWithDiversityDescriptor; | ||
101 | } | ||
102 | public int getNumberOfStatecoderFail() { | 98 | public int getNumberOfStatecoderFail() { |
103 | return numberOfStatecoderFail; | 99 | return numberOfStatecoderFail; |
104 | } | 100 | } |
@@ -117,8 +113,6 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
117 | matchers.add(matcher); | 113 | matchers.add(matcher); |
118 | } | 114 | } |
119 | 115 | ||
120 | this.solutionStoreWithDiversityDescriptor = new SolutionStoreWithDiversityDescriptor(configuration.diversityRequirement); | ||
121 | |||
122 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | 116 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); |
123 | this.comparator = new Comparator<TrajectoryWithFitness>() { | 117 | this.comparator = new Comparator<TrajectoryWithFitness>() { |
124 | @Override | 118 | @Override |
@@ -142,7 +136,7 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
142 | } | 136 | } |
143 | 137 | ||
144 | final Fitness firstfitness = context.calculateFitness(); | 138 | final Fitness firstfitness = context.calculateFitness(); |
145 | checkForSolution(firstfitness); | 139 | solutionStore.newSolution(context); |
146 | 140 | ||
147 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | 141 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); |
148 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); | 142 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); |
@@ -215,7 +209,7 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
215 | context.backtrack(); | 209 | context.backtrack(); |
216 | } else { | 210 | } else { |
217 | final Fitness nextFitness = context.calculateFitness(); | 211 | final Fitness nextFitness = context.calculateFitness(); |
218 | checkForSolution(nextFitness); | 212 | solutionStore.newSolution(context); |
219 | if (context.getDepth() > configuration.searchSpaceConstraints.maxDepth) { | 213 | if (context.getDepth() > configuration.searchSpaceConstraints.maxDepth) { |
220 | logger.debug("Reached max depth."); | 214 | logger.debug("Reached max depth."); |
221 | context.backtrack(); | 215 | context.backtrack(); |
@@ -264,15 +258,6 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
264 | return activationIds; | 258 | return activationIds; |
265 | } | 259 | } |
266 | 260 | ||
267 | private void checkForSolution(final Fitness fitness) { | ||
268 | if (fitness.isSatisifiesHardObjectives()) { | ||
269 | if (solutionStoreWithDiversityDescriptor.isDifferent(context)) { | ||
270 | solutionStoreWithDiversityDescriptor.newSolution(context); | ||
271 | solutionStore.newSolution(context); | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | |||
276 | @Override | 261 | @Override |
277 | public void interruptStrategy() { | 262 | public void interruptStrategy() { |
278 | isInterrupted = true; | 263 | isInterrupted = true; |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend new file mode 100644 index 00000000..fb1b2066 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend | |||
@@ -0,0 +1,184 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import com.google.common.collect.HashMultiset | ||
4 | import com.google.common.collect.ImmutableSet | ||
5 | import com.google.common.collect.Multiset | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodWithTraces | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.DiversityDescriptor | ||
11 | import java.util.Collection | ||
12 | import java.util.HashSet | ||
13 | import java.util.Map | ||
14 | import java.util.Set | ||
15 | import org.eclipse.viatra.dse.base.ThreadContext | ||
16 | import org.eclipse.xtend.lib.annotations.Accessors | ||
17 | |||
18 | interface DiversityChecker { | ||
19 | public static val NO_DIVERSITY_CHECKER = new DiversityChecker { | ||
20 | override isActive() { | ||
21 | false | ||
22 | } | ||
23 | |||
24 | override getTotalRuntime() { | ||
25 | 0 | ||
26 | } | ||
27 | |||
28 | override getSuccessRate() { | ||
29 | 1.0 | ||
30 | } | ||
31 | |||
32 | override newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
33 | true | ||
34 | } | ||
35 | } | ||
36 | |||
37 | def boolean isActive() | ||
38 | |||
39 | def long getTotalRuntime() | ||
40 | |||
41 | def double getSuccessRate() | ||
42 | |||
43 | def boolean newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) | ||
44 | |||
45 | static def of(DiversityDescriptor descriptor) { | ||
46 | if (descriptor.ensureDiversity) { | ||
47 | new NodewiseDiversityChecker(descriptor) | ||
48 | } else { | ||
49 | NO_DIVERSITY_CHECKER | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | abstract class AbstractDiversityChecker implements DiversityChecker { | ||
55 | val DiversityDescriptor descriptor | ||
56 | val PartialInterpretation2ImmutableTypeLattice solutionCoder = new PartialInterpretation2ImmutableTypeLattice | ||
57 | |||
58 | @Accessors(PUBLIC_GETTER) var long totalRuntime = 0 | ||
59 | var int allCheckCount = 0 | ||
60 | var int successfulCheckCount = 0 | ||
61 | |||
62 | protected new(DiversityDescriptor descriptor) { | ||
63 | if (!descriptor.ensureDiversity) { | ||
64 | throw new IllegalArgumentException( | ||
65 | "Diversity description should enforce diversity or NO_DIVERSITY_CHECKER should be used instead.") | ||
66 | } | ||
67 | this.descriptor = descriptor | ||
68 | } | ||
69 | |||
70 | override isActive() { | ||
71 | true | ||
72 | } | ||
73 | |||
74 | override getTotalRuntime() { | ||
75 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | ||
76 | } | ||
77 | |||
78 | override getSuccessRate() { | ||
79 | (allCheckCount as double) / (successfulCheckCount as double) | ||
80 | } | ||
81 | |||
82 | override newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
83 | val start = System.nanoTime | ||
84 | val model = threadContext.model as PartialInterpretation | ||
85 | val representation = solutionCoder.createRepresentation(model, descriptor.range, descriptor.parallels, | ||
86 | descriptor.maxNumber, descriptor.relevantTypes, descriptor.relevantRelations) | ||
87 | val isDifferent = internalNewSolution(representation, solutionId, dominatedSolutionIds) | ||
88 | totalRuntime += System.nanoTime - start | ||
89 | allCheckCount++ | ||
90 | if (isDifferent) { | ||
91 | successfulCheckCount++ | ||
92 | } | ||
93 | isDifferent | ||
94 | } | ||
95 | |||
96 | protected abstract def boolean internalNewSolution( | ||
97 | NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation, | ||
98 | Object solutionId, Collection<Object> dominatedSolutionIds) | ||
99 | } | ||
100 | |||
101 | class NodewiseDiversityChecker extends AbstractDiversityChecker { | ||
102 | var Multiset<Integer> nodeCodes = HashMultiset.create | ||
103 | val Map<Object, Set<Integer>> tracedNodeCodes = newHashMap | ||
104 | |||
105 | new(DiversityDescriptor descriptor) { | ||
106 | super(descriptor) | ||
107 | } | ||
108 | |||
109 | override protected internalNewSolution( | ||
110 | NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation, | ||
111 | Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
112 | val nodeCodesInSolution = ImmutableSet.copyOf(representation.modelRepresentation.keySet.map[hashCode]) | ||
113 | val remainingNodeCodes = if (dominatedSolutionIds.empty) { | ||
114 | nodeCodes | ||
115 | } else { | ||
116 | getRemainingNodeCodes(dominatedSolutionIds) | ||
117 | } | ||
118 | val hasNewCode = nodeCodesInSolution.exists[!remainingNodeCodes.contains(it)] | ||
119 | if (hasNewCode) { | ||
120 | nodeCodes = remainingNodeCodes | ||
121 | nodeCodes.addAll(nodeCodesInSolution) | ||
122 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
123 | tracedNodeCodes.remove(dominatedSolutionId) | ||
124 | } | ||
125 | tracedNodeCodes.put(solutionId, nodeCodesInSolution) | ||
126 | } | ||
127 | hasNewCode | ||
128 | } | ||
129 | |||
130 | private def getRemainingNodeCodes(Collection<Object> dominatedSolutionIds) { | ||
131 | // TODO Optimize multiset operations. | ||
132 | val copyOfNodeCodes = HashMultiset.create(nodeCodes) | ||
133 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
134 | val dominatedModelCode = tracedNodeCodes.get(dominatedSolutionId) | ||
135 | if (dominatedModelCode === null) { | ||
136 | throw new IllegalArgumentException("Unknown dominated solution: " + dominatedSolutionId) | ||
137 | } | ||
138 | copyOfNodeCodes.removeAll(dominatedModelCode) | ||
139 | } | ||
140 | copyOfNodeCodes | ||
141 | } | ||
142 | } | ||
143 | |||
144 | class GraphwiseDiversityChecker extends AbstractDiversityChecker { | ||
145 | var Set<Integer> modelCodes = newHashSet | ||
146 | val Map<Object, Integer> tracedModelCodes = newHashMap | ||
147 | |||
148 | new(DiversityDescriptor descriptor) { | ||
149 | super(descriptor) | ||
150 | } | ||
151 | |||
152 | override protected internalNewSolution( | ||
153 | NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation, | ||
154 | Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
155 | val modelCodeOfSolution = representation.modelRepresentation.hashCode | ||
156 | val remainingModelCodes = if (dominatedSolutionIds.empty) { | ||
157 | modelCodes | ||
158 | } else { | ||
159 | getRemainingModelCodes(dominatedSolutionIds) | ||
160 | } | ||
161 | val isNewCode = !remainingModelCodes.contains(modelCodeOfSolution) | ||
162 | if (isNewCode) { | ||
163 | modelCodes = remainingModelCodes | ||
164 | modelCodes += modelCodeOfSolution | ||
165 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
166 | tracedModelCodes.remove(dominatedSolutionId) | ||
167 | } | ||
168 | tracedModelCodes.put(solutionId, modelCodeOfSolution) | ||
169 | } | ||
170 | isNewCode | ||
171 | } | ||
172 | |||
173 | private def getRemainingModelCodes(Collection<Object> dominatedSolutionIds) { | ||
174 | val copyOfModelCodes = new HashSet(modelCodes) | ||
175 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
176 | val dominatedModelCode = tracedModelCodes.get(dominatedSolutionId) | ||
177 | if (dominatedModelCode === null) { | ||
178 | throw new IllegalArgumentException("Unknown dominated solution: " + dominatedSolutionId) | ||
179 | } | ||
180 | copyOfModelCodes -= dominatedModelCode | ||
181 | } | ||
182 | copyOfModelCodes | ||
183 | } | ||
184 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend deleted file mode 100644 index 1e7f18a8..00000000 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.DiversityDescriptor | ||
6 | import java.util.LinkedList | ||
7 | import java.util.List | ||
8 | import org.eclipse.viatra.dse.base.ThreadContext | ||
9 | import java.util.HashSet | ||
10 | import java.util.Set | ||
11 | |||
12 | enum DiversityGranularity { | ||
13 | Nodewise, Graphwise | ||
14 | } | ||
15 | |||
16 | class SolutionStoreWithDiversityDescriptor { | ||
17 | val DiversityDescriptor descriptor | ||
18 | DiversityGranularity granularity | ||
19 | val PartialInterpretation2ImmutableTypeLattice solutionCoder = new PartialInterpretation2ImmutableTypeLattice | ||
20 | val Set<Integer> solutionCodeList = new HashSet | ||
21 | |||
22 | var long runtime | ||
23 | var int allCheck | ||
24 | var int successfulCheck | ||
25 | |||
26 | new(DiversityDescriptor descriptor) { | ||
27 | if(descriptor.ensureDiversity) { | ||
28 | this.descriptor = descriptor | ||
29 | this.granularity = DiversityGranularity::Nodewise | ||
30 | } else { | ||
31 | this.descriptor = null | ||
32 | this.granularity = DiversityGranularity::Nodewise | ||
33 | } | ||
34 | } | ||
35 | |||
36 | def public isActive() { | ||
37 | descriptor!==null | ||
38 | } | ||
39 | |||
40 | def getSumRuntime() { | ||
41 | return runtime | ||
42 | } | ||
43 | def getSuccessRate() { | ||
44 | return successfulCheck as double / allCheck | ||
45 | } | ||
46 | |||
47 | def isDifferent(ThreadContext context) { | ||
48 | if(active) { | ||
49 | val start = System.nanoTime | ||
50 | val model = context.model as PartialInterpretation | ||
51 | var boolean isDifferent | ||
52 | if(this.granularity == DiversityGranularity::Graphwise) { | ||
53 | val code = solutionCoder.createRepresentation(model, | ||
54 | descriptor.range, | ||
55 | descriptor.parallels, | ||
56 | descriptor.maxNumber, | ||
57 | descriptor.relevantTypes, | ||
58 | descriptor.relevantRelations).modelRepresentation.hashCode | ||
59 | |||
60 | isDifferent = !solutionCodeList.contains(code) | ||
61 | } else if(this.granularity == DiversityGranularity::Nodewise){ | ||
62 | val codes = solutionCoder.createRepresentation(model, | ||
63 | descriptor.range, | ||
64 | descriptor.parallels, | ||
65 | descriptor.maxNumber, | ||
66 | descriptor.relevantTypes, | ||
67 | descriptor.relevantRelations).modelRepresentation.keySet.map[hashCode].toList | ||
68 | val differentCodes = codes.filter[!solutionCodeList.contains(it)] | ||
69 | //println(differentCodes.size) | ||
70 | |||
71 | isDifferent = differentCodes.size>=1 | ||
72 | } else { | ||
73 | throw new UnsupportedOperationException('''Unsupported diversity type: «this.granularity»''') | ||
74 | } | ||
75 | |||
76 | runtime += System.nanoTime - start | ||
77 | allCheck++ | ||
78 | if(isDifferent) { successfulCheck++ } | ||
79 | return isDifferent | ||
80 | } else { | ||
81 | allCheck++ | ||
82 | successfulCheck++ | ||
83 | return true | ||
84 | } | ||
85 | } | ||
86 | |||
87 | def canBeDifferent(ThreadContext context) { | ||
88 | return true | ||
89 | } | ||
90 | |||
91 | def newSolution(ThreadContext context) { | ||
92 | if(active) { | ||
93 | val start = System.nanoTime | ||
94 | val model = context.model as PartialInterpretation | ||
95 | if(this.granularity == DiversityGranularity::Graphwise) { | ||
96 | val code = solutionCoder.createRepresentation(model, | ||
97 | descriptor.range, | ||
98 | descriptor.parallels, | ||
99 | descriptor.maxNumber, | ||
100 | descriptor.relevantTypes, | ||
101 | descriptor.relevantRelations).modelRepresentation.hashCode | ||
102 | |||
103 | solutionCodeList += code.hashCode | ||
104 | } else if(this.granularity == DiversityGranularity::Nodewise){ | ||
105 | val codes = solutionCoder.createRepresentation(model, | ||
106 | descriptor.range, | ||
107 | descriptor.parallels, | ||
108 | descriptor.maxNumber, | ||
109 | descriptor.relevantTypes, | ||
110 | descriptor.relevantRelations).modelRepresentation.keySet.map[hashCode].toList | ||
111 | |||
112 | solutionCodeList += codes.map[it.hashCode] | ||
113 | } else { | ||
114 | throw new UnsupportedOperationException('''Unsupported diversity type: «this.granularity»''') | ||
115 | } | ||
116 | |||
117 | runtime += System.nanoTime - start | ||
118 | } | ||
119 | } | ||
120 | } \ No newline at end of file | ||
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 17df6c55..6bffeb59 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 | |||
@@ -13,10 +13,11 @@ import org.eclipse.viatra.dse.solutionstore.SolutionStore.ISolutionSaver | |||
13 | import org.eclipse.xtend.lib.annotations.Accessors | 13 | import org.eclipse.xtend.lib.annotations.Accessors |
14 | 14 | ||
15 | /** | 15 | /** |
16 | * Based on {@link org.eclipse.viatra.dse.solutionstore.SolutionStore.BestSolutionSaver}. | 16 | * Based on {@link SolutionStore.BestSolutionSaver}. |
17 | */ | 17 | */ |
18 | class ViatraReasonerSolutionSaver implements ISolutionSaver { | 18 | class ViatraReasonerSolutionSaver implements ISolutionSaver { |
19 | @Accessors val solutionCopier = new SolutionCopier | 19 | @Accessors val solutionCopier = new SolutionCopier |
20 | @Accessors val DiversityChecker diversityChecker | ||
20 | val boolean hasExtremalObjectives | 21 | val boolean hasExtremalObjectives |
21 | val int numberOfRequiredSolutions | 22 | val int numberOfRequiredSolutions |
22 | val ObjectiveComparatorHelper comparatorHelper | 23 | val ObjectiveComparatorHelper comparatorHelper |
@@ -24,7 +25,8 @@ class ViatraReasonerSolutionSaver implements ISolutionSaver { | |||
24 | 25 | ||
25 | @Accessors(PUBLIC_SETTER) var Map<Object, Solution> solutionsCollection | 26 | @Accessors(PUBLIC_SETTER) var Map<Object, Solution> solutionsCollection |
26 | 27 | ||
27 | new(IObjective[][] leveledExtremalObjectives, int numberOfRequiredSolutions) { | 28 | new(IObjective[][] leveledExtremalObjectives, int numberOfRequiredSolutions, DiversityChecker diversityChecker) { |
29 | this.diversityChecker = diversityChecker | ||
28 | comparatorHelper = new ObjectiveComparatorHelper(leveledExtremalObjectives) | 30 | comparatorHelper = new ObjectiveComparatorHelper(leveledExtremalObjectives) |
29 | hasExtremalObjectives = leveledExtremalObjectives.exists[!empty] | 31 | hasExtremalObjectives = leveledExtremalObjectives.exists[!empty] |
30 | this.numberOfRequiredSolutions = numberOfRequiredSolutions | 32 | this.numberOfRequiredSolutions = numberOfRequiredSolutions |
@@ -34,12 +36,15 @@ class ViatraReasonerSolutionSaver implements ISolutionSaver { | |||
34 | if (hasExtremalObjectives) { | 36 | if (hasExtremalObjectives) { |
35 | saveBestSolutionOnly(context, id, solutionTrajectory) | 37 | saveBestSolutionOnly(context, id, solutionTrajectory) |
36 | } else { | 38 | } else { |
37 | basicSaveSolution(context, id, solutionTrajectory) | 39 | saveAnyDiverseSolution(context, id, solutionTrajectory) |
38 | } | 40 | } |
39 | } | 41 | } |
40 | 42 | ||
41 | private def saveBestSolutionOnly(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | 43 | private def saveBestSolutionOnly(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { |
42 | val fitness = context.lastFitness | 44 | val fitness = context.lastFitness |
45 | if (!fitness.satisifiesHardObjectives) { | ||
46 | return false | ||
47 | } | ||
43 | val dominatedTrajectories = newArrayList | 48 | val dominatedTrajectories = newArrayList |
44 | for (entry : trajectories.entrySet) { | 49 | for (entry : trajectories.entrySet) { |
45 | val isLastFitnessBetter = comparatorHelper.compare(fitness, entry.value) | 50 | val isLastFitnessBetter = comparatorHelper.compare(fitness, entry.value) |
@@ -54,9 +59,12 @@ class ViatraReasonerSolutionSaver implements ISolutionSaver { | |||
54 | if (dominatedTrajectories.size == 0 && !needsMoreSolutionsWithSameFitness) { | 59 | if (dominatedTrajectories.size == 0 && !needsMoreSolutionsWithSameFitness) { |
55 | return false | 60 | return false |
56 | } | 61 | } |
62 | if (!diversityChecker.newSolution(context, id, dominatedTrajectories.map[solution.stateCode])) { | ||
63 | return false | ||
64 | } | ||
57 | // We must save the new trajectory before removing dominated trajectories | 65 | // We must save the new trajectory before removing dominated trajectories |
58 | // to avoid removing the current solution when it is reachable only via dominated trajectories. | 66 | // to avoid removing the current solution when it is reachable only via dominated trajectories. |
59 | val solutionSaved = basicSaveSolution(context, id, solutionTrajectory) | 67 | val solutionSaved = basicSaveSolution(context, id, solutionTrajectory, fitness) |
60 | for (dominatedTrajectory : dominatedTrajectories) { | 68 | for (dominatedTrajectory : dominatedTrajectories) { |
61 | trajectories -= dominatedTrajectory | 69 | trajectories -= dominatedTrajectory |
62 | val dominatedSolution = dominatedTrajectory.solution | 70 | val dominatedSolution = dominatedTrajectory.solution |
@@ -73,8 +81,18 @@ class ViatraReasonerSolutionSaver implements ISolutionSaver { | |||
73 | solutionSaved | 81 | solutionSaved |
74 | } | 82 | } |
75 | 83 | ||
76 | private def basicSaveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | 84 | private def saveAnyDiverseSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { |
77 | val fitness = context.lastFitness | 85 | val fitness = context.lastFitness |
86 | if (!fitness.satisifiesHardObjectives) { | ||
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 basicSaveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory, Fitness fitness) { | ||
78 | var boolean solutionSaved = false | 96 | var boolean solutionSaved = false |
79 | var dseSolution = solutionsCollection.get(id) | 97 | var dseSolution = solutionsCollection.get(id) |
80 | if (dseSolution === null) { | 98 | if (dseSolution === null) { |