diff options
Diffstat (limited to 'Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/run/Modes3ModelGenerator.xtend')
-rw-r--r-- | Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/run/Modes3ModelGenerator.xtend | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/run/Modes3ModelGenerator.xtend b/Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/run/Modes3ModelGenerator.xtend new file mode 100644 index 00000000..613cb3e4 --- /dev/null +++ b/Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/run/Modes3ModelGenerator.xtend | |||
@@ -0,0 +1,357 @@ | |||
1 | package modes3.run | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import com.google.common.collect.ImmutableSet | ||
5 | import hu.bme.mit.inf.dslreasoner.ecore2logic.EReferenceMapper_RelationsOverTypes_Trace | ||
6 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic | ||
7 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2LogicConfiguration | ||
8 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic_Trace | ||
9 | import hu.bme.mit.inf.dslreasoner.ecore2logic.EcoreMetamodelDescriptor | ||
10 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.Ecore2logicannotationsFactory | ||
11 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.Ecore2logicannotationsPackage | ||
12 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel | ||
13 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicProblemBuilder | ||
14 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.LogiclanguagePackage | ||
15 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDefinition | ||
16 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicproblemPackage | ||
17 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult | ||
18 | import hu.bme.mit.inf.dslreasoner.logic2ecore.Logic2Ecore | ||
19 | import hu.bme.mit.inf.dslreasoner.viatra2logic.Viatra2Logic | ||
20 | import hu.bme.mit.inf.dslreasoner.viatra2logic.Viatra2LogicConfiguration | ||
21 | import hu.bme.mit.inf.dslreasoner.viatra2logic.ViatraQuerySetDescriptor | ||
22 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.Viatra2LogicAnnotationsPackage | ||
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod | ||
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedralScopePropagatorConstraints | ||
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedralScopePropagatorSolver | ||
26 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
27 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic.InstanceModel2Logic | ||
28 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink | ||
29 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | ||
30 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage | ||
31 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretation2Gml | ||
32 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.CostObjectiveConfiguration | ||
33 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.CostObjectiveElementConfiguration | ||
34 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.StateCoderStrategy | ||
35 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasoner | ||
36 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration | ||
37 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PartialModelAsLogicInterpretation | ||
38 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind | ||
39 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold | ||
40 | import hu.bme.mit.inf.dslreasoner.visualisation.pi2graphviz.GraphvizVisualiser | ||
41 | import hu.bme.mit.inf.dslreasoner.workspace.FileSystemWorkspace | ||
42 | import java.util.List | ||
43 | import modes3.Modes3Factory | ||
44 | import modes3.Modes3Package | ||
45 | import modes3.queries.CloseTrains_step_2 | ||
46 | import modes3.queries.CloseTrains_step_3 | ||
47 | import modes3.queries.CloseTrains_step_4 | ||
48 | import modes3.queries.CloseTrains_step_5 | ||
49 | import modes3.queries.CloseTrains_step_6 | ||
50 | import modes3.queries.CloseTrains_step_7 | ||
51 | import modes3.queries.EndOfSiding_step_2 | ||
52 | import modes3.queries.EndOfSiding_step_3 | ||
53 | import modes3.queries.EndOfSiding_step_4 | ||
54 | import modes3.queries.EndOfSiding_step_5 | ||
55 | import modes3.queries.MisalignedTurnout_step_2 | ||
56 | import modes3.queries.MisalignedTurnout_step_3 | ||
57 | import modes3.queries.MisalignedTurnout_step_4 | ||
58 | import modes3.queries.MisalignedTurnout_step_5 | ||
59 | import modes3.queries.Modes3Queries | ||
60 | import modes3.queries.TrainLocations_step_2 | ||
61 | import modes3.queries.TrainLocations_step_3 | ||
62 | import org.eclipse.emf.ecore.EClass | ||
63 | import org.eclipse.emf.ecore.EObject | ||
64 | import org.eclipse.emf.ecore.resource.Resource | ||
65 | import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl | ||
66 | import org.eclipse.viatra.query.patternlanguage.emf.EMFPatternLanguageStandaloneSetup | ||
67 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions | ||
68 | import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchEMFBackendFactory | ||
69 | import org.eclipse.viatra.query.runtime.rete.matcher.ReteBackendFactory | ||
70 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
71 | |||
72 | @FinalFieldsConstructor | ||
73 | class Modes3ModelGenerator { | ||
74 | val MonitoringQuery monitoringQuery | ||
75 | val int modelSize | ||
76 | |||
77 | val ecore2Logic = new Ecore2Logic | ||
78 | val instanceModel2Logic = new InstanceModel2Logic | ||
79 | val viatra2Logic = new Viatra2Logic(ecore2Logic) | ||
80 | val solver = new ViatraReasoner | ||
81 | extension val LogicProblemBuilder = new LogicProblemBuilder | ||
82 | |||
83 | def generate() { | ||
84 | val metamodel = createMetamodelDescriptor() | ||
85 | val metamodelLogic = ecore2Logic.transformMetamodel(metamodel, new Ecore2LogicConfiguration) | ||
86 | val segment = ecore2Logic.TypeofEClass(metamodelLogic.trace, Modes3Package.eINSTANCE.segment) | ||
87 | val connectedTo = ecore2Logic.relationOfReference(metamodelLogic.trace, | ||
88 | Modes3Package.eINSTANCE.segment_ConnectedTo) | ||
89 | val connectedToIndicator = (metamodelLogic.trace. | ||
90 | referenceMapperTrace as EReferenceMapper_RelationsOverTypes_Trace).indicators.get( | ||
91 | Modes3Package.eINSTANCE.segment_ConnectedTo) | ||
92 | val inverseAssertion = Assertion( | ||
93 | '''oppositeReference «connectedTo.name» «connectedTo.name»''', | ||
94 | Forall[ | ||
95 | val src = addVar('''src''', segment) | ||
96 | val trg = addVar('''trg''', segment) | ||
97 | connectedToIndicator.call(src, trg) <=> connectedToIndicator.call(trg, src) | ||
98 | ] | ||
99 | ) | ||
100 | metamodelLogic.output.assertions += inverseAssertion | ||
101 | val inverseAnnotation = Ecore2logicannotationsFactory.eINSTANCE.createInverseRelationAssertion => [ | ||
102 | target = inverseAssertion | ||
103 | inverseA = connectedTo | ||
104 | inverseB = connectedTo | ||
105 | ] | ||
106 | metamodelLogic.output.annotations += inverseAnnotation | ||
107 | val initialModel = loadInitialModel() | ||
108 | val initialModelLogic = instanceModel2Logic.transform(metamodelLogic, initialModel) | ||
109 | val queries = loadQueries | ||
110 | val logic = viatra2Logic.transformQueries(queries, initialModelLogic, new Viatra2LogicConfiguration) | ||
111 | val config = new ViatraReasonerConfiguration => [ | ||
112 | runtimeLimit = 3600 | ||
113 | typeScopes => [ | ||
114 | minNewElements = modelSize | ||
115 | maxNewElements = modelSize | ||
116 | minNewElementsByType => [ | ||
117 | // put(ecore2Logic.TypeofEClass(metamodelLogic.trace, Modes3Package.eINSTANCE.train), modelSize / 5) | ||
118 | // put(ecore2Logic.TypeofEClass(metamodelLogic.trace, Modes3Package.eINSTANCE.turnout), modelSize / 5) | ||
119 | // put(ecore2Logic.TypeofEClass(metamodelLogic.trace, Modes3Package.eINSTANCE.simpleSegment), 3 * modelSize / 5) | ||
120 | ] | ||
121 | maxNewElementsByType => [ | ||
122 | put(ecore2Logic.TypeofEClass(metamodelLogic.trace, Modes3Package.eINSTANCE.train), modelSize / 5) | ||
123 | put(ecore2Logic.TypeofEClass(metamodelLogic.trace, Modes3Package.eINSTANCE.turnout), modelSize / 5) | ||
124 | put(ecore2Logic.TypeofEClass(metamodelLogic.trace, Modes3Package.eINSTANCE.simpleSegment), 3 * modelSize / 5) | ||
125 | ] | ||
126 | ] | ||
127 | solutionScope => [ | ||
128 | numberOfRequiredSolutions = 1 | ||
129 | ] | ||
130 | costObjectives += getObjective(ecore2Logic, metamodelLogic.trace) | ||
131 | scopeWeight = 6 | ||
132 | nameNewElements = false | ||
133 | typeInferenceMethod = TypeInferenceMethod.PreliminaryAnalysis | ||
134 | stateCoderStrategy = StateCoderStrategy.PairwiseNeighbourhood | ||
135 | scopePropagatorStrategy = new ScopePropagatorStrategy.Polyhedral( | ||
136 | PolyhedralScopePropagatorConstraints.Relational, PolyhedralScopePropagatorSolver.Clp) | ||
137 | hints += new Modes3TypeScopeHint(ecore2Logic, metamodelLogic.trace) | ||
138 | unitPropagationPatternGenerators += new Modes3UnitPropagationGenerator(ecore2Logic, metamodelLogic.trace) | ||
139 | debugConfiguration => [ | ||
140 | partialInterpretatioVisualiser = new GraphvizVisualiser | ||
141 | // partalInterpretationVisualisationFrequency = 50 | ||
142 | ] | ||
143 | documentationLevel = DocumentationLevel.NORMAL | ||
144 | ] | ||
145 | val workspace = new FileSystemWorkspace("output/", "") | ||
146 | workspace.writeModel(logic.output, "problem.logicproblem") | ||
147 | val solution = solver.solve(logic.output, config, workspace) | ||
148 | if (solution instanceof ModelResult) { | ||
149 | println("Saving generated solutions") | ||
150 | val logic2Ecore = new Logic2Ecore(ecore2Logic) | ||
151 | val interpretations = solver.getInterpretations(solution) | ||
152 | for (representationIndex : 0 ..< interpretations.size) { | ||
153 | val interpretation = interpretations.get(representationIndex) | ||
154 | val representationNumber = representationIndex + 1 | ||
155 | if (interpretation instanceof PartialModelAsLogicInterpretation) { | ||
156 | val representation = interpretation.partialInterpretation | ||
157 | workspace.writeModel(representation, '''solution«representationNumber».partialinterpretation''') | ||
158 | val partialInterpretation2GML = new PartialInterpretation2Gml | ||
159 | val gml = partialInterpretation2GML.transform(representation) | ||
160 | workspace.writeText('''solution«representationNumber».gml''', gml) | ||
161 | val model = logic2Ecore.transformInterpretation(interpretation, metamodelLogic.trace) | ||
162 | val iterator = model.eAllContents | ||
163 | var int id = 0 | ||
164 | while (iterator.hasNext) { | ||
165 | val obj = iterator.next | ||
166 | val idFeature = obj.eClass.EAllAttributes.findFirst[name == 'id'] | ||
167 | if (idFeature !== null) { | ||
168 | obj.eSet(idFeature, id) | ||
169 | id++ | ||
170 | } | ||
171 | } | ||
172 | workspace.writeModel(model, '''solution«representationNumber».modes3''') | ||
173 | if (representation.newElements.size < 160) { | ||
174 | val rootType = (representation.problem.types.findFirst [ | ||
175 | name == "Modes3ModelRoot class DefinedPart" | ||
176 | ] as TypeDefinition) | ||
177 | val rootIntepretation = representation.partialtypeinterpratation.filter( | ||
178 | PartialComplexTypeInterpretation).findFirst [ | ||
179 | interpretationOf.name == "Modes3ModelRoot class" | ||
180 | ] | ||
181 | rootIntepretation.elements.removeAll(rootType.elements) | ||
182 | representation.problem.elements.removeAll(rootType.elements) | ||
183 | for (relationInterpretation : representation.partialrelationinterpretation) { | ||
184 | relationInterpretation.relationlinks.removeIf [ link | | ||
185 | if (link instanceof BinaryElementRelationLink) { | ||
186 | rootType.elements.contains(link.param1) || | ||
187 | rootType.elements.contains(link.param2) | ||
188 | } else { | ||
189 | false | ||
190 | } | ||
191 | ] | ||
192 | } | ||
193 | rootType.elements.clear | ||
194 | val visualiser = new GraphvizVisualiser | ||
195 | val visualisation = visualiser.visualiseConcretization(representation) | ||
196 | visualisation.writeToFile(workspace, '''solution«representationNumber».png''') | ||
197 | } | ||
198 | } else { | ||
199 | workspace.writeText('''solution«representationNumber».txt''', interpretation.toString) | ||
200 | } | ||
201 | } | ||
202 | } else { | ||
203 | println("Failed to solve problem") | ||
204 | val partial = logic.output | ||
205 | workspace.writeModel(partial, "solution.partialinterpretation") | ||
206 | } | ||
207 | } | ||
208 | |||
209 | static def createMetamodelDescriptor() { | ||
210 | val eClasses = ImmutableList.copyOf(Modes3Package.eINSTANCE.EClassifiers.filter(EClass)) | ||
211 | new EcoreMetamodelDescriptor( | ||
212 | eClasses, | ||
213 | emptySet, | ||
214 | false, | ||
215 | emptyList, | ||
216 | emptyList, | ||
217 | ImmutableList.copyOf(eClasses.flatMap[EReferences]), | ||
218 | emptyList | ||
219 | ) | ||
220 | } | ||
221 | |||
222 | static def List<EObject> loadInitialModel() { | ||
223 | #[Modes3Factory.eINSTANCE.createModes3ModelRoot] | ||
224 | } | ||
225 | |||
226 | def loadQueries() { | ||
227 | val patternsBuilder = ImmutableList.builder | ||
228 | patternsBuilder.addAll(Modes3Queries.instance.specifications) | ||
229 | val patterns = patternsBuilder.build | ||
230 | val validationPatterns = ImmutableSet.copyOf(patterns.filter [ pattern | | ||
231 | pattern.allAnnotations.exists[name == "Constraint"] | ||
232 | ]) | ||
233 | new ViatraQuerySetDescriptor( | ||
234 | patterns, | ||
235 | validationPatterns, | ||
236 | emptyMap | ||
237 | ) | ||
238 | } | ||
239 | |||
240 | def getObjective(Ecore2Logic ecore2Logic, Ecore2Logic_Trace ecore2LogicTrace) { | ||
241 | new CostObjectiveConfiguration => [ | ||
242 | switch (monitoringQuery) { | ||
243 | case closeTrains: { | ||
244 | elements += new CostObjectiveElementConfiguration => [ | ||
245 | patternQualifiedName = CloseTrains_step_2.instance.fullyQualifiedName | ||
246 | weight = 14 + 53 + 11 | ||
247 | ] | ||
248 | elements += new CostObjectiveElementConfiguration => [ | ||
249 | patternQualifiedName = CloseTrains_step_3.instance.fullyQualifiedName | ||
250 | weight = 21 + 14 | ||
251 | ] | ||
252 | elements += new CostObjectiveElementConfiguration => [ | ||
253 | patternQualifiedName = CloseTrains_step_4.instance.fullyQualifiedName | ||
254 | weight = 14 + 44 + 14 + 9 | ||
255 | ] | ||
256 | elements += new CostObjectiveElementConfiguration => [ | ||
257 | patternQualifiedName = CloseTrains_step_5.instance.fullyQualifiedName | ||
258 | weight = 14 + 41 + 11 | ||
259 | ] | ||
260 | elements += new CostObjectiveElementConfiguration => [ | ||
261 | patternQualifiedName = CloseTrains_step_6.instance.fullyQualifiedName | ||
262 | weight = 27 | ||
263 | ] | ||
264 | elements += new CostObjectiveElementConfiguration => [ | ||
265 | patternQualifiedName = CloseTrains_step_7.instance.fullyQualifiedName | ||
266 | weight = 48 | ||
267 | ] | ||
268 | hint = new CloseTrainsObjectiveHint(ecore2Logic, ecore2LogicTrace) | ||
269 | } | ||
270 | case trainLocations: { | ||
271 | elements += new CostObjectiveElementConfiguration => [ | ||
272 | patternQualifiedName = TrainLocations_step_2.instance.fullyQualifiedName | ||
273 | weight = 14 + 53 + 11 | ||
274 | ] | ||
275 | elements += new CostObjectiveElementConfiguration => [ | ||
276 | patternQualifiedName = TrainLocations_step_3.instance.fullyQualifiedName | ||
277 | weight = 48 | ||
278 | ] | ||
279 | hint = new TrainLocationsObjectiveHint(ecore2Logic, ecore2LogicTrace) | ||
280 | } | ||
281 | case misalignedTurnout: { | ||
282 | elements += new CostObjectiveElementConfiguration => [ | ||
283 | patternQualifiedName = MisalignedTurnout_step_2.instance.fullyQualifiedName | ||
284 | weight = 14 + 53 + 11 | ||
285 | ] | ||
286 | elements += new CostObjectiveElementConfiguration => [ | ||
287 | patternQualifiedName = MisalignedTurnout_step_3.instance.fullyQualifiedName | ||
288 | weight = 108 | ||
289 | ] | ||
290 | elements += new CostObjectiveElementConfiguration => [ | ||
291 | patternQualifiedName = MisalignedTurnout_step_4.instance.fullyQualifiedName | ||
292 | weight = 27 | ||
293 | ] | ||
294 | elements += new CostObjectiveElementConfiguration => [ | ||
295 | patternQualifiedName = MisalignedTurnout_step_5.instance.fullyQualifiedName | ||
296 | weight = 48 | ||
297 | ] | ||
298 | hint = new MisalignedTurnoutObjectiveHint(ecore2Logic, ecore2LogicTrace) | ||
299 | } | ||
300 | case endOfSiding: { | ||
301 | elements += new CostObjectiveElementConfiguration => [ | ||
302 | patternQualifiedName = EndOfSiding_step_2.instance.fullyQualifiedName | ||
303 | weight = 14 + 53 + 11 | ||
304 | ] | ||
305 | elements += new CostObjectiveElementConfiguration => [ | ||
306 | patternQualifiedName = EndOfSiding_step_3.instance.fullyQualifiedName | ||
307 | weight = 21 + 14 | ||
308 | ] | ||
309 | elements += new CostObjectiveElementConfiguration => [ | ||
310 | patternQualifiedName = EndOfSiding_step_4.instance.fullyQualifiedName | ||
311 | weight = 14 + 35 + 21 + 15 + 14 + 21 + 15 + 11 | ||
312 | ] | ||
313 | elements += new CostObjectiveElementConfiguration => [ | ||
314 | patternQualifiedName = EndOfSiding_step_5.instance.fullyQualifiedName | ||
315 | weight = 48 | ||
316 | ] | ||
317 | hint = new EndOfSidingObjectiveHint(ecore2Logic, ecore2LogicTrace) | ||
318 | } | ||
319 | default: | ||
320 | throw new IllegalArgumentException("Unknown monitoring query: " + monitoringQuery) | ||
321 | } | ||
322 | kind = ObjectiveKind.HIGHER_IS_BETTER | ||
323 | threshold = ObjectiveThreshold.NO_THRESHOLD | ||
324 | findExtremum = true | ||
325 | ] | ||
326 | } | ||
327 | |||
328 | def static init() { | ||
329 | EMFPatternLanguageStandaloneSetup.doSetup | ||
330 | ViatraQueryEngineOptions.setSystemDefaultBackends(ReteBackendFactory.INSTANCE, ReteBackendFactory.INSTANCE, | ||
331 | LocalSearchEMFBackendFactory.INSTANCE) | ||
332 | LogiclanguagePackage.eINSTANCE.class | ||
333 | LogicproblemPackage.eINSTANCE.class | ||
334 | PartialinterpretationPackage.eINSTANCE.class | ||
335 | Ecore2logicannotationsPackage.eINSTANCE.class | ||
336 | Viatra2LogicAnnotationsPackage.eINSTANCE.class | ||
337 | Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put("*", new XMIResourceFactoryImpl) | ||
338 | } | ||
339 | |||
340 | def static void main(String[] args) { | ||
341 | if (args.length != 2) { | ||
342 | System.err.println("Usage: <query> <model size>") | ||
343 | } | ||
344 | val monitoringQuery = MonitoringQuery.valueOf(args.get(0)) | ||
345 | val modelSize = Integer.parseInt(args.get(1)) | ||
346 | init() | ||
347 | val generator = new Modes3ModelGenerator(monitoringQuery, modelSize) | ||
348 | generator.generate() | ||
349 | } | ||
350 | |||
351 | private static enum MonitoringQuery { | ||
352 | closeTrains, | ||
353 | trainLocations, | ||
354 | endOfSiding, | ||
355 | misalignedTurnout | ||
356 | } | ||
357 | } | ||