diff options
Diffstat (limited to 'Solvers')
84 files changed, 9580 insertions, 0 deletions
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.classpath b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.classpath new file mode 100644 index 00000000..ed0eb24c --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.classpath | |||
@@ -0,0 +1,7 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <classpath> | ||
3 | <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> | ||
4 | <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> | ||
5 | <classpathentry kind="src" path="src/"/> | ||
6 | <classpathentry kind="output" path="bin"/> | ||
7 | </classpath> | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.project b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.project new file mode 100644 index 00000000..aa414f43 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.project | |||
@@ -0,0 +1,28 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <projectDescription> | ||
3 | <name>org.eclipse.viatra.dse</name> | ||
4 | <comment></comment> | ||
5 | <projects> | ||
6 | </projects> | ||
7 | <buildSpec> | ||
8 | <buildCommand> | ||
9 | <name>org.eclipse.jdt.core.javabuilder</name> | ||
10 | <arguments> | ||
11 | </arguments> | ||
12 | </buildCommand> | ||
13 | <buildCommand> | ||
14 | <name>org.eclipse.pde.ManifestBuilder</name> | ||
15 | <arguments> | ||
16 | </arguments> | ||
17 | </buildCommand> | ||
18 | <buildCommand> | ||
19 | <name>org.eclipse.pde.SchemaBuilder</name> | ||
20 | <arguments> | ||
21 | </arguments> | ||
22 | </buildCommand> | ||
23 | </buildSpec> | ||
24 | <natures> | ||
25 | <nature>org.eclipse.pde.PluginNature</nature> | ||
26 | <nature>org.eclipse.jdt.core.javanature</nature> | ||
27 | </natures> | ||
28 | </projectDescription> | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.settings/org.eclipse.jdt.core.prefs b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..9f6ece88 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.settings/org.eclipse.jdt.core.prefs | |||
@@ -0,0 +1,8 @@ | |||
1 | eclipse.preferences.version=1 | ||
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled | ||
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 | ||
4 | org.eclipse.jdt.core.compiler.compliance=1.8 | ||
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error | ||
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error | ||
7 | org.eclipse.jdt.core.compiler.release=disabled | ||
8 | org.eclipse.jdt.core.compiler.source=1.8 | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/MANIFEST.MF b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/MANIFEST.MF new file mode 100644 index 00000000..fabef844 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/MANIFEST.MF | |||
@@ -0,0 +1,387 @@ | |||
1 | Manifest-Version: 1.0 | ||
2 | Automatic-Module-Name: org.eclipse.viatra.dse | ||
3 | Bundle-SymbolicName: org.eclipse.viatra.dse;singleton:=true | ||
4 | Require-Bundle: org.eclipse.viatra.query.runtime;bundle-version="[2.4. | ||
5 | 0,2.5.0)";visibility:=reexport,org.eclipse.viatra.transformation.evm; | ||
6 | bundle-version="[2.4.0,2.5.0)";visibility:=reexport,org.eclipse.emf.e | ||
7 | core,org.eclipse.emf.ecore.xmi;bundle-version="2.7.0",org.eclipse.emf | ||
8 | .edit,org.eclipse.viatra.transformation.runtime.emf;bundle-version="[ | ||
9 | 2.4.0,2.5.0)";visibility:=reexport | ||
10 | Bundle-ManifestVersion: 2 | ||
11 | Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | ||
12 | Bundle-ActivationPolicy: lazy | ||
13 | Eclipse-SourceReferences: scm:git:git://git.eclipse.org/gitroot/viatra | ||
14 | /org.eclipse.viatra.git;path="dse/plugins/org.eclipse.viatra.dse";com | ||
15 | mitId=2a7314b6b21df594743fa017d18ae62da85c73fa | ||
16 | Bundle-Vendor: Eclipse VIATRA Project | ||
17 | Import-Package: com.google.common.base;version="27.1.0",com.google.com | ||
18 | mon.collect;version="27.1.0",com.google.common.util.concurrent;versio | ||
19 | n="27.1.0",org.apache.log4j;version="1.2.15" | ||
20 | Export-Package: org.eclipse.viatra.dse.api,org.eclipse.viatra.dse.api. | ||
21 | strategy.impl,org.eclipse.viatra.dse.api.strategy.interfaces,org.ecli | ||
22 | pse.viatra.dse.base,org.eclipse.viatra.dse.designspace.api,org.eclips | ||
23 | e.viatra.dse.multithreading,org.eclipse.viatra.dse.objectives,org.ecl | ||
24 | ipse.viatra.dse.objectives.impl,org.eclipse.viatra.dse.solutionstore, | ||
25 | org.eclipse.viatra.dse.statecode,org.eclipse.viatra.dse.statecoding,o | ||
26 | rg.eclipse.viatra.dse.statecoding.simple,org.eclipse.viatra.dse.util, | ||
27 | org.eclipse.viatra.dse.visualizer | ||
28 | SCM-Revision: 2a7314b6b21df594743fa017d18ae62da85c73fa | ||
29 | Bundle-Name: VIATRA-DSE framework Base (Incubation) | ||
30 | Bundle-Version: 0.24.0.202005060951 | ||
31 | Build-Jdk-Spec: 1.8 | ||
32 | Created-By: Maven Archiver 3.5.0 | ||
33 | |||
34 | Name: org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObje | ||
35 | ctive.class | ||
36 | SHA-256-Digest: nEIutogP27RZKAUo9eH/DshkhyOF8voUnj4BC/pkhYU= | ||
37 | |||
38 | Name: org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder$1.cla | ||
39 | ss | ||
40 | SHA-256-Digest: t7KG11FngBrFGTPHJuEaP5BvpPqRYMDq8qKuQyccRWQ= | ||
41 | |||
42 | Name: org/eclipse/viatra/dse/base/ThreadContext.class | ||
43 | SHA-256-Digest: 0Z+RpFCBKvn1+SVJSLpRbEpoMATPujvvfqGsBr99mBI= | ||
44 | |||
45 | Name: org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstra | ||
46 | int.class | ||
47 | SHA-256-Digest: 3qw4e1RY7TqpTKHRngBjCRWfJmMmu+DiUnKHO0yXVA4= | ||
48 | |||
49 | Name: org/eclipse/viatra/dse/objectives/IObjective.class | ||
50 | SHA-256-Digest: io0MQDhFysUXcHYcPUZENsy/xLn98SE65b2RbJ7QttM= | ||
51 | |||
52 | Name: org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.class | ||
53 | SHA-256-Digest: yOvisOPQT9D/tuLV5fLonIoDpqi8bSRbPVjtLtv4UKo= | ||
54 | |||
55 | Name: org/eclipse/viatra/dse/base/ExplorerThread.class | ||
56 | SHA-256-Digest: N4tY8yMnFoKGoMyS0RdRtqpGIh6ucbvvAxnf/YPr/xk= | ||
57 | |||
58 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$BestSolutionS | ||
59 | aver.class | ||
60 | SHA-256-Digest: yZkg5ntRMOsrKEgo7kkAaK5J8h11Ng8tzH4QXsLRhsM= | ||
61 | |||
62 | Name: org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy$Sh | ||
63 | aredData.class | ||
64 | SHA-256-Digest: 2jBwT4lfAUh7LDDmpi3JuzyjcWhVeb+53PPB5ZKlGx4= | ||
65 | |||
66 | Name: org/eclipse/viatra/dse/base/DseIdPoolHelper$IGetRuleExecutions.c | ||
67 | lass | ||
68 | SHA-256-Digest: s7Pr9OPNF5baYmoZlOTWl6keA+b1TVxV8zxBXMGewrM= | ||
69 | |||
70 | Name: org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.cl | ||
71 | ass | ||
72 | SHA-256-Digest: 0R8ENAT9UA3BCsveA38VjvR4k+Um3i1fFlQB85inLZY= | ||
73 | |||
74 | Name: org/eclipse/viatra/dse/api/DesignSpaceExplorer.class | ||
75 | SHA-256-Digest: JCDN006fVS56ROn6cV7Ssdl4CN+xtbdiWjVfDkkgRDM= | ||
76 | |||
77 | Name: org/eclipse/viatra/dse/util/EMFHelper$ENamedElementComparator.cl | ||
78 | ass | ||
79 | SHA-256-Digest: J8o5TEdYpuU/6q1qTw3lUIHaE4pEH/EpDUvuTNWusVA= | ||
80 | |||
81 | Name: org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap$EObj | ||
82 | ectComparator.class | ||
83 | SHA-256-Digest: iwLJSS2Ip9WvN2lC8gfg+ys5Cp+P7ZSpGP6QF5lKYKQ= | ||
84 | |||
85 | Name: org/eclipse/viatra/dse/api/DesignSpaceExplorer$DseLoggingLevel.c | ||
86 | lass | ||
87 | SHA-256-Digest: z3h4wzaSMGzPvV4KL6ilStnLdT/mVCNNp7C/AwfQhqk= | ||
88 | |||
89 | Name: org/eclipse/viatra/dse/multithreading/DSEThreadPool.class | ||
90 | SHA-256-Digest: XoKcmDnafPfiyQ0LemN0ni31T+aY+lXp/Q8p157kj/g= | ||
91 | |||
92 | Name: org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.clas | ||
93 | s | ||
94 | SHA-256-Digest: SGlKz9PbynZwkmaJ1rpE0kVUOHl7vl7GOscNFoNEHLg= | ||
95 | |||
96 | Name: org/eclipse/viatra/dse/base/GlobalContext.class | ||
97 | SHA-256-Digest: dLn/Iu9JVDaaKK21VeFAMDXGaJWROEJCWJjULwMzNik= | ||
98 | |||
99 | Name: org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.cla | ||
100 | ss | ||
101 | SHA-256-Digest: L0yK9bhku/F8MX/NyKoBuydeMbMgZir8N0BRcFzHnKs= | ||
102 | |||
103 | Name: org/eclipse/viatra/dse/statecode/IStateCoderFactory.class | ||
104 | SHA-256-Digest: 1GsfU5aBQs1ieo3dblcXFZ07oq9QzWr1NZLppgSdCOM= | ||
105 | |||
106 | Name: org/eclipse/viatra/dse/base/DesignSpaceManager$1.class | ||
107 | SHA-256-Digest: /suIApW5KeZ7OifoR8SRPc3gU+2B8/ZnWInhdpAOTd8= | ||
108 | |||
109 | Name: org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.cla | ||
110 | ss | ||
111 | SHA-256-Digest: vML6AN6aCbn/cKeccmvzRAai47jZJk0CpYhwFQdhwvI= | ||
112 | |||
113 | Name: org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider | ||
114 | .class | ||
115 | SHA-256-Digest: QFWpXui2nID6PKhTHs/1e0gj9u8NiniES6/G0C/oSzM= | ||
116 | |||
117 | Name: org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy$Bf | ||
118 | sSharedObject.class | ||
119 | SHA-256-Digest: wVno1chuJ8pYpfv5cpB0fjsGbO2s+2OWcaVQgoQb5+k= | ||
120 | |||
121 | Name: org/eclipse/viatra/dse/objectives/TrajectoryFitness.class | ||
122 | SHA-256-Digest: DIEgS7SFg5pWuxvFhRn3f7hBt8+qk1+40w9WpOkoyrc= | ||
123 | |||
124 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$1.class | ||
125 | SHA-256-Digest: V5AAqo4/81KOegdl1Wl8jIBrH57y4TdYrj+wOzV2vdM= | ||
126 | |||
127 | Name: org/eclipse/viatra/dse/api/Solution.class | ||
128 | SHA-256-Digest: U71jRd/R8tarIiHM+dETwXiwwPcmXO5m82bDUp/Mduo= | ||
129 | |||
130 | Name: org/eclipse/viatra/dse/util/EMFHelper$EmfHelperException.class | ||
131 | SHA-256-Digest: +OCT0+wqq9XGCze/qDE8hh3zprFMBAnkR7H1J7k/Htk= | ||
132 | |||
133 | Name: org/eclipse/viatra/dse/base/DseEvmRuleBase.class | ||
134 | SHA-256-Digest: iRILqfjFCMPd020YX8dMyRaNlUGfEUTd4N3gnqQRtDo= | ||
135 | |||
136 | Name: org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjecti | ||
137 | ve.class | ||
138 | SHA-256-Digest: wXSfFPucpZyh72nGKuKn83N63Orl75XUM9SkzKfFBi4= | ||
139 | |||
140 | Name: org/eclipse/viatra/dse/api/DSETransformationRule.class | ||
141 | SHA-256-Digest: 01Ngrz/qbLR6j/4z9NxvtD2jHQAHMl698POXw8BSpPY= | ||
142 | |||
143 | Name: org/eclipse/viatra/dse/objectives/impl/ModelQueryType.class | ||
144 | SHA-256-Digest: SS0yM7NbAU0U4KoA4Tzy4gXKZ2IZaszyaqbtSN4GE74= | ||
145 | |||
146 | Name: org/eclipse/viatra/dse/base/DseConflictResolver.class | ||
147 | SHA-256-Digest: kLquKehufJSc2fJoUgztO62ucr1UUqfLQpyiFrY8BJc= | ||
148 | |||
149 | Name: org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.class | ||
150 | SHA-256-Digest: 7tog5/ud60nPTYwPT6HHpHBDeutpFl2KLKXt8GnM3U8= | ||
151 | |||
152 | Name: org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.class | ||
153 | SHA-256-Digest: cbpeCy8w558CbnhljT2TKalNqWBpKlIsMppr6hWDRpw= | ||
154 | |||
155 | Name: org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.class | ||
156 | SHA-256-Digest: mXYUokn/RePXJXnfL7O3AZjvwqFkwiLZ0IipQGgdp0A= | ||
157 | |||
158 | Name: org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.cla | ||
159 | ss | ||
160 | SHA-256-Digest: ef+0X9EnYYjpPiRNmjXrElCCaPekh+Wh6yimRTpp15E= | ||
161 | |||
162 | Name: org/eclipse/viatra/dse/objectives/impl/CompositeObjective.class | ||
163 | SHA-256-Digest: SJiO5Oina3I760xBUDGc4qYp1WrcSG6Yh0+8hQKf69U= | ||
164 | |||
165 | Name: org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.clas | ||
166 | s | ||
167 | SHA-256-Digest: +uKjMIfQvBlKY9djJoP5Wd/EBKMkbrdk7shGdZ0rS2M= | ||
168 | |||
169 | Name: org/eclipse/viatra/dse/api/Objectives.class | ||
170 | SHA-256-Digest: pNQDcSeUV3oOM7aCgscjJwdyysQrMSZCyLhrSWLMUrI= | ||
171 | |||
172 | Name: org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.c | ||
173 | lass | ||
174 | SHA-256-Digest: nf/uvPeNaC8Nu9SPhk+sgvSheB/kh+GqsXXHbm7qer0= | ||
175 | |||
176 | Name: org/eclipse/viatra/dse/api/DSEException.class | ||
177 | SHA-256-Digest: MCUPB2tBDK01enENQDJ+qONxtl+WQyZaJf87iU+NFyU= | ||
178 | |||
179 | Name: org/eclipse/viatra/dse/base/SingletonSetConflictResolver.class | ||
180 | SHA-256-Digest: bd4gh7UG91EkNSE0JrpAKbHDxv6HYhL7YEq7PZZkRjo= | ||
181 | |||
182 | Name: org/eclipse/viatra/dse/statecoding/IObjectsProvider.class | ||
183 | SHA-256-Digest: SIcYuklHbTwYjV+gvS1B77Z0CR/2bannTSL77/qm/Gs= | ||
184 | |||
185 | Name: org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFact | ||
186 | ory.class | ||
187 | SHA-256-Digest: F12xo+nr94L4B1m1w2xmtA7t1TzGin5pFSEqkBmYxC0= | ||
188 | |||
189 | Name: org/eclipse/viatra/dse/api/SolutionTrajectory.class | ||
190 | SHA-256-Digest: uFjxXsF4khsOwgCsmRPMZbSayZ4qTDtwPGxDBH2lG74= | ||
191 | |||
192 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$SimpleSolutio | ||
193 | nSaver.class | ||
194 | SHA-256-Digest: 12aDZULU6fhdXx8a/BvCQwXW7RZfEmIPFueU7GOpBB0= | ||
195 | |||
196 | Name: org/eclipse/viatra/dse/util/Hasher.class | ||
197 | SHA-256-Digest: 0nFBMPZ6/YudYlnE/l8XiECkWIHBRvkdyi9WUCIaN4c= | ||
198 | |||
199 | Name: org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.class | ||
200 | SHA-256-Digest: Ig8utojCZoNY8V37gbZVVJFOX8NZiu2tPsnAIkS1BaU= | ||
201 | |||
202 | Name: org/eclipse/viatra/dse/objectives/IGlobalConstraint.class | ||
203 | SHA-256-Digest: UvJwqLRVvv444GgELIu/tUGs4eV8cf/Anqh6horECP8= | ||
204 | |||
205 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore.class | ||
206 | SHA-256-Digest: V9OJ/9GqLq9cBToiBzapjyCs3mDuk4PkeduT5YpiTwE= | ||
207 | |||
208 | Name: org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.class | ||
209 | SHA-256-Digest: Ra8i2f1YiRldwF06QotRoHkhKJLyGMYJnS6Lco1ldTM= | ||
210 | |||
211 | Name: org/eclipse/viatra/dse/objectives/impl/BaseObjective.class | ||
212 | SHA-256-Digest: DH8BIQo1OvBt5oEtS4sqsjtGOhlD1Nwz2yv7gdW3/hA= | ||
213 | |||
214 | Name: org/eclipse/viatra/dse/api/DesignSpaceExplorer$1.class | ||
215 | SHA-256-Digest: 1AccsshxVCMI2GPkioO7lQtS9JwPx17YrPTSjTZfqBQ= | ||
216 | |||
217 | Name: org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.clas | ||
218 | s | ||
219 | SHA-256-Digest: +eesnPuyvrf4xQOslHAFlNIyd4K9scCn8f6qprCxKzs= | ||
220 | |||
221 | Name: org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.c | ||
222 | lass | ||
223 | SHA-256-Digest: /+Dkno94lswrX5YEr60iH8szAKDL9hfAe2ZZ/amSe20= | ||
224 | |||
225 | Name: org/eclipse/viatra/dse/base/IDseStrategyContext.class | ||
226 | SHA-256-Digest: ACDjZwH6zo71KF8hXuAvC7NWmGPDv9lJ06U/iAptwEw= | ||
227 | |||
228 | Name: org/eclipse/viatra/dse/statecode/IStateCoder.class | ||
229 | SHA-256-Digest: L+foclr4t9XV4ltc7aDor4Ngf135J+UvTpTxCcegz9M= | ||
230 | |||
231 | Name: org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardOb | ||
232 | jective.class | ||
233 | SHA-256-Digest: KB8QybGLqya7vrKCMnwRdCOaJ/URoTIeR1NVYDNiOB4= | ||
234 | |||
235 | Name: org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardO | ||
236 | bjective.class | ||
237 | SHA-256-Digest: TzG4kskc7rM96sfpJc6YsSNF7PyE48NJLkUpkkwqsiI= | ||
238 | |||
239 | Name: org/eclipse/viatra/dse/base/DesignSpaceManager.class | ||
240 | SHA-256-Digest: WlF2FWYiBFQNAW2PsPpPorz64wQBWssTC/73maFotD8= | ||
241 | |||
242 | Name: org/eclipse/viatra/dse/visualizer/IExploreEventHandler.class | ||
243 | SHA-256-Digest: ZJwhUYNU+L1B88hsbfdIejJVUwhnvBjJSDHugw+RFh0= | ||
244 | |||
245 | Name: META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.pro | ||
246 | perties | ||
247 | SHA-256-Digest: 0JWWPFaIUkYh4BehmajscXzAloPgjeIs0iZSPFC/g1g= | ||
248 | |||
249 | Name: org/eclipse/viatra/dse/statecoding/StatecodingDependency.class | ||
250 | SHA-256-Digest: AeHJlVqUAUsjBlYumYq/e/WEBNbtlvCk00SG9rHPO88= | ||
251 | |||
252 | Name: org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.class | ||
253 | SHA-256-Digest: K5feGvnijYpwPJCOvR4m7ChtC7wX7LhLaau5/SBnFek= | ||
254 | |||
255 | Name: org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.class | ||
256 | SHA-256-Digest: gF2AAXk6xxQIDqdn56Aeifqmj71pBicLO7VJJoB64bY= | ||
257 | |||
258 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$ANumberOfEnou | ||
259 | ghSolutions.class | ||
260 | SHA-256-Digest: qAOxgehQKfKkDSF2W2Gk/cXkDIBsQuN4yJ8Q3eRCnps= | ||
261 | |||
262 | Name: META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.xml | ||
263 | SHA-256-Digest: /LSOqjjd6+fmn3MHbXK9bGr7k+1GKE3kgzaDoJkgCQQ= | ||
264 | |||
265 | Name: org/eclipse/viatra/dse/base/DseIdPoolHelper$IdProvider.class | ||
266 | SHA-256-Digest: VRQcpABZNkp3Lgivy9PUraJf04riM1MOZvY64suvo3M= | ||
267 | |||
268 | Name: org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder$2.cla | ||
269 | ss | ||
270 | SHA-256-Digest: NqiG7/1poRDLI2BbRvr2hfHZqH73hfFxBic+4YKHcCM= | ||
271 | |||
272 | Name: org/eclipse/viatra/dse/base/ThreadContext$GetRuleExecutionsImpl. | ||
273 | class | ||
274 | SHA-256-Digest: HGFHcAmOg3O3se9FT4oE4pWZ8EFdyRkkHkBVJZi+hmM= | ||
275 | |||
276 | Name: org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.class | ||
277 | SHA-256-Digest: qJyc4dMUiLGVoJPrMWQtCI2o2HW5p6Ki5J8Ra6wb/gE= | ||
278 | |||
279 | Name: org/eclipse/viatra/dse/designspace/api/IDesignSpace.class | ||
280 | SHA-256-Digest: IS5IjYyUCvaHWBvUsPFeGFv65W+YTG7u+iRXp/eDIuM= | ||
281 | |||
282 | Name: org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.cl | ||
283 | ass | ||
284 | SHA-256-Digest: UfrnKlXVqN8LWbUPSoA5PDiJOT7cnCA46kIXicC5mg0= | ||
285 | |||
286 | Name: org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy$Traje | ||
287 | ctoryWithFitness.class | ||
288 | SHA-256-Digest: n3K90JLwOOVAXsrkROhn0ZNogaAKVdcUpXBj8RUMI3c= | ||
289 | |||
290 | Name: org/eclipse/viatra/dse/util/EMFHelper$MetaModelElements.class | ||
291 | SHA-256-Digest: FjS8V9JksWMjbV9a1dn04gWFH3fctq9HdWSfbMsV5Ck= | ||
292 | |||
293 | Name: org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactor | ||
294 | y.class | ||
295 | SHA-256-Digest: jcBdVzrTpamZrT0pQZHyJJnooB+DKF6ADVS4RRhZGl4= | ||
296 | |||
297 | Name: org/eclipse/viatra/dse/objectives/Fitness.class | ||
298 | SHA-256-Digest: CJPJnXYS0WMnW4JVW2YO5/vvwKhRkRE7qROa87Ailpg= | ||
299 | |||
300 | Name: org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.cl | ||
301 | ass | ||
302 | SHA-256-Digest: 4odjR0x9jzt7Ed/hw6Q+ydZUrQQggqL8y216Lq60azM= | ||
303 | |||
304 | Name: org/eclipse/viatra/dse/api/Strategies.class | ||
305 | SHA-256-Digest: tURHC++pafgodWMnk4CperJDpZ9m4Do6xHAV37bHUoc= | ||
306 | |||
307 | Name: org/eclipse/viatra/dse/statecoding/StatecodingNode.class | ||
308 | SHA-256-Digest: 2xM/ShgCBqpV9tgQZPBxzTSPgbT7lcp7auQE14dEEqc= | ||
309 | |||
310 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$ISolutionSave | ||
311 | r.class | ||
312 | SHA-256-Digest: nuYmJKeNKfM0a9sAbRpA6Knzqu51hlK011aoAQpTH3Q= | ||
313 | |||
314 | Name: org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.cl | ||
315 | ass | ||
316 | SHA-256-Digest: 9ZxUtKP6+hvWqY9l0b+opdginEK1BoksdLqZ+DYViqI= | ||
317 | |||
318 | Name: org/eclipse/viatra/dse/util/EMFHelper.class | ||
319 | SHA-256-Digest: hpOu0HMuLuiLYUbg0rhdfVG4/ZrlVftoKLmTsRAHW/E= | ||
320 | |||
321 | Name: org/eclipse/viatra/dse/base/DesignSpaceManager$2.class | ||
322 | SHA-256-Digest: x8i8lLzE/UkaQJya1kGbTlJnB/JFNy5607FLESkMQXA= | ||
323 | |||
324 | Name: org/eclipse/viatra/dse/base/ActivationCodesConflictSet.class | ||
325 | SHA-256-Digest: 0G/W2cxiS4R9GEpBWovAIEA4brmQ2sTjqi1F7vgS0/c= | ||
326 | |||
327 | Name: org/eclipse/viatra/dse/api/SolutionTrajectory$1.class | ||
328 | SHA-256-Digest: 7epxs7VJgi7Jmo2pKb22m2OLhOOIu3OHTJrWC8HjEzQ= | ||
329 | |||
330 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$IEnoughSoluti | ||
331 | ons.class | ||
332 | SHA-256-Digest: /5Ux9DFOI3UHcG8om2rGzX2k0Yj1lIoeG/tR82P3zpQ= | ||
333 | |||
334 | Name: org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective$Quer | ||
335 | yConstraint.class | ||
336 | SHA-256-Digest: 79pmTnUZbgOHEdGzyj5PIb2eGrd554q3c17LNdbTQxM= | ||
337 | |||
338 | Name: org/eclipse/viatra/dse/objectives/Comparators.class | ||
339 | SHA-256-Digest: V5MzedIHj3KBEBbR4UNAhqmbqB3sHuk183zxMlKhGD4= | ||
340 | |||
341 | Name: org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.class | ||
342 | SHA-256-Digest: VlWdfwyWo39xhvgIF9PedWC+Yv1Q0hYaDBSF7Z+ClSA= | ||
343 | |||
344 | Name: org/eclipse/viatra/dse/base/GlobalContext$ExplorationProcessStat | ||
345 | e.class | ||
346 | SHA-256-Digest: rNnsUlZX7z1yPBoNSfWvoXwKhSAjGUhpBo9CZVJwadw= | ||
347 | |||
348 | Name: org/eclipse/viatra/dse/base/DseIdPoolHelper.class | ||
349 | SHA-256-Digest: 8wUkapQg0xNS3Vy/Mtv18N9dEB9ev/QiH1tYPzFtBN8= | ||
350 | |||
351 | Name: about.html | ||
352 | SHA-256-Digest: Qx53vUKBh4ByLG9I8uUS7GH8BTecG5s70WKYlnHc04k= | ||
353 | |||
354 | Name: org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.class | ||
355 | SHA-256-Digest: bjBZdHvq37DxouRprrTxR0l8CWUCY+aw5JtccbEeAJg= | ||
356 | |||
357 | Name: org/eclipse/viatra/dse/designspace/api/DesignSpace.class | ||
358 | SHA-256-Digest: D51XZw1Z2bCk+PxzX7i8WpE64L9s64FoedEMxM0fSYA= | ||
359 | |||
360 | Name: org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.clas | ||
361 | s | ||
362 | SHA-256-Digest: VYf9HcY2IbUo2d1K+c2rKIFkxNIRFeEi9zr9s1Inc7o= | ||
363 | |||
364 | Name: org/eclipse/viatra/dse/statecoding/StatecodingNodeType.class | ||
365 | SHA-256-Digest: VUsDepoiER2/0o3aIE8uX08eOdXzvKBkfXPpPaow5yU= | ||
366 | |||
367 | Name: org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory. | ||
368 | class | ||
369 | SHA-256-Digest: K51RjSOSyMrj86BO/zgmo4kO83HgxKvrEGeOTo5WoVs= | ||
370 | |||
371 | Name: org/eclipse/viatra/dse/base/ActivationCodesConflictSet$Activatio | ||
372 | nCodesMultiBiMap.class | ||
373 | SHA-256-Digest: DEtZHFLUnrSZG5x15o2lTasPd5+ufqWCCQXg+YXGxQA= | ||
374 | |||
375 | Name: org/eclipse/viatra/dse/statecoding/TheStateCoder.class | ||
376 | SHA-256-Digest: 7iWoLYIXKNGjRgpIHZDuW3i8wBpV5OqO978Fg9WxEK8= | ||
377 | |||
378 | Name: org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.class | ||
379 | SHA-256-Digest: HYJ6Z75XEjy3UGBB00bv/GfxdOey+9MpGM5aJuFm5fM= | ||
380 | |||
381 | Name: org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHand | ||
382 | ler.class | ||
383 | SHA-256-Digest: CmINEWESAe5ynUDWoc8YQQdsmBx1bRLNabbzmoxxsUg= | ||
384 | |||
385 | Name: org/eclipse/viatra/dse/base/DseConflictSet.class | ||
386 | SHA-256-Digest: boreOAKc8L3ZEts53PUwZiZ4l+8Em3aLeXDQBJZihbY= | ||
387 | |||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.properties b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.properties new file mode 100644 index 00000000..33746c20 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.properties | |||
@@ -0,0 +1,3 @@ | |||
1 | artifactId=org.eclipse.viatra.dse | ||
2 | groupId=org.eclipse.viatra | ||
3 | version=0.24.0-SNAPSHOT | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.xml b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.xml new file mode 100644 index 00000000..4d50659f --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.xml | |||
@@ -0,0 +1,14 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <project | ||
3 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | ||
4 | xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | ||
5 | <modelVersion>4.0.0</modelVersion> | ||
6 | <parent> | ||
7 | <artifactId>org.eclipse.viatra.parent.dse</artifactId> | ||
8 | <groupId>org.eclipse.viatra</groupId> | ||
9 | <version>0.24.0-SNAPSHOT</version> | ||
10 | <relativePath>../../../releng/org.eclipse.viatra.parent.dse/pom.xml</relativePath> | ||
11 | </parent> | ||
12 | <artifactId>org.eclipse.viatra.dse</artifactId> | ||
13 | <packaging>eclipse-plugin</packaging> | ||
14 | </project> \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/about.html b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/about.html new file mode 100644 index 00000000..4c69fcc0 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/about.html | |||
@@ -0,0 +1,21 @@ | |||
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> | ||
2 | <html> | ||
3 | <head> | ||
4 | <title>About</title> | ||
5 | <meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1"> | ||
6 | </head> | ||
7 | <body lang="EN-US"> | ||
8 | <h2>About This Content</h2> | ||
9 | |||
10 | <p>March 18, 2019</p> | ||
11 | <h3>License</h3> | ||
12 | |||
13 | <p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the | ||
14 | Eclipse Public License Version 2.0 ("EPL"). A copy of the EPL is available at <a href="http://www.eclipse.org/org/documents/epl-v20.php">http://www.eclipse.org/legal/epl-v20.html</a>. | ||
15 | For purposes of the EPL, "Program" will mean the Content.</p> | ||
16 | |||
17 | <p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party ("Redistributor") and different terms and conditions may | ||
18 | apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise | ||
19 | indicated below, the terms and conditions of the EPL still apply to any source code in the Content and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p> | ||
20 | </body> | ||
21 | </html> \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/build.properties b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/build.properties new file mode 100644 index 00000000..08373bf1 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/build.properties | |||
@@ -0,0 +1,4 @@ | |||
1 | source.. = src/ | ||
2 | bin.includes = META-INF/,\ | ||
3 | .,\ | ||
4 | about.html | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSEException.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSEException.java new file mode 100644 index 00000000..f0da19ed --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSEException.java | |||
@@ -0,0 +1,47 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.api; | ||
10 | |||
11 | /** | ||
12 | * Represents a general runtime exception that happened during the execution of the design space exploration process. | ||
13 | * Problems that cause this exception are not recoverable within the scope of the design space exploration process. | ||
14 | */ | ||
15 | public class DSEException extends RuntimeException { | ||
16 | |||
17 | private static final long serialVersionUID = -8312212010574763824L; | ||
18 | |||
19 | /** | ||
20 | * @see RuntimeException#RuntimeException() | ||
21 | */ | ||
22 | public DSEException() { | ||
23 | super(); | ||
24 | } | ||
25 | |||
26 | /** | ||
27 | * @see RuntimeException#RuntimeException(String) | ||
28 | */ | ||
29 | public DSEException(String message) { | ||
30 | super(message); | ||
31 | } | ||
32 | |||
33 | /** | ||
34 | * @see RuntimeException#RuntimeException(String, Throwable) | ||
35 | */ | ||
36 | public DSEException(String message, Throwable cause) { | ||
37 | super(message, cause); | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * @see RuntimeException#RuntimeException(Throwable) | ||
42 | */ | ||
43 | public DSEException(Throwable cause) { | ||
44 | super(cause); | ||
45 | } | ||
46 | |||
47 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSETransformationRule.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSETransformationRule.java new file mode 100644 index 00000000..8c3511ae --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSETransformationRule.java | |||
@@ -0,0 +1,51 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.api; | ||
10 | |||
11 | import java.util.Objects; | ||
12 | import java.util.function.Consumer; | ||
13 | |||
14 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
15 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
16 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher; | ||
17 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
18 | |||
19 | /** | ||
20 | * An instance of this class is a specification of a graph transformation rule on a given metamodel. Such a rule | ||
21 | * consists of a left hand side (LHS), which is specified by an {@link IQuerySpecification} and a right hand side (RHS), | ||
22 | * which is specified by an {@link Consumer}. | ||
23 | * | ||
24 | * @author Andras Szabolcs Nagy | ||
25 | * | ||
26 | * @param <Match> | ||
27 | * A VIATRA Query pattern match - left hand side of the rule | ||
28 | * @param <Matcher> | ||
29 | * A VIATRA Query pattern matcher - left hand side of the rule | ||
30 | * @deprecated | ||
31 | */ | ||
32 | @Deprecated | ||
33 | public class DSETransformationRule<Match extends IPatternMatch, Matcher extends ViatraQueryMatcher<Match>> extends | ||
34 | BatchTransformationRule<Match, Matcher> { | ||
35 | |||
36 | public DSETransformationRule(String name, IQuerySpecification<Matcher> querySpec, | ||
37 | Consumer<Match> action) { | ||
38 | super(name, querySpec, BatchTransformationRule.STATELESS_RULE_LIFECYCLE, action); | ||
39 | |||
40 | Objects.requireNonNull(name); | ||
41 | Objects.requireNonNull(querySpec); | ||
42 | Objects.requireNonNull(action); | ||
43 | |||
44 | } | ||
45 | |||
46 | public DSETransformationRule(IQuerySpecification<Matcher> querySpec, | ||
47 | Consumer<Match> action) { | ||
48 | this(querySpec.getFullyQualifiedName(), querySpec, action); | ||
49 | } | ||
50 | |||
51 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DesignSpaceExplorer.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DesignSpaceExplorer.java new file mode 100644 index 00000000..9cd6e68a --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DesignSpaceExplorer.java | |||
@@ -0,0 +1,622 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.api; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Set; | ||
14 | import java.util.Timer; | ||
15 | import java.util.TimerTask; | ||
16 | import java.util.concurrent.atomic.AtomicBoolean; | ||
17 | |||
18 | import org.apache.log4j.BasicConfigurator; | ||
19 | import org.apache.log4j.Level; | ||
20 | import org.apache.log4j.Logger; | ||
21 | import org.eclipse.emf.common.notify.Notifier; | ||
22 | import org.eclipse.emf.ecore.EObject; | ||
23 | import org.eclipse.emf.ecore.EPackage; | ||
24 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
25 | import org.eclipse.viatra.dse.base.DesignSpaceManager; | ||
26 | import org.eclipse.viatra.dse.base.GlobalContext; | ||
27 | import org.eclipse.viatra.dse.designspace.api.DesignSpace; | ||
28 | import org.eclipse.viatra.dse.designspace.api.IDesignSpace; | ||
29 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint; | ||
30 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
31 | import org.eclipse.viatra.dse.solutionstore.ISolutionNameProvider; | ||
32 | import org.eclipse.viatra.dse.solutionstore.IdBasedSolutionNameProvider; | ||
33 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
34 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
35 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
36 | import org.eclipse.viatra.dse.statecoding.simple.SimpleStateCoderFactory; | ||
37 | import org.eclipse.viatra.dse.visualizer.IDesignSpaceVisualizer; | ||
38 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
39 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
40 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
41 | |||
42 | /** | ||
43 | * <p> | ||
44 | * The {@link DesignSpaceExplorer} is the main API of the <b>Design Space Exploration</b> engine. | ||
45 | * </p> | ||
46 | * | ||
47 | * <p> | ||
48 | * To parameterize the algorithm one must use the following methods after instantiating: | ||
49 | * <ul> | ||
50 | * <li>{@link #setInitialModel(EObject)} or it's overloads to set the starting model.</li> | ||
51 | * <li>{@link #addTransformationRule(BatchTransformationRule)} to define the transformations.</li> <li | ||
52 | * {@link #addObjective(IObjective)} to define the objective functions. Use the {@link Objectives} helper class for | ||
53 | * instantiating built-in, configurable objectives.</li> | ||
54 | * <li>{@link #startExploration(IStrategy)} or it's overloads to start an exploration with the given exploration | ||
55 | * strategy. Use the {@link Strategies} helper class for instantiating built-in, configurable exploration strategies. | ||
56 | * </li> | ||
57 | * </ul> | ||
58 | * </p> | ||
59 | * | ||
60 | * <p> | ||
61 | * <b>Designs Space Exploration</b> is the process of finding a sequence (or sequences) of predefined transformation | ||
62 | * rules ("transitions") that, if applied in order on the starting model, results in a new model state that fulfills the | ||
63 | * hard (or goal) constraints and is near optimal with respect to the objectives. | ||
64 | * </p> | ||
65 | * | ||
66 | * <p> | ||
67 | * An extension to this paradigm is the introduction of global constraints, which guarantees, that no sequence will be | ||
68 | * returned, which if executed, results in an intermediate model state that violates the specified global constraints, | ||
69 | * including the final state. You can add constraints by invoking {@link #addGlobalConstraint(IGlobalConstraint)}. | ||
70 | * </p> | ||
71 | * | ||
72 | * @author Andras Szabolcs Nagy & Miklos Foldenyi | ||
73 | * | ||
74 | */ | ||
75 | public class DesignSpaceExplorer { | ||
76 | |||
77 | private Notifier model; | ||
78 | |||
79 | private GlobalContext globalContext = new GlobalContext(); | ||
80 | |||
81 | private final Logger logger = Logger.getLogger(this.getClass()); | ||
82 | |||
83 | private Set<EPackage> metaModelPackages = new HashSet<EPackage>(); | ||
84 | |||
85 | private static final String MODEL_NOT_YET_GIVEN = "The starting model is not given yet. Please call the setInitialModel method first."; | ||
86 | |||
87 | private boolean deepCopyModel; | ||
88 | |||
89 | /** | ||
90 | * <p> | ||
91 | * Creates a {@link DesignSpaceExplorer} object that is able to execute a design space exploration process. | ||
92 | * </p> | ||
93 | * | ||
94 | * <p> | ||
95 | * By default the state coder used is the generic (not meta-model specific) {@link GraphHash}. You can provide your | ||
96 | * custom state coder by implementing the {@link IStateCoderFactory} and {@link IStateCoder} interfaces, and passing | ||
97 | * the former to the {@link #setStateCoderFactory(IStateCoderFactory)} method. | ||
98 | * | ||
99 | */ | ||
100 | public DesignSpaceExplorer() { | ||
101 | setDesignspace(new DesignSpace()); | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * Adds a metamodel in the form of {@link EPackage}, which is needed for certain guidance. | ||
106 | * | ||
107 | * @param metaModelPackage | ||
108 | */ | ||
109 | public void addMetaModelPackage(EPackage metaModelPackage) { | ||
110 | metaModelPackages.add(metaModelPackage); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * Defines the initial model of the exploration, and whether it is supposed to be used to execute the DSE process or | ||
115 | * it should be cloned. Please note, that in multithreaded mode any subsequent threads will be working on cloned | ||
116 | * models. | ||
117 | * | ||
118 | * @param model | ||
119 | * The root object of the EMF model. | ||
120 | * @param deepCopyModel | ||
121 | * If it is set to true, the exploration will run on a cloned model. | ||
122 | */ | ||
123 | public void setInitialModel(Notifier model, boolean deepCopyModel) { | ||
124 | this.model = model; | ||
125 | this.deepCopyModel = deepCopyModel; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * Defines the initial model of the exploration. The model will be cloned, which is desired in most cases as the | ||
130 | * given model won't be changed. | ||
131 | * | ||
132 | * @param model | ||
133 | * The root object of the EMF model. | ||
134 | */ | ||
135 | public void setInitialModel(Notifier model) { | ||
136 | setInitialModel(model, true); | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * Defines the initial model of the exploration. The given model won't be cloned, thus the exploration will modify | ||
141 | * it. | ||
142 | * | ||
143 | * @param model | ||
144 | * The root object of the EMF model. It won't be cloned. | ||
145 | */ | ||
146 | public void setInitialModelUncloned(Notifier model) { | ||
147 | setInitialModel(model, false); | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * Adds a {@link BatchTransformationRule}. | ||
152 | * | ||
153 | * @param rule | ||
154 | * The transformationRule. | ||
155 | */ | ||
156 | public void addTransformationRule(BatchTransformationRule<?, ?> rule) { | ||
157 | Preconditions.checkArgument(rule != null); | ||
158 | for (BatchTransformationRule<?, ?> rule2 : globalContext.getTransformations()) { | ||
159 | if (rule.getPrecondition().equals(rule2.getPrecondition())) { | ||
160 | throw new DSEException( | ||
161 | "Two transformation rule (" | ||
162 | + rule.getName() | ||
163 | + "; " | ||
164 | + rule2.getName() | ||
165 | + ") uses the same LHS VIATRA Query pattern (" | ||
166 | + rule.getPrecondition().getFullyQualifiedName() | ||
167 | + "), which may lead to hash collision." | ||
168 | + " Please wrap the pattern with an other pattern with the 'find' keyword (or duplicate the code), and use that for one of the rules LHS."); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | globalContext.getTransformations().add(rule); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * Adds a global constraint to the exploration process. Please see the {@link IGlobalConstraint} interface and its | ||
177 | * implementations for details. | ||
178 | * | ||
179 | * @param constraint | ||
180 | * The global constraint. | ||
181 | * @see IGlobalConstraint | ||
182 | */ | ||
183 | public void addGlobalConstraint(IGlobalConstraint constraint) { | ||
184 | globalContext.getGlobalConstraints().add(constraint); | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * Adds an objective the the exploration process. Please see the {@link IObjective} interface and its | ||
189 | * implementations for details. | ||
190 | * | ||
191 | * @param objective | ||
192 | * The objective. | ||
193 | * @see IObjective | ||
194 | */ | ||
195 | public void addObjective(IObjective objective) { | ||
196 | for (IObjective o : globalContext.getObjectives()) { | ||
197 | if (o.getName().equals(objective.getName())) { | ||
198 | throw new DSEException("Two objectives with the same name cannot be registered:" + o.getName()); | ||
199 | } | ||
200 | } | ||
201 | globalContext.getObjectives().add(objective); | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * Sets a {@link IStateCoderFactory} for which will be used for creating {@link IStateCoder}s. The default | ||
206 | * implementation is the {@link SimpleStateCoderFactory}, which works well in most of the cases. | ||
207 | * | ||
208 | * @param stateCoderFactory | ||
209 | * The factory. | ||
210 | */ | ||
211 | public final void setStateCoderFactory(IStateCoderFactory stateCoderFactory) { | ||
212 | globalContext.setStateCoderFactory(stateCoderFactory); | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * Defines the maximum processing threads that the design space exploration can use. Note, that this is only | ||
217 | * limiting the threads doing the actual calculation. By default this value will be set to the number of logical | ||
218 | * processors (including HyperThreading) in the computer, reported by {@link Runtime#availableProcessors()}. | ||
219 | * | ||
220 | * @param maxNumberOfThreads | ||
221 | * The number of maximum processing threads available to the design space exploration process. | ||
222 | */ | ||
223 | public void setMaxNumberOfThreads(int maxNumberOfThreads) { | ||
224 | globalContext.getThreadPool().setMaximumPoolSize(maxNumberOfThreads); | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * Sets the {@link IDesignSpace} implementation that is to be used during the design space exploration process. By | ||
229 | * default, the {@link DesignSpace} implementation is used. | ||
230 | * | ||
231 | * @param designspace | ||
232 | * The {@link IDesignSpace} implementation. | ||
233 | */ | ||
234 | public final void setDesignspace(IDesignSpace designspace) { | ||
235 | globalContext.setDesignSpace(designspace); | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * Sets the solution store for strategies. Please see the {@link SolutionStore} for how to configure it. | ||
240 | * | ||
241 | * @param solutionStore | ||
242 | * The parameterized {@link SolutionStore} implementation. | ||
243 | */ | ||
244 | public void setSolutionStore(SolutionStore solutionStore) { | ||
245 | globalContext.setSolutionStore(solutionStore); | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * Starts the design space exploration. It returns only when the strategy decides to stop the execution. | ||
250 | * | ||
251 | * @param strategy | ||
252 | * The strategy of the exploration. | ||
253 | */ | ||
254 | public void startExploration(IStrategy strategy) { | ||
255 | startExploration(strategy, true, -1); | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * Starts the design space exploration asynchronously. Completion of the process can be verified by calling | ||
260 | * {@link DesignSpaceExplorer#isDone()}. | ||
261 | * | ||
262 | * @param strategy | ||
263 | * The strategy of the exploration. | ||
264 | */ | ||
265 | public void startExplorationAsync(IStrategy strategy) { | ||
266 | startExploration(strategy, false, -1); | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * Starts the design space exploration with a timeout. It returns only when the strategy decides to stop the | ||
271 | * execution or the given timeout is elapsed. | ||
272 | * | ||
273 | * @param strategy | ||
274 | * The strategy of the exploration. | ||
275 | * @param timeout | ||
276 | * The number of milliseconds before the exploration is forced to stop. | ||
277 | * @return Returns true if the exploration stopped by the timeout. | ||
278 | */ | ||
279 | public boolean startExplorationWithTimeout(IStrategy strategy, long timeout) { | ||
280 | return startExploration(strategy, true, timeout); | ||
281 | } | ||
282 | |||
283 | /** | ||
284 | * Starts the design space exploration asynchronously with a timeout. Completion of the process can be verified by | ||
285 | * calling {@link DesignSpaceExplorer#isDone()}. | ||
286 | * | ||
287 | * @param strategy | ||
288 | * The strategy of the exploration. | ||
289 | * @param timeout | ||
290 | * The number of milliseconds before the exploration is forced to stop. | ||
291 | * @return Returns true if the exploration stopped by the timeout. | ||
292 | */ | ||
293 | public boolean startExplorationAsyncWithTimeout(IStrategy strategy, long timeout) { | ||
294 | return startExploration(strategy, false, timeout); | ||
295 | } | ||
296 | |||
297 | /** | ||
298 | * Starts the design space exploration. If {@code waitForTermination} is true, then it returns only when the | ||
299 | * strategy decides to stop the execution or there was a timeout, otherwise when the exploration process is started | ||
300 | * it returns immediately. In this case, process completion can be verified by calling | ||
301 | * {@link DesignSpaceExplorer#isDone()}. | ||
302 | * | ||
303 | * @param strategy | ||
304 | * The strategy of the exploration. | ||
305 | * @param waitForTermination | ||
306 | * True if the method must wait for the engine to stop, i.e. whether to start synchronously. | ||
307 | * @param timeout | ||
308 | * The number of milliseconds before the exploration is forced to stop. | ||
309 | * @return Returns true if the exploration stopped by the timeout. | ||
310 | */ | ||
311 | public boolean startExploration(IStrategy strategy, boolean waitForTermination, final long timeout) { | ||
312 | initExploration(strategy); | ||
313 | |||
314 | Timer timer = new Timer(); | ||
315 | final AtomicBoolean wasTimeout = new AtomicBoolean(false); | ||
316 | |||
317 | if (timeout > 0) { | ||
318 | TimerTask timerTask = new TimerTask() { | ||
319 | @Override | ||
320 | public void run() { | ||
321 | logger.info("Timeout, stopping threads..."); | ||
322 | globalContext.stopAllThreads(); | ||
323 | wasTimeout.set(true); | ||
324 | } | ||
325 | }; | ||
326 | timer.schedule(timerTask, timeout); | ||
327 | } | ||
328 | |||
329 | if (waitForTermination) { | ||
330 | waitForTerminaition(); | ||
331 | timer.cancel(); | ||
332 | } else { | ||
333 | logger.info("Design space exploration started asynchronously."); | ||
334 | } | ||
335 | |||
336 | return wasTimeout.get(); | ||
337 | |||
338 | } | ||
339 | |||
340 | private void initExploration(IStrategy strategy) { | ||
341 | Preconditions.checkArgument(model != null, MODEL_NOT_YET_GIVEN); | ||
342 | Preconditions.checkArgument(strategy != null, "A strategy must be given. Use the Strategies helper class."); | ||
343 | Preconditions.checkState(!globalContext.getTransformations().isEmpty(), | ||
344 | "At least one transformation rule must be added to start the exploration."); | ||
345 | |||
346 | if (globalContext.getStateCoderFactory() == null) { | ||
347 | if (getMetaModelPackages() == null || getMetaModelPackages().isEmpty()) { | ||
348 | throw new DSEException("Cannot initialize state coder." | ||
349 | + " Please specifiy the EPackages your model uses with addMetaModelPackage(EPackage)"); | ||
350 | } | ||
351 | globalContext.setStateCoderFactory(new SimpleStateCoderFactory(getMetaModelPackages())); | ||
352 | } | ||
353 | |||
354 | logger.info("DesignSpaceExplorer started exploration."); | ||
355 | |||
356 | if (deepCopyModel) { | ||
357 | globalContext.startFirstThread(strategy, model); | ||
358 | } else { | ||
359 | globalContext.startFirstThreadWithoutModelClone(strategy, model); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * Returns all of the found {@link Solution}s, trajectories. Call it after | ||
365 | * {@link DesignSpaceExplorer#startExploration()}. Calling this while the process is running returns the solutions | ||
366 | * that have been found <b>so far</b>. The returned {@link Solution} objects may change internal state after they | ||
367 | * have been returned, if a shorter trajectory has been found to the referred state. | ||
368 | * | ||
369 | * @return The found solutions. | ||
370 | */ | ||
371 | public Collection<Solution> getSolutions() { | ||
372 | return globalContext.getSolutionStore().getSolutions(); | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * Returns an arbitrary solution trajectory or null if the exploration failed to find any. | ||
377 | * | ||
378 | * @return An arbitrary solution trajectory. | ||
379 | */ | ||
380 | public SolutionTrajectory getArbitrarySolution() { | ||
381 | Collection<Solution> solutions = getSolutions(); | ||
382 | if (solutions.isEmpty()) { | ||
383 | return null; | ||
384 | } | ||
385 | return solutions.iterator().next().getArbitraryTrajectory(); | ||
386 | } | ||
387 | |||
388 | /** | ||
389 | * Returns the number of distinct states the exploration process has visited so far. | ||
390 | * | ||
391 | * @return the number of distinct states. | ||
392 | */ | ||
393 | public long getNumberOfStates() { | ||
394 | return globalContext.getDesignSpace().getNumberOfStates(); | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * Returns the number of distinct transitions the exploration process has discovered (but not necessarily traversed) | ||
399 | * so far. | ||
400 | * | ||
401 | * @return the number of distinct transitions. | ||
402 | */ | ||
403 | public long getNumberOfTransitions() { | ||
404 | return globalContext.getDesignSpace().getNumberOfTransitions(); | ||
405 | } | ||
406 | |||
407 | /** | ||
408 | * Returns the {@link EPackage}s, which were registered with the | ||
409 | * {@link DesignSpaceExplorer#addMetaModelPackage(EPackage)} method. | ||
410 | * | ||
411 | * @return The set of meta model packages. | ||
412 | */ | ||
413 | public Set<EPackage> getMetaModelPackages() { | ||
414 | return metaModelPackages; | ||
415 | } | ||
416 | |||
417 | /** | ||
418 | * Returns true if the {@link IExplorerThread strategy} decided to stop, and all the threads finished their work. | ||
419 | * | ||
420 | * @return true if the process has finished, false otherwise. | ||
421 | */ | ||
422 | public boolean isDone() { | ||
423 | return globalContext.isDone(); | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * Returns the {@link GlobalContext} which holds the configurations such as rule, objectives, etc. | ||
428 | * | ||
429 | * @return The global context. | ||
430 | */ | ||
431 | public GlobalContext getGlobalContext() { | ||
432 | return globalContext; | ||
433 | } | ||
434 | |||
435 | /** | ||
436 | * Registers a design space visualizer. Please see the corresponding interface {@link IDesignSpaceVisualizer}. | ||
437 | * | ||
438 | * @see IDesignSpaceVisualizer | ||
439 | * | ||
440 | * @param visualizer | ||
441 | */ | ||
442 | public void addDesignSpaceVisulaizer(IDesignSpaceVisualizer visualizer) { | ||
443 | globalContext.registerDesignSpaceVisualizer(visualizer); | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * Creates a string containing the state codes of all the found solutions and the found trajectories to these | ||
448 | * solutions with fitness values. | ||
449 | * | ||
450 | * @return A pretty string with the solutions. | ||
451 | */ | ||
452 | public String toStringSolutions() { | ||
453 | StringBuilder sb = new StringBuilder(); | ||
454 | Collection<Solution> solutions = getSolutions(); | ||
455 | sb.append("Number of solutions: "); | ||
456 | sb.append(solutions.size()); | ||
457 | sb.append("\n"); | ||
458 | for (Solution solution : solutions) { | ||
459 | sb.append("Solution: "); | ||
460 | sb.append(solution.getStateCode()); | ||
461 | sb.append("\n"); | ||
462 | for (SolutionTrajectory trajectory : solution.getTrajectories()) { | ||
463 | sb.append(" "); | ||
464 | sb.append(trajectory.toPrettyString()); | ||
465 | sb.append("\n"); | ||
466 | } | ||
467 | } | ||
468 | return sb.toString(); | ||
469 | } | ||
470 | |||
471 | /** | ||
472 | * A conflict resolver can filter rule activations the DSE engine will see. The primary use of this is symmetry | ||
473 | * reduction. This function is subject to change for better API. | ||
474 | * | ||
475 | * @param conflictResolver | ||
476 | */ | ||
477 | public void setConflictResolver(ConflictResolver conflictResolver) { | ||
478 | globalContext.setConflictResolver(conflictResolver); | ||
479 | } | ||
480 | |||
481 | /** | ||
482 | * Enumeration for different use cases of logging, including: | ||
483 | * <ul> | ||
484 | * <li>OFF - no error messages.</li> | ||
485 | * <li>WARN - only error and warn messages.</li> | ||
486 | * <li>BASIC - logs basic information on how the exploration is going.</li> | ||
487 | * <li>VERBOSE_STRATEGY - logs everything the exploration strategy is prepared for.</li> | ||
488 | * <li>VERBOSE_FULL - logs every transformation.</li> | ||
489 | * </ul> | ||
490 | * | ||
491 | * @author Andras Szabolcs Nagy | ||
492 | * | ||
493 | */ | ||
494 | public enum DseLoggingLevel { | ||
495 | OFF, WARN, BASIC, VERBOSE_STRATEGY, VERBOSE_FULL | ||
496 | } | ||
497 | |||
498 | /** | ||
499 | * Changes the level of logging. See {@link DseLoggingLevel} for details. | ||
500 | * | ||
501 | * @param dseLoggingLevel | ||
502 | */ | ||
503 | public static void turnOnLogging(DseLoggingLevel dseLoggingLevel) { | ||
504 | switch (dseLoggingLevel) { | ||
505 | case OFF: | ||
506 | Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.OFF); | ||
507 | Logger.getLogger(IStrategy.class).setLevel(Level.OFF); | ||
508 | Logger.getLogger(DesignSpaceManager.class).setLevel(Level.OFF); | ||
509 | break; | ||
510 | case WARN: | ||
511 | Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.WARN); | ||
512 | Logger.getLogger(IStrategy.class).setLevel(Level.WARN); | ||
513 | Logger.getLogger(DesignSpaceManager.class).setLevel(Level.WARN); | ||
514 | break; | ||
515 | case BASIC: | ||
516 | Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.INFO); | ||
517 | Logger.getLogger(IStrategy.class).setLevel(Level.INFO); | ||
518 | Logger.getLogger(DesignSpaceManager.class).setLevel(Level.WARN); | ||
519 | break; | ||
520 | case VERBOSE_STRATEGY: | ||
521 | Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.DEBUG); | ||
522 | Logger.getLogger(IStrategy.class).setLevel(Level.DEBUG); | ||
523 | Logger.getLogger(DesignSpaceManager.class).setLevel(Level.WARN); | ||
524 | break; | ||
525 | case VERBOSE_FULL: | ||
526 | Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.DEBUG); | ||
527 | Logger.getLogger(IStrategy.class).setLevel(Level.DEBUG); | ||
528 | Logger.getLogger(DesignSpaceManager.class).setLevel(Level.DEBUG); | ||
529 | break; | ||
530 | default: | ||
531 | throw new DSEException("Not supported logging level."); | ||
532 | } | ||
533 | } | ||
534 | |||
535 | /** | ||
536 | * Changes the level of logging. See {@link DseLoggingLevel} for details. | ||
537 | * | ||
538 | * Also configures a basic console appender for log4j. | ||
539 | * | ||
540 | * @param dseLoggingLevel | ||
541 | */ | ||
542 | public static void turnOnLoggingWithBasicConfig(DseLoggingLevel dseLoggingLevel) { | ||
543 | BasicConfigurator.configure(); | ||
544 | Logger.getRootLogger().setLevel(Level.WARN); | ||
545 | turnOnLogging(dseLoggingLevel); | ||
546 | } | ||
547 | |||
548 | /** | ||
549 | * Stops the exploration and waits for termination. It has no effect if the exploration is already terminated or not | ||
550 | * even started. | ||
551 | */ | ||
552 | public void stopExploration() { | ||
553 | if (globalContext.isDone()) { | ||
554 | logger.info("Cannot stop exploration - design space exploration has already finished."); | ||
555 | } else if (globalContext.isNotStarted()) { | ||
556 | logger.info("Cannot stop exploration - design space exploration has not been started."); | ||
557 | } else { | ||
558 | globalContext.stopAllThreads(); | ||
559 | waitForTerminaition(); | ||
560 | } | ||
561 | } | ||
562 | |||
563 | /** | ||
564 | * Stops the exploration asynchronously. It has no effect if the exploration is already terminated or not even | ||
565 | * started. | ||
566 | */ | ||
567 | public void stopExplorationAsync() { | ||
568 | if (globalContext.isDone()) { | ||
569 | logger.info("Cannot stop exploration - design space exploration has already finished."); | ||
570 | } else if (globalContext.isNotStarted()) { | ||
571 | logger.info("Cannot stop exploration - design space exploration has not been started."); | ||
572 | } else { | ||
573 | globalContext.stopAllThreads(); | ||
574 | } | ||
575 | } | ||
576 | |||
577 | /** | ||
578 | * Waits for termination. | ||
579 | */ | ||
580 | public void waitForTerminaition() { | ||
581 | globalContext.waitForTermination(); | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * Serializes all the found solutions by transforming the given initial model. | ||
586 | * </p>Files will be named <code>solution[id].xmi</code>. | ||
587 | * @param model The initial model. | ||
588 | */ | ||
589 | public void saveModels(Notifier model) { | ||
590 | this.saveModels(model, "solution", "xmi"); | ||
591 | } | ||
592 | |||
593 | /** | ||
594 | * Serializes all the found solutions by transforming the given initial model. | ||
595 | * </p>Files will be named <code>solution[id].[extension]</code>. | ||
596 | * @param model The initial model. | ||
597 | * @param extension The extension of the omitted file. | ||
598 | */ | ||
599 | public void saveModels(Notifier model, String extension) { | ||
600 | this.saveModels(model, "solution", extension); | ||
601 | } | ||
602 | |||
603 | /** | ||
604 | * Serializes all the found solutions by transforming the given initial model. | ||
605 | * </p>Files will be named <code>[fileNamePrefix][id].[extension]</code>. | ||
606 | * @param model The initial model. | ||
607 | * @param fileNamePrefix The prefix (optionally including a file path) of the omitted file. | ||
608 | * @param extension The extension of the omitted file. | ||
609 | */ | ||
610 | public void saveModels(Notifier model, String fileNamePrefix, String extension) { | ||
611 | globalContext.getSolutionStore().saveModels(model, new IdBasedSolutionNameProvider(fileNamePrefix, extension)); | ||
612 | } | ||
613 | |||
614 | /** | ||
615 | * Serializes all the found solutions by transforming the given initial model. | ||
616 | * </p>Files will be named using the {@link ISolutionNameProvider}. | ||
617 | * @param model The initial model. | ||
618 | */ | ||
619 | public void saveModels(Notifier model, ISolutionNameProvider solutionNameProvider) { | ||
620 | globalContext.getSolutionStore().saveModels(model, solutionNameProvider); | ||
621 | } | ||
622 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Objectives.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Objectives.java new file mode 100644 index 00000000..3b375fac --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Objectives.java | |||
@@ -0,0 +1,153 @@ | |||
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.api; | ||
10 | |||
11 | import org.eclipse.viatra.dse.objectives.impl.CompositeObjective; | ||
12 | import org.eclipse.viatra.dse.objectives.impl.ConstraintsObjective; | ||
13 | import org.eclipse.viatra.dse.objectives.impl.AlwaysSatisfiedDummyHardObjective; | ||
14 | import org.eclipse.viatra.dse.objectives.impl.DepthHardObjective; | ||
15 | import org.eclipse.viatra.dse.objectives.impl.NeverSatisfiedDummyHardObjective; | ||
16 | import org.eclipse.viatra.dse.objectives.impl.NoRuleActivationsHardObjective; | ||
17 | import org.eclipse.viatra.dse.objectives.impl.TrajectoryCostSoftObjective; | ||
18 | |||
19 | /** | ||
20 | * | ||
21 | * Helper class for creating built-in objectives. | ||
22 | * | ||
23 | * @author Andras Szabolcs Nagy | ||
24 | * | ||
25 | */ | ||
26 | public class Objectives { | ||
27 | |||
28 | private Objectives() { | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * This objective uses VIATRA Queries to calculate fitness and/or goal constraints. Use methods on the returned | ||
33 | * objective to configure it. | ||
34 | * | ||
35 | * @param name | ||
36 | * @return The objective. | ||
37 | * @see ConstraintsObjective | ||
38 | */ | ||
39 | public static ConstraintsObjective createConstraintsObjective(String name) { | ||
40 | return new ConstraintsObjective(name); | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * This objective calculates fitness on the trajectory by adding either fix costs to the rules, or by calculating | ||
45 | * custom fitness on activation of rules. | ||
46 | * | ||
47 | * @param name | ||
48 | * @return The objective. | ||
49 | * @see TrajectoryCostSoftObjective | ||
50 | */ | ||
51 | public static TrajectoryCostSoftObjective createTrajcetoryCostObjective(String name) { | ||
52 | return new TrajectoryCostSoftObjective(name); | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * This objective adds a goal constraint that a solution state should not have any activations. | ||
57 | * | ||
58 | * @return The objective. | ||
59 | * @see NoRuleActivationsHardObjective | ||
60 | */ | ||
61 | public static NoRuleActivationsHardObjective createNoRuleActivationsHardConstraint() { | ||
62 | return new NoRuleActivationsHardObjective(); | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * This objective adds a goal constraint that a solution state should not have any activations. | ||
67 | * | ||
68 | * @param name | ||
69 | * @return The objective. | ||
70 | * @see NoRuleActivationsHardObjective | ||
71 | */ | ||
72 | public static NoRuleActivationsHardObjective createNoRuleActivationsHardConstraint(String name) { | ||
73 | return new NoRuleActivationsHardObjective(name); | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * This objective can combine the calculated fitness value of other objectives. Weights are supported. | ||
78 | * | ||
79 | * @param name | ||
80 | * @return The objective. | ||
81 | * @see NoRuleActivationsHardObjective | ||
82 | */ | ||
83 | public static CompositeObjective createCompositeObjective(String name) { | ||
84 | return new CompositeObjective(name); | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid | ||
89 | * solution. | ||
90 | * | ||
91 | * @return The objective. | ||
92 | * @see AlwaysSatisfiedDummyHardObjective | ||
93 | */ | ||
94 | public static AlwaysSatisfiedDummyHardObjective createAlwaysSatisfiedDummyHardObjective() { | ||
95 | return new AlwaysSatisfiedDummyHardObjective(); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid | ||
100 | * solution. | ||
101 | * | ||
102 | * @param name | ||
103 | * @return The objective. | ||
104 | * @see AlwaysSatisfiedDummyHardObjective | ||
105 | */ | ||
106 | public static AlwaysSatisfiedDummyHardObjective createDummyHardObjective(String name) { | ||
107 | return new AlwaysSatisfiedDummyHardObjective(name); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * This hard objective is never fulfilled. Use it if all states should be regarded as an invalid solution. | ||
112 | * | ||
113 | * @return The objective. | ||
114 | * @see AlwaysSatisfiedDummyHardObjective | ||
115 | */ | ||
116 | public static NeverSatisfiedDummyHardObjective createNeverSatisfiedDummyHardObjective() { | ||
117 | return new NeverSatisfiedDummyHardObjective(); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * This hard objective is never fulfilled. Use it if all states should be regarded as an invalid solution. | ||
122 | * | ||
123 | * @return The objective. | ||
124 | * @see AlwaysSatisfiedDummyHardObjective | ||
125 | */ | ||
126 | public static NeverSatisfiedDummyHardObjective createNeverSatisfiedDummyHardObjective(String name) { | ||
127 | return new NeverSatisfiedDummyHardObjective(name); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * This hard objective is fulfilled if the length of the trajectory is in the specified interval (inclusive). Use | ||
132 | * {@link DepthHardObjective#withMinDepth(int)} and {@link DepthHardObjective#withMaxDepth(int)} to configure. | ||
133 | * | ||
134 | * @return The objective. | ||
135 | * @see DepthHardObjective | ||
136 | */ | ||
137 | public static DepthHardObjective createDepthHardObjective() { | ||
138 | return new DepthHardObjective(); | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * This hard objective is fulfilled if the length of the trajectory is in the specified interval (inclusive). Use | ||
143 | * {@link DepthHardObjective#withMinDepth(int)} and {@link DepthHardObjective#withMaxDepth(int)} to configure. | ||
144 | * | ||
145 | * @param name | ||
146 | * @return The objective. | ||
147 | * @see DepthHardObjective | ||
148 | */ | ||
149 | public static DepthHardObjective createDepthHardObjective(String name) { | ||
150 | return new DepthHardObjective(name); | ||
151 | } | ||
152 | |||
153 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Solution.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Solution.java new file mode 100644 index 00000000..b776db7a --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Solution.java | |||
@@ -0,0 +1,60 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.api; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Iterator; | ||
14 | import java.util.Set; | ||
15 | |||
16 | public class Solution { | ||
17 | |||
18 | private Set<SolutionTrajectory> trajectories; | ||
19 | private final Object stateId; | ||
20 | |||
21 | public Solution(Object stateId, SolutionTrajectory trajectory) { | ||
22 | this.stateId = stateId; | ||
23 | trajectories = new HashSet<>(); | ||
24 | trajectories.add(trajectory); | ||
25 | } | ||
26 | |||
27 | public void addTrajectory(SolutionTrajectory trajectory) { | ||
28 | trajectories.add(trajectory); | ||
29 | } | ||
30 | |||
31 | public SolutionTrajectory getArbitraryTrajectory() { | ||
32 | return trajectories.iterator().next(); | ||
33 | } | ||
34 | |||
35 | public SolutionTrajectory getShortestTrajectory() { | ||
36 | Iterator<SolutionTrajectory> iterator = trajectories.iterator(); | ||
37 | SolutionTrajectory shortestTrajecotry = iterator.next(); | ||
38 | int minSize = shortestTrajecotry.getTrajectoryLength(); | ||
39 | |||
40 | while (iterator.hasNext()) { | ||
41 | SolutionTrajectory traj = iterator.next(); | ||
42 | int size = traj.getTrajectoryLength(); | ||
43 | if (size < minSize) { | ||
44 | shortestTrajecotry = traj; | ||
45 | minSize = size; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | return shortestTrajecotry; | ||
50 | } | ||
51 | |||
52 | public Collection<SolutionTrajectory> getTrajectories() { | ||
53 | return trajectories; | ||
54 | } | ||
55 | |||
56 | public Object getStateCode() { | ||
57 | return stateId; | ||
58 | } | ||
59 | |||
60 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/SolutionTrajectory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/SolutionTrajectory.java new file mode 100644 index 00000000..d1a41065 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/SolutionTrajectory.java | |||
@@ -0,0 +1,338 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.api; | ||
10 | |||
11 | import java.lang.reflect.InvocationTargetException; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.List; | ||
14 | import java.util.Objects; | ||
15 | import java.util.function.Consumer; | ||
16 | |||
17 | import org.eclipse.emf.common.notify.Notifier; | ||
18 | import org.eclipse.emf.edit.command.ChangeCommand; | ||
19 | import org.eclipse.emf.edit.domain.EditingDomain; | ||
20 | import org.eclipse.viatra.dse.base.DseIdPoolHelper; | ||
21 | import org.eclipse.viatra.dse.designspace.api.IBacktrackListener; | ||
22 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
23 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
24 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
25 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
26 | import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine; | ||
27 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
28 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
29 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher; | ||
30 | import org.eclipse.viatra.query.runtime.emf.EMFScope; | ||
31 | import org.eclipse.viatra.query.runtime.matchers.ViatraQueryRuntimeException; | ||
32 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
33 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
34 | |||
35 | import com.google.common.util.concurrent.UncheckedExecutionException; | ||
36 | |||
37 | /** | ||
38 | * A SolutionTrajectory represents a trajectory (i.e. sequence of transformation | ||
39 | * rule applications), which can transform the initial model to a desired state. | ||
40 | * An instance of this class holds the the actual rule sequence and the | ||
41 | * corresponding activation codes. Furthermore it can be used to perform the | ||
42 | * transformation on a given model (if possible). | ||
43 | * <p> | ||
44 | * It is also possible to undo the transformation if initialized with an editing | ||
45 | * domain. | ||
46 | * <p> | ||
47 | * The instance of this class can be reused for different models. | ||
48 | * | ||
49 | * @author Andras Szabolcs Nagy | ||
50 | * | ||
51 | */ | ||
52 | public class SolutionTrajectory { | ||
53 | |||
54 | private final List<Object> activationCodes; | ||
55 | private final List<BatchTransformationRule<?, ?>> transformationRules; | ||
56 | private final IStateCoderFactory stateCoderFactory; | ||
57 | private Fitness fitness; | ||
58 | private Solution solution; | ||
59 | |||
60 | private ViatraQueryEngine engine; | ||
61 | private Notifier model; | ||
62 | private EditingDomain editingDomain; | ||
63 | private IStateCoder stateCoder; | ||
64 | private IBacktrackListener listener; | ||
65 | |||
66 | private int currentIndex; | ||
67 | |||
68 | public SolutionTrajectory(final List<Object> activationCodes, | ||
69 | final List<BatchTransformationRule<?, ?>> transformationRules, final IStateCoderFactory stateCoderFactory, | ||
70 | final IBacktrackListener backtrackListener) { | ||
71 | Objects.requireNonNull(transformationRules, "Parameter transformationRules cannot be null!"); | ||
72 | Objects.requireNonNull(stateCoderFactory, "Parameter stateCoderFactory cannot be null!"); | ||
73 | Objects.requireNonNull(activationCodes, "Parameter activations cannot be null!"); | ||
74 | Preconditions.checkState(transformationRules.size() == activationCodes.size(), | ||
75 | "The two List parameters must be the same in size."); | ||
76 | |||
77 | this.activationCodes = activationCodes; | ||
78 | this.transformationRules = transformationRules; | ||
79 | this.stateCoderFactory = stateCoderFactory; | ||
80 | this.listener = backtrackListener; | ||
81 | currentIndex = 0; | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * Initialize this SolutionTrajectory for transforming the model along the | ||
86 | * trajectory. | ||
87 | * | ||
88 | * @param model The model. | ||
89 | * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize. | ||
90 | */ | ||
91 | public void setModel(Notifier model) { | ||
92 | editingDomain = null; | ||
93 | EMFScope scope = new EMFScope(model); | ||
94 | this.engine = ViatraQueryEngine.on(scope); | ||
95 | this.model = model; | ||
96 | stateCoder = stateCoderFactory.createStateCoder(); | ||
97 | stateCoder.init(model); | ||
98 | currentIndex = 0; | ||
99 | DseIdPoolHelper.INSTANCE.disposeByThread(); | ||
100 | DseIdPoolHelper.INSTANCE.registerRules(rule -> { | ||
101 | int id = 0; | ||
102 | for (BatchTransformationRule<?, ?> r : transformationRules.subList(0, currentIndex)) { | ||
103 | if (r.equals(rule)) { | ||
104 | id++; | ||
105 | } | ||
106 | } | ||
107 | return id; | ||
108 | }, new HashSet<BatchTransformationRule<?, ?>>(transformationRules)); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * Initialize this SolutionTrajectory for transforming the given model along the | ||
113 | * trajectory. | ||
114 | * <p> | ||
115 | * The transformation will be reversible by creating an {@link EditingDomain} on | ||
116 | * the model. | ||
117 | * | ||
118 | * @param modelRoot The root of the model. | ||
119 | * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize. | ||
120 | */ | ||
121 | public void setModelWithEditingDomain(Notifier modelRoot) { | ||
122 | setModel(modelRoot); | ||
123 | editingDomain = EMFHelper.createEditingDomain(model); | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Transforms the given model along the trajectory. | ||
128 | * | ||
129 | * @param modelRoot The root of the model. | ||
130 | * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize. | ||
131 | */ | ||
132 | public void doTransformation(Notifier modelRoot) { | ||
133 | setModel(modelRoot); | ||
134 | doTransformation(); | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * Transforms the given model along the trajectory. | ||
139 | * <p> | ||
140 | * The transformation will be reversible by creating an {@link EditingDomain} on | ||
141 | * the model. | ||
142 | * | ||
143 | * @param modelRoot The root of the model. | ||
144 | * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize. | ||
145 | */ | ||
146 | public void doTransformationUndoable(Notifier modelRoot) { | ||
147 | setModelWithEditingDomain(modelRoot); | ||
148 | doTransformation(); | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * Transforms the given model along the trajectory. To initialize the model call | ||
153 | * the {@link SolutionTrajectory#setModel(Notifier)} method. | ||
154 | * | ||
155 | * @throws Exception If the activation to fire is not found. | ||
156 | * Possible problems: wrong model, bad state | ||
157 | * serializer. | ||
158 | * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize. | ||
159 | */ | ||
160 | public void doTransformation() { | ||
161 | while (doNextTransformation()) | ||
162 | ; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * Transforms the given model by one step to the solution (makes one step in the | ||
167 | * trajectory). To initialize the model call the | ||
168 | * {@link SolutionTrajectory#setModel(Notifier)} method. | ||
169 | * | ||
170 | * @throws ViatraQueryRuntimeException | ||
171 | */ | ||
172 | public boolean doNextTransformation() { | ||
173 | if (currentIndex >= activationCodes.size()) { | ||
174 | return false; | ||
175 | } else { | ||
176 | doNextTransformation(currentIndex); | ||
177 | currentIndex++; | ||
178 | return true; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | @SuppressWarnings("unchecked") | ||
183 | private void doNextTransformation(int index) { | ||
184 | Objects.requireNonNull(model, "The model cannot be null! Use the setModel method."); | ||
185 | |||
186 | // cast for the ".process(match)" method. | ||
187 | BatchTransformationRule<?, ?> tr = transformationRules.get(index); | ||
188 | Object activationCode = activationCodes.get(index); | ||
189 | |||
190 | ViatraQueryMatcher<?> matcher = tr.getPrecondition().getMatcher(engine); | ||
191 | |||
192 | boolean isActivationFound = false; | ||
193 | for (final IPatternMatch match : matcher.getAllMatches()) { | ||
194 | Object matchHash = stateCoder.createActivationCode(match); | ||
195 | if (matchHash.equals(activationCode)) { | ||
196 | @SuppressWarnings("rawtypes") | ||
197 | final Consumer action = tr.getAction(); | ||
198 | |||
199 | if (editingDomain == null) { | ||
200 | action.accept(match); | ||
201 | } else { | ||
202 | ChangeCommand cc = new ChangeCommand(model) { | ||
203 | @Override | ||
204 | protected void doExecute() { | ||
205 | action.accept(match); | ||
206 | } | ||
207 | }; | ||
208 | long start = System.nanoTime(); | ||
209 | editingDomain.getCommandStack().execute(cc); | ||
210 | listener.forwardWorked(System.nanoTime() - start); | ||
211 | } | ||
212 | |||
213 | isActivationFound = true; | ||
214 | break; | ||
215 | } | ||
216 | } | ||
217 | if (!isActivationFound) { | ||
218 | throw new UncheckedExecutionException( | ||
219 | "Activation was not found for transformation! Possible cause: wrong model, bad state coder. index: " | ||
220 | + index + " Activation code: " + activationCode, | ||
221 | null); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * Call this method to undo the last transformation. | ||
227 | * | ||
228 | * @return True, if it was successful. | ||
229 | */ | ||
230 | public boolean undoLastTransformation() { | ||
231 | Objects.requireNonNull(editingDomain, "To be able to undo the transformation initialize with editing domain."); | ||
232 | long start = System.nanoTime(); | ||
233 | boolean result; | ||
234 | |||
235 | if (currentIndex > 0) { | ||
236 | try { | ||
237 | ((AdvancedViatraQueryEngine) engine).delayUpdatePropagation(() -> { | ||
238 | editingDomain.getCommandStack().undo(); | ||
239 | return null; | ||
240 | }); | ||
241 | } catch (InvocationTargetException e) { | ||
242 | throw new RuntimeException(e); | ||
243 | } | ||
244 | currentIndex--; | ||
245 | result = true; | ||
246 | } | ||
247 | result = false; | ||
248 | listener.backtrackWorked(System.nanoTime() - start); | ||
249 | return result; | ||
250 | } | ||
251 | |||
252 | /** | ||
253 | * Call this method to undo the transformation. | ||
254 | */ | ||
255 | public void undoTransformation() { | ||
256 | while (undoLastTransformation()) | ||
257 | ; | ||
258 | } | ||
259 | |||
260 | public List<Object> getActivationCodes() { | ||
261 | return activationCodes; | ||
262 | } | ||
263 | |||
264 | public List<BatchTransformationRule<?, ?>> getTransformationRules() { | ||
265 | return transformationRules; | ||
266 | } | ||
267 | |||
268 | public IStateCoderFactory getStateCoderFactory() { | ||
269 | return stateCoderFactory; | ||
270 | } | ||
271 | |||
272 | public ViatraQueryEngine getEngine() { | ||
273 | return engine; | ||
274 | } | ||
275 | |||
276 | public Notifier getModel() { | ||
277 | return model; | ||
278 | } | ||
279 | |||
280 | public IStateCoder getStateCoder() { | ||
281 | return stateCoder; | ||
282 | } | ||
283 | |||
284 | public int getCurrentIndex() { | ||
285 | return currentIndex; | ||
286 | } | ||
287 | |||
288 | public int getTrajectoryLength() { | ||
289 | return activationCodes.size(); | ||
290 | } | ||
291 | |||
292 | public Fitness getFitness() { | ||
293 | return fitness; | ||
294 | } | ||
295 | |||
296 | public void setFitness(Fitness fitness) { | ||
297 | this.fitness = fitness; | ||
298 | } | ||
299 | |||
300 | public String toPrettyString() { | ||
301 | StringBuilder sb = new StringBuilder(); | ||
302 | sb.append("Fitness: "); | ||
303 | sb.append(fitness.toString()); | ||
304 | sb.append(" | Trajectory ("); | ||
305 | sb.append(activationCodes.size()); | ||
306 | sb.append("): "); | ||
307 | for (Object object : activationCodes) { | ||
308 | sb.append(object.toString()); | ||
309 | sb.append(" | "); | ||
310 | } | ||
311 | return sb.toString(); | ||
312 | } | ||
313 | |||
314 | @Override | ||
315 | public int hashCode() { | ||
316 | return activationCodes.hashCode(); | ||
317 | } | ||
318 | |||
319 | @Override | ||
320 | public boolean equals(Object obj) { | ||
321 | if (this == obj) { | ||
322 | return true; | ||
323 | } | ||
324 | if (obj instanceof SolutionTrajectory) { | ||
325 | SolutionTrajectory that = (SolutionTrajectory) obj; | ||
326 | return activationCodes.equals(that.activationCodes); | ||
327 | } | ||
328 | return false; | ||
329 | } | ||
330 | |||
331 | public Solution getSolution() { | ||
332 | return solution; | ||
333 | } | ||
334 | |||
335 | public void setSolution(Solution solution) { | ||
336 | this.solution = solution; | ||
337 | } | ||
338 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Strategies.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Strategies.java new file mode 100644 index 00000000..ed7a90da --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Strategies.java | |||
@@ -0,0 +1,123 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.api; | ||
10 | |||
11 | import org.eclipse.viatra.dse.api.strategy.impl.BestFirstStrategy; | ||
12 | import org.eclipse.viatra.dse.api.strategy.impl.BreadthFirstStrategy; | ||
13 | import org.eclipse.viatra.dse.api.strategy.impl.DepthFirstStrategy; | ||
14 | import org.eclipse.viatra.dse.api.strategy.impl.FixedPriorityStrategy; | ||
15 | import org.eclipse.viatra.dse.api.strategy.impl.HillClimbingStrategy; | ||
16 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
17 | |||
18 | /** | ||
19 | * Helper class for instantiating strategies. To implement a new strategy use the {@link IStrategy} interface. | ||
20 | * | ||
21 | * @author Andras Szabolcs Nagy | ||
22 | * | ||
23 | */ | ||
24 | public final class Strategies { | ||
25 | |||
26 | private Strategies() { | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * Creates a depth-first search exploration strategy without a depth limit. | ||
31 | * | ||
32 | * @return The strategy. | ||
33 | * @see DepthFirstStrategy | ||
34 | */ | ||
35 | public static DepthFirstStrategy createDfsStrategy() { | ||
36 | return new DepthFirstStrategy(); | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * Creates a depth-first search exploration strategy with a depth limit. A negative depth limit means no | ||
41 | * depth limit, zero means that it will check the initial state. | ||
42 | * | ||
43 | * @param depthLimit | ||
44 | * @return The strategy. | ||
45 | * @see DepthFirstStrategy | ||
46 | */ | ||
47 | public static DepthFirstStrategy createDfsStrategy(int depthLimit) { | ||
48 | return new DepthFirstStrategy(depthLimit); | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * Creates a fixed priority exploration strategy without a depth limit. It is a depth-first search exploration | ||
53 | * strategy but from a current state it only explores the activations with the highest priority. Priorities can be | ||
54 | * defined on the strategy itself. | ||
55 | * | ||
56 | * @return The strategy. | ||
57 | * @see FixedPriorityStrategy | ||
58 | */ | ||
59 | public static FixedPriorityStrategy createFixedPriorityStrategy() { | ||
60 | return createFixedPriorityStrategy(-1); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * Creates a fixed priority exploration strategy with a depth limit, where a zero or negative depth limit means no | ||
65 | * depth limit. It is a depth-first search exploration strategy but from a current state it only explores the | ||
66 | * activations with the highest priority. Priorities can be defined on the strategy itself. | ||
67 | * | ||
68 | * @param depthLimit | ||
69 | * @return The strategy. | ||
70 | * @see FixedPriorityStrategy | ||
71 | */ | ||
72 | public static FixedPriorityStrategy createFixedPriorityStrategy(int depthLimit) { | ||
73 | return new FixedPriorityStrategy().withDepthLimit(depthLimit); | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * Creates a breadth-first search exploration strategy without a depth limit. | ||
78 | * | ||
79 | * @return The strategy. | ||
80 | * @see BreadthFirstStrategy | ||
81 | */ | ||
82 | public static BreadthFirstStrategy createBfsStrategy() { | ||
83 | return new BreadthFirstStrategy(); | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * Creates a breadth-first search exploration strategy with a depth limit. A zero or negative depth limit means no | ||
88 | * depth limit. | ||
89 | * | ||
90 | * @param depthLimit | ||
91 | * @return The strategy. | ||
92 | * @see BreadthFirstStrategy | ||
93 | */ | ||
94 | public static BreadthFirstStrategy createBfsStrategy(int depthLimit) { | ||
95 | return new BreadthFirstStrategy(depthLimit); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * Creates a hill climbing exploration strategy. By default, it explores all neighborhood states and chooses the | ||
100 | * best one to continue with until all neighborhood states are dominated by the current state. Other options are | ||
101 | * available on the strategy. | ||
102 | * | ||
103 | * @return The strategy. | ||
104 | * @see HillClimbingStrategy | ||
105 | */ | ||
106 | public static HillClimbingStrategy creatHillClimbingStrategy() { | ||
107 | return new HillClimbingStrategy(); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * See {@link BestFirstStrategy}. | ||
112 | */ | ||
113 | public static BestFirstStrategy createBestFirstStrategy() { | ||
114 | return new BestFirstStrategy(); | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * See {@link BestFirstStrategy}. | ||
119 | */ | ||
120 | public static BestFirstStrategy createBestFirstStrategy(int depthLimit) { | ||
121 | return new BestFirstStrategy(depthLimit); | ||
122 | } | ||
123 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.java new file mode 100644 index 00000000..fe5604a1 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.java | |||
@@ -0,0 +1,228 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.api.strategy.impl; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.Collection; | ||
13 | import java.util.Iterator; | ||
14 | import java.util.PriorityQueue; | ||
15 | |||
16 | import org.apache.log4j.Logger; | ||
17 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
18 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
19 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
20 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | ||
21 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
22 | |||
23 | /** | ||
24 | * This exploration strategy eventually explorers the whole design space but goes in the most promising directions | ||
25 | * first, based on the {@link Fitness}. | ||
26 | * | ||
27 | * There are a few parameter to tune such as | ||
28 | * <ul> | ||
29 | * <li>maximum depth</li> | ||
30 | * <li>continue the exploration from a state that satisfies the hard objectives (the default that it will | ||
31 | * backtrack),</li> | ||
32 | * <li>whether to continue the exploration from the newly explored state if it is at least equally good than the | ||
33 | * previous one or only if it is better (default is "at least equally good").</li> | ||
34 | * </ul> | ||
35 | * | ||
36 | * @author Andras Szabolcs Nagy | ||
37 | * | ||
38 | */ | ||
39 | public class BestFirstStrategy implements IStrategy { | ||
40 | |||
41 | private ThreadContext context; | ||
42 | private SolutionStore solutionStore; | ||
43 | |||
44 | private int maxDepth; | ||
45 | private boolean isInterrupted = false; | ||
46 | private boolean backTrackIfSolution = true; | ||
47 | private boolean onlyBetterFirst = false; | ||
48 | |||
49 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; | ||
50 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
51 | |||
52 | private static class TrajectoryWithFitness { | ||
53 | |||
54 | public Object[] trajectory; | ||
55 | public Fitness fitness; | ||
56 | |||
57 | public TrajectoryWithFitness(Object[] trajectory, Fitness fitness) { | ||
58 | super(); | ||
59 | this.trajectory = trajectory; | ||
60 | this.fitness = fitness; | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public String toString() { | ||
65 | return Arrays.toString(trajectory) + fitness.toString(); | ||
66 | } | ||
67 | |||
68 | } | ||
69 | |||
70 | /** | ||
71 | * Creates a new best-first search algorithm without depth limit. | ||
72 | */ | ||
73 | public BestFirstStrategy() { | ||
74 | this(-1); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * Creates a new best-first search algorithm with depth limit. | ||
79 | * | ||
80 | * @param maxDepth | ||
81 | * A negative <code>maxDepth</code> means no depth limit, zero means the checking of the initial state. | ||
82 | */ | ||
83 | public BestFirstStrategy(int maxDepth) { | ||
84 | if (maxDepth < 0) { | ||
85 | this.maxDepth = Integer.MAX_VALUE; | ||
86 | } else { | ||
87 | this.maxDepth = maxDepth; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | public BestFirstStrategy continueIfHardObjectivesFulfilled() { | ||
92 | backTrackIfSolution = false; | ||
93 | return this; | ||
94 | } | ||
95 | |||
96 | public BestFirstStrategy goOnOnlyIfFitnessIsBetter() { | ||
97 | onlyBetterFirst = true; | ||
98 | return this; | ||
99 | } | ||
100 | |||
101 | @Override | ||
102 | public void initStrategy(ThreadContext context) { | ||
103 | this.context = context; | ||
104 | this.solutionStore = context.getGlobalContext().getSolutionStore(); | ||
105 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | ||
106 | |||
107 | trajectoiresToExplore = new PriorityQueue<TrajectoryWithFitness>(11, | ||
108 | (o1, o2) -> objectiveComparatorHelper.compare(o2.fitness, o1.fitness)); | ||
109 | } | ||
110 | |||
111 | @Override | ||
112 | public void explore() { | ||
113 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | ||
114 | |||
115 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
116 | if (!globalConstraintsAreSatisfied) { | ||
117 | logger.info("Global contraint is not satisifed in the first state. Terminate."); | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | final Fitness firstFittness = context.calculateFitness(); | ||
122 | if (firstFittness.isSatisifiesHardObjectives()) { | ||
123 | context.newSolution(); | ||
124 | logger.info("First state is a solution. Terminate."); | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | if (maxDepth == 0) { | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); | ||
133 | TrajectoryWithFitness currentTrajectoryWithFittness = new TrajectoryWithFitness(firstTrajectory, firstFittness); | ||
134 | trajectoiresToExplore.add(currentTrajectoryWithFittness); | ||
135 | |||
136 | mainLoop: while (!isInterrupted) { | ||
137 | |||
138 | if (currentTrajectoryWithFittness == null) { | ||
139 | if (trajectoiresToExplore.isEmpty()) { | ||
140 | logger.debug("State space is fully traversed."); | ||
141 | return; | ||
142 | } else { | ||
143 | currentTrajectoryWithFittness = trajectoiresToExplore.element(); | ||
144 | if (logger.isDebugEnabled()) { | ||
145 | logger.debug("New trajectory is chosen: " + currentTrajectoryWithFittness); | ||
146 | } | ||
147 | context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFittness.trajectory); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | Collection<Object> activationIds = context.getUntraversedActivationIds(); | ||
152 | Iterator<Object> iterator = activationIds.iterator(); | ||
153 | |||
154 | while (!isInterrupted && iterator.hasNext()) { | ||
155 | final Object nextActivation = iterator.next(); | ||
156 | if (!iterator.hasNext()) { | ||
157 | logger.debug("Last untraversed activation of the state."); | ||
158 | trajectoiresToExplore.remove(currentTrajectoryWithFittness); | ||
159 | } | ||
160 | |||
161 | if (logger.isDebugEnabled()) { | ||
162 | logger.debug("Executing new activation: " + nextActivation); | ||
163 | } | ||
164 | context.executeAcitvationId(nextActivation); | ||
165 | if (context.isCurrentStateAlreadyTraversed()) { | ||
166 | logger.info("The new state is already visited."); | ||
167 | context.backtrack(); | ||
168 | } else if (!context.checkGlobalConstraints()) { | ||
169 | logger.debug("Global contraint is not satisifed."); | ||
170 | context.backtrack(); | ||
171 | } else { | ||
172 | final Fitness nextFitness = context.calculateFitness(); | ||
173 | if (nextFitness.isSatisifiesHardObjectives()) { | ||
174 | solutionStore.newSolution(context); | ||
175 | logger.debug("Found a solution."); | ||
176 | if (backTrackIfSolution) { | ||
177 | context.backtrack(); | ||
178 | continue; | ||
179 | } | ||
180 | } | ||
181 | if (context.getDepth() >= maxDepth) { | ||
182 | logger.debug("Reached max depth."); | ||
183 | context.backtrack(); | ||
184 | continue; | ||
185 | } | ||
186 | |||
187 | TrajectoryWithFitness nextTrajectoryWithFittness = new TrajectoryWithFitness( | ||
188 | context.getTrajectory().toArray(), nextFitness); | ||
189 | trajectoiresToExplore.add(nextTrajectoryWithFittness); | ||
190 | |||
191 | int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFittness.fitness, | ||
192 | nextTrajectoryWithFittness.fitness); | ||
193 | if (compare < 0) { | ||
194 | logger.debug("Better fitness, moving on: " + nextFitness); | ||
195 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | ||
196 | continue mainLoop; | ||
197 | } else if (compare == 0) { | ||
198 | if (onlyBetterFirst) { | ||
199 | logger.debug("Equally good fitness, backtrack: " + nextFitness); | ||
200 | context.backtrack(); | ||
201 | continue; | ||
202 | } else { | ||
203 | logger.debug("Equally good fitness, moving on: " + nextFitness); | ||
204 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | ||
205 | continue mainLoop; | ||
206 | } | ||
207 | } else { | ||
208 | logger.debug("Worse fitness."); | ||
209 | currentTrajectoryWithFittness = null; | ||
210 | continue mainLoop; | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||
215 | logger.debug("State is fully traversed."); | ||
216 | trajectoiresToExplore.remove(currentTrajectoryWithFittness); | ||
217 | currentTrajectoryWithFittness = null; | ||
218 | |||
219 | } | ||
220 | logger.info("Interrupted."); | ||
221 | } | ||
222 | |||
223 | @Override | ||
224 | public void interruptStrategy() { | ||
225 | isInterrupted = true; | ||
226 | } | ||
227 | |||
228 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.java new file mode 100644 index 00000000..6b7d9817 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.java | |||
@@ -0,0 +1,220 @@ | |||
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.api.strategy.impl; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.Iterator; | ||
13 | import java.util.concurrent.BrokenBarrierException; | ||
14 | import java.util.concurrent.ConcurrentLinkedQueue; | ||
15 | import java.util.concurrent.CyclicBarrier; | ||
16 | import java.util.concurrent.atomic.AtomicBoolean; | ||
17 | |||
18 | import org.apache.log4j.Logger; | ||
19 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
20 | import org.eclipse.viatra.dse.base.GlobalContext; | ||
21 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
22 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
23 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
24 | |||
25 | /** | ||
26 | * A breadth-first search algorithm implementation, that | ||
27 | * <ul> | ||
28 | * <li>can work with multiple threads,</li> | ||
29 | * <li>indeterministic,</li> | ||
30 | * <li>saves all states (trajectories) as solutions that fulfill all the hard objectives,</li> | ||
31 | * <li>can have a depth limit,</li> | ||
32 | * <li>will backtrack when a model satisfies the hard objectives (after saving it as a solution) and will not explore | ||
33 | * beyond that state.</li> | ||
34 | * </ul> | ||
35 | * | ||
36 | * @author Andras Szabolcs Nagy | ||
37 | * | ||
38 | */ | ||
39 | public class BreadthFirstStrategy implements IStrategy { | ||
40 | |||
41 | private static final class BfsSharedObject { | ||
42 | private final ConcurrentLinkedQueue<Object[]> trajectoryQueue1 = new ConcurrentLinkedQueue<>(); | ||
43 | private final ConcurrentLinkedQueue<Object[]> trajectoryQueue2 = new ConcurrentLinkedQueue<>(); | ||
44 | |||
45 | private final AtomicBoolean pushToQueue1 = new AtomicBoolean(false); | ||
46 | private final AtomicBoolean designSpaceTraversed = new AtomicBoolean(false); | ||
47 | |||
48 | public final CyclicBarrier barrier; | ||
49 | |||
50 | public BfsSharedObject(int numberOfThreads) { | ||
51 | barrier = new CyclicBarrier(numberOfThreads, () -> { | ||
52 | boolean oldValue = pushToQueue1.get(); | ||
53 | pushToQueue1.set(!oldValue); | ||
54 | if (trajectoryQueue1.isEmpty() && trajectoryQueue2.isEmpty()) { | ||
55 | designSpaceTraversed.set(true); | ||
56 | } | ||
57 | }); | ||
58 | } | ||
59 | |||
60 | public Object[] poll() { | ||
61 | if (pushToQueue1.get()) { | ||
62 | return trajectoryQueue2.poll(); | ||
63 | } else { | ||
64 | return trajectoryQueue1.poll(); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | public void push(Object[] trajectory) { | ||
69 | if (pushToQueue1.get()) { | ||
70 | trajectoryQueue1.add(trajectory); | ||
71 | } else { | ||
72 | trajectoryQueue2.add(trajectory); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | public boolean isDesignSpaceTraversed() { | ||
77 | return designSpaceTraversed.get(); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | private int maxDepth = 0; | ||
82 | private BfsSharedObject shared; | ||
83 | private boolean isInterrupted = false; | ||
84 | private ThreadContext context; | ||
85 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
86 | private SolutionStore solutionStore; | ||
87 | private boolean isFirstThread = false; | ||
88 | |||
89 | /** | ||
90 | * Creates a new breadth-first search algorithm without depth limit. | ||
91 | */ | ||
92 | public BreadthFirstStrategy() { | ||
93 | this.maxDepth = Integer.MAX_VALUE; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * Creates a new breadth-first search algorithm with depth limit. | ||
98 | * | ||
99 | * @param maxDepth | ||
100 | * A negative <code>maxDepth</code> means no depth limit, zero means the checking of the initial state. | ||
101 | */ | ||
102 | public BreadthFirstStrategy(int maxDepth) { | ||
103 | if (maxDepth < 0) { | ||
104 | this.maxDepth = Integer.MAX_VALUE; | ||
105 | } else { | ||
106 | this.maxDepth = maxDepth; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | @Override | ||
111 | public void initStrategy(ThreadContext context) { | ||
112 | this.context = context; | ||
113 | this.solutionStore = context.getGlobalContext().getSolutionStore(); | ||
114 | |||
115 | GlobalContext globalContext = context.getGlobalContext(); | ||
116 | if (globalContext.getSharedObject() == null) { | ||
117 | isFirstThread = true; | ||
118 | shared = new BfsSharedObject(globalContext.getThreadPool().getMaximumPoolSize()); | ||
119 | globalContext.setSharedObject(shared); | ||
120 | logger.info("Breadth-first exploration strategy is inited."); | ||
121 | } else { | ||
122 | shared = (BfsSharedObject) globalContext.getSharedObject(); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | @Override | ||
127 | public void explore() { | ||
128 | |||
129 | if (isFirstThread) { | ||
130 | |||
131 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
132 | if (!globalConstraintsAreSatisfied) { | ||
133 | logger.info("Global contraint is not satisifed in the first state. Terminate."); | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | Fitness fitness = context.calculateFitness(); | ||
138 | if (fitness.isSatisifiesHardObjectives()) { | ||
139 | context.newSolution(); | ||
140 | logger.info("First state is a solution. Terminate."); | ||
141 | return; | ||
142 | } | ||
143 | |||
144 | Object[] currentTrajectory = context.getTrajectory().toArray(new Object[0]); | ||
145 | |||
146 | shared.push(currentTrajectory); | ||
147 | |||
148 | startThreads(); | ||
149 | } else { | ||
150 | try { | ||
151 | shared.barrier.await(); | ||
152 | } catch (InterruptedException | BrokenBarrierException e) { | ||
153 | } | ||
154 | } | ||
155 | |||
156 | mainLoop: while (!isInterrupted && !shared.isDesignSpaceTraversed()) { | ||
157 | |||
158 | Object[] next = shared.poll(); | ||
159 | while (next == null) { | ||
160 | try { | ||
161 | logger.debug("Reached barrier."); | ||
162 | shared.barrier.await(); | ||
163 | } catch (InterruptedException | BrokenBarrierException e1) { | ||
164 | } | ||
165 | if (isInterrupted || shared.isDesignSpaceTraversed()) { | ||
166 | break mainLoop; | ||
167 | } | ||
168 | next = shared.poll(); | ||
169 | } | ||
170 | |||
171 | context.backtrackUntilRoot(); | ||
172 | |||
173 | context.executeTrajectory(next); | ||
174 | |||
175 | Collection<Object> activationIds = context.getCurrentActivationIds(); | ||
176 | int i = activationIds.size() - 1; | ||
177 | |||
178 | while (!isInterrupted && i >= 0) { | ||
179 | |||
180 | Iterator<Object> iterator = activationIds.iterator(); | ||
181 | int index = i--; | ||
182 | while (iterator.hasNext() && index > 0) { | ||
183 | index--; | ||
184 | iterator.next(); | ||
185 | } | ||
186 | Object activationIdToTry = iterator.next(); | ||
187 | |||
188 | context.executeAcitvationId(activationIdToTry); | ||
189 | |||
190 | if (context.isCurrentStateAlreadyTraversed()) { | ||
191 | logger.info("The new state is already visited."); | ||
192 | } else if (!context.checkGlobalConstraints()) { | ||
193 | logger.debug("Global contraint is not satisifed."); | ||
194 | } else if (context.calculateFitness().isSatisifiesHardObjectives()) { | ||
195 | solutionStore.newSolution(context); | ||
196 | logger.debug("Found a solution."); | ||
197 | } else if (context.getDepth() >= maxDepth) { | ||
198 | logger.debug("Reached max depth."); | ||
199 | } else { | ||
200 | Object[] currentTrajectory = context.getTrajectory().toArray(new Object[0]); | ||
201 | shared.push(currentTrajectory); | ||
202 | } | ||
203 | |||
204 | context.backtrack(); | ||
205 | } | ||
206 | |||
207 | } | ||
208 | } | ||
209 | |||
210 | private void startThreads() { | ||
211 | context.startAllThreads(() -> new BreadthFirstStrategy(maxDepth)); | ||
212 | } | ||
213 | |||
214 | @Override | ||
215 | public void interruptStrategy() { | ||
216 | isInterrupted = true; | ||
217 | shared.barrier.reset(); | ||
218 | } | ||
219 | |||
220 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.java new file mode 100644 index 00000000..22a4a683 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.java | |||
@@ -0,0 +1,188 @@ | |||
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.api.strategy.impl; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.Iterator; | ||
13 | import java.util.Random; | ||
14 | import java.util.concurrent.atomic.AtomicBoolean; | ||
15 | |||
16 | import org.apache.log4j.Logger; | ||
17 | import org.eclipse.viatra.dse.api.DSEException; | ||
18 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
19 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
20 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
21 | |||
22 | /** | ||
23 | * A depth-first search algorithm implementation, that | ||
24 | * <ul> | ||
25 | * <li>can work with multiple threads,</li> | ||
26 | * <li>randomly traverses the search space,</li> | ||
27 | * <li>saves all states (trajectories) as solutions that fulfill all the hard objectives,</li> | ||
28 | * <li>can have a depth limit,</li> | ||
29 | * <li>will backtrack when a model satisfies the hard objectives (after saving it as a solution), which can be modified | ||
30 | * by calling {@link #continueIfHardObjectivesFulfilled()}</li> | ||
31 | * </ul> | ||
32 | * | ||
33 | * @author Andras Szabolcs Nagy | ||
34 | * | ||
35 | */ | ||
36 | public class DepthFirstStrategy implements IStrategy { | ||
37 | |||
38 | private int maxDepth; | ||
39 | private AtomicBoolean isInterrupted = new AtomicBoolean(false); | ||
40 | private ThreadContext context; | ||
41 | |||
42 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
43 | |||
44 | private Random random = new Random(); | ||
45 | private boolean backTrackIfSolution = true; | ||
46 | |||
47 | /** | ||
48 | * Creates a new depth-first search algorithm without depth limit. | ||
49 | */ | ||
50 | public DepthFirstStrategy() { | ||
51 | this.maxDepth = Integer.MAX_VALUE; | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * Creates a new depth-first search algorithm with depth limit. | ||
56 | * | ||
57 | * @param maxDepth | ||
58 | * A negative <code>maxDepth</code> means no depth limit, zero means the checking of the initial state. | ||
59 | */ | ||
60 | public DepthFirstStrategy(int maxDepth) { | ||
61 | if (maxDepth < 0) { | ||
62 | this.maxDepth = Integer.MAX_VALUE; | ||
63 | } else { | ||
64 | this.maxDepth = maxDepth; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * If called, the algorithm will not backtrack after the hard objectives are fulfilled, instead it goes deeper in | ||
70 | * the search space. | ||
71 | */ | ||
72 | public DepthFirstStrategy continueIfHardObjectivesFulfilled() { | ||
73 | backTrackIfSolution = false; | ||
74 | return this; | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public void initStrategy(ThreadContext context) { | ||
79 | this.context = context; | ||
80 | |||
81 | if (context.getSharedObject() == null) { | ||
82 | context.setSharedObject(new Object()); | ||
83 | logger.info("Depth-first exploration strategy is initied."); | ||
84 | startThreads(); | ||
85 | } | ||
86 | |||
87 | } | ||
88 | |||
89 | private void startThreads() { | ||
90 | context.startAllThreads(() -> new DepthFirstStrategy(maxDepth)); | ||
91 | } | ||
92 | |||
93 | @Override | ||
94 | public void explore() { | ||
95 | |||
96 | mainloop: do { | ||
97 | |||
98 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
99 | if (!globalConstraintsAreSatisfied) { | ||
100 | boolean isSuccessfulUndo = context.backtrack(); | ||
101 | if (!isSuccessfulUndo) { | ||
102 | logger.info("Global contraint is not satisifed and cannot backtrack."); | ||
103 | break; | ||
104 | } else { | ||
105 | logger.debug("Global contraint is not satisifed, backtrack."); | ||
106 | continue; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | Fitness fitness = context.calculateFitness(); | ||
111 | if (fitness.isSatisifiesHardObjectives()) { | ||
112 | context.newSolution(); | ||
113 | if (backTrackIfSolution) { | ||
114 | boolean isSuccessfulUndo = context.backtrack(); | ||
115 | if (!isSuccessfulUndo) { | ||
116 | logger.info("Found a solution but cannot backtrack."); | ||
117 | break; | ||
118 | } else { | ||
119 | logger.debug("Found a solution, backtrack."); | ||
120 | continue; | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (context.getDepth() >= maxDepth) { | ||
126 | boolean isSuccessfulUndo = context.backtrack(); | ||
127 | if (!isSuccessfulUndo) { | ||
128 | logger.info("Reached max depth but cannot bactrack."); | ||
129 | break; | ||
130 | } else { | ||
131 | logger.debug("Reached max depth, bactrack."); | ||
132 | continue; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | if (isInterrupted.get()) { | ||
137 | logger.info("Interrupted, stop exploration."); | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | Object activationId = null; | ||
142 | Collection<Object> activationIds; | ||
143 | |||
144 | do { | ||
145 | activationIds = context.getUntraversedActivationIds(); | ||
146 | if (activationIds.isEmpty()) { | ||
147 | boolean isSuccessfulUndo = context.backtrack(); | ||
148 | if (!isSuccessfulUndo) { | ||
149 | logger.info("No more transitions from current state and cannot backtrack."); | ||
150 | break mainloop; | ||
151 | } else { | ||
152 | logger.debug("No more transitions from current state, backtrack."); | ||
153 | continue; | ||
154 | } | ||
155 | } | ||
156 | } while (activationIds.isEmpty()); | ||
157 | |||
158 | int index = random.nextInt(activationIds.size()); | ||
159 | |||
160 | Iterator<Object> iterator = activationIds.iterator(); | ||
161 | while (index-- > 0) { | ||
162 | iterator.next(); | ||
163 | } | ||
164 | activationId = iterator.next(); | ||
165 | |||
166 | context.executeAcitvationId(activationId); | ||
167 | |||
168 | boolean loopInTrajectory = context.isCurrentStateInTrajectory(); | ||
169 | if (loopInTrajectory) { | ||
170 | boolean isSuccessfulUndo = context.backtrack(); | ||
171 | if (!isSuccessfulUndo) { | ||
172 | throw new DSEException("The new state is present in the trajectoy but cannot bactkrack. Should never happen!"); | ||
173 | } else { | ||
174 | logger.info("The new state is already visited in the trajectory, backtrack."); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | } while (true); | ||
179 | |||
180 | logger.info("Terminated."); | ||
181 | } | ||
182 | |||
183 | @Override | ||
184 | public void interruptStrategy() { | ||
185 | isInterrupted.set(true); | ||
186 | } | ||
187 | |||
188 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.java new file mode 100644 index 00000000..4ccda4ce --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.java | |||
@@ -0,0 +1,208 @@ | |||
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.api.strategy.impl; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.List; | ||
14 | import java.util.Map; | ||
15 | import java.util.Random; | ||
16 | import java.util.concurrent.atomic.AtomicBoolean; | ||
17 | |||
18 | import org.apache.log4j.Logger; | ||
19 | import org.eclipse.viatra.dse.api.DSEException; | ||
20 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
21 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
22 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
23 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
24 | |||
25 | import com.google.common.collect.Lists; | ||
26 | |||
27 | /** | ||
28 | * Works as {@link DepthFirstStrategy} but: | ||
29 | * <ul> | ||
30 | * <li>works only with single thread,</li> | ||
31 | * <li>in a given state, it only traverses the activations with locally the highest priority.</li> | ||
32 | * </ul> | ||
33 | * | ||
34 | * @author Andras Szabolcs Nagy | ||
35 | * | ||
36 | */ | ||
37 | public class FixedPriorityStrategy implements IStrategy { | ||
38 | |||
39 | private int maxDepth = Integer.MAX_VALUE; | ||
40 | private AtomicBoolean isInterrupted = new AtomicBoolean(false); | ||
41 | private ThreadContext context; | ||
42 | |||
43 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
44 | private Map<BatchTransformationRule<?, ?>, Integer> priorities = new HashMap<BatchTransformationRule<?, ?>, Integer>(); | ||
45 | |||
46 | private Random random = new Random(); | ||
47 | private Map<Object, List<Object>> bestPriorityInState = new HashMap<>(); | ||
48 | |||
49 | /** | ||
50 | * Adds a depth limit to the strategy. | ||
51 | * | ||
52 | * @param depthLimit | ||
53 | * The depth limit. | ||
54 | * @return The actual instance to enable a builder pattern like usage. | ||
55 | */ | ||
56 | public FixedPriorityStrategy withDepthLimit(int maxDepth) { | ||
57 | if (maxDepth < 0) { | ||
58 | this.maxDepth = Integer.MAX_VALUE; | ||
59 | } else { | ||
60 | this.maxDepth = maxDepth; | ||
61 | } | ||
62 | return this; | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * Assigns a priority to a rule. Unassigned rule will have a priority of 0. | ||
67 | * | ||
68 | * @param rule | ||
69 | * The transformation rule. | ||
70 | * @param priority | ||
71 | * The priority of the rule. Higher is better. | ||
72 | * @return The actual instance to enable a builder pattern like usage. | ||
73 | */ | ||
74 | public FixedPriorityStrategy withRulePriority(BatchTransformationRule<?, ?> rule, int priority) { | ||
75 | priorities.put(rule, priority); | ||
76 | return this; | ||
77 | } | ||
78 | |||
79 | public Map<BatchTransformationRule<?, ?>, Integer> getPriorities() { | ||
80 | return priorities; | ||
81 | } | ||
82 | |||
83 | @Override | ||
84 | public void initStrategy(ThreadContext context) { | ||
85 | this.context = context; | ||
86 | |||
87 | logger.info("Fixed priority exploration strategy is initied."); | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public void explore() { | ||
92 | |||
93 | mainloop: do { | ||
94 | |||
95 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
96 | if (!globalConstraintsAreSatisfied) { | ||
97 | boolean isSuccessfulUndo = context.backtrack(); | ||
98 | if (!isSuccessfulUndo) { | ||
99 | logger.info("Global contraint is not satisifed and cannot backtrack."); | ||
100 | break; | ||
101 | } else { | ||
102 | logger.debug("Global contraint is not satisifed, backtrack."); | ||
103 | continue; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | Fitness fitness = context.calculateFitness(); | ||
108 | if (fitness.isSatisifiesHardObjectives()) { | ||
109 | context.newSolution(); | ||
110 | boolean isSuccessfulUndo = context.backtrack(); | ||
111 | if (!isSuccessfulUndo) { | ||
112 | logger.info("Found a solution but cannot backtrack."); | ||
113 | break; | ||
114 | } else { | ||
115 | logger.debug("Found a solution, backtrack."); | ||
116 | continue; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | if (context.getDepth() >= maxDepth) { | ||
121 | boolean isSuccessfulUndo = context.backtrack(); | ||
122 | if (!isSuccessfulUndo) { | ||
123 | logger.info("Reached max depth but cannot bactrack."); | ||
124 | break; | ||
125 | } else { | ||
126 | logger.debug("Reached max depth, bactrack."); | ||
127 | continue; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | if (isInterrupted.get()) { | ||
132 | logger.info("Interrupted, stop exploration."); | ||
133 | break; | ||
134 | } | ||
135 | |||
136 | List<Object> transitions; | ||
137 | |||
138 | do { | ||
139 | |||
140 | transitions = bestPriorityInState.get(context.getCurrentStateId()); | ||
141 | |||
142 | if (transitions == null) { | ||
143 | Integer bestPriority = getBestPriority(context.getCurrentActivationIds()); | ||
144 | transitions = Lists.newArrayList(); | ||
145 | for (Object iTransition : context.getCurrentActivationIds()) { | ||
146 | Integer integer = priorities.get(context.getRuleByActivationId(iTransition)); | ||
147 | if (integer == null) { | ||
148 | integer = Integer.valueOf(0); | ||
149 | } | ||
150 | if (integer.equals(bestPriority)) { | ||
151 | transitions.add(iTransition); | ||
152 | } | ||
153 | } | ||
154 | bestPriorityInState.put(context.getCurrentStateId(), transitions); | ||
155 | } | ||
156 | |||
157 | if (transitions.isEmpty()) { | ||
158 | boolean isSuccessfulUndo = context.backtrack(); | ||
159 | if (!isSuccessfulUndo) { | ||
160 | logger.info("No more transitions from current state and cannot backtrack."); | ||
161 | break mainloop; | ||
162 | } else { | ||
163 | logger.debug("No more transitions from current state, backtrack."); | ||
164 | continue; | ||
165 | } | ||
166 | } | ||
167 | } while (transitions.isEmpty()); | ||
168 | |||
169 | int index = random.nextInt(transitions.size()); | ||
170 | Object transition = transitions.remove(index); | ||
171 | |||
172 | context.executeAcitvationId(transition); | ||
173 | |||
174 | boolean loopInTrajectory = context.isCurrentStateInTrajectory(); | ||
175 | if (loopInTrajectory) { | ||
176 | boolean isSuccessfulUndo = context.backtrack(); | ||
177 | if (!isSuccessfulUndo) { | ||
178 | throw new DSEException( | ||
179 | "The new state is present in the trajectoy but cannot bactkrack. Should never happen!"); | ||
180 | } else { | ||
181 | logger.info("The new state is already visited in the trajectory, backtrack."); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | } while (true); | ||
186 | |||
187 | logger.info("Terminated."); | ||
188 | } | ||
189 | |||
190 | @Override | ||
191 | public void interruptStrategy() { | ||
192 | isInterrupted.set(true); | ||
193 | } | ||
194 | |||
195 | private Integer getBestPriority(Collection<? extends Object> transitions) { | ||
196 | Integer bestPriority = Integer.MIN_VALUE; | ||
197 | for (Object iTransition : transitions) { | ||
198 | Integer priority = priorities.get(context.getRuleByActivationId(iTransition)); | ||
199 | if (priority == null) { | ||
200 | priority = Integer.valueOf(0); | ||
201 | } | ||
202 | if (priority > bestPriority) { | ||
203 | bestPriority = priority; | ||
204 | } | ||
205 | } | ||
206 | return bestPriority; | ||
207 | } | ||
208 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.java new file mode 100644 index 00000000..0ccb0668 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.java | |||
@@ -0,0 +1,142 @@ | |||
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.api.strategy.impl; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collection; | ||
13 | import java.util.Random; | ||
14 | import java.util.concurrent.atomic.AtomicBoolean; | ||
15 | |||
16 | import org.apache.log4j.Logger; | ||
17 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
18 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
19 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
20 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | ||
21 | import org.eclipse.viatra.dse.objectives.TrajectoryFitness; | ||
22 | |||
23 | public class HillClimbingStrategy implements IStrategy { | ||
24 | |||
25 | private AtomicBoolean isInterrupted = new AtomicBoolean(false); | ||
26 | private ThreadContext context; | ||
27 | |||
28 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
29 | |||
30 | private Random random = new Random(); | ||
31 | private double percentOfOpenedStates; | ||
32 | private ObjectiveComparatorHelper objectiveComparatorHelper; | ||
33 | |||
34 | public HillClimbingStrategy() { | ||
35 | this(2); | ||
36 | } | ||
37 | |||
38 | public HillClimbingStrategy(double percentOfOpenedStates) { | ||
39 | this.percentOfOpenedStates = percentOfOpenedStates; | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public void initStrategy(ThreadContext context) { | ||
44 | this.context = context; | ||
45 | objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | ||
46 | logger.info("Hill climbing exploration strategy is initied."); | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public void explore() { | ||
51 | |||
52 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
53 | if (!globalConstraintsAreSatisfied) { | ||
54 | boolean isSuccessfulUndo = context.backtrack(); | ||
55 | if (!isSuccessfulUndo) { | ||
56 | logger.info("Global contraint is not satisifed and cannot backtrack."); | ||
57 | return; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | mainloop: do { | ||
62 | |||
63 | Fitness previousFitness = context.calculateFitness(); | ||
64 | |||
65 | logger.debug("Current depth: " + context.getDepth() + " Fitness: " + previousFitness); | ||
66 | |||
67 | Collection<Object> transitionsFromCurrentState = context.getCurrentActivationIds(); | ||
68 | |||
69 | while (transitionsFromCurrentState.isEmpty()) { | ||
70 | logger.debug("No transitions from current state: considered as a solution."); | ||
71 | saveSolutionAndBacktrack(); | ||
72 | continue mainloop; | ||
73 | } | ||
74 | |||
75 | ArrayList<Object> transitionsToTry = new ArrayList<>(transitionsFromCurrentState.size()); | ||
76 | for (Object transition : transitionsFromCurrentState) { | ||
77 | transitionsToTry.add(transition); | ||
78 | } | ||
79 | double numberOfTransitionsToTry = transitionsToTry.size() * percentOfOpenedStates; | ||
80 | |||
81 | for (; numberOfTransitionsToTry > 0 && !transitionsToTry.isEmpty(); numberOfTransitionsToTry--) { | ||
82 | int index = random.nextInt(transitionsToTry.size()); | ||
83 | Object transition = transitionsToTry.remove(index); | ||
84 | |||
85 | context.executeAcitvationId(transition); | ||
86 | |||
87 | if (!context.checkGlobalConstraints()) { | ||
88 | logger.debug("Global contraint is not satisifed, backtrack."); | ||
89 | context.backtrack(); | ||
90 | continue; | ||
91 | } | ||
92 | if (context.isCurrentStateInTrajectory()) { | ||
93 | logger.debug("Current state is in trajectory, backtrack."); | ||
94 | context.backtrack(); | ||
95 | continue; | ||
96 | } | ||
97 | |||
98 | Fitness fitness = context.calculateFitness(); | ||
99 | objectiveComparatorHelper.addTrajectoryFitness( | ||
100 | new TrajectoryFitness(context.getTrajectoryInfo().getLastActivationId(), fitness)); | ||
101 | context.backtrack(); | ||
102 | } | ||
103 | |||
104 | if (objectiveComparatorHelper.getTrajectoryFitnesses().isEmpty()) { | ||
105 | logger.debug("No viable transitions from current state: considered as a solution."); | ||
106 | saveSolutionAndBacktrack(); | ||
107 | continue; | ||
108 | } | ||
109 | |||
110 | TrajectoryFitness randomBestFitness = objectiveComparatorHelper.getRandomBest(); | ||
111 | objectiveComparatorHelper.clearTrajectoryFitnesses(); | ||
112 | |||
113 | int compare = objectiveComparatorHelper.compare(previousFitness, randomBestFitness.fitness); | ||
114 | |||
115 | if (compare > 0) { | ||
116 | saveSolutionAndBacktrack(); | ||
117 | continue; | ||
118 | } else { | ||
119 | previousFitness = randomBestFitness.fitness; | ||
120 | Object transition = randomBestFitness.trajectory[randomBestFitness.trajectory.length - 1]; | ||
121 | context.executeAcitvationId(transition); | ||
122 | } | ||
123 | |||
124 | } while (!isInterrupted.get()); | ||
125 | |||
126 | logger.info("Terminated."); | ||
127 | } | ||
128 | |||
129 | private void saveSolutionAndBacktrack() { | ||
130 | context.calculateFitness(); | ||
131 | context.newSolution(); | ||
132 | logger.debug("Found solution: " + context.getTrajectoryInfo().toString()); | ||
133 | logger.debug("Backtrack for more solutions, if needed."); | ||
134 | context.backtrackUntilRoot(); | ||
135 | } | ||
136 | |||
137 | @Override | ||
138 | public void interruptStrategy() { | ||
139 | isInterrupted.set(true); | ||
140 | } | ||
141 | |||
142 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.java new file mode 100644 index 00000000..af8fb8cc --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.java | |||
@@ -0,0 +1,163 @@ | |||
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.api.strategy.impl; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.Iterator; | ||
13 | import java.util.Random; | ||
14 | import java.util.concurrent.atomic.AtomicBoolean; | ||
15 | import java.util.concurrent.atomic.AtomicInteger; | ||
16 | |||
17 | import org.apache.log4j.Logger; | ||
18 | import org.eclipse.viatra.dse.api.DSEException; | ||
19 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
20 | import org.eclipse.viatra.dse.base.GlobalContext; | ||
21 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
22 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
23 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
24 | |||
25 | public class RandomSearchStrategy implements IStrategy { | ||
26 | |||
27 | private static class SharedData { | ||
28 | public final AtomicInteger triesLeft; | ||
29 | public final int minDepth; | ||
30 | public final int maxDepth; | ||
31 | |||
32 | public SharedData(int minDepth, int maxDepth, int numberOfTries) { | ||
33 | this.minDepth = minDepth; | ||
34 | this.maxDepth = maxDepth; | ||
35 | this.triesLeft = new AtomicInteger(numberOfTries); | ||
36 | } | ||
37 | } | ||
38 | |||
39 | private int maxDepth = -1; | ||
40 | private Random rnd = new Random(); | ||
41 | private SharedData shared; | ||
42 | private TrajectoryInfo trajectoryInfo; | ||
43 | int nth; | ||
44 | private ThreadContext context; | ||
45 | private AtomicBoolean isInterrupted = new AtomicBoolean(false); | ||
46 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
47 | |||
48 | public RandomSearchStrategy(int minDepth, int maxDepth, int numberOfTries) { | ||
49 | shared = new SharedData(minDepth, maxDepth, numberOfTries); | ||
50 | } | ||
51 | |||
52 | private RandomSearchStrategy() { | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public void initStrategy(ThreadContext context) { | ||
57 | this.context = context; | ||
58 | trajectoryInfo = context.getTrajectoryInfo(); | ||
59 | GlobalContext gc = context.getGlobalContext(); | ||
60 | |||
61 | Object sharedObject = gc.getSharedObject(); | ||
62 | if (sharedObject == null) { | ||
63 | gc.setSharedObject(shared); | ||
64 | logger.info("Random exploration strategy is initied."); | ||
65 | startThreads(); | ||
66 | } else { | ||
67 | shared = (SharedData) sharedObject; | ||
68 | } | ||
69 | |||
70 | maxDepth = rnd.nextInt(shared.maxDepth - shared.minDepth) + shared.minDepth; | ||
71 | |||
72 | } | ||
73 | |||
74 | @Override | ||
75 | public void explore() { | ||
76 | |||
77 | do { | ||
78 | |||
79 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
80 | if (!globalConstraintsAreSatisfied) { | ||
81 | boolean isSuccessfulUndo = context.backtrack(); | ||
82 | if (!isSuccessfulUndo) { | ||
83 | logger.info("Global contraint is not satisifed and cannot backtrack."); | ||
84 | break; | ||
85 | } else { | ||
86 | logger.debug("Global contraint is not satisifed, backtrack."); | ||
87 | continue; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | Fitness fitness = context.calculateFitness(); | ||
92 | if (fitness.isSatisifiesHardObjectives()) { | ||
93 | context.newSolution(); | ||
94 | boolean isSuccessfulUndo = context.backtrack(); | ||
95 | if (!isSuccessfulUndo) { | ||
96 | logger.info("Found a solution but cannot backtrack."); | ||
97 | break; | ||
98 | } else { | ||
99 | logger.debug("Found a solution, backtrack."); | ||
100 | continue; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | if (trajectoryInfo.getDepth() < maxDepth) { | ||
105 | |||
106 | Collection<Object> transitions = context.getCurrentActivationIds(); | ||
107 | int index = rnd.nextInt(transitions.size()); | ||
108 | Object transition = getByIndex(transitions, index); | ||
109 | context.executeAcitvationId(transition); | ||
110 | |||
111 | } else { | ||
112 | |||
113 | nth = shared.triesLeft.getAndDecrement(); | ||
114 | logger.debug(nth + " tries left"); | ||
115 | if (nth > 0) { | ||
116 | |||
117 | context.backtrackUntilRoot(); | ||
118 | maxDepth = rnd.nextInt(shared.maxDepth - shared.minDepth) + shared.minDepth; | ||
119 | |||
120 | } else { | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | boolean loopInTrajectory = context.isCurrentStateInTrajectory(); | ||
126 | if (loopInTrajectory) { | ||
127 | boolean isSuccessfulUndo = context.backtrack(); | ||
128 | if (!isSuccessfulUndo) { | ||
129 | throw new DSEException( | ||
130 | "The new state is present in the trajectoy but cannot bactkrack. Should never happen!"); | ||
131 | } else { | ||
132 | logger.info("The new state is already visited in the trajectory, backtrack."); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | } while (isInterrupted.get()); | ||
137 | |||
138 | logger.info("Terminated."); | ||
139 | } | ||
140 | |||
141 | @Override | ||
142 | public void interruptStrategy() { | ||
143 | isInterrupted.set(true); | ||
144 | } | ||
145 | |||
146 | private void startThreads() { | ||
147 | context.startAllThreads(RandomSearchStrategy::new); | ||
148 | } | ||
149 | |||
150 | private static Object getByIndex(Collection<Object> availableTransitions, int index) { | ||
151 | int i = 0; | ||
152 | Iterator<Object> iterator = availableTransitions.iterator(); | ||
153 | while (iterator.hasNext()) { | ||
154 | Object transition = iterator.next(); | ||
155 | if (i == index) { | ||
156 | return transition; | ||
157 | } else { | ||
158 | ++i; | ||
159 | } | ||
160 | } | ||
161 | throw new IndexOutOfBoundsException("size: " + availableTransitions.size() + ", index: " + index); | ||
162 | } | ||
163 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.java new file mode 100644 index 00000000..8c164396 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.java | |||
@@ -0,0 +1,44 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.api.strategy.interfaces; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
13 | |||
14 | /** | ||
15 | * This high level interface is responsible for defining basic operations of an exploration strategy. | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public interface IStrategy { | ||
21 | |||
22 | /** | ||
23 | * Initializes the strategy with a specific {@link ThreadContext}. | ||
24 | * | ||
25 | * @param context | ||
26 | * The context. | ||
27 | */ | ||
28 | void initStrategy(ThreadContext context); | ||
29 | |||
30 | /** | ||
31 | * This method explores the design space as the implementation specifies. It will be called only once, hence the | ||
32 | * exploration loop is run by the implementation. The termination condition is also specified by the implementation | ||
33 | * and when it returns the exploration thread will be disposed. | ||
34 | */ | ||
35 | void explore(); | ||
36 | |||
37 | /** | ||
38 | * The implementation of this interface should be ready to be interrupted. If this method is called, the | ||
39 | * {@link IStrategy#explore()} method should return ASAP. | ||
40 | * | ||
41 | * This method is also called by the {@link SolutionStore} class if enough solutions are found. | ||
42 | */ | ||
43 | void interruptStrategy(); | ||
44 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory.java new file mode 100644 index 00000000..b3352d13 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory.java | |||
@@ -0,0 +1,13 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.api.strategy.interfaces; | ||
10 | |||
11 | public interface IStrategyFactory { | ||
12 | IStrategy createStrategy(); | ||
13 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ActivationCodesConflictSet.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ActivationCodesConflictSet.java new file mode 100644 index 00000000..d3990c23 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ActivationCodesConflictSet.java | |||
@@ -0,0 +1,213 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.base; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.HashSet; | ||
14 | import java.util.Map; | ||
15 | import java.util.Objects; | ||
16 | import java.util.Set; | ||
17 | |||
18 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
19 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
20 | import org.eclipse.viatra.transformation.evm.api.Activation; | ||
21 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
22 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
23 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictSet; | ||
24 | |||
25 | public class ActivationCodesConflictSet implements ChangeableConflictSet { | ||
26 | |||
27 | private static class ActivationCodesMultiBiMap { | ||
28 | public Map<Activation<?>, Object> activationsToCodes = new HashMap<>(); | ||
29 | public Map<Object, Set<Activation<?>>> codesToActivations = new HashMap<>(); | ||
30 | |||
31 | public void addActivation(Activation<?> activation, Object activationCode) { | ||
32 | activationsToCodes.put(activation, activationCode); | ||
33 | codesToActivations.computeIfAbsent(activationCode, k -> new HashSet<>()).add(activation); | ||
34 | } | ||
35 | |||
36 | public void removeActivaion(Activation<?> activation) { | ||
37 | Object activationCode = activationsToCodes.remove(activation); | ||
38 | Set<Activation<?>> activations = codesToActivations.get(activationCode); | ||
39 | if (activations != null) { | ||
40 | activations.remove(activation); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | public void clear() { | ||
45 | activationsToCodes.clear(); | ||
46 | codesToActivations.clear(); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | protected ActivationCodesMultiBiMap activationCodes; | ||
51 | protected IStateCoder stateCoder; | ||
52 | |||
53 | protected Set<Activation<?>> newActivations = new HashSet<>(); | ||
54 | protected Set<Activation<?>> removedActivations = new HashSet<>(); | ||
55 | // private Logger logger = Logger.getLogger(getClass()); | ||
56 | |||
57 | private boolean isIncremental = false; | ||
58 | private ConflictSet nextActivationsConflictSet; | ||
59 | |||
60 | public void setIncremental(boolean isIncremental) { | ||
61 | this.isIncremental = isIncremental; | ||
62 | } | ||
63 | |||
64 | public ActivationCodesConflictSet(ConflictSet nextActivationsConflictSet, IStateCoder stateCoder) { | ||
65 | Objects.requireNonNull(nextActivationsConflictSet); | ||
66 | this.nextActivationsConflictSet = nextActivationsConflictSet; | ||
67 | this.stateCoder = stateCoder; | ||
68 | activationCodes = new ActivationCodesMultiBiMap(); | ||
69 | } | ||
70 | |||
71 | private Object createActivationCode(Activation<?> activation) { | ||
72 | return stateCoder.createActivationCode((IPatternMatch) activation.getAtom()); | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public boolean removeActivation(Activation<?> activation) { | ||
77 | if (isIncremental) { | ||
78 | //* | ||
79 | removedActivations.add(activation); | ||
80 | newActivations.remove(activation); | ||
81 | /*/ | ||
82 | if(!removedActivations.add(activation)) { | ||
83 | logger.debug("Abnormal: already marked to remove: " + activation); | ||
84 | } else { | ||
85 | logger.debug("marked to remove: " + activation); | ||
86 | } | ||
87 | if(newActivations.remove(activation)) { | ||
88 | logger.debug("Abnormal: removed from new activations: " + activation); | ||
89 | } | ||
90 | //*/ | ||
91 | } | ||
92 | return false; | ||
93 | } | ||
94 | |||
95 | @Override | ||
96 | public boolean addActivation(Activation<?> activation) { | ||
97 | if (isIncremental) { | ||
98 | //* | ||
99 | newActivations.add(activation); | ||
100 | removedActivations.remove(activation); | ||
101 | /*/ | ||
102 | if (activation.isEnabled()) { | ||
103 | if (!newActivations.add(activation)) { | ||
104 | logger.debug("Abnormal: already added as new: " + activation); | ||
105 | } else { | ||
106 | logger.debug("activation added: " + activation); | ||
107 | } | ||
108 | } | ||
109 | if(removedActivations.remove(activation)) { | ||
110 | logger.debug("Abnormal: was already marked to remove: " + activation); | ||
111 | } | ||
112 | //*/ | ||
113 | } | ||
114 | return false; | ||
115 | } | ||
116 | |||
117 | public Object getActivationId(Activation<?> activation) { | ||
118 | return activationCodes.activationsToCodes.get(activation); | ||
119 | } | ||
120 | |||
121 | public Activation<?> getActivation(Object activationId) { | ||
122 | Set<Activation<?>> activationsSet = activationCodes.codesToActivations.get(activationId); | ||
123 | if (activationsSet == null || activationsSet.isEmpty()) { | ||
124 | return null; | ||
125 | } else { | ||
126 | return activationsSet.iterator().next(); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | public void updateActivationCodes() { | ||
131 | // logger.debug("Updating activation codes."); | ||
132 | |||
133 | if (isIncremental) { | ||
134 | for (Activation<?> activation : removedActivations) { | ||
135 | activationCodes.removeActivaion(activation); | ||
136 | // logger.debug("removed activation: " + activationId); | ||
137 | } | ||
138 | |||
139 | for (Activation<?> activation : newActivations) { | ||
140 | if (activation.getState().isInactive()) { | ||
141 | continue; | ||
142 | } | ||
143 | Object activationCode = createActivationCode(activation); | ||
144 | activationCodes.addActivation(activation, activationCode); | ||
145 | // logger.debug("new activation: " + activationId); | ||
146 | // Activation<?> similarActivation = activationIds.inverse().get(activationId); | ||
147 | // if (similarActivation != null) { | ||
148 | // logger.debug("Activation " + toStringAct(activation) + " is already present with id: " + activationId); | ||
149 | // if (similarActivation.isEnabled()) { | ||
150 | // logger.warn("Duplicate activation code: " + activationId); | ||
151 | // } else { | ||
152 | // logger.debug("Force put: " + activationId); | ||
153 | // } | ||
154 | // continue; | ||
155 | // } | ||
156 | // activationIds.put(activation, activationId); | ||
157 | } | ||
158 | removedActivations.clear(); | ||
159 | newActivations.clear(); | ||
160 | } else { | ||
161 | activationCodes.clear(); | ||
162 | for (Activation<?> activation : nextActivationsConflictSet.getNextActivations()) { | ||
163 | Object activationCode = createActivationCode(activation); | ||
164 | activationCodes.addActivation(activation, activationCode); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | |||
169 | } | ||
170 | |||
171 | protected void reinitWithActivations(ConflictSet nextActivationsConflictSet) { | ||
172 | this.nextActivationsConflictSet = nextActivationsConflictSet; | ||
173 | activationCodes.clear(); | ||
174 | for (Activation<?> activation : nextActivationsConflictSet.getNextActivations()) { | ||
175 | Object activationCode = createActivationCode(activation); | ||
176 | activationCodes.addActivation(activation, activationCode); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | @Override | ||
181 | public Activation<?> getNextActivation() { | ||
182 | throw new UnsupportedOperationException(); | ||
183 | } | ||
184 | |||
185 | @Override | ||
186 | public Set<Activation<?>> getNextActivations() { | ||
187 | throw new UnsupportedOperationException(); | ||
188 | } | ||
189 | |||
190 | @Override | ||
191 | public Set<Activation<?>> getConflictingActivations() { | ||
192 | throw new UnsupportedOperationException(); | ||
193 | } | ||
194 | |||
195 | @Override | ||
196 | public ConflictResolver getConflictResolver() { | ||
197 | throw new UnsupportedOperationException(); | ||
198 | } | ||
199 | |||
200 | @Override | ||
201 | public String toString() { | ||
202 | StringBuilder sb = new StringBuilder(); | ||
203 | for (Object activationCode : activationCodes.activationsToCodes.values()) { | ||
204 | sb.append(activationCode); | ||
205 | sb.append(" | "); | ||
206 | } | ||
207 | return sb.toString(); | ||
208 | } | ||
209 | |||
210 | public Collection<Object> getCurrentActivationCodes() { | ||
211 | return activationCodes.activationsToCodes.values(); | ||
212 | } | ||
213 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java new file mode 100644 index 00000000..4c6b4097 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java | |||
@@ -0,0 +1,563 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.base; | ||
10 | |||
11 | import java.lang.reflect.InvocationTargetException; | ||
12 | import java.util.ArrayList; | ||
13 | import java.util.Collection; | ||
14 | import java.util.HashMap; | ||
15 | import java.util.Iterator; | ||
16 | import java.util.List; | ||
17 | import java.util.Map; | ||
18 | import java.util.Random; | ||
19 | |||
20 | import org.apache.log4j.Logger; | ||
21 | import org.eclipse.emf.common.notify.Notifier; | ||
22 | import org.eclipse.emf.edit.command.ChangeCommand; | ||
23 | import org.eclipse.emf.edit.domain.EditingDomain; | ||
24 | import org.eclipse.viatra.dse.api.DSEException; | ||
25 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
26 | import org.eclipse.viatra.dse.designspace.api.IBacktrackListener; | ||
27 | import org.eclipse.viatra.dse.designspace.api.IDesignSpace; | ||
28 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
29 | import org.eclipse.viatra.dse.objectives.ActivationFitnessProcessor; | ||
30 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
31 | import org.eclipse.viatra.dse.visualizer.IExploreEventHandler; | ||
32 | import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine; | ||
33 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
34 | import org.eclipse.viatra.transformation.evm.api.Activation; | ||
35 | import org.eclipse.viatra.transformation.evm.api.Context; | ||
36 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
37 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
38 | |||
39 | public class DesignSpaceManager implements IBacktrackListener { | ||
40 | |||
41 | private final IStateCoder stateCoder; | ||
42 | private final EditingDomain domain; | ||
43 | private Notifier model; | ||
44 | |||
45 | private IDesignSpace designSpace; | ||
46 | |||
47 | private final TrajectoryInfo trajectory; | ||
48 | |||
49 | // the occurence vector callback | ||
50 | private List<IExploreEventHandler> handlers; | ||
51 | |||
52 | // Dummy context for evm | ||
53 | private final Context evmContext = Context.create(); | ||
54 | |||
55 | private Logger logger = Logger.getLogger(this.getClass()); | ||
56 | |||
57 | private boolean isNewState = false; | ||
58 | private Map<BatchTransformationRule<?, ?>, ActivationFitnessProcessor> activationFitnessProcessors; | ||
59 | private Map<BatchTransformationRule<?, ?>, String> activationFitnessProcessorNames; | ||
60 | private ThreadContext context; | ||
61 | |||
62 | private ActivationCodesConflictSet activationCodes; | ||
63 | private ChangeableConflictSet conflictSet; | ||
64 | |||
65 | private AdvancedViatraQueryEngine engine; | ||
66 | |||
67 | private Random random = new Random(); | ||
68 | |||
69 | private long forwardTime = 0; | ||
70 | private long backtrackingTime = 0; | ||
71 | |||
72 | public DesignSpaceManager(ThreadContext context) { | ||
73 | |||
74 | this.context = context; | ||
75 | model = context.getModel(); | ||
76 | designSpace = context.getGlobalContext().getDesignSpace(); | ||
77 | domain = context.getEditingDomain(); | ||
78 | |||
79 | conflictSet = context.getConflictResolver().getLastCreatedConflictSet(); | ||
80 | |||
81 | stateCoder = context.getStateCoder(); | ||
82 | Object initialStateId = stateCoder.createStateCode(); | ||
83 | designSpace.addState(null, null, initialStateId); | ||
84 | |||
85 | activationCodes = context.getActivationCodesConflictSet(); | ||
86 | |||
87 | engine = (AdvancedViatraQueryEngine) context.getQueryEngine(); | ||
88 | |||
89 | this.trajectory = new TrajectoryInfo(initialStateId); | ||
90 | |||
91 | logger.debug("DesignSpaceManager initialized with initial model: " + initialStateId); | ||
92 | } | ||
93 | |||
94 | public void fireActivation(final Object transition) { | ||
95 | if (fireActivationSilent(transition)) { | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | StringBuilder sb = new StringBuilder(); | ||
100 | sb.append( | ||
101 | "A retrieved Transition SHOULD have a matching Activation. Possible causes: the state serializer is faulty; the algorithm choosed a wrong Transition."); | ||
102 | sb.append("\nSought transition: "); | ||
103 | sb.append(transition); | ||
104 | Object currentStateId = getCurrentState(); | ||
105 | sb.append("\nCurrent known state: "); | ||
106 | sb.append(currentStateId); | ||
107 | Object actualStateId = stateCoder.createStateCode(); | ||
108 | sb.append("\nActual state: "); | ||
109 | sb.append((actualStateId.equals(currentStateId) ? "same as current" : actualStateId)); | ||
110 | sb.append("\n"); | ||
111 | sb.append(trajectory); | ||
112 | sb.append("\nAvailable transitions:"); | ||
113 | for (Activation<?> act : conflictSet.getNextActivations()) { | ||
114 | IPatternMatch match = (IPatternMatch) act.getAtom(); | ||
115 | Object code = generateMatchCode(match); | ||
116 | sb.append("\n\t"); | ||
117 | sb.append(code); | ||
118 | } | ||
119 | |||
120 | throw new DSEException(sb.toString()); | ||
121 | } | ||
122 | |||
123 | public boolean tryFireActivation(final Object transition) { | ||
124 | return fireActivationSilent(transition); | ||
125 | } | ||
126 | |||
127 | private boolean fireActivationSilent(final Object transition) { | ||
128 | final Activation<?> activation = getActivationById(transition); | ||
129 | |||
130 | if (activation == null) { | ||
131 | return false; | ||
132 | } | ||
133 | |||
134 | BatchTransformationRule<?, ?> rule = getRuleByActivation(activation); | ||
135 | |||
136 | Map<String, Double> measureCosts = new HashMap<String, Double>(); | ||
137 | if (activationFitnessProcessors != null && activationFitnessProcessors.containsKey(rule)) { | ||
138 | IPatternMatch match = (IPatternMatch) activation.getAtom(); | ||
139 | ActivationFitnessProcessor processor = activationFitnessProcessors.get(rule); | ||
140 | double fitness = processor.process(match); | ||
141 | measureCosts.put(activationFitnessProcessorNames.get(rule), fitness); | ||
142 | } | ||
143 | |||
144 | ChangeCommand rc = new ChangeCommand(model) { | ||
145 | @Override | ||
146 | protected void doExecute() { | ||
147 | activation.fire(evmContext); | ||
148 | } | ||
149 | }; | ||
150 | |||
151 | Object previousState = trajectory.getCurrentStateId(); | ||
152 | |||
153 | long start = System.nanoTime(); | ||
154 | domain.getCommandStack().execute(rc); | ||
155 | forwardTime += System.nanoTime() - start; | ||
156 | |||
157 | Object newStateId = stateCoder.createStateCode(); | ||
158 | updateActivationCodes(); | ||
159 | |||
160 | if (designSpace != null) { | ||
161 | isNewState = !designSpace.isTraversed(newStateId); | ||
162 | designSpace.addState(previousState, transition, newStateId); | ||
163 | } | ||
164 | |||
165 | trajectory.addStep(transition, rule, newStateId, measureCosts); | ||
166 | |||
167 | if (handlers != null) { | ||
168 | for (IExploreEventHandler iExploreEventHandler : handlers) { | ||
169 | iExploreEventHandler.transitionFired(transition); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | logger.debug("Executed activation: " + transition);/* | ||
174 | * + " from state: " + previousState + " to " + newStateId); | ||
175 | */ | ||
176 | |||
177 | return true; | ||
178 | } | ||
179 | |||
180 | public boolean executeRandomActivationId() { | ||
181 | Collection<Object> transitions = getTransitionsFromCurrentState(); | ||
182 | int size = transitions.size(); | ||
183 | if (size == 0) { | ||
184 | return false; | ||
185 | } | ||
186 | |||
187 | int index = random.nextInt(size); | ||
188 | Iterator<Object> iterator = transitions.iterator(); | ||
189 | for (int i = 0; i < index; ++i) { | ||
190 | iterator.next(); | ||
191 | } | ||
192 | Object transition = iterator.next(); | ||
193 | |||
194 | fireActivation(transition); | ||
195 | return true; | ||
196 | } | ||
197 | |||
198 | public int executeTrajectory(Object[] trajectoryToExecute) { | ||
199 | return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, false, true); | ||
200 | } | ||
201 | |||
202 | public int executeTrajectory(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex) { | ||
203 | return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, false, true); | ||
204 | } | ||
205 | |||
206 | public int executeTrajectoryByTrying(Object[] trajectoryToExecute) { | ||
207 | return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, true, true); | ||
208 | } | ||
209 | |||
210 | public int executeTrajectoryByTrying(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex) { | ||
211 | return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, true, true); | ||
212 | } | ||
213 | |||
214 | public int executeTrajectoryWithoutStateCoding(Object[] trajectoryToExecute) { | ||
215 | return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, false, false); | ||
216 | } | ||
217 | |||
218 | public int executeTrajectoryWithoutStateCoding(Object[] trajectoryToExecute, int fromIncludedIndex, | ||
219 | int toExcludedIndex) { | ||
220 | return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, false, false); | ||
221 | } | ||
222 | |||
223 | public int executeTrajectoryByTryingWithoutStateCoding(Object[] trajectoryToExecute) { | ||
224 | return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, true, false); | ||
225 | } | ||
226 | |||
227 | public int executeTrajectoryByTryingWithoutStateCoding(Object[] trajectoryToExecute, int fromIncludedIndex, | ||
228 | int toExcludedIndex) { | ||
229 | return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, true, false); | ||
230 | } | ||
231 | |||
232 | private int executeTrajectory(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex, | ||
233 | boolean tryAllActivations, boolean createStateCode) { | ||
234 | logger.debug("Executing trajectory."); | ||
235 | int unsuccesfulIndex = -1; | ||
236 | if (tryAllActivations) { | ||
237 | unsuccesfulIndex = 0; | ||
238 | } | ||
239 | for (int i = fromIncludedIndex; i < toExcludedIndex; i++) { | ||
240 | Object activationId = trajectoryToExecute[i]; | ||
241 | final Activation<?> activation = getActivationById(activationId); | ||
242 | |||
243 | if (activation == null) { | ||
244 | logger.debug("Couldn't execute activation: " + activationId); | ||
245 | if (tryAllActivations) { | ||
246 | unsuccesfulIndex++; | ||
247 | continue; | ||
248 | } else { | ||
249 | unsuccesfulIndex = i; | ||
250 | logger.debug("Trajectory execution stopped at index " + i + "/" + trajectoryToExecute.length); | ||
251 | break; | ||
252 | } | ||
253 | } | ||
254 | |||
255 | BatchTransformationRule<?, ?> rule = getRuleByActivation(activation); | ||
256 | |||
257 | Map<String, Double> measureCosts = new HashMap<String, Double>(); | ||
258 | if (activationFitnessProcessors != null && activationFitnessProcessors.containsKey(rule)) { | ||
259 | IPatternMatch match = (IPatternMatch) activation.getAtom(); | ||
260 | ActivationFitnessProcessor processor = activationFitnessProcessors.get(rule); | ||
261 | double fitness = processor.process(match); | ||
262 | measureCosts.put(activationFitnessProcessorNames.get(rule), fitness); | ||
263 | } | ||
264 | |||
265 | ChangeCommand rc = new ChangeCommand(model) { | ||
266 | @Override | ||
267 | protected void doExecute() { | ||
268 | activation.fire(evmContext); | ||
269 | } | ||
270 | }; | ||
271 | |||
272 | long start = System.nanoTime(); | ||
273 | domain.getCommandStack().execute(rc); | ||
274 | forwardTime += System.nanoTime() - start; | ||
275 | |||
276 | Object newStateId = null; | ||
277 | if (createStateCode) { | ||
278 | newStateId = stateCoder.createStateCode(); | ||
279 | } | ||
280 | updateActivationCodes(); | ||
281 | |||
282 | trajectory.addStep(activationId, rule, newStateId, measureCosts); | ||
283 | |||
284 | logger.debug("Activation executed: " + activationId); | ||
285 | } | ||
286 | if (!createStateCode) { | ||
287 | trajectory.modifyLastStateCode(stateCoder.createStateCode()); | ||
288 | } | ||
289 | logger.debug("Trajectory execution finished."); | ||
290 | return unsuccesfulIndex; | ||
291 | |||
292 | } | ||
293 | |||
294 | public Object getTransitionByActivation(Activation<?> activation) { | ||
295 | return activationCodes.getActivationId(activation); | ||
296 | } | ||
297 | |||
298 | public Activation<?> getActivationById(Object activationId) { | ||
299 | return activationCodes.getActivation(activationId); | ||
300 | } | ||
301 | |||
302 | public BatchTransformationRule<?, ?> getRuleByActivation(Activation<?> activation) { | ||
303 | return context.getGlobalContext().getSpecificationRuleMap().get(activation.getInstance().getSpecification()); | ||
304 | } | ||
305 | |||
306 | public BatchTransformationRule<?, ?> getRuleByActivationId(Object activationId) { | ||
307 | return getRuleByActivation(getActivationById(activationId)); | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * Returns true if the given state is not owned by this crawler. | ||
312 | * | ||
313 | **/ | ||
314 | public boolean isNewModelStateAlreadyTraversed() { | ||
315 | return !isNewState; | ||
316 | } | ||
317 | |||
318 | public List<Object> getTrajectoryFromRoot() { | ||
319 | return trajectory.getTrajectory(); | ||
320 | } | ||
321 | |||
322 | public Collection<Object> getTransitionsFromCurrentState() { | ||
323 | return activationCodes.getCurrentActivationCodes(); | ||
324 | } | ||
325 | |||
326 | public Collection<Object> getUntraversedTransitionsFromCurrentState() { | ||
327 | if (designSpace == null) { | ||
328 | throw new DSEException("Unsupported without a design space"); | ||
329 | } | ||
330 | Object currentState = trajectory.getCurrentStateId(); | ||
331 | Collection<Object> traversedIds = designSpace.getActivationIds(currentState); | ||
332 | |||
333 | List<Object> untraversedTransitions = new ArrayList<>(); | ||
334 | for (Object activationId : activationCodes.getCurrentActivationCodes()) { | ||
335 | if (!traversedIds.contains(activationId)) { | ||
336 | untraversedTransitions.add(activationId); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | return untraversedTransitions; | ||
341 | } | ||
342 | |||
343 | public boolean undoLastTransformation() { | ||
344 | |||
345 | if (!trajectory.canStepBack()) { | ||
346 | return false; | ||
347 | } | ||
348 | |||
349 | long start = System.nanoTime(); | ||
350 | try { | ||
351 | engine.delayUpdatePropagation(() -> { | ||
352 | domain.getCommandStack().undo(); | ||
353 | return null; | ||
354 | }); | ||
355 | } catch (InvocationTargetException e) { | ||
356 | throw new RuntimeException(e); | ||
357 | } | ||
358 | updateActivationCodes(); | ||
359 | |||
360 | Object lastActivationId = trajectory.getLastActivationId(); | ||
361 | |||
362 | trajectory.backtrack(); | ||
363 | |||
364 | if (handlers != null) { | ||
365 | for (IExploreEventHandler iExploreEventHandler : handlers) { | ||
366 | iExploreEventHandler.undo(lastActivationId); | ||
367 | } | ||
368 | } | ||
369 | |||
370 | logger.debug("Backtrack."); | ||
371 | backtrackingTime += System.nanoTime() - start; | ||
372 | |||
373 | return true; | ||
374 | } | ||
375 | |||
376 | public void backtrackXTimes(int steps) { | ||
377 | long start = System.nanoTime(); | ||
378 | try { | ||
379 | engine.delayUpdatePropagation(() -> { | ||
380 | for (int i = steps; i > 0; i--) { | ||
381 | domain.getCommandStack().undo(); | ||
382 | trajectory.backtrack(); | ||
383 | } | ||
384 | return null; | ||
385 | }); | ||
386 | } catch (InvocationTargetException e) { | ||
387 | throw new RuntimeException(e); | ||
388 | } | ||
389 | backtrackingTime += System.nanoTime() - start; | ||
390 | updateActivationCodes(); | ||
391 | logger.debug("Backtracked " + steps + " times."); | ||
392 | } | ||
393 | |||
394 | public int backtrackUntilLastCommonActivation(Object[] newTrajectory) { | ||
395 | long start = System.nanoTime(); | ||
396 | Iterator<Object> currentTrajectoryIterator = trajectory.getTrajectory().iterator(); | ||
397 | if (!currentTrajectoryIterator.hasNext()) { | ||
398 | return 0; | ||
399 | } | ||
400 | int indexOfLastCommonActivation = 0; | ||
401 | for (Object activationCode : newTrajectory) { | ||
402 | if (currentTrajectoryIterator.hasNext()) { | ||
403 | Object activationCodeFromCurrent = currentTrajectoryIterator.next(); | ||
404 | if (activationCodeFromCurrent.equals(activationCode)) { | ||
405 | indexOfLastCommonActivation++; | ||
406 | } else { | ||
407 | break; | ||
408 | } | ||
409 | } else { | ||
410 | // current trajectory is smaller | ||
411 | break; | ||
412 | } | ||
413 | } | ||
414 | int numberOfBacktracks = trajectory.getDepth() - indexOfLastCommonActivation; | ||
415 | if (numberOfBacktracks > 0) { | ||
416 | try { | ||
417 | engine.delayUpdatePropagation(() -> { | ||
418 | for (int i = numberOfBacktracks; i > 0; i--) { | ||
419 | domain.getCommandStack().undo(); | ||
420 | trajectory.backtrack(); | ||
421 | } | ||
422 | return null; | ||
423 | }); | ||
424 | } catch (InvocationTargetException e) { | ||
425 | throw new RuntimeException(e); | ||
426 | } | ||
427 | } | ||
428 | backtrackingTime += System.nanoTime() - start; | ||
429 | updateActivationCodes(); | ||
430 | logger.debug("Backtracked " + numberOfBacktracks + " times."); | ||
431 | return indexOfLastCommonActivation; | ||
432 | } | ||
433 | |||
434 | public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory) { | ||
435 | executeTrajectoryWithMinimalBacktrack(trajectory, trajectory.length); | ||
436 | } | ||
437 | |||
438 | public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory, int toExcludedIndex) { | ||
439 | int fromIndex = backtrackUntilLastCommonActivation(trajectory); | ||
440 | executeTrajectory(trajectory, fromIndex, toExcludedIndex, false, true); | ||
441 | } | ||
442 | |||
443 | public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory) { | ||
444 | executeTrajectoryWithMinimalBacktrackWithoutStateCoding(trajectory, trajectory.length); | ||
445 | } | ||
446 | |||
447 | public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory, int toExcludedIndex) { | ||
448 | int fromIndex = backtrackUntilLastCommonActivation(trajectory); | ||
449 | executeTrajectory(trajectory, fromIndex, toExcludedIndex, false, false); | ||
450 | Object stateCode = stateCoder.createStateCode(); | ||
451 | this.trajectory.modifyLastStateCode(stateCode); | ||
452 | } | ||
453 | |||
454 | public void undoUntilRoot() { | ||
455 | long start = System.nanoTime(); | ||
456 | try { | ||
457 | engine.delayUpdatePropagation(() -> { | ||
458 | while (trajectory.canStepBack()) { | ||
459 | domain.getCommandStack().undo(); | ||
460 | trajectory.backtrack(); | ||
461 | } | ||
462 | return null; | ||
463 | }); | ||
464 | } catch (InvocationTargetException e) { | ||
465 | throw new RuntimeException(e); | ||
466 | } | ||
467 | backtrackingTime += System.nanoTime() - start; | ||
468 | updateActivationCodes(); | ||
469 | logger.debug("Backtracked to root."); | ||
470 | } | ||
471 | |||
472 | private Object generateMatchCode(IPatternMatch match) { | ||
473 | return stateCoder.createActivationCode(match); | ||
474 | } | ||
475 | |||
476 | public Object getCurrentState() { | ||
477 | return trajectory.getCurrentStateId(); | ||
478 | } | ||
479 | |||
480 | public SolutionTrajectory createSolutionTrajectroy() { | ||
481 | return trajectory.createSolutionTrajectory(context.getGlobalContext().getStateCoderFactory(), this); | ||
482 | } | ||
483 | |||
484 | public TrajectoryInfo getTrajectoryInfo() { | ||
485 | return trajectory; | ||
486 | } | ||
487 | |||
488 | public void setDesignSpace(IDesignSpace designSpace) { | ||
489 | this.designSpace = designSpace; | ||
490 | } | ||
491 | |||
492 | public IDesignSpace getDesignSpace() { | ||
493 | return designSpace; | ||
494 | } | ||
495 | |||
496 | public void registerExploreEventHandler(IExploreEventHandler handler) { | ||
497 | if (handler == null) { | ||
498 | return; | ||
499 | } | ||
500 | if (handlers == null) { | ||
501 | handlers = new ArrayList<IExploreEventHandler>(); | ||
502 | } | ||
503 | handlers.add(handler); | ||
504 | } | ||
505 | |||
506 | public void deregisterExploreEventHandler(IExploreEventHandler handler) { | ||
507 | if (handler == null) { | ||
508 | return; | ||
509 | } | ||
510 | if (handlers != null) { | ||
511 | handlers.remove(handler); | ||
512 | } | ||
513 | } | ||
514 | |||
515 | public void registerActivationCostProcessor(String name, BatchTransformationRule<?, ?> rule, | ||
516 | ActivationFitnessProcessor activationFitnessProcessor) { | ||
517 | if (activationFitnessProcessors == null || activationFitnessProcessorNames == null) { | ||
518 | activationFitnessProcessors = new HashMap<BatchTransformationRule<?, ?>, ActivationFitnessProcessor>(); | ||
519 | activationFitnessProcessorNames = new HashMap<BatchTransformationRule<?, ?>, String>(); | ||
520 | } | ||
521 | activationFitnessProcessors.put(rule, activationFitnessProcessor); | ||
522 | activationFitnessProcessorNames.put(rule, name); | ||
523 | } | ||
524 | |||
525 | public boolean isCurentStateInTrajectory() { | ||
526 | Object currentStateId = trajectory.getCurrentStateId(); | ||
527 | List<Object> stateTrajectory = trajectory.getStateTrajectory(); | ||
528 | int size = stateTrajectory.size(); | ||
529 | for (int i = 0; i < size - 1; i++) { | ||
530 | Object stateId = stateTrajectory.get(i); | ||
531 | if (currentStateId.equals(stateId)) { | ||
532 | return true; | ||
533 | } | ||
534 | } | ||
535 | return false; | ||
536 | } | ||
537 | |||
538 | public IStateCoder getStateCoder() { | ||
539 | return stateCoder; | ||
540 | } | ||
541 | |||
542 | private void updateActivationCodes() { | ||
543 | activationCodes.updateActivationCodes(); | ||
544 | } | ||
545 | |||
546 | public long getForwardTime() { | ||
547 | return forwardTime; | ||
548 | } | ||
549 | |||
550 | public long getBacktrackingTime() { | ||
551 | return backtrackingTime; | ||
552 | } | ||
553 | |||
554 | @Override | ||
555 | public void forwardWorked(long nanos) { | ||
556 | forwardTime += nanos; | ||
557 | } | ||
558 | |||
559 | @Override | ||
560 | public void backtrackWorked(long nanos) { | ||
561 | backtrackingTime += nanos; | ||
562 | } | ||
563 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictResolver.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictResolver.java new file mode 100644 index 00000000..35504b56 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictResolver.java | |||
@@ -0,0 +1,35 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.base; | ||
10 | |||
11 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
12 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
13 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
14 | |||
15 | public class DseConflictResolver implements ConflictResolver { | ||
16 | |||
17 | private ConflictResolver activationOrderingconflictResolver; | ||
18 | private IStateCoder stateCoder; | ||
19 | private DseConflictSet lastCreatedConflictSet; | ||
20 | |||
21 | public DseConflictResolver(ConflictResolver activationOrderingConflictResolver, IStateCoder stateCoder) { | ||
22 | this.activationOrderingconflictResolver = activationOrderingConflictResolver; | ||
23 | this.stateCoder = stateCoder; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public ChangeableConflictSet createConflictSet() { | ||
28 | lastCreatedConflictSet = new DseConflictSet(this, activationOrderingconflictResolver, stateCoder); | ||
29 | return lastCreatedConflictSet; | ||
30 | } | ||
31 | |||
32 | public DseConflictSet getLastCreatedConflictSet() { | ||
33 | return lastCreatedConflictSet; | ||
34 | } | ||
35 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictSet.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictSet.java new file mode 100644 index 00000000..cba595f4 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictSet.java | |||
@@ -0,0 +1,83 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.base; | ||
10 | |||
11 | import java.util.Set; | ||
12 | |||
13 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
14 | import org.eclipse.viatra.transformation.evm.api.Activation; | ||
15 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
16 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
17 | |||
18 | public class DseConflictSet implements ChangeableConflictSet { | ||
19 | |||
20 | private ActivationCodesConflictSet activationCodesConflictSet; | ||
21 | private ChangeableConflictSet activationOrderingConflictSet; | ||
22 | private ChangeableConflictSet prevActivationOrderingConflictSet; | ||
23 | private ConflictResolver resolver; | ||
24 | |||
25 | public DseConflictSet(ConflictResolver resolver, ConflictResolver activationOrderingConflictResolver, | ||
26 | IStateCoder stateCoder) { | ||
27 | this.resolver = resolver; | ||
28 | activationOrderingConflictSet = activationOrderingConflictResolver.createConflictSet(); | ||
29 | activationCodesConflictSet = new ActivationCodesConflictSet(activationOrderingConflictSet, stateCoder); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public Activation<?> getNextActivation() { | ||
34 | return activationOrderingConflictSet.getNextActivation(); | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public Set<Activation<?>> getNextActivations() { | ||
39 | return activationOrderingConflictSet.getNextActivations(); | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public Set<Activation<?>> getConflictingActivations() { | ||
44 | return activationOrderingConflictSet.getConflictingActivations(); | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public ConflictResolver getConflictResolver() { | ||
49 | return resolver; | ||
50 | } | ||
51 | |||
52 | @Override | ||
53 | public boolean addActivation(Activation<?> activation) { | ||
54 | activationCodesConflictSet.addActivation(activation); | ||
55 | return activationOrderingConflictSet.addActivation(activation); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public boolean removeActivation(Activation<?> activation) { | ||
60 | activationCodesConflictSet.removeActivation(activation); | ||
61 | return activationOrderingConflictSet.removeActivation(activation); | ||
62 | } | ||
63 | |||
64 | public ActivationCodesConflictSet getActivationCodesConflictSet() { | ||
65 | return activationCodesConflictSet; | ||
66 | } | ||
67 | |||
68 | public void changeActivationOrderingConflictSet(ChangeableConflictSet newActivationOrderingConflictSet) { | ||
69 | for (Activation<?> activation : activationOrderingConflictSet.getConflictingActivations()) { | ||
70 | newActivationOrderingConflictSet.addActivation(activation); | ||
71 | } | ||
72 | activationCodesConflictSet.reinitWithActivations(newActivationOrderingConflictSet); | ||
73 | ChangeableConflictSet tmp = activationOrderingConflictSet; | ||
74 | activationOrderingConflictSet = newActivationOrderingConflictSet; | ||
75 | prevActivationOrderingConflictSet = tmp; | ||
76 | } | ||
77 | |||
78 | public void changeActivationOrderingConflictSetBack() { | ||
79 | ChangeableConflictSet newActivationOrderingConflictSet = | ||
80 | prevActivationOrderingConflictSet.getConflictResolver().createConflictSet(); | ||
81 | changeActivationOrderingConflictSet(newActivationOrderingConflictSet); | ||
82 | } | ||
83 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseEvmRuleBase.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseEvmRuleBase.java new file mode 100644 index 00000000..838c1d1b --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseEvmRuleBase.java | |||
@@ -0,0 +1,21 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.base; | ||
10 | |||
11 | import org.eclipse.viatra.transformation.evm.api.Agenda; | ||
12 | import org.eclipse.viatra.transformation.evm.api.RuleBase; | ||
13 | import org.eclipse.viatra.transformation.evm.api.event.EventRealm; | ||
14 | |||
15 | public class DseEvmRuleBase extends RuleBase { | ||
16 | |||
17 | public DseEvmRuleBase(EventRealm eventRealm, Agenda agenda) { | ||
18 | super(eventRealm, agenda); | ||
19 | } | ||
20 | |||
21 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseIdPoolHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseIdPoolHelper.java new file mode 100644 index 00000000..f6fee7be --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseIdPoolHelper.java | |||
@@ -0,0 +1,68 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.base; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.concurrent.ConcurrentHashMap; | ||
14 | |||
15 | import org.eclipse.viatra.dse.api.DSEException; | ||
16 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
17 | |||
18 | public enum DseIdPoolHelper { | ||
19 | |||
20 | INSTANCE; | ||
21 | |||
22 | public static interface IGetRuleExecutions { | ||
23 | int getRuleExecutions(BatchTransformationRule<?, ?> rule); | ||
24 | } | ||
25 | |||
26 | public static class IdProvider { | ||
27 | |||
28 | private final BatchTransformationRule<?, ?> rule; | ||
29 | private IGetRuleExecutions getRuleExecutions; | ||
30 | |||
31 | public IdProvider(IGetRuleExecutions getRuleExecutions, BatchTransformationRule<?, ?> rule) { | ||
32 | this.getRuleExecutions = getRuleExecutions; | ||
33 | this.rule = rule; | ||
34 | } | ||
35 | |||
36 | public int getId() { | ||
37 | return getRuleExecutions.getRuleExecutions(rule); | ||
38 | } | ||
39 | |||
40 | } | ||
41 | |||
42 | private ConcurrentHashMap<Thread, HashMap<BatchTransformationRule<?, ?>, IdProvider>> idProviders = new ConcurrentHashMap<>(); | ||
43 | |||
44 | public int getId(BatchTransformationRule<?, ?> rule) { | ||
45 | Thread currentThread = Thread.currentThread(); | ||
46 | HashMap<BatchTransformationRule<?, ?>, IdProvider> ruleMap = idProviders.get(currentThread); | ||
47 | if (ruleMap == null) { | ||
48 | throw new DSEException("There is no registered id provider"); | ||
49 | } | ||
50 | IdProvider idProvider = ruleMap.get(rule); | ||
51 | return idProvider.getId(); | ||
52 | } | ||
53 | |||
54 | public void registerRules(IGetRuleExecutions getRuleExecutions, Collection<BatchTransformationRule<?, ?>> rules) { | ||
55 | Thread currentThread = Thread.currentThread(); | ||
56 | HashMap<BatchTransformationRule<?, ?>, IdProvider> ruleMap = new HashMap<>(); | ||
57 | for (BatchTransformationRule<?, ?> rule : rules) { | ||
58 | IdProvider idProvider = new IdProvider(getRuleExecutions, rule); | ||
59 | ruleMap.put(rule, idProvider); | ||
60 | } | ||
61 | idProviders.put(currentThread, ruleMap); | ||
62 | } | ||
63 | |||
64 | public void disposeByThread() { | ||
65 | Thread currentThread = Thread.currentThread(); | ||
66 | idProviders.remove(currentThread); | ||
67 | } | ||
68 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ExplorerThread.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ExplorerThread.java new file mode 100644 index 00000000..f2231e5c --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ExplorerThread.java | |||
@@ -0,0 +1,88 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.base; | ||
10 | |||
11 | import org.apache.log4j.Logger; | ||
12 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
13 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
14 | import org.eclipse.viatra.transformation.evm.api.RuleEngine; | ||
15 | |||
16 | /** | ||
17 | * This class implements the {@link Runnable} interface, to able to run an exploration strategy in a separate thread. It | ||
18 | * is also responsible to initialize the exploration, start the exploration (call the {@link IStrategy#explore()} | ||
19 | * method), catch any exception during exploration and to shutdown the thread correctly. | ||
20 | * | ||
21 | * @author Földenyi Miklos & Nagy Andras Szabolcs | ||
22 | * | ||
23 | */ | ||
24 | public class ExplorerThread implements Runnable { | ||
25 | |||
26 | private final ThreadContext threadContext; | ||
27 | |||
28 | private IStrategy strategy; | ||
29 | |||
30 | public ExplorerThread(final ThreadContext context) { | ||
31 | this.threadContext = context; | ||
32 | strategy = threadContext.getStrategy(); | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * Signals the {@link IStrategy} instance that execution should be stopped. By contract, the strategy is to | ||
37 | * stop execution at the next stage of execution where stopping and exiting is appropriate. | ||
38 | */ | ||
39 | public void stopRunning() { | ||
40 | strategy.interruptStrategy(); | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * Starts the design space exploration. Returns only when the {@link IStrategy#explore()} method returns. | ||
45 | */ | ||
46 | public void run() { | ||
47 | GlobalContext globalContext = threadContext.getGlobalContext(); | ||
48 | try { | ||
49 | |||
50 | threadContext.init(); | ||
51 | |||
52 | strategy.initStrategy(threadContext); | ||
53 | |||
54 | strategy.explore(); | ||
55 | |||
56 | threadContext.backtrackUntilRoot(); | ||
57 | |||
58 | } catch (Throwable e) { | ||
59 | Logger.getLogger(IStrategy.class).error("Thread stopped unexpectedly!", e); | ||
60 | globalContext.registerException(e); | ||
61 | } finally { | ||
62 | globalContext.strategyFinished(this); | ||
63 | dispose(); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * Disposes of this strategy. Recursively calls dispose on the underlying {@link RuleEngine} and | ||
69 | * {@link ViatraQueryEngine}. Calling this is only required if the design space exploration was launched in thread, as | ||
70 | * the underlying engines get collected on the stop of the running {@link Thread}. | ||
71 | */ | ||
72 | public void dispose() { | ||
73 | threadContext.getRuleEngine().dispose(); | ||
74 | DseIdPoolHelper.INSTANCE.disposeByThread(); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * Returns the associated {@link ThreadContext} that houses all the thread specific data about the exploration | ||
79 | * process, and is also the gateway to the {@link GlobalContext} which stores data relevant to the design space | ||
80 | * exploration process as a whole. | ||
81 | * | ||
82 | * @return the relevant {@link ThreadContext}. | ||
83 | */ | ||
84 | public ThreadContext getThreadContext() { | ||
85 | return threadContext; | ||
86 | } | ||
87 | |||
88 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java new file mode 100644 index 00000000..7325ead3 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java | |||
@@ -0,0 +1,374 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.base; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collection; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.HashSet; | ||
15 | import java.util.List; | ||
16 | import java.util.Map; | ||
17 | import java.util.Set; | ||
18 | import java.util.concurrent.ConcurrentLinkedQueue; | ||
19 | import java.util.concurrent.atomic.AtomicBoolean; | ||
20 | |||
21 | import org.apache.log4j.Logger; | ||
22 | import org.eclipse.emf.common.notify.Notifier; | ||
23 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
24 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategyFactory; | ||
25 | import org.eclipse.viatra.dse.designspace.api.IDesignSpace; | ||
26 | import org.eclipse.viatra.dse.multithreading.DSEThreadPool; | ||
27 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint; | ||
28 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
29 | import org.eclipse.viatra.dse.objectives.LeveledObjectivesHelper; | ||
30 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
31 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
32 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
33 | import org.eclipse.viatra.dse.visualizer.IDesignSpaceVisualizer; | ||
34 | import org.eclipse.viatra.transformation.evm.api.RuleSpecification; | ||
35 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
36 | import org.eclipse.viatra.transformation.evm.specific.ConflictResolvers; | ||
37 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
38 | |||
39 | import com.google.common.base.Preconditions; | ||
40 | import com.google.common.collect.ImmutableList; | ||
41 | |||
42 | /** | ||
43 | * Creates new contexts for strategies. It is needed because of the multithreading. | ||
44 | * | ||
45 | * @author Andras Szabolcs Nagy | ||
46 | * | ||
47 | */ | ||
48 | public class GlobalContext { | ||
49 | |||
50 | // **** fields and methods for multi threading *****// | ||
51 | // *************************************************// | ||
52 | |||
53 | public enum ExplorationProcessState { | ||
54 | NOT_STARTED, | ||
55 | RUNNING, | ||
56 | STOPPING, | ||
57 | COMPLETED | ||
58 | } | ||
59 | |||
60 | private ConcurrentLinkedQueue<Throwable> exceptions = new ConcurrentLinkedQueue<Throwable>(); | ||
61 | |||
62 | private volatile ExplorationProcessState state = ExplorationProcessState.NOT_STARTED; | ||
63 | private final Set<ExplorerThread> runningThreads = new HashSet<ExplorerThread>(); | ||
64 | private DSEThreadPool threadPool = new DSEThreadPool(); | ||
65 | private int numberOfStartedThreads = 0; | ||
66 | private IDesignSpace designSpace; | ||
67 | |||
68 | private AtomicBoolean firstThreadContextInited = new AtomicBoolean(false); | ||
69 | private AtomicBoolean firstThreadContextIniting = new AtomicBoolean(false); | ||
70 | |||
71 | private Map<RuleSpecification<?>, BatchTransformationRule<?,?>> specificationRuleMap; | ||
72 | |||
73 | private Object terminationSnycObject = new Object(); | ||
74 | |||
75 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
76 | |||
77 | private boolean isAlreadyInited; | ||
78 | |||
79 | public void waitForTermination() { | ||
80 | synchronized (terminationSnycObject) { | ||
81 | while (!isDone()) { | ||
82 | try { | ||
83 | terminationSnycObject.wait(); | ||
84 | } catch (InterruptedException e) { | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * Starts a new thread to explore the design space. | ||
92 | * | ||
93 | * @param originalThreadContext The context of the thread which starts the new thread. | ||
94 | * @param model The model to start from. | ||
95 | * @param cloneModel It should be true in most cases. | ||
96 | * @param strategy The strategy, the thread will use. | ||
97 | * @return The {@link ExplorerThread} | ||
98 | */ | ||
99 | private synchronized ExplorerThread tryStartNewThread(ThreadContext originalThreadContext, Notifier model, | ||
100 | IStrategy strategy) { | ||
101 | |||
102 | if(!isAlreadyInited) { | ||
103 | isAlreadyInited = true; | ||
104 | init(); | ||
105 | } | ||
106 | |||
107 | if (state != ExplorationProcessState.COMPLETED && state != ExplorationProcessState.STOPPING | ||
108 | && threadPool.canStartNewThread()) { | ||
109 | |||
110 | ThreadContext newThreadContext = new ThreadContext(this, strategy, model); | ||
111 | |||
112 | // TODO : clone undo list? slave strategy can't go further back... | ||
113 | ExplorerThread explorerThread = new ExplorerThread(newThreadContext); | ||
114 | newThreadContext.setExplorerThread(explorerThread); | ||
115 | |||
116 | boolean isSuccessful = threadPool.tryStartNewStrategy(explorerThread); | ||
117 | |||
118 | if (isSuccessful) { | ||
119 | runningThreads.add(explorerThread); | ||
120 | |||
121 | state = ExplorationProcessState.RUNNING; | ||
122 | ++numberOfStartedThreads; | ||
123 | |||
124 | logger.info("New thread started, active threads: " + runningThreads.size()); | ||
125 | |||
126 | return explorerThread; | ||
127 | } | ||
128 | } | ||
129 | return null; | ||
130 | } | ||
131 | |||
132 | public synchronized ExplorerThread tryStartNewThread(ThreadContext originalThreadContext, IStrategy strategy) { | ||
133 | return tryStartNewThread(originalThreadContext, EMFHelper.clone(originalThreadContext.getModel()), strategy); | ||
134 | } | ||
135 | |||
136 | public synchronized ExplorerThread tryStartNewThreadWithoutModelClone(ThreadContext originalThreadContext, | ||
137 | IStrategy strategy) { | ||
138 | return tryStartNewThread(originalThreadContext, originalThreadContext.getModel(), strategy); | ||
139 | } | ||
140 | |||
141 | public synchronized ExplorerThread startFirstThread(IStrategy strategy, Notifier model) { | ||
142 | Preconditions.checkState(!isAlreadyInited, "First thread is already started."); | ||
143 | return tryStartNewThread(null, EMFHelper.clone(model), strategy); | ||
144 | } | ||
145 | |||
146 | public synchronized ExplorerThread startFirstThreadWithoutModelClone(IStrategy strategy, Notifier model) { | ||
147 | Preconditions.checkState(!isAlreadyInited, "First thread is already started."); | ||
148 | return tryStartNewThread(null, model, strategy); | ||
149 | } | ||
150 | |||
151 | public synchronized void startAllThreads(ThreadContext originalThreadContext, IStrategyFactory strategyFactory) { | ||
152 | while (canStartNewThread()) { | ||
153 | tryStartNewThread(originalThreadContext, strategyFactory.createStrategy()); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * Starts a new thread to explore the design space. | ||
159 | * | ||
160 | * @param strategyBase | ||
161 | * The {@link Strategy}. | ||
162 | * @param tedToClone | ||
163 | * The model to clone. Hint: context.getTed() | ||
164 | */ | ||
165 | |||
166 | public synchronized void strategyFinished(ExplorerThread strategy) { | ||
167 | runningThreads.remove(strategy); | ||
168 | |||
169 | logger.info("Thread finished, active threads: " + runningThreads.size()); | ||
170 | |||
171 | // is the first part necessary? | ||
172 | if (runningThreads.isEmpty()) { | ||
173 | state = ExplorationProcessState.COMPLETED; | ||
174 | threadPool.shutdown(); | ||
175 | |||
176 | // if the main thread (which started the exploration) | ||
177 | // is waiting for the solution, than wake it up | ||
178 | synchronized (terminationSnycObject) { | ||
179 | terminationSnycObject.notify(); | ||
180 | logger.info("Exploration terminated."); | ||
181 | } | ||
182 | |||
183 | } | ||
184 | } | ||
185 | |||
186 | public synchronized boolean isDone() { | ||
187 | return state == ExplorationProcessState.COMPLETED && runningThreads.isEmpty(); | ||
188 | } | ||
189 | |||
190 | public synchronized boolean isNotStarted() { | ||
191 | return state == ExplorationProcessState.NOT_STARTED; | ||
192 | } | ||
193 | |||
194 | public boolean canStartNewThread() { | ||
195 | return (state == ExplorationProcessState.NOT_STARTED || state == ExplorationProcessState.RUNNING) | ||
196 | && threadPool.canStartNewThread(); | ||
197 | } | ||
198 | |||
199 | public synchronized void stopAllThreads() { | ||
200 | if (state == ExplorationProcessState.RUNNING) { | ||
201 | state = ExplorationProcessState.STOPPING; | ||
202 | logger.info("Stopping all threads."); | ||
203 | for (ExplorerThread strategy : runningThreads) { | ||
204 | strategy.stopRunning(); | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | |||
209 | public void registerException(Throwable e) { | ||
210 | exceptions.add(e); | ||
211 | } | ||
212 | |||
213 | // ******* fields and methods for exploration *******// | ||
214 | // **************************************************// | ||
215 | |||
216 | private List<IObjective> objectives = new ArrayList<IObjective>(); | ||
217 | private IObjective[][] leveledObjectives; | ||
218 | private List<IGlobalConstraint> globalConstraints = new ArrayList<IGlobalConstraint>(); | ||
219 | private Set<BatchTransformationRule<?, ?>> transformations = new HashSet<BatchTransformationRule<?, ?>>(); | ||
220 | private IStateCoderFactory stateCoderFactory; | ||
221 | private SolutionStore solutionStore = new SolutionStore(1); | ||
222 | private Object sharedObject; | ||
223 | private List<IDesignSpaceVisualizer> visualizers; | ||
224 | |||
225 | private ConflictResolver conflictResolver = ConflictResolvers.createArbitraryResolver(); | ||
226 | |||
227 | private void init() { | ||
228 | leveledObjectives = new LeveledObjectivesHelper(objectives).initLeveledObjectives(); | ||
229 | |||
230 | specificationRuleMap = new HashMap<>(); | ||
231 | for (BatchTransformationRule<?,?> rule : transformations) { | ||
232 | specificationRuleMap.put(rule.getRuleSpecification(), rule); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | public List<IDesignSpaceVisualizer> getVisualizers() { | ||
237 | return ImmutableList.copyOf(visualizers); | ||
238 | } | ||
239 | |||
240 | public void registerDesignSpaceVisualizer(IDesignSpaceVisualizer visualizer) { | ||
241 | if (visualizer == null) { | ||
242 | return; | ||
243 | } | ||
244 | if (visualizers == null) { | ||
245 | visualizers = new ArrayList<IDesignSpaceVisualizer>(); | ||
246 | } | ||
247 | visualizers.add(visualizer); | ||
248 | } | ||
249 | |||
250 | public void deregisterDesignSpaceVisualizer(IDesignSpaceVisualizer visualizer) { | ||
251 | if (visualizer == null) { | ||
252 | return; | ||
253 | } | ||
254 | if (visualizers != null) { | ||
255 | visualizers.remove(visualizer); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | public boolean isDesignSpaceVisualizerRegistered(IDesignSpaceVisualizer visualizer) { | ||
260 | if (visualizers != null) { | ||
261 | return visualizers.contains(visualizer); | ||
262 | } | ||
263 | return false; | ||
264 | } | ||
265 | |||
266 | public void initVisualizersForThread(ThreadContext threadContext) { | ||
267 | if (visualizers != null && !visualizers.isEmpty()) { | ||
268 | for (IDesignSpaceVisualizer visualizer : visualizers) { | ||
269 | visualizer.init(threadContext); | ||
270 | threadContext.getDesignSpaceManager().registerExploreEventHandler(visualizer); | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | public boolean isExceptionHappendInOtherThread() { | ||
276 | return !exceptions.isEmpty(); | ||
277 | } | ||
278 | |||
279 | public Collection<Throwable> getExceptions() { | ||
280 | return exceptions; | ||
281 | } | ||
282 | |||
283 | public IStateCoderFactory getStateCoderFactory() { | ||
284 | return stateCoderFactory; | ||
285 | } | ||
286 | |||
287 | public void setStateCoderFactory(IStateCoderFactory stateCoderFactory) { | ||
288 | this.stateCoderFactory = stateCoderFactory; | ||
289 | } | ||
290 | |||
291 | public Set<BatchTransformationRule<?, ?>> getTransformations() { | ||
292 | return transformations; | ||
293 | } | ||
294 | |||
295 | public void setTransformations(Set<BatchTransformationRule<?, ?>> transformations) { | ||
296 | this.transformations = transformations; | ||
297 | } | ||
298 | |||
299 | public DSEThreadPool getThreadPool() { | ||
300 | return threadPool; | ||
301 | } | ||
302 | |||
303 | public IDesignSpace getDesignSpace() { | ||
304 | return designSpace; | ||
305 | } | ||
306 | |||
307 | public void setDesignSpace(IDesignSpace designSpace) { | ||
308 | this.designSpace = designSpace; | ||
309 | } | ||
310 | |||
311 | public int getNumberOfStartedThreads() { | ||
312 | return numberOfStartedThreads; | ||
313 | } | ||
314 | |||
315 | public Object getSharedObject() { | ||
316 | return sharedObject; | ||
317 | } | ||
318 | |||
319 | public void setSharedObject(Object sharedObject) { | ||
320 | this.sharedObject = sharedObject; | ||
321 | } | ||
322 | |||
323 | public ExplorationProcessState getState() { | ||
324 | return state; | ||
325 | } | ||
326 | |||
327 | public List<IObjective> getObjectives() { | ||
328 | return objectives; | ||
329 | } | ||
330 | |||
331 | public void setObjectives(List<IObjective> objectives) { | ||
332 | this.objectives = objectives; | ||
333 | } | ||
334 | |||
335 | public List<IGlobalConstraint> getGlobalConstraints() { | ||
336 | return globalConstraints; | ||
337 | } | ||
338 | |||
339 | public void setGlobalConstraints(List<IGlobalConstraint> globalConstraints) { | ||
340 | this.globalConstraints = globalConstraints; | ||
341 | } | ||
342 | |||
343 | AtomicBoolean getFirstThreadContextInited() { | ||
344 | return firstThreadContextInited; | ||
345 | } | ||
346 | |||
347 | AtomicBoolean getFirstThreadContextIniting() { | ||
348 | return firstThreadContextIniting; | ||
349 | } | ||
350 | |||
351 | public IObjective[][] getLeveledObjectives() { | ||
352 | return leveledObjectives; | ||
353 | } | ||
354 | |||
355 | public void setSolutionStore(SolutionStore solutionStore) { | ||
356 | this.solutionStore = solutionStore; | ||
357 | } | ||
358 | |||
359 | public SolutionStore getSolutionStore() { | ||
360 | return solutionStore; | ||
361 | } | ||
362 | |||
363 | public Map<RuleSpecification<?>, BatchTransformationRule<?, ?>> getSpecificationRuleMap() { | ||
364 | return specificationRuleMap; | ||
365 | } | ||
366 | |||
367 | public void setConflictResolver(ConflictResolver conflictResolver) { | ||
368 | this.conflictResolver = conflictResolver; | ||
369 | } | ||
370 | |||
371 | public ConflictResolver getConflictResolver() { | ||
372 | return conflictResolver; | ||
373 | } | ||
374 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/IDseStrategyContext.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/IDseStrategyContext.java new file mode 100644 index 00000000..d630964f --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/IDseStrategyContext.java | |||
@@ -0,0 +1,117 @@ | |||
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.base; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.List; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import org.eclipse.emf.common.notify.Notifier; | ||
16 | import org.eclipse.emf.edit.domain.EditingDomain; | ||
17 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
18 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategyFactory; | ||
19 | import org.eclipse.viatra.dse.designspace.api.IDesignSpace; | ||
20 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
21 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
22 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint; | ||
23 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
24 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | ||
25 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
26 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
27 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
28 | import org.eclipse.viatra.transformation.evm.api.Activation; | ||
29 | import org.eclipse.viatra.transformation.evm.api.RuleEngine; | ||
30 | import org.eclipse.viatra.transformation.evm.api.RuleSpecification; | ||
31 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
32 | |||
33 | /** | ||
34 | * This interface is only to overview the required methods for exploration strategies. It is not used explicitly. | ||
35 | * | ||
36 | * @author Andras Szabolcs Nagy | ||
37 | * | ||
38 | */ | ||
39 | public interface IDseStrategyContext { | ||
40 | |||
41 | void init(); | ||
42 | |||
43 | Notifier getModel(); | ||
44 | EditingDomain getEditingDomain(); | ||
45 | ViatraQueryEngine getQueryEngine(); | ||
46 | RuleEngine getRuleEngine(); | ||
47 | IStrategy getStrategy(); | ||
48 | ExplorerThread getExplorerThread(); | ||
49 | List<IObjective> getObjectives(); | ||
50 | IObjective[][] getLeveledObjectives(); | ||
51 | List<IGlobalConstraint> getGlobalConstraints(); | ||
52 | |||
53 | SolutionStore getSolutionStore(); | ||
54 | void newSolution(); | ||
55 | // TODO void newSolution(TrajectoryFitness trajectoryFitness); | ||
56 | |||
57 | |||
58 | ObjectiveComparatorHelper getObjectiveComparatorHelper(); | ||
59 | |||
60 | GlobalContext getGlobalContext(); | ||
61 | Set<BatchTransformationRule<?, ?>> getRules(); | ||
62 | BatchTransformationRule<?, ?> getRuleByRuleSpecification(RuleSpecification<?> ruleSpecification); | ||
63 | ExplorerThread tryStartNewThread(IStrategy strategy); /*IDseStrategyContext originalContext*/ | ||
64 | ExplorerThread tryStartNewThreadWithoutModelClone(IStrategy strategy); | ||
65 | void startAllThreads(IStrategyFactory strategyFactory); | ||
66 | Object getSharedObject(); | ||
67 | void setSharedObject(Object sharedObject); | ||
68 | |||
69 | |||
70 | DesignSpaceManager getDesignSpaceManager(); | ||
71 | IStateCoder getStateCoder(); | ||
72 | IDesignSpace getDesignSpace(); | ||
73 | TrajectoryInfo getTrajectoryInfo(); | ||
74 | List<Object> getTrajectory(); | ||
75 | List<Object> getTrajectoryCopied(); | ||
76 | int getDepth(); | ||
77 | Object getCurrentStateId(); | ||
78 | |||
79 | Object getTransitionByActivation(Activation<?> activation); | ||
80 | Activation<?> getActivationById(Object activationId); | ||
81 | BatchTransformationRule<?, ?> getRuleByActivation(Activation<?> activation); | ||
82 | BatchTransformationRule<?, ?> getRuleByActivationId(Object activationId); | ||
83 | |||
84 | Collection<Object> getCurrentActivationIds(); | ||
85 | Collection<Object> getUntraversedActivationIds(); | ||
86 | // TODO Object getArbitraryActivationId(); | ||
87 | // TODO Object getArbitraryUntraversedActivationId(); | ||
88 | |||
89 | void executeAcitvationId(Object activationId); | ||
90 | boolean tryExecuteAcitvationId(Object activationId); | ||
91 | boolean executeRandomActivationId(); | ||
92 | void executeTrajectory(Object[] activationIds); | ||
93 | void executeTrajectory(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex); | ||
94 | int executeTrajectoryByTrying(Object[] activationIds); | ||
95 | int executeTrajectoryByTrying(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex); | ||
96 | int executeTrajectoryWithoutStateCoding(Object[] activationIds); | ||
97 | int executeTrajectoryWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex); | ||
98 | int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds); | ||
99 | int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex); | ||
100 | void executeTrajectoryWithMinimalBacktrack(Object[] trajectory); | ||
101 | void executeTrajectoryWithMinimalBacktrack(Object[] trajectory, int toExcludedIndex); | ||
102 | void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory); | ||
103 | void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory, int toExcludedIndex); | ||
104 | |||
105 | boolean backtrack(); | ||
106 | // TODO int backtrack(int times); | ||
107 | void backtrackUntilLastCommonActivation(Object[] trajectory); | ||
108 | void backtrackUntilRoot(); | ||
109 | |||
110 | Fitness calculateFitness(); | ||
111 | Fitness getLastFitness(); | ||
112 | boolean checkGlobalConstraints(); | ||
113 | boolean isCurrentStateAlreadyTraversed(); | ||
114 | // this needs states stored: | ||
115 | boolean isCurrentStateInTrajectory(); | ||
116 | |||
117 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/SingletonSetConflictResolver.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/SingletonSetConflictResolver.java new file mode 100644 index 00000000..8c0a715a --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/SingletonSetConflictResolver.java | |||
@@ -0,0 +1,53 @@ | |||
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.base; | ||
10 | |||
11 | import org.eclipse.viatra.transformation.evm.api.RuleEngine; | ||
12 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
13 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
14 | |||
15 | /** | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public class SingletonSetConflictResolver implements ConflictResolver { | ||
21 | |||
22 | protected ChangeableConflictSet conflictSet; | ||
23 | protected ConflictResolver conflictResolver; | ||
24 | protected ConflictResolver prevConflictResolver; | ||
25 | protected RuleEngine ruleEngine; | ||
26 | |||
27 | public SingletonSetConflictResolver(ConflictResolver conflictResolver) { | ||
28 | this.conflictResolver = conflictResolver; | ||
29 | conflictSet = conflictResolver.createConflictSet(); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public ChangeableConflictSet createConflictSet() { | ||
34 | return conflictSet; | ||
35 | } | ||
36 | |||
37 | public void changeConflictResolver(ConflictResolver conflictResolver) { | ||
38 | ConflictResolver tmp = this.conflictResolver; | ||
39 | this.conflictResolver = conflictResolver; | ||
40 | prevConflictResolver = tmp; | ||
41 | conflictSet = conflictResolver.createConflictSet(); | ||
42 | ruleEngine.setConflictResolver(this); | ||
43 | } | ||
44 | |||
45 | public void changeConflictResolverBack() { | ||
46 | changeConflictResolver(prevConflictResolver); | ||
47 | } | ||
48 | |||
49 | public void setRuleEngine(RuleEngine ruleEngine) { | ||
50 | this.ruleEngine = ruleEngine; | ||
51 | ruleEngine.setConflictResolver(this); | ||
52 | } | ||
53 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ThreadContext.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ThreadContext.java new file mode 100644 index 00000000..b62442ce --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ThreadContext.java | |||
@@ -0,0 +1,542 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.base; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collection; | ||
13 | import java.util.List; | ||
14 | import java.util.Set; | ||
15 | import java.util.concurrent.atomic.AtomicBoolean; | ||
16 | |||
17 | import org.apache.log4j.Logger; | ||
18 | import org.eclipse.emf.common.notify.Notifier; | ||
19 | import org.eclipse.emf.edit.domain.EditingDomain; | ||
20 | import org.eclipse.viatra.dse.api.DSEException; | ||
21 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
22 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategyFactory; | ||
23 | import org.eclipse.viatra.dse.designspace.api.IDesignSpace; | ||
24 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
25 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
26 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint; | ||
27 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
28 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | ||
29 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
30 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
31 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
32 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
33 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
34 | import org.eclipse.viatra.query.runtime.emf.EMFScope; | ||
35 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
36 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
37 | import org.eclipse.viatra.transformation.evm.api.Activation; | ||
38 | import org.eclipse.viatra.transformation.evm.api.RuleEngine; | ||
39 | import org.eclipse.viatra.transformation.evm.api.RuleSpecification; | ||
40 | import org.eclipse.viatra.transformation.evm.api.event.EventFilter; | ||
41 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
42 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
43 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictSet; | ||
44 | import org.eclipse.viatra.transformation.evm.specific.RuleEngines; | ||
45 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
46 | |||
47 | /** | ||
48 | * This class holds all the information that is related to a single processing thread of the DesignSpaceExploration | ||
49 | * process. For any attributes related to the Design Space Exploration process as a whole, see {@link GlobalContext}. | ||
50 | * | ||
51 | * @author Miklos Foldenyi | ||
52 | * | ||
53 | */ | ||
54 | public class ThreadContext implements IDseStrategyContext{ | ||
55 | |||
56 | private final GlobalContext globalContext; | ||
57 | private final IStrategy strategy; | ||
58 | private ExplorerThread explorerThread; | ||
59 | private RuleEngine ruleEngine; | ||
60 | private ViatraQueryEngine queryEngine; | ||
61 | private EditingDomain domain; | ||
62 | private Notifier model; | ||
63 | private DesignSpaceManager designSpaceManager; | ||
64 | private List<IObjective> objectives; | ||
65 | private List<IGlobalConstraint> globalConstraints; | ||
66 | private Fitness lastFitness; | ||
67 | private ObjectiveComparatorHelper objectiveComparatorHelper; | ||
68 | private IStateCoder stateCoder; | ||
69 | private DseConflictResolver dseConflictResolver; | ||
70 | private DseConflictSet dseConflictSet; | ||
71 | private ActivationCodesConflictSet activationCodesConflictSet; | ||
72 | |||
73 | /** | ||
74 | * This value is true after the {@link ThreadContext} has been initialized in it's own thread. | ||
75 | */ | ||
76 | private AtomicBoolean inited = new AtomicBoolean(false); | ||
77 | |||
78 | private boolean isFirstThread = false; | ||
79 | private IObjective[][] leveledObjectives; | ||
80 | |||
81 | private static class GetRuleExecutionsImpl implements DseIdPoolHelper.IGetRuleExecutions { | ||
82 | |||
83 | private List<BatchTransformationRule<?, ?>> executedRules; | ||
84 | |||
85 | public GetRuleExecutionsImpl(List<BatchTransformationRule<?, ?>> executedRulesView) { | ||
86 | this.executedRules = executedRulesView; | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public int getRuleExecutions(BatchTransformationRule<?, ?> rule) { | ||
91 | int nextId = 0; | ||
92 | for (BatchTransformationRule<?, ?> r : executedRules) { | ||
93 | if (r.equals(rule)) { | ||
94 | nextId ++; | ||
95 | } | ||
96 | } | ||
97 | return nextId; | ||
98 | } | ||
99 | |||
100 | } | ||
101 | |||
102 | public DseConflictResolver getConflictResolver() { | ||
103 | return dseConflictResolver; | ||
104 | } | ||
105 | |||
106 | public ConflictSet getConflictSet() { | ||
107 | return dseConflictSet; | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Creates a {@link ThreadContext} and sets it up to be initialized on the given {@link TransactionalEditingDomain} | ||
112 | * | ||
113 | * @param globalContext | ||
114 | * @param strategyBase | ||
115 | * @param domain | ||
116 | * @param trajectoryInfoToClone | ||
117 | * @param parentGuidance | ||
118 | */ | ||
119 | public ThreadContext(final GlobalContext globalContext, IStrategy strategy, Notifier model) { | ||
120 | Preconditions.checkArgument(model != null, "Cannot initialize ThreadContext on a null model."); | ||
121 | this.globalContext = globalContext; | ||
122 | this.strategy = strategy; | ||
123 | this.model = model; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Initializes the {@link ThreadContext} by initializing the underlying {@link ViatraQueryEngine} and | ||
128 | * {@link RuleEngine}. {@link Guidance} initialization is also happening within this method. | ||
129 | * | ||
130 | * @throws DSEException | ||
131 | */ | ||
132 | public void init() { | ||
133 | |||
134 | AtomicBoolean isFirst = globalContext.getFirstThreadContextIniting(); | ||
135 | AtomicBoolean isFirstReady = globalContext.getFirstThreadContextInited(); | ||
136 | if (!isFirstReady.get()) { | ||
137 | if (!isFirst.compareAndSet(false, true)) { | ||
138 | try { | ||
139 | do { | ||
140 | Thread.sleep(5); | ||
141 | } while (!isFirstReady.get()); | ||
142 | } catch (InterruptedException e) { | ||
143 | } | ||
144 | } else { | ||
145 | isFirstThread = true; | ||
146 | } | ||
147 | } | ||
148 | // prohibit re-initialization | ||
149 | Preconditions.checkArgument(!inited.getAndSet(true), "This Thread context has been initialized already!"); | ||
150 | |||
151 | try { | ||
152 | // initialize query engine | ||
153 | final EMFScope scope = new EMFScope(model); | ||
154 | queryEngine = ViatraQueryEngine.on(scope); | ||
155 | |||
156 | |||
157 | stateCoder = getGlobalContext().getStateCoderFactory().createStateCoder(); | ||
158 | stateCoder.init(model); | ||
159 | stateCoder.createStateCode(); | ||
160 | |||
161 | ConflictResolver activationOrderingCconflictResolver = globalContext.getConflictResolver(); | ||
162 | dseConflictResolver = new DseConflictResolver(activationOrderingCconflictResolver, stateCoder); | ||
163 | |||
164 | ruleEngine = RuleEngines.createViatraQueryRuleEngine(queryEngine); | ||
165 | ruleEngine.setConflictResolver(dseConflictResolver); | ||
166 | for (BatchTransformationRule<?, ?> tr : globalContext.getTransformations()) { | ||
167 | ruleEngine.addRule(tr.getRuleSpecification(), (EventFilter<IPatternMatch>) tr.getFilter()); | ||
168 | } | ||
169 | dseConflictSet = dseConflictResolver.getLastCreatedConflictSet(); | ||
170 | activationCodesConflictSet = dseConflictSet.getActivationCodesConflictSet(); | ||
171 | activationCodesConflictSet.updateActivationCodes(); | ||
172 | |||
173 | |||
174 | } catch (ViatraQueryException e) { | ||
175 | throw new DSEException("Failed to create unmanaged ViatraQueryEngine on the model.", e); | ||
176 | } | ||
177 | |||
178 | if (isFirstThread) { | ||
179 | |||
180 | objectives = globalContext.getObjectives(); | ||
181 | leveledObjectives = globalContext.getLeveledObjectives(); | ||
182 | globalConstraints = globalContext.getGlobalConstraints(); | ||
183 | |||
184 | } else { | ||
185 | objectives = new ArrayList<IObjective>(); | ||
186 | |||
187 | IObjective[][] leveledObjectivesToCopy = globalContext.getLeveledObjectives(); | ||
188 | leveledObjectives = new IObjective[leveledObjectivesToCopy.length][]; | ||
189 | for (int i = 0; i < leveledObjectivesToCopy.length; i++) { | ||
190 | leveledObjectives[i] = new IObjective[leveledObjectivesToCopy[i].length]; | ||
191 | for (int j = 0; j < leveledObjectivesToCopy[i].length; j++) { | ||
192 | leveledObjectives[i][j] = leveledObjectivesToCopy[i][j].createNew(); | ||
193 | objectives.add(leveledObjectives[i][j]); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | globalConstraints = new ArrayList<IGlobalConstraint>(); | ||
198 | for (IGlobalConstraint globalConstraint : globalContext.getGlobalConstraints()) { | ||
199 | globalConstraints.add(globalConstraint.createNew()); | ||
200 | } | ||
201 | |||
202 | } | ||
203 | // create the thread specific DesignSpaceManager | ||
204 | this.domain = EMFHelper.createEditingDomain(model); | ||
205 | designSpaceManager = new DesignSpaceManager(this); | ||
206 | |||
207 | boolean isThereHardObjective = false; | ||
208 | for (IObjective objective : objectives) { | ||
209 | objective.init(this); | ||
210 | if (objective.isHardObjective()) { | ||
211 | isThereHardObjective = true; | ||
212 | } | ||
213 | } | ||
214 | if (!isThereHardObjective) { | ||
215 | Logger.getLogger(IStrategy.class).warn( | ||
216 | "No hard objective is specified: all reachable state is a solution. Use a dummy hard objective to be explicit."); | ||
217 | } | ||
218 | |||
219 | for (IGlobalConstraint globalConstraint : globalConstraints) { | ||
220 | globalConstraint.init(this); | ||
221 | } | ||
222 | |||
223 | DseIdPoolHelper.INSTANCE.registerRules(new GetRuleExecutionsImpl(getDesignSpaceManager().getTrajectoryInfo().getRules()), getRules()); | ||
224 | |||
225 | globalContext.initVisualizersForThread(this); | ||
226 | |||
227 | if (isFirstThread) { | ||
228 | isFirstReady.set(true); | ||
229 | } | ||
230 | |||
231 | } | ||
232 | |||
233 | public Fitness calculateFitness() { | ||
234 | Fitness result = new Fitness(); | ||
235 | |||
236 | boolean satisifiesHardObjectives = true; | ||
237 | |||
238 | for (IObjective objective : objectives) { | ||
239 | Double fitness = objective.getFitness(this); | ||
240 | result.put(objective.getName(), fitness); | ||
241 | if (objective.isHardObjective() && !objective.satisifiesHardObjective(fitness)) { | ||
242 | satisifiesHardObjectives = false; | ||
243 | } | ||
244 | } | ||
245 | |||
246 | result.setSatisifiesHardObjectives(satisifiesHardObjectives); | ||
247 | |||
248 | lastFitness = result; | ||
249 | |||
250 | return result; | ||
251 | } | ||
252 | |||
253 | public boolean checkGlobalConstraints() { | ||
254 | for (IGlobalConstraint globalConstraint : globalContext.getGlobalConstraints()) { | ||
255 | if (!globalConstraint.checkGlobalConstraint(this)) { | ||
256 | return false; | ||
257 | } | ||
258 | } | ||
259 | return true; | ||
260 | } | ||
261 | |||
262 | public RuleEngine getRuleEngine() { | ||
263 | return ruleEngine; | ||
264 | } | ||
265 | |||
266 | public GlobalContext getGlobalContext() { | ||
267 | return globalContext; | ||
268 | } | ||
269 | |||
270 | public DesignSpaceManager getDesignSpaceManager() { | ||
271 | return designSpaceManager; | ||
272 | } | ||
273 | |||
274 | public EditingDomain getEditingDomain() { | ||
275 | return domain; | ||
276 | } | ||
277 | |||
278 | public Notifier getModel() { | ||
279 | return model; | ||
280 | } | ||
281 | |||
282 | public ViatraQueryEngine getQueryEngine() { | ||
283 | return queryEngine; | ||
284 | } | ||
285 | |||
286 | public IStrategy getStrategy() { | ||
287 | return strategy; | ||
288 | } | ||
289 | |||
290 | public ExplorerThread getExplorerThread() { | ||
291 | return explorerThread; | ||
292 | } | ||
293 | |||
294 | public void setExplorerThread(ExplorerThread explorerThread) { | ||
295 | this.explorerThread = explorerThread; | ||
296 | } | ||
297 | |||
298 | public Fitness getLastFitness() { | ||
299 | return lastFitness; | ||
300 | } | ||
301 | |||
302 | public ObjectiveComparatorHelper getObjectiveComparatorHelper() { | ||
303 | if (objectiveComparatorHelper == null) { | ||
304 | objectiveComparatorHelper = new ObjectiveComparatorHelper(leveledObjectives); | ||
305 | } | ||
306 | return objectiveComparatorHelper; | ||
307 | } | ||
308 | |||
309 | public IObjective[][] getLeveledObjectives() { | ||
310 | return leveledObjectives; | ||
311 | } | ||
312 | |||
313 | public List<IObjective> getObjectives() { | ||
314 | return objectives; | ||
315 | } | ||
316 | |||
317 | public List<IGlobalConstraint> getGlobalConstraints() { | ||
318 | return globalConstraints; | ||
319 | } | ||
320 | |||
321 | @Override | ||
322 | public SolutionStore getSolutionStore() { | ||
323 | return globalContext.getSolutionStore(); | ||
324 | } | ||
325 | |||
326 | @Override | ||
327 | public void newSolution() { | ||
328 | globalContext.getSolutionStore().newSolution(this); | ||
329 | } | ||
330 | |||
331 | @Override | ||
332 | public Object getSharedObject() { | ||
333 | return globalContext.getSharedObject(); | ||
334 | } | ||
335 | |||
336 | @Override | ||
337 | public void setSharedObject(Object sharedObject) { | ||
338 | globalContext.setSharedObject(sharedObject); | ||
339 | } | ||
340 | |||
341 | @Override | ||
342 | public Set<BatchTransformationRule<?, ?>> getRules() { | ||
343 | return globalContext.getTransformations(); | ||
344 | } | ||
345 | |||
346 | @Override | ||
347 | public BatchTransformationRule<?, ?> getRuleByRuleSpecification(RuleSpecification<?> ruleSpecification) { | ||
348 | return globalContext.getSpecificationRuleMap().get(ruleSpecification); | ||
349 | } | ||
350 | |||
351 | @Override | ||
352 | public ExplorerThread tryStartNewThread(IStrategy strategy) { | ||
353 | return globalContext.tryStartNewThread(this, strategy); | ||
354 | } | ||
355 | |||
356 | @Override | ||
357 | public ExplorerThread tryStartNewThreadWithoutModelClone(IStrategy strategy) { | ||
358 | return globalContext.tryStartNewThreadWithoutModelClone(this, strategy); | ||
359 | } | ||
360 | |||
361 | @Override | ||
362 | public void startAllThreads(IStrategyFactory strategyFactory) { | ||
363 | globalContext.startAllThreads(this, strategyFactory); | ||
364 | } | ||
365 | |||
366 | @Override | ||
367 | public IStateCoder getStateCoder() { | ||
368 | return stateCoder; | ||
369 | } | ||
370 | |||
371 | @Override | ||
372 | public IDesignSpace getDesignSpace() { | ||
373 | return globalContext.getDesignSpace(); | ||
374 | } | ||
375 | |||
376 | @Override | ||
377 | public TrajectoryInfo getTrajectoryInfo() { | ||
378 | return designSpaceManager.getTrajectoryInfo(); | ||
379 | } | ||
380 | |||
381 | @Override | ||
382 | public List<Object> getTrajectory() { | ||
383 | return designSpaceManager.getTrajectoryInfo().getTrajectory(); | ||
384 | } | ||
385 | |||
386 | @Override | ||
387 | public List<Object> getTrajectoryCopied() { | ||
388 | return new ArrayList<Object>(getTrajectory()); | ||
389 | } | ||
390 | |||
391 | @Override | ||
392 | public int getDepth() { | ||
393 | return designSpaceManager.getTrajectoryInfo().getDepth(); | ||
394 | } | ||
395 | |||
396 | @Override | ||
397 | public Object getCurrentStateId() { | ||
398 | return designSpaceManager.getTrajectoryInfo().getCurrentStateId(); | ||
399 | } | ||
400 | |||
401 | @Override | ||
402 | public Object getTransitionByActivation(Activation<?> activation) { | ||
403 | return designSpaceManager.getTransitionByActivation(activation); | ||
404 | } | ||
405 | |||
406 | @Override | ||
407 | public Activation<?> getActivationById(Object activationId) { | ||
408 | return designSpaceManager.getActivationById(activationId); | ||
409 | } | ||
410 | |||
411 | @Override | ||
412 | public BatchTransformationRule<?, ?> getRuleByActivation(Activation<?> activation) { | ||
413 | return designSpaceManager.getRuleByActivation(activation); | ||
414 | } | ||
415 | |||
416 | @Override | ||
417 | public BatchTransformationRule<?, ?> getRuleByActivationId(Object activationId) { | ||
418 | return designSpaceManager.getRuleByActivationId(activationId); | ||
419 | } | ||
420 | |||
421 | @Override | ||
422 | public Collection<Object> getCurrentActivationIds() { | ||
423 | return designSpaceManager.getTransitionsFromCurrentState(); | ||
424 | } | ||
425 | |||
426 | @Override | ||
427 | public Collection<Object> getUntraversedActivationIds() { | ||
428 | return designSpaceManager.getUntraversedTransitionsFromCurrentState(); | ||
429 | } | ||
430 | |||
431 | @Override | ||
432 | public void executeAcitvationId(Object activationId) { | ||
433 | designSpaceManager.fireActivation(activationId); | ||
434 | } | ||
435 | |||
436 | @Override | ||
437 | public boolean tryExecuteAcitvationId(Object activationId) { | ||
438 | return designSpaceManager.tryFireActivation(activationId); | ||
439 | } | ||
440 | |||
441 | @Override | ||
442 | public boolean executeRandomActivationId() { | ||
443 | return designSpaceManager.executeRandomActivationId(); | ||
444 | } | ||
445 | |||
446 | @Override | ||
447 | public void executeTrajectory(Object[] activationIds) { | ||
448 | designSpaceManager.executeTrajectory(activationIds); | ||
449 | } | ||
450 | |||
451 | @Override | ||
452 | public void executeTrajectory(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) { | ||
453 | designSpaceManager.executeTrajectory(activationIds, fromIncludedIndex, toExcludedIndex); | ||
454 | } | ||
455 | |||
456 | @Override | ||
457 | public int executeTrajectoryByTrying(Object[] activationIds) { | ||
458 | return designSpaceManager.executeTrajectoryByTrying(activationIds); | ||
459 | } | ||
460 | |||
461 | @Override | ||
462 | public int executeTrajectoryByTrying(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) { | ||
463 | return designSpaceManager.executeTrajectoryByTrying(activationIds, fromIncludedIndex, toExcludedIndex); | ||
464 | } | ||
465 | |||
466 | @Override | ||
467 | public int executeTrajectoryWithoutStateCoding(Object[] activationIds) { | ||
468 | return designSpaceManager.executeTrajectoryWithoutStateCoding(activationIds); | ||
469 | } | ||
470 | |||
471 | @Override | ||
472 | public int executeTrajectoryWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) { | ||
473 | return designSpaceManager.executeTrajectoryWithoutStateCoding(activationIds, fromIncludedIndex, toExcludedIndex); | ||
474 | } | ||
475 | |||
476 | @Override | ||
477 | public int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds) { | ||
478 | return designSpaceManager.executeTrajectoryByTryingWithoutStateCoding(activationIds); | ||
479 | } | ||
480 | |||
481 | @Override | ||
482 | public int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) { | ||
483 | return designSpaceManager.executeTrajectoryByTryingWithoutStateCoding(activationIds, fromIncludedIndex, toExcludedIndex); | ||
484 | } | ||
485 | |||
486 | @Override | ||
487 | public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory) { | ||
488 | designSpaceManager.executeTrajectoryWithMinimalBacktrack(trajectory); | ||
489 | } | ||
490 | |||
491 | @Override | ||
492 | public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory, int toExcludedIndex) { | ||
493 | designSpaceManager.executeTrajectoryWithMinimalBacktrack(trajectory, toExcludedIndex); | ||
494 | } | ||
495 | |||
496 | @Override | ||
497 | public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory) { | ||
498 | designSpaceManager.executeTrajectoryWithMinimalBacktrackWithoutStateCoding(trajectory); | ||
499 | } | ||
500 | |||
501 | @Override | ||
502 | public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory, int toExcludedIndex) { | ||
503 | designSpaceManager.executeTrajectoryWithMinimalBacktrackWithoutStateCoding(trajectory, toExcludedIndex); | ||
504 | } | ||
505 | |||
506 | @Override | ||
507 | public boolean backtrack() { | ||
508 | return designSpaceManager.undoLastTransformation(); | ||
509 | } | ||
510 | |||
511 | @Override | ||
512 | public void backtrackUntilLastCommonActivation(Object[] trajectory) { | ||
513 | designSpaceManager.backtrackUntilLastCommonActivation(trajectory); | ||
514 | } | ||
515 | |||
516 | @Override | ||
517 | public void backtrackUntilRoot() { | ||
518 | designSpaceManager.undoUntilRoot(); | ||
519 | } | ||
520 | |||
521 | @Override | ||
522 | public boolean isCurrentStateAlreadyTraversed() { | ||
523 | return designSpaceManager.isNewModelStateAlreadyTraversed(); | ||
524 | } | ||
525 | |||
526 | @Override | ||
527 | public boolean isCurrentStateInTrajectory() { | ||
528 | return designSpaceManager.isCurentStateInTrajectory(); | ||
529 | } | ||
530 | |||
531 | public ActivationCodesConflictSet getActivationCodesConflictSet() { | ||
532 | return activationCodesConflictSet; | ||
533 | } | ||
534 | |||
535 | public void changeActivationOrdering(ChangeableConflictSet activationOrderingConflictSet) { | ||
536 | this.dseConflictSet.changeActivationOrderingConflictSet(activationOrderingConflictSet); | ||
537 | } | ||
538 | |||
539 | public void changeActivationOrderingBack() { | ||
540 | this.dseConflictSet.changeActivationOrderingConflictSetBack(); | ||
541 | } | ||
542 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/DesignSpace.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/DesignSpace.java new file mode 100644 index 00000000..bc0f08d4 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/DesignSpace.java | |||
@@ -0,0 +1,106 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.designspace.api; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collection; | ||
13 | import java.util.Collections; | ||
14 | import java.util.HashMap; | ||
15 | import java.util.HashSet; | ||
16 | import java.util.List; | ||
17 | import java.util.Map; | ||
18 | import java.util.Random; | ||
19 | import java.util.Set; | ||
20 | |||
21 | public class DesignSpace implements IDesignSpace { | ||
22 | |||
23 | Set<Object> statesView; | ||
24 | |||
25 | Set<Object> rootStates; | ||
26 | Set<Object> rootStatesView; | ||
27 | |||
28 | Map<Object, List<Object>> statesAndActivations; | ||
29 | |||
30 | Random random = new Random(); | ||
31 | |||
32 | public DesignSpace() { | ||
33 | rootStates = new HashSet<>(); | ||
34 | rootStatesView = Collections.unmodifiableSet(rootStates); | ||
35 | |||
36 | statesAndActivations = new HashMap<>(); | ||
37 | statesView = statesAndActivations.keySet(); | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public synchronized Collection<Object> getStates() { | ||
42 | return statesView; | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public synchronized Collection<Object> getRoots() { | ||
47 | return rootStatesView; | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public synchronized void addState(Object sourceStateId, Object firedActivationId, Object newStateId) { | ||
52 | |||
53 | List<Object> activationIds = statesAndActivations.get(newStateId); | ||
54 | |||
55 | if (activationIds == null) { | ||
56 | activationIds = new ArrayList<Object>(); | ||
57 | statesAndActivations.put(newStateId, activationIds); | ||
58 | |||
59 | if (sourceStateId == null) { | ||
60 | rootStates.add(newStateId); | ||
61 | return; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | activationIds = statesAndActivations.get(sourceStateId); | ||
66 | |||
67 | if (activationIds == null) { | ||
68 | activationIds = new ArrayList<Object>(); | ||
69 | activationIds.add(firedActivationId); | ||
70 | statesAndActivations.put(sourceStateId, activationIds); | ||
71 | } else { | ||
72 | activationIds.add(firedActivationId); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | public synchronized boolean isTraversed(Object stateId) { | ||
77 | return statesAndActivations.containsKey(stateId); | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public synchronized Collection<Object> getActivationIds(Object stateId) { | ||
82 | return statesAndActivations.get(stateId); | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | public synchronized Object getRandomActivationId(Object stateId) { | ||
87 | List<Object> activations = statesAndActivations.get(stateId); | ||
88 | int index = random.nextInt(activations.size()); | ||
89 | return activations.get(index); | ||
90 | } | ||
91 | |||
92 | @Override | ||
93 | public synchronized long getNumberOfStates() { | ||
94 | return statesAndActivations.size(); | ||
95 | } | ||
96 | |||
97 | @Override | ||
98 | public synchronized long getNumberOfTransitions() { | ||
99 | int numberOfTransitions = 0; | ||
100 | for (List<Object> activations : statesAndActivations.values()) { | ||
101 | numberOfTransitions += activations.size(); | ||
102 | } | ||
103 | return numberOfTransitions; | ||
104 | } | ||
105 | |||
106 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IBacktrackListener.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IBacktrackListener.java new file mode 100644 index 00000000..5c688276 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IBacktrackListener.java | |||
@@ -0,0 +1,7 @@ | |||
1 | package org.eclipse.viatra.dse.designspace.api; | ||
2 | |||
3 | public interface IBacktrackListener { | ||
4 | void forwardWorked(long nanos); | ||
5 | |||
6 | void backtrackWorked(long nanos); | ||
7 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IDesignSpace.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IDesignSpace.java new file mode 100644 index 00000000..a1d64bbf --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IDesignSpace.java | |||
@@ -0,0 +1,27 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.designspace.api; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | public interface IDesignSpace { | ||
14 | |||
15 | Collection<Object> getStates(); | ||
16 | Collection<Object> getRoots(); | ||
17 | void addState(Object sourceStateId, Object firedActivationId, Object newStateId); | ||
18 | |||
19 | boolean isTraversed(Object stateId); | ||
20 | |||
21 | Collection<Object> getActivationIds(Object stateId); | ||
22 | Object getRandomActivationId(Object stateId); | ||
23 | |||
24 | long getNumberOfStates(); | ||
25 | long getNumberOfTransitions(); | ||
26 | |||
27 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.java new file mode 100644 index 00000000..acd88416 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.java | |||
@@ -0,0 +1,154 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.designspace.api; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collections; | ||
13 | import java.util.List; | ||
14 | import java.util.Map; | ||
15 | import java.util.Objects; | ||
16 | |||
17 | import org.eclipse.viatra.dse.api.DSEException; | ||
18 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
19 | import org.eclipse.viatra.dse.base.DesignSpaceManager; | ||
20 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
21 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
22 | |||
23 | public class TrajectoryInfo { | ||
24 | |||
25 | private final List<Object> trajectory; | ||
26 | private final List<Object> trajectoryView; | ||
27 | private final List<BatchTransformationRule<?, ?>> rules; | ||
28 | private final List<BatchTransformationRule<?, ?>> rulesView; | ||
29 | private final List<Object> stateIds; | ||
30 | private final List<Object> stateIdsView; | ||
31 | private final List<Map<String, Double>> measuredCosts; | ||
32 | |||
33 | public TrajectoryInfo(Object initialStateId) { | ||
34 | Objects.requireNonNull(initialStateId); | ||
35 | |||
36 | stateIds = new ArrayList<>(); | ||
37 | stateIds.add(initialStateId); | ||
38 | |||
39 | trajectory = new ArrayList<>(); | ||
40 | rules = new ArrayList<>(); | ||
41 | measuredCosts = new ArrayList<>(); | ||
42 | |||
43 | trajectoryView = Collections.unmodifiableList(trajectory); | ||
44 | stateIdsView = Collections.unmodifiableList(stateIds); | ||
45 | rulesView = Collections.unmodifiableList(rules); | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * Copy constructor | ||
50 | * | ||
51 | * @since 0.17 | ||
52 | */ | ||
53 | public TrajectoryInfo(TrajectoryInfo other) { | ||
54 | this(other.stateIds, other.trajectory, other.rules, other.measuredCosts); | ||
55 | } | ||
56 | |||
57 | protected TrajectoryInfo(List<Object> stateIds, List<Object> trajectory, List<BatchTransformationRule<?, ?>> rules, List<Map<String, Double>> measuredCosts) { | ||
58 | |||
59 | this.stateIds = new ArrayList<>(stateIds); | ||
60 | this.trajectory = new ArrayList<>(trajectory); | ||
61 | this.rules = new ArrayList<>(rules); | ||
62 | trajectoryView = Collections.unmodifiableList(trajectory); | ||
63 | stateIdsView = Collections.unmodifiableList(stateIds); | ||
64 | rulesView = Collections.unmodifiableList(rules); | ||
65 | this.measuredCosts = new ArrayList<>(measuredCosts); | ||
66 | } | ||
67 | |||
68 | public void addStep(Object activationId, BatchTransformationRule<?, ?> rule, Object newStateId, Map<String, Double> measuredCosts) { | ||
69 | stateIds.add(newStateId); | ||
70 | trajectory.add(activationId); | ||
71 | rules.add(rule); | ||
72 | this.measuredCosts.add(measuredCosts); | ||
73 | } | ||
74 | |||
75 | public void backtrack() { | ||
76 | int size = trajectory.size(); | ||
77 | |||
78 | if (size == 0) { | ||
79 | throw new DSEException("Cannot step back any further!"); | ||
80 | } | ||
81 | |||
82 | trajectory.remove(size - 1); | ||
83 | rules.remove(size - 1); | ||
84 | stateIds.remove(size); | ||
85 | measuredCosts.remove(size - 1); | ||
86 | } | ||
87 | |||
88 | public Object getInitialStateId() { | ||
89 | return stateIds.get(0); | ||
90 | } | ||
91 | |||
92 | public Object getCurrentStateId() { | ||
93 | return stateIds.get(stateIds.size() - 1); | ||
94 | } | ||
95 | |||
96 | public Object getLastActivationId() { | ||
97 | return trajectory.get(trajectory.size() - 1); | ||
98 | } | ||
99 | |||
100 | public List<Object> getTrajectory() { | ||
101 | return trajectoryView; | ||
102 | } | ||
103 | |||
104 | public List<Object> getStateTrajectory() { | ||
105 | return stateIdsView; | ||
106 | } | ||
107 | |||
108 | public List<BatchTransformationRule<?, ?>> getRules() { | ||
109 | return rulesView; | ||
110 | } | ||
111 | |||
112 | public int getDepth() { | ||
113 | return trajectory.size(); | ||
114 | } | ||
115 | |||
116 | public List<Map<String, Double>> getMeasuredCosts() { | ||
117 | return measuredCosts; | ||
118 | } | ||
119 | |||
120 | public SolutionTrajectory createSolutionTrajectory(final IStateCoderFactory stateCoderFactory, final IBacktrackListener listener) { | ||
121 | |||
122 | List<Object> activationIds = new ArrayList<>(trajectory); | ||
123 | List<BatchTransformationRule<?, ?>> copiedRules = new ArrayList<>(rules); | ||
124 | |||
125 | return new SolutionTrajectory(activationIds, copiedRules, stateCoderFactory, listener); | ||
126 | } | ||
127 | |||
128 | public boolean canStepBack() { | ||
129 | return !trajectory.isEmpty(); | ||
130 | } | ||
131 | |||
132 | @Override | ||
133 | public String toString() { | ||
134 | StringBuilder sb = new StringBuilder("Trajectory:\n"); | ||
135 | for (Object activationId : trajectory) { | ||
136 | sb.append(activationId); | ||
137 | sb.append("\n"); | ||
138 | } | ||
139 | return sb.toString(); | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * This method is only used by the {@link DesignSpaceManager}. | ||
144 | * @param stateCode | ||
145 | * @return false if the initial state code is the last one, otherwise true. | ||
146 | */ | ||
147 | public boolean modifyLastStateCode(Object stateCode) { | ||
148 | if (stateIds.size() == 1) { | ||
149 | return false; | ||
150 | } | ||
151 | stateIds.set(stateIds.size() - 1, stateCode); | ||
152 | return true; | ||
153 | } | ||
154 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/multithreading/DSEThreadPool.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/multithreading/DSEThreadPool.java new file mode 100644 index 00000000..17e96a75 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/multithreading/DSEThreadPool.java | |||
@@ -0,0 +1,58 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.multithreading; | ||
10 | |||
11 | import java.util.concurrent.RejectedExecutionException; | ||
12 | import java.util.concurrent.SynchronousQueue; | ||
13 | import java.util.concurrent.ThreadPoolExecutor; | ||
14 | import java.util.concurrent.TimeUnit; | ||
15 | |||
16 | import org.apache.log4j.Logger; | ||
17 | import org.eclipse.viatra.dse.api.DesignSpaceExplorer; | ||
18 | import org.eclipse.viatra.dse.base.ExplorerThread; | ||
19 | |||
20 | /** | ||
21 | * | ||
22 | * @author Andras Szabolcs Nagy | ||
23 | * | ||
24 | */ | ||
25 | public class DSEThreadPool extends ThreadPoolExecutor { | ||
26 | |||
27 | private static final long THREAD_KEEP_ALIVE_IN_SECONDS = 60; | ||
28 | |||
29 | public DSEThreadPool() { | ||
30 | // Based on the Executors.newCachedThreadPool() | ||
31 | super(0, getProcNumber(), THREAD_KEEP_ALIVE_IN_SECONDS, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); | ||
32 | } | ||
33 | |||
34 | // helper for constructor | ||
35 | private static int getProcNumber() { | ||
36 | return Runtime.getRuntime().availableProcessors(); | ||
37 | } | ||
38 | |||
39 | public boolean tryStartNewStrategy(ExplorerThread strategy) { | ||
40 | |||
41 | if (!canStartNewThread()) { | ||
42 | return false; | ||
43 | } | ||
44 | |||
45 | try { | ||
46 | submit(strategy); | ||
47 | } catch (RejectedExecutionException e) { | ||
48 | Logger.getLogger(DesignSpaceExplorer.class).info("Couldn't start new thread.", e); | ||
49 | return false; | ||
50 | } | ||
51 | |||
52 | return true; | ||
53 | } | ||
54 | |||
55 | public boolean canStartNewThread() { | ||
56 | return getMaximumPoolSize() > getActiveCount(); | ||
57 | } | ||
58 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.java new file mode 100644 index 00000000..c06d2916 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives; | ||
10 | |||
11 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
12 | |||
13 | public interface ActivationFitnessProcessor { | ||
14 | public double process(IPatternMatch match); | ||
15 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Comparators.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Comparators.java new file mode 100644 index 00000000..b1bd9349 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Comparators.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives; | ||
10 | |||
11 | import java.util.Comparator; | ||
12 | |||
13 | /** | ||
14 | * This helper class holds comparators for objective implementations. | ||
15 | * | ||
16 | * @author Andras Szabolcs Nagy | ||
17 | * | ||
18 | */ | ||
19 | public class Comparators { | ||
20 | |||
21 | private Comparators() { /*Utility class constructor*/ } | ||
22 | |||
23 | public static final Comparator<Double> HIGHER_IS_BETTER = (o1, o2) -> o1.compareTo(o2); | ||
24 | |||
25 | public static final Comparator<Double> LOWER_IS_BETTER = (o1, o2) -> o2.compareTo(o1); | ||
26 | |||
27 | private static final Double ZERO = Double.valueOf(0); | ||
28 | |||
29 | public static final Comparator<Double> DIFFERENCE_TO_ZERO_IS_BETTER = (o1, o2) -> ZERO.compareTo(Math.abs(o1)-Math.abs(o2)); | ||
30 | |||
31 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Fitness.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Fitness.java new file mode 100644 index 00000000..8beef3bd --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Fitness.java | |||
@@ -0,0 +1,29 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives; | ||
10 | |||
11 | import java.util.HashMap; | ||
12 | |||
13 | public class Fitness extends HashMap<String, Double>{ | ||
14 | |||
15 | private boolean satisifiesHardObjectives; | ||
16 | |||
17 | public boolean isSatisifiesHardObjectives() { | ||
18 | return satisifiesHardObjectives; | ||
19 | } | ||
20 | |||
21 | public void setSatisifiesHardObjectives(boolean satisifiesHardObjectives) { | ||
22 | this.satisifiesHardObjectives = satisifiesHardObjectives; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public String toString() { | ||
27 | return super.toString() + " hardObjectives=" + satisifiesHardObjectives; | ||
28 | } | ||
29 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IGlobalConstraint.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IGlobalConstraint.java new file mode 100644 index 00000000..2f7f0347 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IGlobalConstraint.java | |||
@@ -0,0 +1,58 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | |||
13 | /** | ||
14 | * | ||
15 | * Implementation of this interface represents a global constraint of the DSE problem, which can halt an exploration | ||
16 | * continuing from a state which dissatisfies the global constraint. | ||
17 | * <p> | ||
18 | * Certain global constraints can have inner state for the validation. In this case a new instance is necessary for | ||
19 | * every new thread, and the {@code createNew} method should not return the same instance more than once. | ||
20 | * | ||
21 | * @author Andras Szabolcs Nagy | ||
22 | * | ||
23 | */ | ||
24 | public interface IGlobalConstraint { | ||
25 | |||
26 | /** | ||
27 | * Returns the name of the global constraint. | ||
28 | * | ||
29 | * @return The name of the global constraint. | ||
30 | */ | ||
31 | String getName(); | ||
32 | |||
33 | /** | ||
34 | * Checks whether the current state satisfies the global constraint. | ||
35 | * | ||
36 | * @param context | ||
37 | * The {@link ThreadContext} which contains the necessary information. | ||
38 | * @return True if the state is valid and exploration can be continued from the actual state. | ||
39 | */ | ||
40 | boolean checkGlobalConstraint(ThreadContext context); | ||
41 | |||
42 | /** | ||
43 | * Initializes the global constraint. It is called exactly once for every thread starts. | ||
44 | * | ||
45 | * @param context | ||
46 | * The {@link ThreadContext}. | ||
47 | */ | ||
48 | void init(ThreadContext context); | ||
49 | |||
50 | /** | ||
51 | * Returns an instance of the {@link IGlobalConstraint}. If it returns the same instance, all the methods has to be | ||
52 | * thread save as they are called concurrently. | ||
53 | * | ||
54 | * @return An instance of the global constraint. | ||
55 | */ | ||
56 | IGlobalConstraint createNew(); | ||
57 | |||
58 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IObjective.java new file mode 100644 index 00000000..849dd4e8 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IObjective.java | |||
@@ -0,0 +1,110 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives; | ||
10 | |||
11 | import java.util.Comparator; | ||
12 | |||
13 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
14 | |||
15 | /** | ||
16 | * | ||
17 | * Implementation of this interface represents a single objective of the DSE problem, which can assess a solution | ||
18 | * (trajectory) in a single number. It has a name and a comparator which orders two solution based on the calculated | ||
19 | * value. | ||
20 | * <p> | ||
21 | * Objectives can be either hard or soft objectives. Hard objectives can be satisfied or unsatisfied. If all of the hard | ||
22 | * objectives are satisfied on a single solution, then it is considered to be a valid (or goal) solution. | ||
23 | * <p> | ||
24 | * Certain objectives can have inner state for calculating the fitness value. In this case a new instance is necessary | ||
25 | * for every new thread, and the {@code createNew} method should not return the same instance more than once. | ||
26 | * | ||
27 | * @author Andras Szabolcs Nagy | ||
28 | * | ||
29 | */ | ||
30 | public interface IObjective { | ||
31 | |||
32 | /** | ||
33 | * Returns the name of the objective. | ||
34 | * | ||
35 | * @return The name of the objective. | ||
36 | */ | ||
37 | String getName(); | ||
38 | |||
39 | /** | ||
40 | * Sets the {@link Comparator} which is used to compare fitness (doubles). It determines whether the objective is to | ||
41 | * minimize or maximize (or minimize or maximize a delta from a given number). | ||
42 | * | ||
43 | * @param comparator The comparator. | ||
44 | */ | ||
45 | void setComparator(Comparator<Double> comparator); | ||
46 | |||
47 | /** | ||
48 | * Returns a {@link Comparator} which is used to compare fitness (doubles). It determines whether the objective is | ||
49 | * to minimize or maximize (or minimize or maximize a delta from a given number). | ||
50 | * | ||
51 | * @return The comparator. | ||
52 | */ | ||
53 | Comparator<Double> getComparator(); | ||
54 | |||
55 | /** | ||
56 | * Calculates the value of the objective on a given solution (trajectory). | ||
57 | * | ||
58 | * @param context | ||
59 | * The {@link ThreadContext} | ||
60 | * @return The objective value in double. | ||
61 | */ | ||
62 | Double getFitness(ThreadContext context); | ||
63 | |||
64 | /** | ||
65 | * Initializes the objective. It is called exactly once for every thread starts. | ||
66 | * | ||
67 | * @param context | ||
68 | * The {@link ThreadContext}. | ||
69 | */ | ||
70 | void init(ThreadContext context); | ||
71 | |||
72 | /** | ||
73 | * Returns an instance of the {@link IObjective}. If it returns the same instance, all the methods has to be thread | ||
74 | * save as they are called concurrently. | ||
75 | * | ||
76 | * @return An instance of the objective. | ||
77 | */ | ||
78 | IObjective createNew(); | ||
79 | |||
80 | /** | ||
81 | * Returns true if the objective is a hard objective. In such a case the method | ||
82 | * {@link IObjective#satisifiesHardObjective(Double)} is called. | ||
83 | * | ||
84 | * @return True if the objective is a hard objective. | ||
85 | * @see IObjective#satisifiesHardObjective(Double) | ||
86 | * @see IObjective | ||
87 | */ | ||
88 | boolean isHardObjective(); | ||
89 | |||
90 | /** | ||
91 | * Determines if the given fitness value satisfies the hard objective. | ||
92 | * | ||
93 | * @param fitness | ||
94 | * The fitness value of a solution. | ||
95 | * @return True if it satisfies the hard objective or it is a soft constraint. | ||
96 | * @see IObjective | ||
97 | */ | ||
98 | boolean satisifiesHardObjective(Double fitness); | ||
99 | |||
100 | /** | ||
101 | * Set the level of the objective. | ||
102 | */ | ||
103 | void setLevel(int level); | ||
104 | |||
105 | /** | ||
106 | * Gets the level of the objective. | ||
107 | */ | ||
108 | int getLevel(); | ||
109 | |||
110 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.java new file mode 100644 index 00000000..2d81629b --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.java | |||
@@ -0,0 +1,114 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy 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.objectives; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Arrays; | ||
13 | import java.util.Comparator; | ||
14 | import java.util.List; | ||
15 | |||
16 | public class LeveledObjectivesHelper { | ||
17 | |||
18 | private List<IObjective> objectives = new ArrayList<IObjective>(); | ||
19 | private IObjective[][] leveledObjectives; | ||
20 | |||
21 | public LeveledObjectivesHelper(List<IObjective> objectives) { | ||
22 | this.objectives = objectives; | ||
23 | } | ||
24 | |||
25 | public IObjective[][] initLeveledObjectives() { | ||
26 | if (objectives.isEmpty()) { | ||
27 | leveledObjectives = new IObjective[0][0]; | ||
28 | return leveledObjectives; | ||
29 | } | ||
30 | |||
31 | int level = objectives.get(0).getLevel(); | ||
32 | boolean oneLevelOnly = true; | ||
33 | for (IObjective objective : objectives) { | ||
34 | if (objective.getLevel() != level) { | ||
35 | oneLevelOnly = false; | ||
36 | break; | ||
37 | } | ||
38 | } | ||
39 | |||
40 | if (oneLevelOnly) { | ||
41 | leveledObjectives = new IObjective[1][objectives.size()]; | ||
42 | for (int i = 0; i < objectives.size(); i++) { | ||
43 | leveledObjectives[0][i] = objectives.get(i); | ||
44 | } | ||
45 | return leveledObjectives; | ||
46 | } | ||
47 | |||
48 | IObjective[] objectivesArray = getSortedByLevelObjectives(objectives); | ||
49 | |||
50 | int numberOfLevels = getNumberOfObjectiveLevels(objectivesArray); | ||
51 | |||
52 | leveledObjectives = new IObjective[numberOfLevels][]; | ||
53 | |||
54 | fillLeveledObjectives(objectivesArray); | ||
55 | |||
56 | return leveledObjectives; | ||
57 | } | ||
58 | |||
59 | private void fillLeveledObjectives(IObjective[] objectivesArray) { | ||
60 | int actLevel = objectivesArray[0].getLevel(); | ||
61 | int levelIndex = 0; | ||
62 | int lastIndex = 0; | ||
63 | int corrigationForLastLevel = 0; | ||
64 | boolean oneObjectiveAtLastLevel = false; | ||
65 | for (int i = 0; i < objectivesArray.length; i++) { | ||
66 | if (i == objectivesArray.length - 1) { | ||
67 | corrigationForLastLevel = 1; | ||
68 | if (objectivesArray[i - 1].getLevel() != objectivesArray[i].getLevel()) { | ||
69 | oneObjectiveAtLastLevel = true; | ||
70 | corrigationForLastLevel = 0; | ||
71 | } | ||
72 | } | ||
73 | if (objectivesArray[i].getLevel() != actLevel || corrigationForLastLevel == 1 || oneObjectiveAtLastLevel) { | ||
74 | leveledObjectives[levelIndex] = new IObjective[i - lastIndex + corrigationForLastLevel]; | ||
75 | for (int j = lastIndex; j < i + corrigationForLastLevel; j++) { | ||
76 | leveledObjectives[levelIndex][j - lastIndex] = objectivesArray[j]; | ||
77 | } | ||
78 | if (oneObjectiveAtLastLevel) { | ||
79 | leveledObjectives[levelIndex + 1] = new IObjective[1]; | ||
80 | leveledObjectives[levelIndex + 1][0] = objectivesArray[i]; | ||
81 | } | ||
82 | actLevel = objectivesArray[i].getLevel(); | ||
83 | levelIndex++; | ||
84 | lastIndex = i; | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | private int getNumberOfObjectiveLevels(IObjective[] objectivesArray) { | ||
90 | |||
91 | int actLevel = objectivesArray[0].getLevel(); | ||
92 | int numberOfLevels = 1; | ||
93 | |||
94 | for (int i = 1; i < objectivesArray.length; i++) { | ||
95 | if (objectivesArray[i].getLevel() != actLevel) { | ||
96 | numberOfLevels++; | ||
97 | actLevel = objectivesArray[i].getLevel(); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | return numberOfLevels; | ||
102 | } | ||
103 | |||
104 | private IObjective[] getSortedByLevelObjectives(List<IObjective> objectives) { | ||
105 | IObjective[] objectivesArray = objectives.toArray(new IObjective[objectives.size()]); | ||
106 | Arrays.sort(objectivesArray, Comparator.comparingInt(IObjective::getLevel)); | ||
107 | return objectivesArray; | ||
108 | } | ||
109 | |||
110 | public IObjective[][] getLeveledObjectives() { | ||
111 | return leveledObjectives; | ||
112 | } | ||
113 | |||
114 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.java new file mode 100644 index 00000000..39139bb0 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.java | |||
@@ -0,0 +1,217 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Arrays; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.List; | ||
15 | import java.util.Map; | ||
16 | import java.util.Random; | ||
17 | |||
18 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
19 | |||
20 | /** | ||
21 | * This class is responsible to compare and sort fitness values. {@link TrajectoryFitness} instances can be added to an | ||
22 | * instance of this class, that it can sort them. | ||
23 | * | ||
24 | * @author András Szabolcs Nagy | ||
25 | */ | ||
26 | public class ObjectiveComparatorHelper { | ||
27 | |||
28 | private IObjective[][] leveledObjectives; | ||
29 | private List<TrajectoryFitness> trajectoryFitnesses = new ArrayList<TrajectoryFitness>(); | ||
30 | private Random random = new Random(); | ||
31 | private boolean computeCrowdingDistance = false; | ||
32 | |||
33 | public ObjectiveComparatorHelper(IObjective[][] leveledObjectives) { | ||
34 | this.leveledObjectives = leveledObjectives; | ||
35 | } | ||
36 | |||
37 | public void setComputeCrowdingDistance(boolean computeCrowdingDistance) { | ||
38 | this.computeCrowdingDistance = computeCrowdingDistance; | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * Compares two fitnesses based on hierarchical dominance. Returns -1 if the second parameter {@code o2} is a better | ||
43 | * solution ({@code o2} dominates {@code o1}), 1 if the first parameter {@code o1} is better ({@code o1} dominates | ||
44 | * {@code o2}) and returns 0 if they are non-dominating each other. | ||
45 | */ | ||
46 | public int compare(Fitness o1, Fitness o2) { | ||
47 | |||
48 | levelsLoop: for (int i = 0; i < leveledObjectives.length; i++) { | ||
49 | |||
50 | boolean o1HasBetterFitness = false; | ||
51 | boolean o2HasBetterFitness = false; | ||
52 | |||
53 | for (IObjective objective : leveledObjectives[i]) { | ||
54 | String objectiveName = objective.getName(); | ||
55 | int sgn = objective.getComparator().compare(o1.get(objectiveName), o2.get(objectiveName)); | ||
56 | |||
57 | if (sgn < 0) { | ||
58 | o2HasBetterFitness = true; | ||
59 | } | ||
60 | if (sgn > 0) { | ||
61 | o1HasBetterFitness = true; | ||
62 | } | ||
63 | if (o1HasBetterFitness && o2HasBetterFitness) { | ||
64 | continue levelsLoop; | ||
65 | } | ||
66 | } | ||
67 | if (o2HasBetterFitness && !o1HasBetterFitness) { | ||
68 | return -1; | ||
69 | } else if (!o2HasBetterFitness && o1HasBetterFitness) { | ||
70 | return 1; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | |||
76 | } | ||
77 | |||
78 | /** | ||
79 | * Adds a {@link TrajectoryFitness} to an inner list to compare later. | ||
80 | * | ||
81 | * @param trajectoryFitness | ||
82 | */ | ||
83 | public void addTrajectoryFitness(TrajectoryFitness trajectoryFitness) { | ||
84 | trajectoryFitnesses.add(trajectoryFitness); | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * Clears the inner {@link TrajectoryFitness} list. | ||
89 | */ | ||
90 | public void clearTrajectoryFitnesses() { | ||
91 | trajectoryFitnesses.clear(); | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * Returns the inner {@link TrajectoryFitness} list. | ||
96 | */ | ||
97 | public List<TrajectoryFitness> getTrajectoryFitnesses() { | ||
98 | return trajectoryFitnesses; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * Returns a random {@link TrajectoryFitness} from the pareto front. | ||
103 | */ | ||
104 | public TrajectoryFitness getRandomBest() { | ||
105 | List<TrajectoryFitness> paretoFront = getParetoFront(); | ||
106 | int randomIndex = random.nextInt(paretoFront.size()); | ||
107 | return paretoFront.get(randomIndex); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Returns the pareto front of the previously added {@link TrajectoryFitness}. | ||
112 | */ | ||
113 | public List<TrajectoryFitness> getParetoFront() { | ||
114 | return getFronts().get(0); | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * Returns the previously added {@link TrajectoryFitness} instances in fronts. | ||
119 | */ | ||
120 | public List<? extends List<TrajectoryFitness>> getFronts() { | ||
121 | Preconditions.checkArgument(!trajectoryFitnesses.isEmpty(), "No trajectory fitnesses were added."); | ||
122 | List<ArrayList<TrajectoryFitness>> fronts = new ArrayList<ArrayList<TrajectoryFitness>>(); | ||
123 | |||
124 | Map<TrajectoryFitness, ArrayList<TrajectoryFitness>> dominatedInstances = new HashMap<TrajectoryFitness, ArrayList<TrajectoryFitness>>(); | ||
125 | Map<TrajectoryFitness, Integer> dominatingInstances = new HashMap<TrajectoryFitness, Integer>(); | ||
126 | |||
127 | // calculate dominations | ||
128 | for (TrajectoryFitness TrajectoryFitnessP : trajectoryFitnesses) { | ||
129 | dominatedInstances.put(TrajectoryFitnessP, new ArrayList<TrajectoryFitness>()); | ||
130 | dominatingInstances.put(TrajectoryFitnessP, 0); | ||
131 | |||
132 | for (TrajectoryFitness TrajectoryFitnessQ : trajectoryFitnesses) { | ||
133 | int dominates = compare(TrajectoryFitnessP.fitness, TrajectoryFitnessQ.fitness); | ||
134 | if (dominates > 0) { | ||
135 | dominatedInstances.get(TrajectoryFitnessP).add(TrajectoryFitnessQ); | ||
136 | } else if (dominates < 0) { | ||
137 | dominatingInstances.put(TrajectoryFitnessP, dominatingInstances.get(TrajectoryFitnessP) + 1); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | if (dominatingInstances.get(TrajectoryFitnessP) == 0) { | ||
142 | // p belongs to the first front | ||
143 | TrajectoryFitnessP.rank = 1; | ||
144 | if (fronts.isEmpty()) { | ||
145 | ArrayList<TrajectoryFitness> firstDominationFront = new ArrayList<TrajectoryFitness>(); | ||
146 | firstDominationFront.add(TrajectoryFitnessP); | ||
147 | fronts.add(firstDominationFront); | ||
148 | } else { | ||
149 | List<TrajectoryFitness> firstDominationFront = fronts.get(0); | ||
150 | firstDominationFront.add(TrajectoryFitnessP); | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | |||
155 | // create fronts | ||
156 | int i = 1; | ||
157 | while (fronts.size() == i) { | ||
158 | ArrayList<TrajectoryFitness> nextDominationFront = new ArrayList<TrajectoryFitness>(); | ||
159 | for (TrajectoryFitness TrajectoryFitnessP : fronts.get(i - 1)) { | ||
160 | for (TrajectoryFitness TrajectoryFitnessQ : dominatedInstances.get(TrajectoryFitnessP)) { | ||
161 | dominatingInstances.put(TrajectoryFitnessQ, dominatingInstances.get(TrajectoryFitnessQ) - 1); | ||
162 | if (dominatingInstances.get(TrajectoryFitnessQ) == 0) { | ||
163 | TrajectoryFitnessQ.rank = i + 1; | ||
164 | nextDominationFront.add(TrajectoryFitnessQ); | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | i++; | ||
169 | if (!nextDominationFront.isEmpty()) { | ||
170 | if (computeCrowdingDistance) { | ||
171 | crowdingDistanceAssignment(nextDominationFront, leveledObjectives); | ||
172 | } | ||
173 | fronts.add(nextDominationFront); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | return fronts; | ||
178 | } | ||
179 | |||
180 | /** | ||
181 | * Executes the crowding distance assignment for the specified front. | ||
182 | * | ||
183 | * @param front | ||
184 | */ | ||
185 | public static void crowdingDistanceAssignment(List<TrajectoryFitness> front, IObjective[][] leveledObjectives) { | ||
186 | |||
187 | for (TrajectoryFitness InstanceData : front) { | ||
188 | // initialize crowding distance | ||
189 | InstanceData.crowdingDistance = 0; | ||
190 | } | ||
191 | |||
192 | for (final IObjective[] objectives : leveledObjectives) { | ||
193 | for (final IObjective objective : objectives) { | ||
194 | |||
195 | final String m = objective.getName(); | ||
196 | TrajectoryFitness[] sortedFront = front.toArray(new TrajectoryFitness[0]); | ||
197 | // sort using m-th objective value | ||
198 | Arrays.sort(sortedFront, (o1, o2) -> objective.getComparator().compare(o1.fitness.get(m), o2.fitness.get(m))); | ||
199 | // so that boundary points are always selected | ||
200 | sortedFront[0].crowdingDistance = Double.POSITIVE_INFINITY; | ||
201 | sortedFront[sortedFront.length - 1].crowdingDistance = Double.POSITIVE_INFINITY; | ||
202 | // If minimal and maximal fitness value for this objective are | ||
203 | // equal, then do not change crowding distance | ||
204 | if (sortedFront[0].fitness.get(m) != sortedFront[sortedFront.length - 1].fitness.get(m)) { | ||
205 | for (int i = 1; i < sortedFront.length - 1; i++) { | ||
206 | double newCrowdingDistance = sortedFront[i].crowdingDistance; | ||
207 | newCrowdingDistance += (sortedFront[i + 1].fitness.get(m) - sortedFront[i - 1].fitness.get(m)) | ||
208 | / (sortedFront[sortedFront.length - 1].fitness.get(m) - sortedFront[0].fitness.get(m)); | ||
209 | |||
210 | sortedFront[i].crowdingDistance = newCrowdingDistance; | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/TrajectoryFitness.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/TrajectoryFitness.java new file mode 100644 index 00000000..f783afac --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/TrajectoryFitness.java | |||
@@ -0,0 +1,84 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.List; | ||
13 | |||
14 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
15 | |||
16 | /** | ||
17 | * This class represents a trajectory and its fitness. | ||
18 | * @author Andras Szabolcs Nagy | ||
19 | * | ||
20 | */ | ||
21 | public class TrajectoryFitness { | ||
22 | |||
23 | public Object[] trajectory; | ||
24 | public Fitness fitness; | ||
25 | |||
26 | public int rank; | ||
27 | public double crowdingDistance; | ||
28 | |||
29 | private int hash; | ||
30 | |||
31 | public int survive; | ||
32 | |||
33 | /** | ||
34 | * Creates a {@link TrajectoryFitness} with the full trajectory. | ||
35 | * @param trajectory The trajectory. | ||
36 | * @param fitness The fitness. | ||
37 | */ | ||
38 | public TrajectoryFitness(Object[] trajectory, Fitness fitness) { | ||
39 | this.fitness = fitness; | ||
40 | this.trajectory = trajectory; | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * Creates a {@link TrajectoryFitness} with the full trajectory. | ||
45 | * @param trajectoryInfo The trajectory. | ||
46 | * @param fitness The fitness. | ||
47 | */ | ||
48 | public TrajectoryFitness(TrajectoryInfo trajectoryInfo, Fitness fitness) { | ||
49 | this.fitness = fitness; | ||
50 | List<Object> fullTraj = trajectoryInfo.getTrajectory(); | ||
51 | trajectory = fullTraj.toArray(new Object[fullTraj.size()]); | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * Creates a {@link TrajectoryFitness} with the given activation id} | ||
56 | * @param transition The transition. | ||
57 | * @param fitness The fitness. | ||
58 | */ | ||
59 | public TrajectoryFitness(Object transition, Fitness fitness) { | ||
60 | this.fitness = fitness; | ||
61 | trajectory = new Object[] {transition}; | ||
62 | } | ||
63 | |||
64 | @Override | ||
65 | public boolean equals(Object obj) { | ||
66 | if (obj instanceof TrajectoryFitness) { | ||
67 | return Arrays.equals(trajectory, ((TrajectoryFitness) obj).trajectory); | ||
68 | } | ||
69 | return false; | ||
70 | } | ||
71 | |||
72 | @Override | ||
73 | public int hashCode() { | ||
74 | if (hash == 0 && trajectory.length > 0) { | ||
75 | hash = Arrays.hashCode(trajectory); | ||
76 | } | ||
77 | return hash; | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public String toString() { | ||
82 | return Arrays.toString(trajectory) + fitness.toString(); | ||
83 | } | ||
84 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardObjective.java new file mode 100644 index 00000000..9898a3b5 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardObjective.java | |||
@@ -0,0 +1,52 @@ | |||
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.objectives.impl; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
13 | |||
14 | /** | ||
15 | * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid solution. | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public class AlwaysSatisfiedDummyHardObjective extends BaseObjective { | ||
21 | |||
22 | private static final String DEFAULT_NAME = "AlwaysSatisfiedDummyHardObjective"; | ||
23 | |||
24 | public AlwaysSatisfiedDummyHardObjective() { | ||
25 | super(DEFAULT_NAME); | ||
26 | } | ||
27 | |||
28 | public AlwaysSatisfiedDummyHardObjective(String name) { | ||
29 | super(name); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public Double getFitness(ThreadContext context) { | ||
34 | return 0d; | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public boolean isHardObjective() { | ||
39 | return true; | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public boolean satisifiesHardObjective(Double fitness) { | ||
44 | return true; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public IObjective createNew() { | ||
49 | return this; | ||
50 | } | ||
51 | |||
52 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/BaseObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/BaseObjective.java new file mode 100644 index 00000000..0a1de875 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/BaseObjective.java | |||
@@ -0,0 +1,150 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives.impl; | ||
10 | |||
11 | import java.util.Comparator; | ||
12 | import java.util.Objects; | ||
13 | |||
14 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
15 | import org.eclipse.viatra.dse.objectives.Comparators; | ||
16 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
17 | |||
18 | /** | ||
19 | * This abstract class implements the basic functionality of an objective ({@link IObjective} namely its name, | ||
20 | * comparator, level and fitness hard constraint. | ||
21 | * | ||
22 | * @author Andras Szabolcs Nagy | ||
23 | * | ||
24 | */ | ||
25 | public abstract class BaseObjective implements IObjective { | ||
26 | |||
27 | protected final String name; | ||
28 | protected Comparator<Double> comparator = Comparators.HIGHER_IS_BETTER; | ||
29 | protected int level = 0; | ||
30 | |||
31 | protected double fitnessConstraint; | ||
32 | protected boolean isThereFitnessConstraint = false; | ||
33 | protected Comparator<Double> fitnessConstraintComparator; | ||
34 | |||
35 | public BaseObjective(String name) { | ||
36 | Objects.requireNonNull(name, "Name of the objective cannot be null."); | ||
37 | this.name = name; | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public String getName() { | ||
42 | return name; | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public void setComparator(Comparator<Double> comparator) { | ||
47 | this.comparator = comparator; | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public Comparator<Double> getComparator() { | ||
52 | return comparator; | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public void setLevel(int level) { | ||
57 | this.level = level; | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public int getLevel() { | ||
62 | return level; | ||
63 | } | ||
64 | |||
65 | public BaseObjective withLevel(int level) { | ||
66 | setLevel(level); | ||
67 | return this; | ||
68 | } | ||
69 | |||
70 | public BaseObjective withComparator(Comparator<Double> comparator) { | ||
71 | setComparator(comparator); | ||
72 | return this; | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * Adds a hard constraint on the fitness value. For example, the fitness value must be better than 10 to accept the | ||
77 | * current state as a solution. | ||
78 | * | ||
79 | * @param fitnessConstraint | ||
80 | * Solutions should be better than this value. | ||
81 | * @param fitnessConstraintComparator | ||
82 | * {@link Comparator} to determine if the current state is better than the given value. | ||
83 | * @return The actual instance to enable builder pattern like usage. | ||
84 | */ | ||
85 | public BaseObjective withHardConstraintOnFitness(double fitnessConstraint, | ||
86 | Comparator<Double> fitnessConstraintComparator) { | ||
87 | this.fitnessConstraint = fitnessConstraint; | ||
88 | this.fitnessConstraintComparator = fitnessConstraintComparator; | ||
89 | this.isThereFitnessConstraint = true; | ||
90 | return this; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * Adds a hard constraint on the fitness value. For example, the fitness value must be better than 10 to accept the | ||
95 | * current state as a solution. The provided comparator will be used. | ||
96 | * | ||
97 | * @param fitnessConstraint | ||
98 | * Solutions should be better than this value. | ||
99 | * @return The actual instance to enable builder pattern like usage. | ||
100 | */ | ||
101 | public BaseObjective withHardConstraintOnFitness(double fitnessConstraint) { | ||
102 | return withHardConstraintOnFitness(fitnessConstraint, null); | ||
103 | } | ||
104 | |||
105 | @Override | ||
106 | public void init(ThreadContext context) { | ||
107 | if (fitnessConstraintComparator == null) { | ||
108 | fitnessConstraintComparator = comparator; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | @Override | ||
113 | public boolean isHardObjective() { | ||
114 | return isThereFitnessConstraint; | ||
115 | } | ||
116 | |||
117 | @Override | ||
118 | public boolean satisifiesHardObjective(Double fitness) { | ||
119 | if (isThereFitnessConstraint) { | ||
120 | int compare = fitnessConstraintComparator.compare(fitness, fitnessConstraint); | ||
121 | if (compare < 0) { | ||
122 | return false; | ||
123 | } | ||
124 | } | ||
125 | return true; | ||
126 | } | ||
127 | |||
128 | @Override | ||
129 | public int hashCode() { | ||
130 | return name.hashCode(); | ||
131 | } | ||
132 | |||
133 | @Override | ||
134 | public boolean equals(Object obj) { | ||
135 | if (this == obj) { | ||
136 | return true; | ||
137 | } | ||
138 | if (obj instanceof BaseObjective) { | ||
139 | BaseObjective baseObjective = (BaseObjective) obj; | ||
140 | return name.equals(baseObjective.getName()); | ||
141 | } | ||
142 | return false; | ||
143 | } | ||
144 | |||
145 | @Override | ||
146 | public String toString() { | ||
147 | return name; | ||
148 | } | ||
149 | |||
150 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java new file mode 100644 index 00000000..cc48d22e --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java | |||
@@ -0,0 +1,137 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives.impl; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.List; | ||
13 | import java.util.Objects; | ||
14 | |||
15 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
16 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
17 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
18 | |||
19 | /** | ||
20 | * This objective collects a list of other objectives. It returns the weighted sum of the objectives. | ||
21 | * | ||
22 | * @author Andras Szabolcs Nagy | ||
23 | * | ||
24 | */ | ||
25 | public class CompositeObjective extends BaseObjective { | ||
26 | |||
27 | public static final String DEFAULT_NAME = "CompositeObjective"; | ||
28 | protected List<IObjective> objectives; | ||
29 | protected List<Double> weights; | ||
30 | protected boolean hardObjective; | ||
31 | |||
32 | public CompositeObjective(String name, List<IObjective> objectives, List<Double> weights) { | ||
33 | super(name); | ||
34 | Objects.requireNonNull(objectives, "The list of objectives cannot be null."); | ||
35 | Objects.requireNonNull(weights, "The list of weights cannot be null."); | ||
36 | Preconditions.checkState(objectives.size() == weights.size(), "The size of the objectives and weights must match."); | ||
37 | this.objectives = objectives; | ||
38 | this.weights = weights; | ||
39 | } | ||
40 | |||
41 | public CompositeObjective(List<IObjective> objectives, List<Double> weights) { | ||
42 | this(DEFAULT_NAME, objectives, weights); | ||
43 | } | ||
44 | |||
45 | public CompositeObjective(String name) { | ||
46 | this(name, new ArrayList<IObjective>(), new ArrayList<Double>()); | ||
47 | } | ||
48 | |||
49 | public CompositeObjective() { | ||
50 | this(DEFAULT_NAME, new ArrayList<IObjective>(), new ArrayList<Double>()); | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * Adds a new objective. | ||
55 | * | ||
56 | * @param objective | ||
57 | * @return The actual instance to enable builder pattern like usage. | ||
58 | */ | ||
59 | public CompositeObjective withObjective(IObjective objective) { | ||
60 | objectives.add(objective); | ||
61 | weights.add(1d); | ||
62 | return this; | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * Adds a new objective. | ||
67 | * | ||
68 | * @param objective | ||
69 | * @return The actual instance to enable builder pattern like usage. | ||
70 | */ | ||
71 | public CompositeObjective withObjective(IObjective objective, double weight) { | ||
72 | objectives.add(objective); | ||
73 | weights.add(weight); | ||
74 | return this; | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public Double getFitness(ThreadContext context) { | ||
79 | |||
80 | double result = 0; | ||
81 | |||
82 | for (int i = 0; i < objectives.size(); i++) { | ||
83 | IObjective objective = objectives.get(i); | ||
84 | Double weight = weights.get(i); | ||
85 | result += objective.getFitness(context) * weight; | ||
86 | } | ||
87 | return result; | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public void init(ThreadContext context) { | ||
92 | super.init(context); | ||
93 | hardObjective = false; | ||
94 | for (IObjective objective : objectives) { | ||
95 | objective.init(context); | ||
96 | if (objective.isHardObjective()) { | ||
97 | hardObjective = true; | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | |||
102 | @Override | ||
103 | public IObjective createNew() { | ||
104 | |||
105 | List<IObjective> newObjectives = new ArrayList<IObjective>(); | ||
106 | |||
107 | for (IObjective objective : objectives) { | ||
108 | newObjectives.add(objective.createNew()); | ||
109 | } | ||
110 | |||
111 | CompositeObjective objective = new CompositeObjective(name, newObjectives, weights); | ||
112 | if (isThereFitnessConstraint) { | ||
113 | objective.withHardConstraintOnFitness(fitnessConstraint, fitnessConstraintComparator); | ||
114 | } | ||
115 | |||
116 | return objective.withComparator(comparator).withLevel(level); | ||
117 | } | ||
118 | |||
119 | @Override | ||
120 | public boolean isHardObjective() { | ||
121 | return hardObjective; | ||
122 | } | ||
123 | |||
124 | @Override | ||
125 | public boolean satisifiesHardObjective(Double fitness) { | ||
126 | |||
127 | boolean hardObjectiveSatisfied = true; | ||
128 | |||
129 | for (IObjective objective : objectives) { | ||
130 | hardObjectiveSatisfied = objective.satisifiesHardObjective(fitness) ? hardObjectiveSatisfied : false; | ||
131 | } | ||
132 | |||
133 | hardObjectiveSatisfied = super.satisifiesHardObjective(fitness) ? hardObjectiveSatisfied : false; | ||
134 | |||
135 | return hardObjectiveSatisfied; | ||
136 | } | ||
137 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.java new file mode 100644 index 00000000..77d416f5 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.java | |||
@@ -0,0 +1,316 @@ | |||
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.objectives.impl; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.List; | ||
13 | import java.util.Objects; | ||
14 | |||
15 | import org.eclipse.viatra.dse.api.DSEException; | ||
16 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
17 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
18 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
19 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
20 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
21 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher; | ||
22 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
23 | |||
24 | /** | ||
25 | * This objective serves as soft and as hard objective at the same time by defining two lists of VIATRA Query | ||
26 | * specifications. | ||
27 | * | ||
28 | * As a soft objective, it collects a list of VIATRA Query specifications, which have predefined weights. Then the | ||
29 | * fitness value of an arbitrary solution is calculated in the following way: | ||
30 | * <p> | ||
31 | * <code>fitness = sum( pattern[i].countMatches() * weight[i] )</code> | ||
32 | * <p> | ||
33 | * As a hard objective it collects a separate list of VIATRA Query specifications. If every one of them has a match the | ||
34 | * hard constraint is considered to be fulfilled. | ||
35 | * | ||
36 | * @author Andras Szabolcs Nagy | ||
37 | * @see IObjective | ||
38 | * | ||
39 | */ | ||
40 | public class ConstraintsObjective extends BaseObjective { | ||
41 | |||
42 | public static final String DEFAULT_NAME = "ConstraintsObjective"; | ||
43 | |||
44 | public static class QueryConstraint { | ||
45 | public final String name; | ||
46 | public final IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query; | ||
47 | public final Double weight; | ||
48 | public final ModelQueryType type; | ||
49 | |||
50 | public QueryConstraint(String name, | ||
51 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query, Double weight, | ||
52 | ModelQueryType type) { | ||
53 | this.name = name; | ||
54 | this.query = query; | ||
55 | this.weight = weight; | ||
56 | this.type = type; | ||
57 | } | ||
58 | |||
59 | public QueryConstraint(String name, | ||
60 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query, Double weight) { | ||
61 | this(name, query, weight, ModelQueryType.MUST_HAVE_MATCH); | ||
62 | } | ||
63 | |||
64 | public QueryConstraint(String name, | ||
65 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query, ModelQueryType type) { | ||
66 | this(name, query, 0d, type); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | protected List<QueryConstraint> softConstraints; | ||
71 | protected List<QueryConstraint> hardConstraints; | ||
72 | |||
73 | protected List<ViatraQueryMatcher<? extends IPatternMatch>> softMatchers; | ||
74 | protected List<ViatraQueryMatcher<? extends IPatternMatch>> hardMatchers; | ||
75 | protected List<Integer> softMatches; | ||
76 | protected List<Integer> hardMatches; | ||
77 | |||
78 | public ConstraintsObjective(String name, List<QueryConstraint> softConstraints, | ||
79 | List<QueryConstraint> hardConstraints) { | ||
80 | super(name); | ||
81 | Objects.requireNonNull(softConstraints, "The list of soft constraints cannot be null."); | ||
82 | Objects.requireNonNull(hardConstraints, "The list of hard constraints cannot be null."); | ||
83 | |||
84 | this.softConstraints = softConstraints; | ||
85 | this.hardConstraints = hardConstraints; | ||
86 | } | ||
87 | |||
88 | public ConstraintsObjective(String name, List<QueryConstraint> hardConstraints) { | ||
89 | this(name, new ArrayList<QueryConstraint>(), hardConstraints); | ||
90 | } | ||
91 | |||
92 | public ConstraintsObjective(List<QueryConstraint> hardConstraints) { | ||
93 | this(DEFAULT_NAME, new ArrayList<QueryConstraint>(), hardConstraints); | ||
94 | } | ||
95 | |||
96 | public ConstraintsObjective(String name) { | ||
97 | this(name, new ArrayList<QueryConstraint>(), new ArrayList<QueryConstraint>()); | ||
98 | } | ||
99 | |||
100 | public ConstraintsObjective() { | ||
101 | this(DEFAULT_NAME, new ArrayList<QueryConstraint>(), new ArrayList<QueryConstraint>()); | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * Adds a new soft constraint. | ||
106 | * | ||
107 | * @param name | ||
108 | * A name for the soft constraint. | ||
109 | * @param softConstraint | ||
110 | * A VIATRA Query pattern specification. | ||
111 | * @param weight | ||
112 | * The weight of the pattern. | ||
113 | * @return The actual instance to enable builder pattern like usage. | ||
114 | */ | ||
115 | public ConstraintsObjective withSoftConstraint(String name, | ||
116 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> softConstraint, double weight) { | ||
117 | softConstraints.add(new QueryConstraint(name, softConstraint, weight)); | ||
118 | return this; | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * Adds a new soft constraint with the name of the query specification's fully qualified name. | ||
123 | * | ||
124 | * @param softConstraint | ||
125 | * A VIATRA Query pattern specification. | ||
126 | * @param weight | ||
127 | * The weight of the pattern. | ||
128 | * @return The actual instance to enable builder pattern like usage. | ||
129 | */ | ||
130 | public ConstraintsObjective withSoftConstraint( | ||
131 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> softConstraint, double weight) { | ||
132 | return withSoftConstraint(softConstraint.getFullyQualifiedName(), softConstraint, weight); | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * Adds a new hard constraint. | ||
137 | * | ||
138 | * @param name | ||
139 | * A name for the hard constraint. | ||
140 | * @param softConstraint | ||
141 | * A VIATRA Query pattern specification. | ||
142 | * @param type | ||
143 | * {@link ModelQueryType}, which determines whether the constraint should have at least one match or none | ||
144 | * at all. | ||
145 | * @return The actual instance to enable builder pattern like usage. | ||
146 | */ | ||
147 | public ConstraintsObjective withHardConstraint(String name, | ||
148 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint, | ||
149 | ModelQueryType type) { | ||
150 | hardConstraints.add(new QueryConstraint(name, hardConstraint, type)); | ||
151 | return this; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * Adds a new hard constraint with the default {@link ModelQueryType#MUST_HAVE_MATCH}. | ||
156 | * | ||
157 | * @param name | ||
158 | * A name for the hard constraint. | ||
159 | * @param softConstraint | ||
160 | * A VIATRA Query pattern specification. | ||
161 | * @return The actual instance to enable builder pattern like usage. | ||
162 | */ | ||
163 | public ConstraintsObjective withHardConstraint(String name, | ||
164 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint) { | ||
165 | hardConstraints.add(new QueryConstraint(name, hardConstraint, ModelQueryType.MUST_HAVE_MATCH)); | ||
166 | return this; | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Adds a new hard constraint with the name of the query specification's fully qualified name and the default | ||
171 | * {@link ModelQueryType#MUST_HAVE_MATCH}. | ||
172 | * | ||
173 | * @param softConstraint | ||
174 | * A VIATRA Query pattern specification. | ||
175 | * @return The actual instance to enable builder pattern like usage. | ||
176 | */ | ||
177 | public ConstraintsObjective withHardConstraint( | ||
178 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint) { | ||
179 | return withHardConstraint(hardConstraint.getFullyQualifiedName(), hardConstraint, | ||
180 | ModelQueryType.MUST_HAVE_MATCH); | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * Adds a new hard constraint with the name of the query specification's fully qualified name. | ||
185 | * | ||
186 | * @param softConstraint | ||
187 | * A VIATRA Query pattern specification. | ||
188 | * @param type | ||
189 | * {@link ModelQueryType}, which determines whether the constraint should have at least one match or none | ||
190 | * at all. | ||
191 | * @return The actual instance to enable builder pattern like usage. | ||
192 | */ | ||
193 | public ConstraintsObjective withHardConstraint( | ||
194 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint, | ||
195 | ModelQueryType type) { | ||
196 | return withHardConstraint(hardConstraint.getFullyQualifiedName(), hardConstraint, type); | ||
197 | } | ||
198 | |||
199 | @Override | ||
200 | public Double getFitness(ThreadContext context) { | ||
201 | |||
202 | if (softConstraints.isEmpty()) { | ||
203 | return 0d; | ||
204 | } | ||
205 | |||
206 | double result = 0; | ||
207 | |||
208 | for (int i = 0; i < softConstraints.size(); i++) { | ||
209 | int countMatches = softMatchers.get(i).countMatches(); | ||
210 | result += countMatches * softConstraints.get(i).weight; | ||
211 | softMatches.set(i, Integer.valueOf(countMatches)); | ||
212 | } | ||
213 | |||
214 | return result; | ||
215 | } | ||
216 | |||
217 | @Override | ||
218 | public void init(ThreadContext context) { | ||
219 | |||
220 | super.init(context); | ||
221 | |||
222 | softMatches = new ArrayList<Integer>(softConstraints.size()); | ||
223 | softMatchers = new ArrayList<ViatraQueryMatcher<? extends IPatternMatch>>(softConstraints.size()); | ||
224 | hardMatches = new ArrayList<Integer>(hardConstraints.size()); | ||
225 | hardMatchers = new ArrayList<ViatraQueryMatcher<? extends IPatternMatch>>(hardConstraints.size()); | ||
226 | for (int i = 0; i < softConstraints.size(); i++) { | ||
227 | softMatches.add(0); | ||
228 | } | ||
229 | for (int i = 0; i < hardConstraints.size(); i++) { | ||
230 | hardMatches.add(0); | ||
231 | } | ||
232 | |||
233 | try { | ||
234 | ViatraQueryEngine queryEngine = context.getQueryEngine(); | ||
235 | |||
236 | for (QueryConstraint qc : softConstraints) { | ||
237 | softMatchers.add(qc.query.getMatcher(queryEngine)); | ||
238 | } | ||
239 | |||
240 | for (QueryConstraint qc : hardConstraints) { | ||
241 | hardMatchers.add(qc.query.getMatcher(queryEngine)); | ||
242 | } | ||
243 | |||
244 | } catch (ViatraQueryException e) { | ||
245 | throw new DSEException("Couldn't initialize the VIATRA Query matcher, see inner exception", e); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | @Override | ||
250 | public IObjective createNew() { | ||
251 | new ArrayList<Double>(softConstraints.size()); | ||
252 | ConstraintsObjective result = new ConstraintsObjective(name, softConstraints, hardConstraints); | ||
253 | if (isThereFitnessConstraint) { | ||
254 | result.withHardConstraintOnFitness(fitnessConstraint, fitnessConstraintComparator); | ||
255 | } | ||
256 | return result.withComparator(comparator).withLevel(level); | ||
257 | } | ||
258 | |||
259 | @Override | ||
260 | public boolean isHardObjective() { | ||
261 | return !hardConstraints.isEmpty() || super.isHardObjective(); | ||
262 | } | ||
263 | |||
264 | @Override | ||
265 | public boolean satisifiesHardObjective(Double fitness) { | ||
266 | |||
267 | boolean result = true; | ||
268 | |||
269 | for (int i = 0; i < hardConstraints.size(); i++) { | ||
270 | ModelQueryType type = hardConstraints.get(i).type; | ||
271 | int countMatches = hardMatchers.get(i).countMatches(); | ||
272 | hardMatches.set(i, Integer.valueOf(countMatches)); | ||
273 | if ((type.equals(ModelQueryType.MUST_HAVE_MATCH) && countMatches <= 0) | ||
274 | || (type.equals(ModelQueryType.NO_MATCH) && countMatches > 0)) { | ||
275 | result = false; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | result = super.satisifiesHardObjective(fitness) ? result : false; | ||
280 | |||
281 | return result; | ||
282 | } | ||
283 | |||
284 | public List<QueryConstraint> getSoftConstraints() { | ||
285 | return softConstraints; | ||
286 | } | ||
287 | |||
288 | public List<QueryConstraint> getHardConstraints() { | ||
289 | return hardConstraints; | ||
290 | } | ||
291 | |||
292 | public String getSoftName(int index) { | ||
293 | return softConstraints.get(index).name; | ||
294 | } | ||
295 | |||
296 | public String getHardName(int index) { | ||
297 | return hardConstraints.get(index).name; | ||
298 | } | ||
299 | |||
300 | public List<Integer> getSoftMatches() { | ||
301 | return softMatches; | ||
302 | } | ||
303 | |||
304 | public List<Integer> getHardMatches() { | ||
305 | return hardMatches; | ||
306 | } | ||
307 | |||
308 | public List<String> getSoftNames() { | ||
309 | List<String> softNames = new ArrayList<>(softConstraints.size()); | ||
310 | for (QueryConstraint qc : softConstraints) { | ||
311 | softNames.add(qc.name); | ||
312 | } | ||
313 | return softNames; | ||
314 | } | ||
315 | |||
316 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.java new file mode 100644 index 00000000..b21da397 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.java | |||
@@ -0,0 +1,89 @@ | |||
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.objectives.impl; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
13 | |||
14 | /** | ||
15 | * This hard objective is fulfilled if the trajectory is in the specified interval (inclusive). | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public class DepthHardObjective extends BaseObjective { | ||
21 | |||
22 | private static final String DEFAULT_NAME = "DepthHardObjective"; | ||
23 | protected int minDepth; | ||
24 | protected int maxDepth; | ||
25 | private ThreadContext context; | ||
26 | |||
27 | public DepthHardObjective() { | ||
28 | this(DEFAULT_NAME, 0, Integer.MAX_VALUE); | ||
29 | } | ||
30 | |||
31 | public DepthHardObjective(String name) { | ||
32 | this(name, 0, Integer.MAX_VALUE); | ||
33 | } | ||
34 | |||
35 | public DepthHardObjective(int minDepth) { | ||
36 | this(DEFAULT_NAME, minDepth, Integer.MAX_VALUE); | ||
37 | } | ||
38 | |||
39 | public DepthHardObjective(String name, int minDepth) { | ||
40 | this(name, minDepth, Integer.MAX_VALUE); | ||
41 | } | ||
42 | |||
43 | public DepthHardObjective(int minDepth, int maxDepth) { | ||
44 | this(DEFAULT_NAME, minDepth, maxDepth); | ||
45 | } | ||
46 | |||
47 | public DepthHardObjective(String name, int minDepth, int maxDepth) { | ||
48 | super(name); | ||
49 | this.minDepth = minDepth; | ||
50 | this.maxDepth = maxDepth; | ||
51 | } | ||
52 | |||
53 | public DepthHardObjective withMinDepth(int minDepth) { | ||
54 | this.minDepth = minDepth; | ||
55 | return this; | ||
56 | } | ||
57 | |||
58 | public DepthHardObjective withMaxDepth(int maxDepth) { | ||
59 | this.maxDepth = maxDepth; | ||
60 | return this; | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public void init(ThreadContext context) { | ||
65 | super.init(context); | ||
66 | this.context = context; | ||
67 | } | ||
68 | |||
69 | @Override | ||
70 | public Double getFitness(ThreadContext context) { | ||
71 | return 0d; | ||
72 | } | ||
73 | |||
74 | @Override | ||
75 | public boolean isHardObjective() { | ||
76 | return true; | ||
77 | } | ||
78 | |||
79 | @Override | ||
80 | public boolean satisifiesHardObjective(Double fitness) { | ||
81 | return minDepth <= context.getDepth() && context.getDepth() <= maxDepth; | ||
82 | } | ||
83 | |||
84 | @Override | ||
85 | public IObjective createNew() { | ||
86 | return new DepthHardObjective(name, minDepth, maxDepth); | ||
87 | } | ||
88 | |||
89 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstraint.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstraint.java new file mode 100644 index 00000000..7616b4a2 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstraint.java | |||
@@ -0,0 +1,116 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives.impl; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.List; | ||
13 | import java.util.Objects; | ||
14 | |||
15 | import org.eclipse.viatra.dse.api.DSEException; | ||
16 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
17 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint; | ||
18 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
19 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
20 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
21 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher; | ||
22 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
23 | |||
24 | /** | ||
25 | * This global constraint collects a list of VIATRA Query pattern and checks if any of them has a match on along a trajectory. | ||
26 | * If any of the patterns has a match then it is unsatisfied and the exploration should backtrack. | ||
27 | * | ||
28 | * @author Andras Szabolcs Nagy | ||
29 | * | ||
30 | */ | ||
31 | public class ModelQueriesGlobalConstraint implements IGlobalConstraint { | ||
32 | |||
33 | public static final String GLOBAL_CONSTRAINT = "GlobalConstraint"; | ||
34 | protected String name; | ||
35 | protected List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> constraints; | ||
36 | protected List<ViatraQueryMatcher<? extends IPatternMatch>> matchers = new ArrayList<ViatraQueryMatcher<? extends IPatternMatch>>(); | ||
37 | protected ModelQueryType type = ModelQueryType.NO_MATCH; | ||
38 | |||
39 | public ModelQueriesGlobalConstraint(String name, | ||
40 | List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> constraints) { | ||
41 | Objects.requireNonNull(name, "Name of the global constraint cannot be null."); | ||
42 | Objects.requireNonNull(constraints, "The list of constraints cannot be null."); | ||
43 | |||
44 | this.name = name; | ||
45 | this.constraints = constraints; | ||
46 | } | ||
47 | |||
48 | public ModelQueriesGlobalConstraint( | ||
49 | List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> constraints) { | ||
50 | this(GLOBAL_CONSTRAINT, constraints); | ||
51 | } | ||
52 | |||
53 | public ModelQueriesGlobalConstraint(String name) { | ||
54 | this(name, new ArrayList<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>>()); | ||
55 | } | ||
56 | |||
57 | public ModelQueriesGlobalConstraint() { | ||
58 | this(GLOBAL_CONSTRAINT, | ||
59 | new ArrayList<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>>()); | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * Adds a new VIATRA Query pattern. | ||
64 | * | ||
65 | * @param constraint | ||
66 | * A VIATRA Query pattern. | ||
67 | * @return The actual instance to enable builder pattern like usage. | ||
68 | */ | ||
69 | public ModelQueriesGlobalConstraint withConstraint( | ||
70 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> constraint) { | ||
71 | constraints.add(constraint); | ||
72 | return this; | ||
73 | } | ||
74 | |||
75 | public ModelQueriesGlobalConstraint withType(ModelQueryType type) { | ||
76 | this.type = type; | ||
77 | return this; | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public String getName() { | ||
82 | return name; | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | public boolean checkGlobalConstraint(ThreadContext context) { | ||
87 | for (ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { | ||
88 | if ((type.equals(ModelQueryType.NO_MATCH) && matcher.countMatches() > 0) | ||
89 | || (type.equals(ModelQueryType.MUST_HAVE_MATCH) && matcher.countMatches() == 0)) { | ||
90 | return false; | ||
91 | } | ||
92 | } | ||
93 | return true; | ||
94 | } | ||
95 | |||
96 | @Override | ||
97 | public void init(ThreadContext context) { | ||
98 | try { | ||
99 | ViatraQueryEngine queryEngine = context.getQueryEngine(); | ||
100 | |||
101 | for (IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification : constraints) { | ||
102 | ViatraQueryMatcher<? extends IPatternMatch> matcher = querySpecification.getMatcher(queryEngine); | ||
103 | matchers.add(matcher); | ||
104 | } | ||
105 | |||
106 | } catch (ViatraQueryException e) { | ||
107 | throw new DSEException("Couldn't get the VIATRA Query matcher, see inner exception", e); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | @Override | ||
112 | public IGlobalConstraint createNew() { | ||
113 | return new ModelQueriesGlobalConstraint(name, constraints); | ||
114 | } | ||
115 | |||
116 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueryType.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueryType.java new file mode 100644 index 00000000..76390352 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueryType.java | |||
@@ -0,0 +1,14 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives.impl; | ||
10 | |||
11 | public enum ModelQueryType { | ||
12 | MUST_HAVE_MATCH, | ||
13 | NO_MATCH | ||
14 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardObjective.java new file mode 100644 index 00000000..27cf139c --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardObjective.java | |||
@@ -0,0 +1,52 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.objectives.impl; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
13 | |||
14 | /** | ||
15 | * This hard objective is never fulfilled. Use it if all states should be regarded as an invalid solution. | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public class NeverSatisfiedDummyHardObjective extends BaseObjective { | ||
21 | |||
22 | private static final String DEFAULT_NAME = "NeverSatisfiedDummyHardObjective"; | ||
23 | |||
24 | public NeverSatisfiedDummyHardObjective() { | ||
25 | super(DEFAULT_NAME); | ||
26 | } | ||
27 | |||
28 | public NeverSatisfiedDummyHardObjective(String name) { | ||
29 | super(name); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public Double getFitness(ThreadContext context) { | ||
34 | return 0d; | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public boolean isHardObjective() { | ||
39 | return true; | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public boolean satisifiesHardObjective(Double fitness) { | ||
44 | return false; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public IObjective createNew() { | ||
49 | return this; | ||
50 | } | ||
51 | |||
52 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObjective.java new file mode 100644 index 00000000..756d94ec --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObjective.java | |||
@@ -0,0 +1,59 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.objectives.impl; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
13 | |||
14 | /** | ||
15 | * This hard objective is satisfied if there are no rule activations from the current state (returning 1 in this case). | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public class NoRuleActivationsHardObjective extends BaseObjective { | ||
21 | |||
22 | protected static final String DEFAULT_NAME = "NoMoreActivationHardObjective"; | ||
23 | private ThreadContext context; | ||
24 | |||
25 | public NoRuleActivationsHardObjective(String name) { | ||
26 | super(name); | ||
27 | } | ||
28 | |||
29 | public NoRuleActivationsHardObjective() { | ||
30 | this(DEFAULT_NAME); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public Double getFitness(ThreadContext context) { | ||
35 | return 0d; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public void init(ThreadContext context) { | ||
40 | super.init(context); | ||
41 | this.context = context; | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public IObjective createNew() { | ||
46 | return new NoRuleActivationsHardObjective(name); | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public boolean isHardObjective() { | ||
51 | return true; | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public boolean satisifiesHardObjective(Double fitness) { | ||
56 | return context.getConflictSet().getNextActivations().isEmpty(); | ||
57 | } | ||
58 | |||
59 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjective.java new file mode 100644 index 00000000..25ff45ae --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjective.java | |||
@@ -0,0 +1,148 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.objectives.impl; | ||
10 | |||
11 | import java.util.HashMap; | ||
12 | import java.util.List; | ||
13 | import java.util.Map; | ||
14 | import java.util.Map.Entry; | ||
15 | import java.util.Objects; | ||
16 | |||
17 | import org.eclipse.viatra.dse.base.DesignSpaceManager; | ||
18 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
19 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
20 | import org.eclipse.viatra.dse.objectives.ActivationFitnessProcessor; | ||
21 | import org.eclipse.viatra.dse.objectives.Comparators; | ||
22 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
23 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
24 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
25 | |||
26 | /** | ||
27 | * This soft objective calculates a fitness value based on the length of the trajectory. Costs to the rules can be | ||
28 | * assigned. | ||
29 | * | ||
30 | * @author Andras Szabolcs Nagy | ||
31 | * | ||
32 | */ | ||
33 | public class TrajectoryCostSoftObjective extends BaseObjective { | ||
34 | |||
35 | public static final String DEFAULT_NAME = "TrajectoryCostObjective"; | ||
36 | protected Map<BatchTransformationRule<?, ?>, Double> fixCosts; | ||
37 | protected Map<BatchTransformationRule<?, ?>, ActivationFitnessProcessor> activationCostProcessors; | ||
38 | protected double trajectoryLengthWeight = 0.0; | ||
39 | protected boolean calculateTrajectoryLengthWeight; | ||
40 | |||
41 | public TrajectoryCostSoftObjective(String name) { | ||
42 | super(name); | ||
43 | comparator = Comparators.LOWER_IS_BETTER; | ||
44 | } | ||
45 | |||
46 | public TrajectoryCostSoftObjective() { | ||
47 | this(DEFAULT_NAME); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * Sets the cost of a rule. | ||
52 | * | ||
53 | * @param rule | ||
54 | * @param cost | ||
55 | * @return The actual instance to enable builder pattern like usage. | ||
56 | */ | ||
57 | public TrajectoryCostSoftObjective withRuleCost(BatchTransformationRule<?, ?> rule, double cost) { | ||
58 | Objects.requireNonNull(rule); | ||
59 | if (fixCosts == null) { | ||
60 | fixCosts = new HashMap<BatchTransformationRule<?, ?>, Double>(); | ||
61 | } | ||
62 | Preconditions.checkArgument(!fixCosts.containsKey(rule)); | ||
63 | fixCosts.put(rule, cost); | ||
64 | return this; | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * Sets an activation processor for a rule. | ||
69 | * | ||
70 | * @param rule | ||
71 | * @param activationCostProcessor | ||
72 | * @return The actual instance to enable builder pattern like usage. | ||
73 | */ | ||
74 | public TrajectoryCostSoftObjective withActivationCost(BatchTransformationRule<?, ?> rule, | ||
75 | ActivationFitnessProcessor activationCostProcessor) { | ||
76 | Objects.requireNonNull(rule); | ||
77 | Objects.requireNonNull(activationCostProcessor); | ||
78 | if (activationCostProcessors == null) { | ||
79 | activationCostProcessors = new HashMap<BatchTransformationRule<?, ?>, ActivationFitnessProcessor>(); | ||
80 | } | ||
81 | Preconditions.checkArgument(!activationCostProcessors.containsKey(rule)); | ||
82 | activationCostProcessors.put(rule, activationCostProcessor); | ||
83 | return this; | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * The length of the trajectory multiplied with given parameter will be added to the fitness value. | ||
88 | * | ||
89 | * @param trajectoryLengthWeight | ||
90 | * The weight of a transformation rule application. | ||
91 | * @return The actual instance to enable builder pattern like usage. | ||
92 | */ | ||
93 | public TrajectoryCostSoftObjective withTrajectoryLengthWeight(double trajectoryLengthWeight) { | ||
94 | this.trajectoryLengthWeight = trajectoryLengthWeight; | ||
95 | this.calculateTrajectoryLengthWeight = true; | ||
96 | return this; | ||
97 | } | ||
98 | |||
99 | @Override | ||
100 | public Double getFitness(ThreadContext context) { | ||
101 | |||
102 | DesignSpaceManager dsm = context.getDesignSpaceManager(); | ||
103 | TrajectoryInfo trajectoryInfo = dsm.getTrajectoryInfo(); | ||
104 | List<Object> trajectory = trajectoryInfo.getTrajectory(); | ||
105 | List<BatchTransformationRule<?, ?>> rules = trajectoryInfo.getRules(); | ||
106 | |||
107 | double result = 0; | ||
108 | |||
109 | for (int i = 0; i < trajectory.size(); i++) { | ||
110 | BatchTransformationRule<?, ?> rule = rules.get(i); | ||
111 | |||
112 | Double cost = fixCosts.get(rule); | ||
113 | if (cost != null) { | ||
114 | result += cost; | ||
115 | } | ||
116 | |||
117 | Map<String, Double> costs = trajectoryInfo.getMeasuredCosts().get(i); | ||
118 | if (costs != null) { | ||
119 | cost = costs.get(name); | ||
120 | if (cost != null) { | ||
121 | result += cost; | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | |||
126 | if (calculateTrajectoryLengthWeight) { | ||
127 | result += trajectory.size() * trajectoryLengthWeight; | ||
128 | } | ||
129 | |||
130 | return result; | ||
131 | } | ||
132 | |||
133 | @Override | ||
134 | public void init(ThreadContext context) { | ||
135 | super.init(context); | ||
136 | DesignSpaceManager dsm = context.getDesignSpaceManager(); | ||
137 | if (activationCostProcessors != null) { | ||
138 | for (Entry<BatchTransformationRule<?, ?>, ActivationFitnessProcessor> entry : activationCostProcessors.entrySet()) { | ||
139 | dsm.registerActivationCostProcessor(name, entry.getKey(), entry.getValue()); | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | |||
144 | @Override | ||
145 | public IObjective createNew() { | ||
146 | return this; | ||
147 | } | ||
148 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.java new file mode 100644 index 00000000..8d74e856 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.java | |||
@@ -0,0 +1,40 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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 org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
12 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
13 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
14 | import org.eclipse.viatra.dse.solutionstore.SolutionStore.ISolutionSaver; | ||
15 | |||
16 | /** | ||
17 | * Contains callback methods which are called when a solution is found by the exploration {@link IStrategy}. | ||
18 | * | ||
19 | * @author Andras Szabolcs Nagy | ||
20 | * | ||
21 | */ | ||
22 | public interface ISolutionFoundHandler { | ||
23 | |||
24 | /** | ||
25 | * Called when a solution is saved by the {@link ISolutionSaver}. Later, this solution can be omitted from the final | ||
26 | * set of solutions. | ||
27 | * | ||
28 | * @param context | ||
29 | * @param trajectory | ||
30 | */ | ||
31 | void solutionFound(ThreadContext context, SolutionTrajectory trajectory); | ||
32 | |||
33 | /** | ||
34 | * Called when the exploration found a solution but it was not saved because of certain conditions. | ||
35 | * | ||
36 | * @param context | ||
37 | * @param trajectory | ||
38 | */ | ||
39 | void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory); | ||
40 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.java new file mode 100644 index 00000000..36e6b5b7 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.java | |||
@@ -0,0 +1,18 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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 | /** | ||
12 | * Provides file name when a model is searialzed. | ||
13 | * @author Andras Szabolcs Nagy | ||
14 | * | ||
15 | */ | ||
16 | public interface ISolutionNameProvider { | ||
17 | String getName(); | ||
18 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider.java new file mode 100644 index 00000000..43460015 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider.java | |||
@@ -0,0 +1,37 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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 | /** | ||
12 | * Provides file name with a String <code>[prefix][id].[extension]</code> pattern. | ||
13 | * @author Andras Szabolcs Nagy | ||
14 | * | ||
15 | */ | ||
16 | public class IdBasedSolutionNameProvider implements ISolutionNameProvider { | ||
17 | |||
18 | private int id = 1; | ||
19 | private String prefix; | ||
20 | private String extension; | ||
21 | |||
22 | public IdBasedSolutionNameProvider(String prefix, String extension) { | ||
23 | this.extension = extension; | ||
24 | this.prefix = prefix; | ||
25 | |||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public String getName() { | ||
30 | StringBuilder sb = new StringBuilder(prefix); | ||
31 | sb.append(id++); | ||
32 | sb.append('.'); | ||
33 | sb.append(extension); | ||
34 | return sb.toString(); | ||
35 | } | ||
36 | |||
37 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.java new file mode 100644 index 00000000..118f0c75 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.java | |||
@@ -0,0 +1,28 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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 org.apache.log4j.Logger; | ||
12 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
13 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
14 | |||
15 | public class LogSolutionHandler implements ISolutionFoundHandler { | ||
16 | |||
17 | Logger logger = Logger.getLogger(LogSolutionHandler.class); | ||
18 | |||
19 | @Override | ||
20 | public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) { | ||
21 | logger.info("Solution registered: " + trajectory.toPrettyString()); | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) { | ||
26 | logger.debug("Not good enough solution: " + trajectory.toPrettyString()); | ||
27 | } | ||
28 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHandler.java new file mode 100644 index 00000000..bbbe60de --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHandler.java | |||
@@ -0,0 +1,55 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy 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.HashSet; | ||
12 | |||
13 | import org.eclipse.emf.common.notify.Notifier; | ||
14 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
15 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
16 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
17 | |||
18 | public class ModelSaverSolutionFoundHandler implements ISolutionFoundHandler { | ||
19 | |||
20 | private HashSet<Object> savedSolutions = new HashSet<Object>(); | ||
21 | private ISolutionNameProvider solutionNameProvider; | ||
22 | |||
23 | public ModelSaverSolutionFoundHandler() { | ||
24 | solutionNameProvider = new IdBasedSolutionNameProvider("solution", "xmi"); | ||
25 | } | ||
26 | |||
27 | public ModelSaverSolutionFoundHandler(String extension) { | ||
28 | solutionNameProvider = new IdBasedSolutionNameProvider("solution", extension); | ||
29 | } | ||
30 | |||
31 | public ModelSaverSolutionFoundHandler(String prefix, String extension) { | ||
32 | solutionNameProvider = new IdBasedSolutionNameProvider(prefix, extension); | ||
33 | } | ||
34 | |||
35 | public ModelSaverSolutionFoundHandler(ISolutionNameProvider solutionNameProvider) { | ||
36 | this.solutionNameProvider = solutionNameProvider; | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) { | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) { | ||
45 | Object stateCode = trajectory.getSolution().getStateCode(); | ||
46 | |||
47 | if (savedSolutions.contains(stateCode)) { | ||
48 | return; | ||
49 | } | ||
50 | |||
51 | savedSolutions.add(stateCode); | ||
52 | Notifier clonedModel = EMFHelper.clone(context.getModel()); | ||
53 | EMFHelper.saveModel(clonedModel, solutionNameProvider.getName()); | ||
54 | } | ||
55 | } \ No newline at end of file | ||
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 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoder.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoder.java new file mode 100644 index 00000000..f163f1a5 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoder.java | |||
@@ -0,0 +1,82 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.statecode; | ||
10 | |||
11 | import org.eclipse.emf.common.notify.Notifier; | ||
12 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
13 | |||
14 | /** | ||
15 | * <p> | ||
16 | * To be able to efficiently explore a design space, a state that has been explored before through an other trajectory | ||
17 | * needs to be recognized and ignored accordingly. | ||
18 | * </p> | ||
19 | * | ||
20 | * <p> | ||
21 | * This is done by generating a pseudo-unique value (object) that is only depended on the relevant parts of the model's | ||
22 | * internal state, that is, the values of two states can only be equal if the states themselves can be considered equal. | ||
23 | * </p> | ||
24 | * | ||
25 | * <p> | ||
26 | * The processing engine however assumes, that any two states that share this pseudo-unique value has the same | ||
27 | * characteristics, meaning they have the same amount and type of outgoing transitions available, and firing the | ||
28 | * appropriate transitions from both states also result in states that share their pseudo-unique identifier. If this | ||
29 | * condition is not satisfied, the exploration process's result will be non-deterministic, and in consequence, solutions | ||
30 | * can be lost. | ||
31 | * </p> | ||
32 | * | ||
33 | * <p> | ||
34 | * In addition to providing pseudo-unique identifiers to model states, the state coder must provide pseud-unique | ||
35 | * identifiers to the outgoing transitions as well, but they only need to be unique on the scope of the particular | ||
36 | * state, not globally. Global addressing thus can be achieved by considering the pseudo-unique identifier of the state | ||
37 | * and the pseudo-unique identifier of the transition together if needed. | ||
38 | * </p> | ||
39 | * | ||
40 | * <p> | ||
41 | * Both identifiers can be arbitrary objects, and equality is checked by calling {@link Object#equals(Object)} on the | ||
42 | * two identifiers. | ||
43 | * </p> | ||
44 | * | ||
45 | * <p> | ||
46 | * For any particular implementation an {@link IStateCoderFactory} implementation must also be supplied that handles the | ||
47 | * creation of {@link IStateCoder} instances. | ||
48 | * </p> | ||
49 | * | ||
50 | * <p> | ||
51 | * Usually it is unnecessary to represent everything from the model in a state code, only the parts which are modified | ||
52 | * by the transformation rules. | ||
53 | * </p> | ||
54 | * | ||
55 | * @author Miklos Foldenyi, Andras Szabolcs Nagy | ||
56 | * | ||
57 | */ | ||
58 | public interface IStateCoder { | ||
59 | |||
60 | /** | ||
61 | * Initializes the state coder on the given model. | ||
62 | * | ||
63 | * @param notifier | ||
64 | */ | ||
65 | void init(Notifier notifier); | ||
66 | |||
67 | /** | ||
68 | * Returns a pseudo-unique identifier that describes the underlying model's current internal state. | ||
69 | * | ||
70 | * @return an arbitrary {@link Object} that can be used as the identifier. | ||
71 | */ | ||
72 | Object createStateCode(); | ||
73 | |||
74 | /** | ||
75 | * Returns a pseudo-unique identifier that describes the given {@link IPatternMatch} in the context of the | ||
76 | * underlying model's current internal state. | ||
77 | * | ||
78 | * @return an arbitrary {@link Object} that can be used as the identifier in the given state. | ||
79 | */ | ||
80 | Object createActivationCode(IPatternMatch match); | ||
81 | |||
82 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoderFactory.java new file mode 100644 index 00000000..cf8bdf8d --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoderFactory.java | |||
@@ -0,0 +1,29 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.statecode; | ||
10 | |||
11 | /** | ||
12 | * Interface for a factory class that creates instances of {@link IStateCoder} objects. This is required because state | ||
13 | * coders have to be created on-demand if the design space exploration process decides that a new thread is to be | ||
14 | * spawned. Since each thread requires it's own working model instance and a state coder is linked to the underlying | ||
15 | * model, a new {@link IStateCoder} needs to be created per processing thread. | ||
16 | * | ||
17 | * @author Miklos Foldenyi, Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public interface IStateCoderFactory { | ||
21 | |||
22 | /** | ||
23 | * Creates a new {@link IStateCoder} instance specific to this {@link IStateCoderFactory}. | ||
24 | * | ||
25 | * @return the new {@link IStateCoder} instance specific to this working model. | ||
26 | */ | ||
27 | IStateCoder createStateCoder(); | ||
28 | |||
29 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProvider.java new file mode 100644 index 00000000..afcba7b6 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProvider.java | |||
@@ -0,0 +1,45 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | import org.eclipse.emf.common.notify.Notifier; | ||
14 | import org.eclipse.emf.ecore.EClass; | ||
15 | import org.eclipse.emf.ecore.EObject; | ||
16 | |||
17 | /** | ||
18 | * Implementation of this interface is responsible to provide {@link EObject}s of a given {@link EClass} for | ||
19 | * {@link TheStateCoder} | ||
20 | * | ||
21 | * @author Andras Szabolcs Nagy | ||
22 | * | ||
23 | */ | ||
24 | public interface IObjectsProvider { | ||
25 | |||
26 | /** | ||
27 | * Initialize the {@link IObjectsProvider} on a given model and {@link StatecodingDependencyGraph}. | ||
28 | * | ||
29 | * @param notifier | ||
30 | * The root of the model. | ||
31 | * @param statecodingDependencyGraph | ||
32 | * The state coding dependency graph. | ||
33 | */ | ||
34 | void init(Notifier notifier, StatecodingDependencyGraph statecodingDependencyGraph); | ||
35 | |||
36 | /** | ||
37 | * Returns the instances of an {@link EClass} in a model. | ||
38 | * | ||
39 | * @param eClass | ||
40 | * The class of the objects. | ||
41 | * @return The collection of the instances. | ||
42 | */ | ||
43 | Collection<EObject> getEObjects(EClass eClass); | ||
44 | |||
45 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.java new file mode 100644 index 00000000..931eb1a2 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.java | |||
@@ -0,0 +1,25 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | /** | ||
12 | * Interface for creating {@link IObjectsProvider} instances. | ||
13 | * | ||
14 | * @author Andras Szabolcs Nagy | ||
15 | */ | ||
16 | public interface IObjectsProviderFactory { | ||
17 | |||
18 | /** | ||
19 | * Creates an {@link IObjectsProvider} implementation. | ||
20 | * | ||
21 | * @return The newly created {@link IObjectsProvider}. | ||
22 | */ | ||
23 | IObjectsProvider createObjectsProvider(); | ||
24 | |||
25 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.java new file mode 100644 index 00000000..e38d45d3 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.java | |||
@@ -0,0 +1,60 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import org.apache.log4j.Logger; | ||
16 | import org.eclipse.emf.common.notify.Notifier; | ||
17 | import org.eclipse.emf.ecore.EClass; | ||
18 | import org.eclipse.emf.ecore.EObject; | ||
19 | import org.eclipse.viatra.dse.api.DSEException; | ||
20 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
21 | import org.eclipse.viatra.query.runtime.base.api.IndexingLevel; | ||
22 | import org.eclipse.viatra.query.runtime.base.api.NavigationHelper; | ||
23 | import org.eclipse.viatra.query.runtime.emf.EMFScope; | ||
24 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
25 | |||
26 | public class IncrementalObjectProvider implements IObjectsProvider { | ||
27 | |||
28 | private Logger logger = Logger.getLogger(getClass()); | ||
29 | private NavigationHelper baseIndex; | ||
30 | |||
31 | @Override | ||
32 | public void init(Notifier notifier, StatecodingDependencyGraph statecodingDependencyGraph) { | ||
33 | |||
34 | try { | ||
35 | EMFScope scope = new EMFScope(notifier); | ||
36 | ViatraQueryEngine queryEngine = ViatraQueryEngine.on(scope); | ||
37 | |||
38 | Set<EClass> classes = new HashSet<EClass>(); | ||
39 | // Set<EReference> references = new HashSet<EReference>(); | ||
40 | for (StatecodingNode node : statecodingDependencyGraph.getNodes()) { | ||
41 | classes.add(node.getClazz()); | ||
42 | // for (StatecodingDependency dependency : node.getStatecodingDependencies()) { | ||
43 | // // TODO inverse reference | ||
44 | // references.add(dependency.eReference); | ||
45 | // } | ||
46 | } | ||
47 | baseIndex = EMFScope.extractUnderlyingEMFIndex(queryEngine); | ||
48 | baseIndex.registerEClasses(classes, IndexingLevel.FULL); | ||
49 | } catch (ViatraQueryException e) { | ||
50 | logger.error("Failed to initialize VIATRA Query engine on the given notifier", e); | ||
51 | throw new DSEException("Failed to initialize VIATRA Query engine on the given notifier"); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public Collection<EObject> getEObjects(EClass eClass) { | ||
57 | return baseIndex.getAllInstances(eClass); | ||
58 | } | ||
59 | |||
60 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFactory.java new file mode 100644 index 00000000..97011436 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFactory.java | |||
@@ -0,0 +1,18 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | public class IncrementalObjectProviderFactory implements IObjectsProviderFactory { | ||
12 | |||
13 | @Override | ||
14 | public IncrementalObjectProvider createObjectsProvider() { | ||
15 | return new IncrementalObjectProvider(); | ||
16 | } | ||
17 | |||
18 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependency.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependency.java new file mode 100644 index 00000000..67b1982d --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependency.java | |||
@@ -0,0 +1,33 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | import org.eclipse.emf.ecore.EReference; | ||
12 | |||
13 | public class StatecodingDependency { | ||
14 | |||
15 | protected EReference eReference; | ||
16 | protected StatecodingNode node; | ||
17 | protected boolean isContained; | ||
18 | protected StatecodingDependencyType type; | ||
19 | |||
20 | public StatecodingDependency(EReference eReference, StatecodingNode node, boolean isContained, | ||
21 | StatecodingDependencyType type) { | ||
22 | super(); | ||
23 | this.eReference = eReference; | ||
24 | this.node = node; | ||
25 | this.isContained = isContained; | ||
26 | this.type = type; | ||
27 | } | ||
28 | |||
29 | public StatecodingDependency(EReference eReference, StatecodingNode node) { | ||
30 | this(eReference, node, false, StatecodingDependencyType.NORMAL); | ||
31 | } | ||
32 | |||
33 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.java new file mode 100644 index 00000000..6f7255a3 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.java | |||
@@ -0,0 +1,44 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.List; | ||
13 | |||
14 | import org.eclipse.emf.ecore.EClass; | ||
15 | |||
16 | public class StatecodingDependencyGraph { | ||
17 | |||
18 | private List<StatecodingNode> nodes = new ArrayList<StatecodingNode>(); | ||
19 | |||
20 | public StatecodingNode createNode(EClass clazz) { | ||
21 | StatecodingNode node = new StatecodingNode(clazz); | ||
22 | node.setGraph(this); | ||
23 | addNode(node); | ||
24 | return node; | ||
25 | } | ||
26 | |||
27 | public void addNode(StatecodingNode node) { | ||
28 | nodes.add(node); | ||
29 | } | ||
30 | |||
31 | public StatecodingNode getNodeByClass(EClass eClass) { | ||
32 | for (StatecodingNode node : nodes) { | ||
33 | if (node.getClazz().equals(eClass)) { | ||
34 | return node; | ||
35 | } | ||
36 | } | ||
37 | return null; | ||
38 | } | ||
39 | |||
40 | public List<StatecodingNode> getNodes() { | ||
41 | return nodes; | ||
42 | } | ||
43 | |||
44 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.java new file mode 100644 index 00000000..bdd4677d --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | public enum StatecodingDependencyType { | ||
12 | |||
13 | NORMAL, | ||
14 | INVERSE | ||
15 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNode.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNode.java new file mode 100644 index 00000000..91fc28cf --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNode.java | |||
@@ -0,0 +1,100 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Comparator; | ||
13 | import java.util.List; | ||
14 | import java.util.Set; | ||
15 | import java.util.TreeSet; | ||
16 | |||
17 | import org.eclipse.emf.ecore.EAttribute; | ||
18 | import org.eclipse.emf.ecore.EClass; | ||
19 | import org.eclipse.emf.ecore.EReference; | ||
20 | |||
21 | public class StatecodingNode { | ||
22 | |||
23 | private StatecodingDependencyGraph graph; | ||
24 | |||
25 | private final EClass clazz; | ||
26 | private Set<EAttribute> attributes = new TreeSet<EAttribute>(Comparator.comparing(EAttribute::getName)); | ||
27 | private List<StatecodingDependency> dependencies = new ArrayList<StatecodingDependency>(); | ||
28 | private boolean stateCodeIsId = false; | ||
29 | private StatecodingNodeType statecodingNodeType = StatecodingNodeType.CREATE_AND_DELETE; | ||
30 | |||
31 | public StatecodingNode(EClass clazz) { | ||
32 | this.clazz = clazz; | ||
33 | } | ||
34 | |||
35 | public StatecodingNode withAttribute(EAttribute attribute) { | ||
36 | attributes.add(attribute); | ||
37 | return this; | ||
38 | } | ||
39 | |||
40 | public StatecodingNode withType(StatecodingNodeType type) { | ||
41 | statecodingNodeType = type; | ||
42 | return this; | ||
43 | } | ||
44 | |||
45 | public StatecodingNode withUniqueness() { | ||
46 | stateCodeIsId = true; | ||
47 | return this; | ||
48 | } | ||
49 | |||
50 | public StatecodingNode withDependency(EReference reference, StatecodingNode node) { | ||
51 | dependencies.add(new StatecodingDependency(reference, node)); | ||
52 | return this; | ||
53 | } | ||
54 | |||
55 | public StatecodingNode withInverseDependency(EReference reference, StatecodingNode node) { | ||
56 | dependencies.add(new StatecodingDependency(reference, node, false, StatecodingDependencyType.INVERSE)); | ||
57 | return this; | ||
58 | } | ||
59 | |||
60 | public void addDependency(StatecodingDependency statecodingDependency) { | ||
61 | dependencies.add(statecodingDependency); | ||
62 | } | ||
63 | |||
64 | public EClass getClazz() { | ||
65 | return clazz; | ||
66 | } | ||
67 | |||
68 | public boolean isStateCodeIsId() { | ||
69 | return stateCodeIsId; | ||
70 | } | ||
71 | |||
72 | public void setStateCodeIsId(boolean stateCodeIsId) { | ||
73 | this.stateCodeIsId = stateCodeIsId; | ||
74 | } | ||
75 | |||
76 | public StatecodingNodeType getStatecodingNodeType() { | ||
77 | return statecodingNodeType; | ||
78 | } | ||
79 | |||
80 | public void setStatecodingNodeType(StatecodingNodeType statecodingNodeType) { | ||
81 | this.statecodingNodeType = statecodingNodeType; | ||
82 | } | ||
83 | |||
84 | public Set<EAttribute> getAttributes() { | ||
85 | return attributes; | ||
86 | } | ||
87 | |||
88 | public List<StatecodingDependency> getStatecodingDependencies() { | ||
89 | return dependencies; | ||
90 | } | ||
91 | |||
92 | public StatecodingDependencyGraph getGraph() { | ||
93 | return graph; | ||
94 | } | ||
95 | |||
96 | public void setGraph(StatecodingDependencyGraph graph) { | ||
97 | this.graph = graph; | ||
98 | } | ||
99 | |||
100 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNodeType.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNodeType.java new file mode 100644 index 00000000..c902a7a6 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNodeType.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | public enum StatecodingNodeType { | ||
12 | |||
13 | FIXED, | ||
14 | ONLY_CREATE, | ||
15 | ONLY_DELETE, | ||
16 | CREATE_AND_DELETE | ||
17 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoder.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoder.java new file mode 100644 index 00000000..4601ff08 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoder.java | |||
@@ -0,0 +1,215 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.Collection; | ||
13 | import java.util.List; | ||
14 | import java.util.Set; | ||
15 | |||
16 | import org.eclipse.emf.common.notify.Notifier; | ||
17 | import org.eclipse.emf.common.util.EList; | ||
18 | import org.eclipse.emf.ecore.EAttribute; | ||
19 | import org.eclipse.emf.ecore.EObject; | ||
20 | import org.eclipse.viatra.dse.api.DSEException; | ||
21 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
22 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
23 | |||
24 | public class TheStateCoder implements IStateCoder { | ||
25 | |||
26 | private StatecodingDependencyGraph sdg; | ||
27 | private IObjectsProvider objectProvider; | ||
28 | |||
29 | public TheStateCoder(StatecodingDependencyGraph sdg, IObjectsProvider objectProvider) { | ||
30 | this.sdg = sdg; | ||
31 | this.objectProvider = objectProvider; | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | public void init(Notifier notifier) { | ||
36 | // TODO checks | ||
37 | // TODO node sorting based on traversal - in factory | ||
38 | |||
39 | // this.notifier = notifier; | ||
40 | // try { | ||
41 | // EMFScope scope = new EMFScope(notifier); | ||
42 | // queryEngine = ViatraQueryEngine.on(scope); | ||
43 | // } catch (ViatraQueryException e1) { | ||
44 | // logger.error("Failed to initialize VIATRA Query engine on the given notifier", e1); | ||
45 | // throw new DSEException("Failed to initialize VIATRA Query engine on the given notifier"); | ||
46 | // } | ||
47 | |||
48 | objectProvider.init(notifier, sdg); | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public String createStateCode() { | ||
53 | |||
54 | StringBuilder sb = new StringBuilder(); | ||
55 | |||
56 | // TODO sort | ||
57 | for (StatecodingNode node : sdg.getNodes()) { | ||
58 | sb.append(node.getClazz().getName()); | ||
59 | sb.append(':'); | ||
60 | sb.append(addStateCode(node)); | ||
61 | sb.append('|'); | ||
62 | } | ||
63 | sb.deleteCharAt(sb.length() - 1); | ||
64 | |||
65 | return sb.toString(); | ||
66 | |||
67 | } | ||
68 | |||
69 | @Override | ||
70 | public Object createActivationCode(IPatternMatch match) { | ||
71 | // TODO root object | ||
72 | // TODO parameterless? | ||
73 | |||
74 | int i = 0; | ||
75 | StringBuilder sb = new StringBuilder(); | ||
76 | Object object; | ||
77 | do { | ||
78 | object = match.get(i++); | ||
79 | if (object != null) { | ||
80 | if (object instanceof EObject) { | ||
81 | EObject eObject = (EObject) object; | ||
82 | sb.append(addStateCode(sdg.getNodeByClass(eObject.eClass()), eObject)); | ||
83 | } else { | ||
84 | // TODO toString or not to toString | ||
85 | } | ||
86 | } | ||
87 | } while (object != null); | ||
88 | |||
89 | return sb.toString(); | ||
90 | } | ||
91 | |||
92 | public String addStateCode(StatecodingNode node, EObject eObject) { | ||
93 | StringBuilder sb = new StringBuilder(); | ||
94 | |||
95 | Set<EAttribute> attributes = node.getAttributes(); | ||
96 | if (!attributes.isEmpty()) { | ||
97 | for (EAttribute eAttribute : attributes) { | ||
98 | // attributes are sorted | ||
99 | // TODO handle collection | ||
100 | sb.append(eObject.eGet(eAttribute)); | ||
101 | sb.append(';'); | ||
102 | } | ||
103 | sb.deleteCharAt(sb.length() - 1); | ||
104 | } | ||
105 | |||
106 | List<StatecodingDependency> dependencies = node.getStatecodingDependencies(); | ||
107 | int dependenciesSize = dependencies.size(); | ||
108 | if (dependenciesSize > 0) { | ||
109 | String[] codeParts = new String[dependenciesSize]; | ||
110 | int i = 0; | ||
111 | for (StatecodingDependency dependency : dependencies) { | ||
112 | String code = addStateCodeFromDependency(dependency, eObject); | ||
113 | codeParts[i++] = code; | ||
114 | } | ||
115 | Arrays.sort(codeParts); | ||
116 | |||
117 | sb.append("("); | ||
118 | sb.append(codeParts[0]); | ||
119 | for (i = 1; i < codeParts.length; i++) { | ||
120 | sb.append(';'); | ||
121 | sb.append(codeParts[i]); | ||
122 | } | ||
123 | sb.append(")"); | ||
124 | } | ||
125 | return sb.toString(); | ||
126 | } | ||
127 | |||
128 | public String addStateCode(StatecodingNode node) { | ||
129 | Collection<EObject> eObjects = objectProvider.getEObjects(node.getClazz()); | ||
130 | int size = eObjects.size(); | ||
131 | |||
132 | if (size > 0) { | ||
133 | String[] codeParts = new String[size]; | ||
134 | int i = 0; | ||
135 | for (EObject eObject : eObjects) { | ||
136 | String code = addStateCode(node, eObject); | ||
137 | codeParts[i++] = code; | ||
138 | } | ||
139 | Arrays.sort(codeParts); | ||
140 | |||
141 | StringBuilder sb = new StringBuilder(); | ||
142 | sb.append(codeParts[0]); | ||
143 | for (i = 1; i < codeParts.length; i++) { | ||
144 | sb.append(';'); | ||
145 | sb.append(codeParts[i]); | ||
146 | } | ||
147 | return sb.toString(); | ||
148 | } | ||
149 | |||
150 | return ""; | ||
151 | } | ||
152 | |||
153 | public String addStateCodeFromDependency(StatecodingDependency sd, EObject eObject) { | ||
154 | |||
155 | if (sd.type.equals(StatecodingDependencyType.NORMAL)) { | ||
156 | |||
157 | Object eReferred = eObject.eGet(sd.eReference); | ||
158 | if (eReferred == null) { | ||
159 | return ""; | ||
160 | } else if (eReferred instanceof EList<?>) { | ||
161 | EList<?> refferedList = (EList<?>) eReferred; | ||
162 | // TODO test | ||
163 | if (!refferedList.isEmpty()) { | ||
164 | |||
165 | String[] codeParts = new String[refferedList.size()]; | ||
166 | int i = 0; | ||
167 | for (Object referredEObject : refferedList) { | ||
168 | String code = addStateCode(sd.node, (EObject) referredEObject); | ||
169 | codeParts[i++] = code; | ||
170 | } | ||
171 | Arrays.sort(codeParts); | ||
172 | |||
173 | StringBuilder sb = new StringBuilder(); | ||
174 | sb.append('['); | ||
175 | sb.append(codeParts[0]); | ||
176 | for (i = 1; i < codeParts.length; i++) { | ||
177 | sb.append(';'); | ||
178 | sb.append(codeParts[i]); | ||
179 | } | ||
180 | sb.append(']'); | ||
181 | return sb.toString(); | ||
182 | |||
183 | } | ||
184 | } else if (eReferred instanceof EObject) { | ||
185 | return addStateCode(sd.node, (EObject) eReferred); | ||
186 | } else { | ||
187 | throw new DSEException("The EObject " + eObject.toString() + " does not have a feature " | ||
188 | + eReferred.toString() + "."); | ||
189 | } | ||
190 | |||
191 | } else { | ||
192 | for (EObject dependentEObject : objectProvider.getEObjects(sd.node.getClazz())) { | ||
193 | Object eReferred = dependentEObject.eGet(sd.eReference); | ||
194 | if (eReferred == null) { | ||
195 | continue; | ||
196 | } else if (eReferred instanceof EList<?>) { | ||
197 | // TODO this is slow, use VIATRA Query | ||
198 | for (Object referredEObject : ((EList<?>) eReferred)) { | ||
199 | if (referredEObject.equals(eObject)) { | ||
200 | return addStateCode(sd.node, (EObject) dependentEObject); | ||
201 | } | ||
202 | } | ||
203 | } else if (eReferred.equals(eObject)) { | ||
204 | // Probably never happens? | ||
205 | return addStateCode(sd.node, (EObject) dependentEObject); | ||
206 | } else { | ||
207 | throw new DSEException("The EObject " + eObject.toString() + " does not have a feature " | ||
208 | + eReferred.toString() + "."); | ||
209 | } | ||
210 | } | ||
211 | } | ||
212 | |||
213 | return ""; | ||
214 | } | ||
215 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.java new file mode 100644 index 00000000..eeb6e48f --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.java | |||
@@ -0,0 +1,40 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding; | ||
10 | |||
11 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
12 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
13 | |||
14 | public class TheStateCoderFactory implements IStateCoderFactory { | ||
15 | |||
16 | private StatecodingDependencyGraph sdg; | ||
17 | private IObjectsProviderFactory objectProviderFactory; | ||
18 | |||
19 | public TheStateCoderFactory(StatecodingDependencyGraph sdg) { | ||
20 | this(sdg, new IncrementalObjectProviderFactory()); | ||
21 | } | ||
22 | |||
23 | public TheStateCoderFactory(StatecodingDependencyGraph sdg, IObjectsProviderFactory objectProviderFactory) { | ||
24 | this.sdg = sdg; | ||
25 | this.objectProviderFactory = objectProviderFactory; | ||
26 | |||
27 | // TODO cyclic dependency? - exception | ||
28 | |||
29 | // TODO make plan for traversal | ||
30 | |||
31 | // TODO If the type is FIXED and all dependency is FIXED then do not create state code for it (them) | ||
32 | // This is not true :( e.g. matchmaking - they are fixed, but the references must be encoded | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public IStateCoder createStateCoder() { | ||
37 | return new TheStateCoder(sdg, objectProviderFactory.createObjectsProvider()); | ||
38 | } | ||
39 | |||
40 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java new file mode 100644 index 00000000..0f0759ae --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java | |||
@@ -0,0 +1,250 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding.simple; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.Collection; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.HashSet; | ||
15 | import java.util.List; | ||
16 | import java.util.Map; | ||
17 | import java.util.Set; | ||
18 | |||
19 | import org.eclipse.emf.common.notify.Notifier; | ||
20 | import org.eclipse.emf.ecore.EAttribute; | ||
21 | import org.eclipse.emf.ecore.EClass; | ||
22 | import org.eclipse.emf.ecore.EObject; | ||
23 | import org.eclipse.emf.ecore.EReference; | ||
24 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
25 | import org.eclipse.emf.ecore.EStructuralFeature.Setting; | ||
26 | import org.eclipse.viatra.dse.api.DSEException; | ||
27 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
28 | import org.eclipse.viatra.dse.util.EMFHelper.MetaModelElements; | ||
29 | import org.eclipse.viatra.dse.util.ValueComparableEObjectStringMap; | ||
30 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
31 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
32 | import org.eclipse.viatra.query.runtime.base.api.FeatureListener; | ||
33 | import org.eclipse.viatra.query.runtime.base.api.IndexingLevel; | ||
34 | import org.eclipse.viatra.query.runtime.base.api.InstanceListener; | ||
35 | import org.eclipse.viatra.query.runtime.base.api.NavigationHelper; | ||
36 | import org.eclipse.viatra.query.runtime.emf.EMFBaseIndexWrapper; | ||
37 | import org.eclipse.viatra.query.runtime.emf.EMFScope; | ||
38 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
39 | |||
40 | /** | ||
41 | * | ||
42 | * @author Andras Szabolcs Nagy | ||
43 | * | ||
44 | */ | ||
45 | public class SimpleStateCoder implements IStateCoder { | ||
46 | |||
47 | private Set<EClass> classes; | ||
48 | private Set<EStructuralFeature> features; | ||
49 | private NavigationHelper navigationHelper; | ||
50 | |||
51 | private Map<EClass, Map<EObject, String>> objectCodes; | ||
52 | private int maxDepth; | ||
53 | |||
54 | private Set<EObject> changedOrNewEObjects = new HashSet<EObject>(); | ||
55 | private Set<EObject> deletedClasses = new HashSet<EObject>(); | ||
56 | |||
57 | public SimpleStateCoder(MetaModelElements metaModelElements) { | ||
58 | this.maxDepth = 1; | ||
59 | |||
60 | classes = metaModelElements.classes; | ||
61 | features = new HashSet<EStructuralFeature>(metaModelElements.attributes); | ||
62 | features.addAll(metaModelElements.references); | ||
63 | } | ||
64 | |||
65 | @Override | ||
66 | public void init(Notifier notifier) { | ||
67 | try { | ||
68 | EMFScope scope = new EMFScope(notifier); | ||
69 | ViatraQueryEngine queryEngine = ViatraQueryEngine.on(scope); | ||
70 | EMFBaseIndexWrapper baseIndex = (EMFBaseIndexWrapper) queryEngine.getBaseIndex(); | ||
71 | navigationHelper = baseIndex.getNavigationHelper(); | ||
72 | navigationHelper.registerObservedTypes(classes, null, features, IndexingLevel.FULL); | ||
73 | } catch (ViatraQueryException e) { | ||
74 | throw new DSEException(e); | ||
75 | } | ||
76 | |||
77 | objectCodes = new HashMap<EClass, Map<EObject, String>>(); | ||
78 | for (EClass eClass : classes) { | ||
79 | Map<EObject, String> codes = new ValueComparableEObjectStringMap(); | ||
80 | |||
81 | objectCodes.put(eClass, codes); | ||
82 | |||
83 | for (EObject eObject : navigationHelper.getDirectInstances(eClass)) { | ||
84 | codes.put(eObject, createObjectCodeWithDepth(eObject, maxDepth)); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | navigationHelper.addFeatureListener(features, new FeatureListener() { | ||
89 | |||
90 | @Override | ||
91 | public void featureInserted(EObject host, EStructuralFeature feature, Object value) { | ||
92 | changedOrNewEObjects.add(host); | ||
93 | } | ||
94 | |||
95 | @Override | ||
96 | public void featureDeleted(EObject host, EStructuralFeature feature, Object value) { | ||
97 | changedOrNewEObjects.add(host); | ||
98 | if (value instanceof EObject) { | ||
99 | changedOrNewEObjects.add((EObject) value); | ||
100 | } | ||
101 | } | ||
102 | }); | ||
103 | |||
104 | navigationHelper.addInstanceListener(classes, new InstanceListener() { | ||
105 | |||
106 | @Override | ||
107 | public void instanceInserted(EClass clazz, EObject instance) { | ||
108 | changedOrNewEObjects.add(instance); | ||
109 | } | ||
110 | |||
111 | @Override | ||
112 | public void instanceDeleted(EClass clazz, EObject instance) { | ||
113 | deletedClasses.add(instance); | ||
114 | } | ||
115 | }); | ||
116 | } | ||
117 | |||
118 | private String createObjectCodeWithDepth(EObject eObject, int depth) { | ||
119 | |||
120 | StringBuilder sb = new StringBuilder(); | ||
121 | |||
122 | Collection<EAttribute> attributes = eObject.eClass().getEAllAttributes(); | ||
123 | for (EAttribute eAttribute : attributes) { | ||
124 | Object value = eObject.eGet(eAttribute); | ||
125 | sb.append(value); | ||
126 | sb.append(','); | ||
127 | } | ||
128 | if (!attributes.isEmpty()) { | ||
129 | sb.deleteCharAt(sb.length() - 1); | ||
130 | } | ||
131 | if (depth > 0) { | ||
132 | sb.append('-'); | ||
133 | Collection<EReference> eReferences = eObject.eClass().getEAllReferences(); | ||
134 | for (EReference eReference : eReferences) { | ||
135 | Object value = eObject.eGet(eReference); | ||
136 | if (value == null) { | ||
137 | sb.append("null,"); | ||
138 | } else if (value instanceof EObject) { | ||
139 | sb.append(createObjectCodeWithDepth((EObject) value, depth - 1)); | ||
140 | sb.append(','); | ||
141 | } else { | ||
142 | List<EObject> referencedEObjects = (List<EObject>) value; | ||
143 | if (!referencedEObjects.isEmpty()) { | ||
144 | |||
145 | String[] codes = new String[referencedEObjects.size()]; | ||
146 | int index = 0; | ||
147 | for (EObject referencedEObject : referencedEObjects) { | ||
148 | codes[index++] = createObjectCodeWithDepth(referencedEObject, depth - 1); | ||
149 | } | ||
150 | Arrays.sort(codes); | ||
151 | sb.append('('); | ||
152 | for (String code : codes) { | ||
153 | sb.append(code); | ||
154 | } | ||
155 | sb.append("),"); | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | sb.deleteCharAt(sb.length() - 1); | ||
160 | } | ||
161 | return sb.toString(); | ||
162 | } | ||
163 | |||
164 | @Override | ||
165 | public Object createStateCode() { | ||
166 | |||
167 | refreshObjectCodes(); | ||
168 | |||
169 | StringBuilder sb = new StringBuilder(); | ||
170 | |||
171 | for (EClass eClass : classes) { | ||
172 | |||
173 | Set<EObject> instances = navigationHelper.getDirectInstances(eClass); | ||
174 | |||
175 | if (!instances.isEmpty()) { | ||
176 | |||
177 | sb.append(eClass.getName()); | ||
178 | sb.append(':'); | ||
179 | |||
180 | String[] codesToSort = new String[instances.size()]; | ||
181 | int index = 0; | ||
182 | Map<EObject, String> codes = objectCodes.get(eClass); | ||
183 | for (EObject eObject : instances) { | ||
184 | codesToSort[index++] = codes.get(eObject); | ||
185 | } | ||
186 | Arrays.sort(codesToSort); | ||
187 | for (String string : codesToSort) { | ||
188 | sb.append(string); | ||
189 | sb.append(';'); | ||
190 | } | ||
191 | sb.deleteCharAt(sb.length() - 1); | ||
192 | sb.append('|'); | ||
193 | } | ||
194 | } | ||
195 | if (sb.length() != 0) { | ||
196 | sb.deleteCharAt(sb.length() - 1); | ||
197 | } | ||
198 | return sb.toString(); | ||
199 | } | ||
200 | |||
201 | private void refreshObjectCodes() { | ||
202 | for (EObject eObject : deletedClasses) { | ||
203 | EClass eClass = eObject.eClass(); | ||
204 | objectCodes.get(eClass).remove(eObject); | ||
205 | } | ||
206 | deletedClasses.clear(); | ||
207 | |||
208 | Set<EObject> objectsToRecode = new HashSet<EObject>(); | ||
209 | for (EObject eObject : changedOrNewEObjects) { | ||
210 | objectsToRecode.add(eObject); | ||
211 | for (Setting setting : navigationHelper.getInverseReferences(eObject)) { | ||
212 | objectsToRecode.add(setting.getEObject()); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | for (EObject eObject : objectsToRecode) { | ||
217 | EClass eClass = eObject.eClass(); | ||
218 | objectCodes.get(eClass).put(eObject, createObjectCodeWithDepth(eObject, maxDepth)); | ||
219 | } | ||
220 | changedOrNewEObjects.clear(); | ||
221 | } | ||
222 | |||
223 | @Override | ||
224 | public Object createActivationCode(IPatternMatch match) { | ||
225 | |||
226 | StringBuilder sb = new StringBuilder(); | ||
227 | String[] tokens = match.specification().getFullyQualifiedName().split("\\."); | ||
228 | sb.append(tokens[tokens.length - 1]); | ||
229 | sb.append(':'); | ||
230 | Object param; | ||
231 | for (int i = 0; (param = match.get(i)) != null; i++) { | ||
232 | EObject eObject = (EObject) param; | ||
233 | |||
234 | Collection<EAttribute> attributes = eObject.eClass().getEAllAttributes(); | ||
235 | for (EAttribute eAttribute : attributes) { | ||
236 | Object value = eObject.eGet(eAttribute); | ||
237 | sb.append(value); | ||
238 | sb.append(','); | ||
239 | } | ||
240 | if (!attributes.isEmpty()) { | ||
241 | sb.deleteCharAt(sb.length() - 1); | ||
242 | } | ||
243 | |||
244 | sb.append('|'); | ||
245 | } | ||
246 | sb.deleteCharAt(sb.length() - 1); | ||
247 | return sb.toString().intern(); | ||
248 | } | ||
249 | |||
250 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactory.java new file mode 100644 index 00000000..d776e8a8 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactory.java | |||
@@ -0,0 +1,38 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.statecoding.simple; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashSet; | ||
13 | |||
14 | import org.eclipse.emf.ecore.EPackage; | ||
15 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
16 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
17 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
18 | import org.eclipse.viatra.dse.util.EMFHelper.MetaModelElements; | ||
19 | |||
20 | /** | ||
21 | * | ||
22 | * @author Andras Szabolcs Nagy | ||
23 | * | ||
24 | */ | ||
25 | public class SimpleStateCoderFactory implements IStateCoderFactory { | ||
26 | |||
27 | private MetaModelElements metaModelElements; | ||
28 | |||
29 | public SimpleStateCoderFactory(Collection<EPackage> metaModelPackages) { | ||
30 | metaModelElements = EMFHelper.getAllMetaModelElements(new HashSet<EPackage>(metaModelPackages)); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public IStateCoder createStateCoder() { | ||
35 | return new SimpleStateCoder(metaModelElements); | ||
36 | } | ||
37 | |||
38 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/EMFHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/EMFHelper.java new file mode 100644 index 00000000..14b3acfb --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/EMFHelper.java | |||
@@ -0,0 +1,424 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.util; | ||
10 | |||
11 | import java.io.IOException; | ||
12 | import java.util.Collections; | ||
13 | import java.util.Comparator; | ||
14 | import java.util.HashMap; | ||
15 | import java.util.HashSet; | ||
16 | import java.util.List; | ||
17 | import java.util.Map; | ||
18 | import java.util.Objects; | ||
19 | import java.util.Set; | ||
20 | import java.util.TreeSet; | ||
21 | |||
22 | import org.apache.log4j.Logger; | ||
23 | import org.eclipse.emf.common.command.BasicCommandStack; | ||
24 | import org.eclipse.emf.common.notify.Notifier; | ||
25 | import org.eclipse.emf.common.util.EList; | ||
26 | import org.eclipse.emf.common.util.URI; | ||
27 | import org.eclipse.emf.ecore.EAttribute; | ||
28 | import org.eclipse.emf.ecore.EClass; | ||
29 | import org.eclipse.emf.ecore.EClassifier; | ||
30 | import org.eclipse.emf.ecore.ENamedElement; | ||
31 | import org.eclipse.emf.ecore.EObject; | ||
32 | import org.eclipse.emf.ecore.EPackage; | ||
33 | import org.eclipse.emf.ecore.EReference; | ||
34 | import org.eclipse.emf.ecore.resource.Resource; | ||
35 | import org.eclipse.emf.ecore.resource.ResourceSet; | ||
36 | import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; | ||
37 | import org.eclipse.emf.ecore.util.EcoreUtil.Copier; | ||
38 | import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; | ||
39 | import org.eclipse.emf.edit.command.AddCommand; | ||
40 | import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; | ||
41 | import org.eclipse.emf.edit.domain.EditingDomain; | ||
42 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
43 | |||
44 | /** | ||
45 | * This class contains static helper methods. | ||
46 | * @author Andras Szabolcs Nagy | ||
47 | */ | ||
48 | public final class EMFHelper { | ||
49 | |||
50 | private static final Logger logger = Logger.getLogger(EMFHelper.class); | ||
51 | |||
52 | private EMFHelper() { | ||
53 | } | ||
54 | |||
55 | public static class EmfHelperException extends RuntimeException { | ||
56 | private static final long serialVersionUID = 7635796550669616626L; | ||
57 | |||
58 | public EmfHelperException(String string) { | ||
59 | super(string); | ||
60 | } | ||
61 | public EmfHelperException(String string, Throwable e) { | ||
62 | super(string, e); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * Gets the {@link EditingDomain} of either an {@link EObject}, {@link Resource} or {@link ResourceSet}. | ||
68 | * @param notifier The {@link Notifier}. | ||
69 | * @return The EditingDomain. | ||
70 | */ | ||
71 | public static EditingDomain getEditingDomain(Notifier notifier) { | ||
72 | Objects.requireNonNull(notifier); | ||
73 | if (notifier instanceof EObject) { | ||
74 | EObject eObject = (EObject) notifier; | ||
75 | return AdapterFactoryEditingDomain.getEditingDomainFor(eObject); | ||
76 | } else if (notifier instanceof Resource) { | ||
77 | Resource resource = (Resource) notifier; | ||
78 | EList<EObject> contents = resource.getContents(); | ||
79 | if (contents.isEmpty()) { | ||
80 | return null; | ||
81 | } | ||
82 | return AdapterFactoryEditingDomain.getEditingDomainFor(contents.get(0)); | ||
83 | } else if (notifier instanceof ResourceSet) { | ||
84 | ResourceSet resourceSet = (ResourceSet) notifier; | ||
85 | if (resourceSet.getResources().isEmpty()) { | ||
86 | return null; | ||
87 | } | ||
88 | return getEditingDomain(resourceSet.getResources().get(0)); | ||
89 | } | ||
90 | |||
91 | return null; | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * Creates (or gets if already exists) an {@link EditingDomain} over the given {@link Notifier}, | ||
96 | * either an {@link EObject}, {@link Resource} or {@link ResourceSet}. | ||
97 | * @param notifier The {@link Notifier}. | ||
98 | * @return The EditingDomain. | ||
99 | */ | ||
100 | public static EditingDomain createEditingDomain(Notifier notifier) { | ||
101 | |||
102 | EditingDomain domain = getEditingDomain(notifier); | ||
103 | if (domain != null) { | ||
104 | return domain; | ||
105 | } | ||
106 | |||
107 | registerExtensionForXmiSerializer("dummyext"); | ||
108 | |||
109 | if (notifier instanceof EObject) { | ||
110 | EObject eObject = (EObject) notifier; | ||
111 | |||
112 | domain = new AdapterFactoryEditingDomain(null, new BasicCommandStack()); | ||
113 | Resource resource = domain.getResourceSet().createResource(URI.createFileURI("dummy.dummyext")); | ||
114 | domain.getCommandStack().execute(new AddCommand(domain, resource.getContents(), eObject)); | ||
115 | |||
116 | return domain; | ||
117 | |||
118 | } else if (notifier instanceof Resource) { | ||
119 | Resource resource = (Resource) notifier; | ||
120 | |||
121 | ResourceSet resourceSet = resource.getResourceSet(); | ||
122 | if (resourceSet != null) { | ||
123 | return new AdapterFactoryEditingDomain(null, new BasicCommandStack(), resourceSet); | ||
124 | } else { | ||
125 | domain = new AdapterFactoryEditingDomain(null, new BasicCommandStack(), (ResourceSet) null); | ||
126 | resourceSet = domain.getResourceSet(); | ||
127 | domain.getCommandStack().execute(new AddCommand(domain, resourceSet.getResources(), resource)); | ||
128 | return domain; | ||
129 | } | ||
130 | |||
131 | } else if (notifier instanceof ResourceSet) { | ||
132 | return new AdapterFactoryEditingDomain(null, new BasicCommandStack(), (ResourceSet) notifier); | ||
133 | } else { | ||
134 | throw new EmfHelperException("Not supported argument type."); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * Saves the EMF model (EObject or Resource) into the given file. An {@link XMIResourceFactoryImpl} will be | ||
140 | * registered if not already. | ||
141 | * | ||
142 | * Doesn't throw exception but logs an error if the save was unsuccessful. | ||
143 | * | ||
144 | * @param model Can be an {@link EObject} or a {@link Resource}. | ||
145 | * @param fileName | ||
146 | */ | ||
147 | public static void saveModel(Notifier model, String fileName) { | ||
148 | |||
149 | Objects.requireNonNull(model); | ||
150 | Preconditions.checkArgument(fileName != null && !fileName.isEmpty(), "File name is null or empty."); | ||
151 | |||
152 | int extensionIndex = fileName.lastIndexOf('.'); | ||
153 | |||
154 | Preconditions.checkState(extensionIndex > -1 && extensionIndex != fileName.length() - 1, "Bad file extension."); | ||
155 | |||
156 | String ext = fileName.substring(extensionIndex + 1); | ||
157 | |||
158 | registerExtensionForXmiSerializer(ext); | ||
159 | |||
160 | URI uri = URI.createFileURI(fileName); | ||
161 | Resource resource; | ||
162 | |||
163 | if (model instanceof ResourceSet) { | ||
164 | throw new EmfHelperException("Unsupported type: ResourceSet"); | ||
165 | } else if (model instanceof Resource) { | ||
166 | resource = (Resource) model; | ||
167 | } else if (model instanceof EObject) { | ||
168 | EObject root = (EObject) model; | ||
169 | ResourceSet resSet = new ResourceSetImpl(); | ||
170 | resource = resSet.createResource(uri); | ||
171 | resource.getContents().add(root); | ||
172 | } else { | ||
173 | throw new EmfHelperException("Unkown type: " + model.getClass()); | ||
174 | } | ||
175 | |||
176 | resource.setURI(uri); | ||
177 | saveResource(resource); | ||
178 | } | ||
179 | |||
180 | private static void saveResource(Resource resource) { | ||
181 | try { | ||
182 | resource.save(Collections.emptyMap()); | ||
183 | } catch (IOException e) { | ||
184 | logger.error(e); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * Loads a model as a {@link Resource}. In headless mode, don't forget to call XYZPackage.eINSTANCE. | ||
190 | */ | ||
191 | public static Resource loadModel(String fileName) throws IOException { | ||
192 | Preconditions.checkArgument(fileName != null && !fileName.isEmpty(), "File name is null or empty."); | ||
193 | int extensionIndex = fileName.lastIndexOf('.'); | ||
194 | Preconditions.checkState(extensionIndex > -1 && extensionIndex != fileName.length() - 1, "Bad file extension."); | ||
195 | |||
196 | String ext = fileName.substring(extensionIndex + 1); | ||
197 | registerExtensionForXmiSerializer(ext); | ||
198 | |||
199 | ResourceSetImpl rSet = new ResourceSetImpl(); | ||
200 | URI fileUri = URI.createFileURI(fileName); | ||
201 | Resource resource = rSet.createResource(fileUri); | ||
202 | |||
203 | resource.load(null); | ||
204 | return resource; | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * Retrieves the root EObject from a Resource or ResourceSet. | ||
209 | * <ul> | ||
210 | * <li>Returns null if there is no content.</li> | ||
211 | * <li>Returns the notifier itself if it is an EObject.</li> | ||
212 | * <li>Logs a warn if there are multiple roots.</li> | ||
213 | * </ul> | ||
214 | * | ||
215 | * @param notifier | ||
216 | * @return The root EObject or null. | ||
217 | */ | ||
218 | public static EObject getRootEObject(Notifier notifier) { | ||
219 | if (notifier instanceof EObject) { | ||
220 | return (EObject) notifier; | ||
221 | } else if (notifier instanceof Resource) { | ||
222 | Resource resource = (Resource) notifier; | ||
223 | List<EObject> contents = resource.getContents(); | ||
224 | if (contents.size() > 1) { | ||
225 | logger.warn("Resource has more than one root."); | ||
226 | } | ||
227 | if (contents.isEmpty()) { | ||
228 | return null; | ||
229 | } else { | ||
230 | return contents.get(0); | ||
231 | } | ||
232 | } else if (notifier instanceof ResourceSet) { | ||
233 | ResourceSet resourceSet = (ResourceSet) notifier; | ||
234 | List<Resource> resources = resourceSet.getResources(); | ||
235 | if (resources.size() > 1) { | ||
236 | logger.warn("ResourceSet has more than one resources."); | ||
237 | } | ||
238 | if (resources.isEmpty()) { | ||
239 | return null; | ||
240 | } else { | ||
241 | return getRootEObject(resources.get(0)); | ||
242 | } | ||
243 | } else { | ||
244 | throw new EmfHelperException("Unkown type: " + notifier.getClass()); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * Registers an {@link XMIResourceFactoryImpl} for the given extension. | ||
250 | * @param ext The extension as a String. | ||
251 | */ | ||
252 | public static void registerExtensionForXmiSerializer(String ext) { | ||
253 | Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE; | ||
254 | Map<String, Object> m = reg.getExtensionToFactoryMap(); | ||
255 | m.computeIfAbsent(ext, e -> new XMIResourceFactoryImpl()); | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * Clones the given model. Either an {@link EObject}, {@link Resource} or {@link ResourceSet}. | ||
260 | * @param notifier The root container of the model. | ||
261 | * @return The cloned model. | ||
262 | */ | ||
263 | public static Notifier clone(Notifier notifier) { | ||
264 | Copier copier = new Copier(); | ||
265 | Notifier clonedModel = clone(notifier, copier, null); | ||
266 | copier.copyReferences(); | ||
267 | return clonedModel; | ||
268 | } | ||
269 | |||
270 | private static Notifier clone(Notifier notifier, Copier copier, ResourceSet resourceSetToCloneTo) { | ||
271 | Objects.requireNonNull(copier); | ||
272 | |||
273 | if (notifier instanceof EObject) { | ||
274 | EObject eObject = (EObject) notifier; | ||
275 | return copier.copy(eObject); | ||
276 | } else if (notifier instanceof Resource) { | ||
277 | Resource resource = (Resource) notifier; | ||
278 | ResourceSet rSetTemp = resourceSetToCloneTo; | ||
279 | if (resourceSetToCloneTo == null) { | ||
280 | rSetTemp = new ResourceSetImpl(); | ||
281 | } | ||
282 | Resource clonedResource = rSetTemp.createResource(URI.createFileURI("dummy.dummyext")); | ||
283 | |||
284 | for (EObject eObject : resource.getContents()) { | ||
285 | EObject clonedEObject = copier.copy(eObject); | ||
286 | clonedResource.getContents().add(clonedEObject); | ||
287 | } | ||
288 | |||
289 | return clonedResource; | ||
290 | } else if (notifier instanceof ResourceSet) { | ||
291 | ResourceSet resourceSet = (ResourceSet) notifier; | ||
292 | ResourceSetImpl clonedResourceSet = new ResourceSetImpl(); | ||
293 | |||
294 | for (Resource resource : resourceSet.getResources()) { | ||
295 | clone(resource, copier, clonedResourceSet); | ||
296 | } | ||
297 | |||
298 | return clonedResourceSet; | ||
299 | } else { | ||
300 | throw new EmfHelperException("Not supported argument type."); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | public static class ENamedElementComparator implements Comparator<ENamedElement> { | ||
305 | @Override | ||
306 | public int compare(ENamedElement eClass1, ENamedElement eClass2) { | ||
307 | return eClass1.getName().compareTo(eClass2.getName()); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * This class is used to store | ||
313 | * <ul> | ||
314 | * <li>{@link EClass}es,</li> | ||
315 | * <li>{@link EAttribute}s,</li> | ||
316 | * <li>{@link EReference}s,</li> | ||
317 | * <li>EAttributes by EClasses,</li> | ||
318 | * <li>EReferences by EClasses</li> | ||
319 | * </ul> | ||
320 | * for a given set of {@link EPackage}s. | ||
321 | * | ||
322 | */ | ||
323 | public static class MetaModelElements { | ||
324 | public Set<EPackage> metaModelPackages; | ||
325 | public Set<EClass> classes; | ||
326 | public Set<EAttribute> attributes; | ||
327 | public Set<EReference> references; | ||
328 | public Map<EClass, Set<EAttribute>> attributesOfClass; | ||
329 | public Map<EClass, Set<EReference>> referencesOfClass; | ||
330 | } | ||
331 | |||
332 | /** | ||
333 | * Traverses the full metamodel on the given {@link EPackage}s and returns all the classes, attributes and | ||
334 | * references it contains. | ||
335 | * | ||
336 | * @param metaModelPackages | ||
337 | * The set of {@link EPackage}s. | ||
338 | * @return A {@link MetaModelElements} instance containing the metamodel elements. | ||
339 | */ | ||
340 | public static MetaModelElements getAllMetaModelElements(Set<EPackage> metaModelPackages) { | ||
341 | return getMetaModelElements(metaModelPackages, true, true, true); | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * Return a {@link MetaModelElements} instance populated with its {@link MetaModelElements#classes}. | ||
346 | * | ||
347 | * @param metaModelPackages | ||
348 | * The set of {@link EPackage}s. | ||
349 | * @return AA {@link MetaModelElements} instance. | ||
350 | */ | ||
351 | public static MetaModelElements getClasses(Set<EPackage> metaModelPackages) { | ||
352 | return getMetaModelElements(metaModelPackages, true, false, false); | ||
353 | } | ||
354 | |||
355 | /** | ||
356 | * Return a {@link MetaModelElements} instance populated with its {@link MetaModelElements#references} and | ||
357 | * {@link MetaModelElements#referencesOfClass}. | ||
358 | * | ||
359 | * @param metaModelPackages | ||
360 | * The set of {@link EPackage}s. | ||
361 | * @return AA {@link MetaModelElements} instance. | ||
362 | */ | ||
363 | public static MetaModelElements getReferences(Set<EPackage> metaModelPackages) { | ||
364 | return getMetaModelElements(metaModelPackages, false, true, false); | ||
365 | } | ||
366 | |||
367 | /** | ||
368 | * Return a {@link MetaModelElements} instance populated with its {@link MetaModelElements#attributes} and | ||
369 | * {@link MetaModelElements#attributesOfClass}. | ||
370 | * | ||
371 | * @param metaModelPackages | ||
372 | * The set of {@link EPackage}s. | ||
373 | * @return AA {@link MetaModelElements} instance. | ||
374 | */ | ||
375 | public static MetaModelElements getAttrbiutes(Set<EPackage> metaModelPackages) { | ||
376 | return getMetaModelElements(metaModelPackages, false, false, true); | ||
377 | } | ||
378 | |||
379 | private static MetaModelElements getMetaModelElements(Set<EPackage> metaModelPackages, boolean getClasses, | ||
380 | boolean getReferences, boolean getAttrbiutes) { | ||
381 | |||
382 | Comparator<ENamedElement> comparator = new ENamedElementComparator(); | ||
383 | |||
384 | MetaModelElements result = new MetaModelElements(); | ||
385 | result.metaModelPackages = metaModelPackages; | ||
386 | if (getClasses) { | ||
387 | result.classes = new TreeSet<EClass>(comparator); | ||
388 | } | ||
389 | if (getReferences) { | ||
390 | result.references = new HashSet<EReference>(); | ||
391 | result.referencesOfClass = new HashMap<EClass, Set<EReference>>(); | ||
392 | } | ||
393 | if (getAttrbiutes) { | ||
394 | result.attributes = new HashSet<EAttribute>(); | ||
395 | result.attributesOfClass = new HashMap<EClass, Set<EAttribute>>(); | ||
396 | } | ||
397 | for (EPackage ePackage : metaModelPackages) { | ||
398 | for (EClassifier eClassifier : ePackage.getEClassifiers()) { | ||
399 | if (eClassifier instanceof EClass) { | ||
400 | EClass eClass = ((EClass) eClassifier); | ||
401 | if (getClasses) { | ||
402 | result.classes.add(eClass); | ||
403 | } | ||
404 | if (getReferences) { | ||
405 | result.referencesOfClass.put(eClass, new TreeSet<EReference>(comparator)); | ||
406 | for (EReference eReference : eClass.getEAllReferences()) { | ||
407 | result.references.add(eReference); | ||
408 | result.referencesOfClass.get(eClass).add(eReference); | ||
409 | } | ||
410 | } | ||
411 | if (getAttrbiutes) { | ||
412 | result.attributesOfClass.put(eClass, new TreeSet<EAttribute>(comparator)); | ||
413 | for (EAttribute eAttribute : eClass.getEAllAttributes()) { | ||
414 | result.attributes.add(eAttribute); | ||
415 | result.attributesOfClass.get(eClass).add(eAttribute); | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | return result; | ||
422 | } | ||
423 | |||
424 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/Hasher.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/Hasher.java new file mode 100644 index 00000000..0c5d7eba --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/Hasher.java | |||
@@ -0,0 +1,86 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.util; | ||
10 | |||
11 | import java.math.BigInteger; | ||
12 | import java.security.MessageDigest; | ||
13 | import java.security.NoSuchAlgorithmException; | ||
14 | |||
15 | import org.eclipse.viatra.dse.api.DSEException; | ||
16 | |||
17 | /** | ||
18 | * Utility class that encapsulates a {@link MessageDigest} instance to aid calculating hash values more easily, and to | ||
19 | * reuse a {@link MessageDigest} instance. | ||
20 | * | ||
21 | */ | ||
22 | public final class Hasher { | ||
23 | private MessageDigest md; | ||
24 | |||
25 | private static final int HEX = 16; | ||
26 | |||
27 | private Hasher(MessageDigest md) { | ||
28 | this.md = md; | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * Calculates and returns a hash value. | ||
33 | * | ||
34 | * @param data | ||
35 | * the data to be hashed in a {@link String}. | ||
36 | * @return the hash value in some {@link String} representation. | ||
37 | */ | ||
38 | public String hash(String data) { | ||
39 | md.update(data.getBytes(), 0, data.length()); | ||
40 | return new String(md.digest()); | ||
41 | } | ||
42 | |||
43 | @SuppressWarnings("unused") | ||
44 | private String alternateHashBest(String data) { | ||
45 | md.update(data.getBytes(), 0, data.length()); | ||
46 | return new String(md.digest()); | ||
47 | } | ||
48 | |||
49 | @SuppressWarnings("unused") | ||
50 | private String alternateHashSecondBest(String data) { | ||
51 | md.update(data.getBytes(), 0, data.length()); | ||
52 | return new BigInteger(1, md.digest()).toString(HEX); | ||
53 | } | ||
54 | |||
55 | @SuppressWarnings("unused") | ||
56 | private String alternateHashThirdBest(String data) { | ||
57 | md.update(data.getBytes(), 0, data.length()); | ||
58 | byte[] array = md.digest(); | ||
59 | StringBuilder sb = new StringBuilder(); | ||
60 | for (int i = 0; i < array.length; i++) { | ||
61 | sb.append(Integer.toHexString((int) array[i])); | ||
62 | } | ||
63 | return sb.toString(); | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * Returns a {@link Hasher} with an internal {@link MessageDigest} that is based on the protocol named | ||
68 | * {@code protocoll}. | ||
69 | * | ||
70 | * @param protocoll | ||
71 | * the name of the hash algorythm. | ||
72 | * @return the initialized {@link Hasher} | ||
73 | * | ||
74 | * @throws DSEException | ||
75 | * on initialization failure. | ||
76 | */ | ||
77 | public static Hasher getHasher(String protocoll) { | ||
78 | try { | ||
79 | return new Hasher(MessageDigest.getInstance(protocoll)); | ||
80 | } catch (NoSuchAlgorithmException e) { | ||
81 | throw new DSEException(e); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | public static final String SHA1_PROTOCOLL = "SHA-1"; | ||
86 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.java new file mode 100644 index 00000000..49af05d1 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.java | |||
@@ -0,0 +1,63 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy 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.util; | ||
10 | |||
11 | import java.util.Comparator; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.Map; | ||
14 | import java.util.TreeMap; | ||
15 | |||
16 | import org.eclipse.emf.ecore.EObject; | ||
17 | |||
18 | import com.google.common.base.Functions; | ||
19 | import com.google.common.collect.Ordering; | ||
20 | |||
21 | /** | ||
22 | * | ||
23 | * This custom {@link TreeMap} implementation enables to store {@link EObject}-{@link String} pairs sorted by values | ||
24 | * (strings). It works as expected if the map is modified in any way, hence the map will still be sorted by values on | ||
25 | * the new set of entries. | ||
26 | * | ||
27 | * It is allowed to have two entries with the same EObject key (and also with same values). | ||
28 | * | ||
29 | * The short coming of the class is that EObjects are compared to each other by their | ||
30 | * {@link System#identityHashCode(Object)}, which may lead to unexpected errors. | ||
31 | * | ||
32 | * @author Andras Szabolcs Nagy | ||
33 | * | ||
34 | */ | ||
35 | public class ValueComparableEObjectStringMap extends TreeMap<EObject, String> { | ||
36 | |||
37 | private static final class EObjectComparator implements Comparator<EObject> { | ||
38 | @Override | ||
39 | public int compare(EObject o1, EObject o2) { | ||
40 | return Integer.valueOf(System.identityHashCode(o1)).compareTo(Integer.valueOf(System.identityHashCode(o2))); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | private final Map<EObject, String> innerMap; | ||
45 | |||
46 | public ValueComparableEObjectStringMap() { | ||
47 | this(new HashMap<EObject, String>()); | ||
48 | } | ||
49 | |||
50 | private ValueComparableEObjectStringMap(Map<EObject, String> innerMap) { | ||
51 | super(Ordering.natural().onResultOf(Functions.forMap(innerMap)).compound(new EObjectComparator())); | ||
52 | this.innerMap = innerMap; | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public String put(EObject keyEObject, String stringValue) { | ||
57 | if (innerMap.containsKey(keyEObject)) { | ||
58 | remove(keyEObject); | ||
59 | } | ||
60 | innerMap.put(keyEObject, stringValue); | ||
61 | return super.put(keyEObject, stringValue); | ||
62 | } | ||
63 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.java new file mode 100644 index 00000000..bb8000d5 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.java | |||
@@ -0,0 +1,56 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.visualizer; | ||
10 | |||
11 | public class DesignSpaceVisualizerOptions { | ||
12 | |||
13 | public boolean showExplorationTrace = true; | ||
14 | public boolean showStateCodes = true; | ||
15 | public boolean showTransitionCodes = true; | ||
16 | |||
17 | public DesignSpaceVisualizerOptions withOutExploraionTrace() { | ||
18 | showExplorationTrace = false; | ||
19 | return this; | ||
20 | } | ||
21 | |||
22 | public DesignSpaceVisualizerOptions withOutstateCodes() { | ||
23 | showStateCodes = false; | ||
24 | return this; | ||
25 | } | ||
26 | |||
27 | public DesignSpaceVisualizerOptions withOutTransitionCodes() { | ||
28 | showTransitionCodes = false; | ||
29 | return this; | ||
30 | } | ||
31 | |||
32 | public boolean isShowExplorationTrace() { | ||
33 | return showExplorationTrace; | ||
34 | } | ||
35 | |||
36 | public void setShowExplorationTrace(boolean showExplorationTrace) { | ||
37 | this.showExplorationTrace = showExplorationTrace; | ||
38 | } | ||
39 | |||
40 | public boolean isShowStateCodes() { | ||
41 | return showStateCodes; | ||
42 | } | ||
43 | |||
44 | public void setShowStateCodes(boolean showStateCodes) { | ||
45 | this.showStateCodes = showStateCodes; | ||
46 | } | ||
47 | |||
48 | public boolean isShowTransitionCodes() { | ||
49 | return showTransitionCodes; | ||
50 | } | ||
51 | |||
52 | public void setShowTransitionCodes(boolean showTransitionCodes) { | ||
53 | this.showTransitionCodes = showTransitionCodes; | ||
54 | } | ||
55 | |||
56 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.java new file mode 100644 index 00000000..da598b91 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.java | |||
@@ -0,0 +1,39 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.visualizer; | ||
10 | |||
11 | import org.eclipse.viatra.dse.api.DesignSpaceExplorer; | ||
12 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
13 | |||
14 | /** | ||
15 | * | ||
16 | * An implementation of this interface is notified about the traversal of the design space from every traversing thread, | ||
17 | * if registered to the {@link DesignSpaceExplorer}. Its purpose is to able to visualize the design space (a directed | ||
18 | * graph with IDs of the nodes and transitions) and to able to visualize the order of the exploration (the trace of a | ||
19 | * thread). | ||
20 | * | ||
21 | * @author Andras Szabolcs Nagy | ||
22 | * | ||
23 | */ | ||
24 | public interface IDesignSpaceVisualizer extends IExploreEventHandler { | ||
25 | |||
26 | /** | ||
27 | * Initializes the instance with a starting thread's context. Can be called multiple times and concurrently. | ||
28 | * | ||
29 | * @see DesignSpaceVisualizerOptions | ||
30 | * @param context | ||
31 | */ | ||
32 | void init(ThreadContext context); | ||
33 | |||
34 | /** | ||
35 | * Saves the captured data. | ||
36 | */ | ||
37 | void save(); | ||
38 | |||
39 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IExploreEventHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IExploreEventHandler.java new file mode 100644 index 00000000..9f902f31 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IExploreEventHandler.java | |||
@@ -0,0 +1,40 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, 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.visualizer; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.DesignSpaceManager; | ||
12 | |||
13 | /** | ||
14 | * An implementation of this interface is notified about every move in the design space (firing a rule activation or | ||
15 | * undoing it) of a single thread, if registered to the corresponding {@link DesignSpaceManager}. Its methods are called | ||
16 | * synchronously, therefore the implementation can have an impact on the performance. Also note, if the same instance is | ||
17 | * registered to multiple threads ({@link DesignSpaceManager}), it has to be thread safe. | ||
18 | * | ||
19 | * @author Andras Szabolcs Nagy | ||
20 | * | ||
21 | */ | ||
22 | public interface IExploreEventHandler { | ||
23 | |||
24 | /** | ||
25 | * Called by the {@link DesignSpaceManager}, after a rule activation (transition) is fired. Multiple calls with the | ||
26 | * same transition can occur. | ||
27 | * | ||
28 | * @param transition The fired transition. | ||
29 | */ | ||
30 | void transitionFired(Object transition); | ||
31 | |||
32 | /** | ||
33 | * Called by the {@link DesignSpaceManager}, after undoing the previously fired rule activation (transition). | ||
34 | * Multiple calls with the same transition can occur. | ||
35 | * | ||
36 | * @param transition The undone transition. | ||
37 | */ | ||
38 | void undo(Object transition); | ||
39 | |||
40 | } | ||