diff options
Diffstat (limited to 'Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3')
3 files changed, 539 insertions, 0 deletions
diff --git a/Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/queries/Modes3Queries.vql b/Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/queries/Modes3Queries.vql new file mode 100644 index 00000000..982e6cec --- /dev/null +++ b/Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/queries/Modes3Queries.vql | |||
@@ -0,0 +1,112 @@ | |||
1 | package modes3.queries | ||
2 | |||
3 | import "http://www.ece.mcgill.ca/wcet/modes3" | ||
4 | |||
5 | @Constraint(message = "turnoutInSegments", severity = "error", key = { T }) | ||
6 | pattern turnoutInSegments(T : Turnout) { | ||
7 | Modes3ModelRoot.segments(_, T); | ||
8 | } | ||
9 | |||
10 | pattern connectedTo(S1 : Segment, S2 : Segment) { | ||
11 | Segment.connectedTo(S1, S2); | ||
12 | } | ||
13 | |||
14 | @Constraint(message = "connectedToNotSymmetric", severity = "error", key = { S1, S2 }) | ||
15 | pattern connectedToNotSymmetric(S1 : Segment, S2 : Segment) { | ||
16 | Segment.connectedTo(S1, S2); | ||
17 | neg find connectedTo(S2, S1); | ||
18 | } | ||
19 | |||
20 | @Constraint(message = "connectedToReflexive", severity = "error", key = { S }) | ||
21 | pattern connectedToReflexive(S : Segment) { | ||
22 | Segment.connectedTo(S, S); | ||
23 | } | ||
24 | |||
25 | pattern turnoutOutput(T : Turnout, S : Segment) { | ||
26 | Turnout.straight(T, S); | ||
27 | } or { | ||
28 | Turnout.divergent(T, S); | ||
29 | } | ||
30 | |||
31 | @Constraint(message = "outputReflexive", severity = "error", key = { T }) | ||
32 | pattern outputReflexive(T : Turnout) { | ||
33 | find turnoutOutput(T, T); | ||
34 | } | ||
35 | |||
36 | @Constraint(message = "turnoutOutputsAreSame", severity = "error", key = { T }) | ||
37 | pattern turnoutOutputsAreSame(T : Turnout) { | ||
38 | Turnout.straight(T, S); | ||
39 | Turnout.divergent(T, S); | ||
40 | } | ||
41 | |||
42 | pattern turnout(T : Turnout) { | ||
43 | Turnout(T); | ||
44 | } | ||
45 | |||
46 | pattern output(S1 : Segment, S2 : Segment) { | ||
47 | Segment.connectedTo(S1, S2); | ||
48 | } or { | ||
49 | find turnoutOutput(S1, S2); | ||
50 | } | ||
51 | |||
52 | //@Constraint(message = "noInputOfSegment", severity = "error", key = { S }) | ||
53 | //pattern noInputOfSegment(S : Segment) { | ||
54 | // neg find turnout(S); | ||
55 | // neg find output(_, S); | ||
56 | //} | ||
57 | |||
58 | @Constraint(message = "tooManyInputsOfSegment", severity = "error", key = { S }) | ||
59 | pattern tooManyInputsOfSegment(S : Segment) { | ||
60 | neg find turnout(S); | ||
61 | find output(I1, S); | ||
62 | find output(I2, S); | ||
63 | find output(I3, S); | ||
64 | I1 != I2; | ||
65 | I1 != I3; | ||
66 | I2 != I3; | ||
67 | } | ||
68 | |||
69 | @Constraint(message = "turnoutConnectedToBothOutputs", severity = "error", key = { T }) | ||
70 | pattern turnoutConnectedToBothOutputs(T : Turnout) { | ||
71 | Turnout.straight(T, Straight); | ||
72 | Turnout.divergent(T, Divergent); | ||
73 | Segment.connectedTo(T, Straight); | ||
74 | Segment.connectedTo(T, Divergent); | ||
75 | } | ||
76 | |||
77 | pattern extraInputOfTurnout(T : Turnout, S : Segment) { | ||
78 | Turnout.straight(T, Straight); | ||
79 | Turnout.divergent(T, Divergent); | ||
80 | find output(S, T); | ||
81 | S != Straight; | ||
82 | S != Divergent; | ||
83 | } | ||
84 | |||
85 | @Constraint(message = "noExtraInputOfTurnout", severity = "error", key = { T }) | ||
86 | pattern noExtraInputOfTurnout(T : Turnout) { | ||
87 | neg find extraInputOfTurnout(T, _); | ||
88 | } | ||
89 | |||
90 | @Constraint(message = "tooManyExtraInputsOfTurnout", severity = "error", key = { T }) | ||
91 | pattern tooManyExtraInputsOfTurnout(T : Turnout) { | ||
92 | find extraInputOfTurnout(T, I1); | ||
93 | find extraInputOfTurnout(T, I2); | ||
94 | I1 != I2; | ||
95 | } | ||
96 | |||
97 | pattern adjacent(S1 : Segment, S2 : Segment) { | ||
98 | find output(S1, S2); | ||
99 | } or { | ||
100 | find turnoutOutput(S2, S1); | ||
101 | } | ||
102 | |||
103 | pattern reachable(S1 : Segment, S2 : Segment) { | ||
104 | S1 == S2; | ||
105 | } or { | ||
106 | find adjacent+(S1, S2); | ||
107 | } | ||
108 | |||
109 | @Constraint(message = "unreachable", severity = "error", key = { S1, S2 }) | ||
110 | pattern unreachable(S1 : Segment, S2 : Segment) { | ||
111 | neg find reachable(S1, S2); | ||
112 | } | ||
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..71d1798f --- /dev/null +++ b/Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/run/Modes3ModelGenerator.xtend | |||
@@ -0,0 +1,222 @@ | |||
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.EcoreMetamodelDescriptor | ||
9 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.Ecore2logicannotationsFactory | ||
10 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.Ecore2logicannotationsPackage | ||
11 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicProblemBuilder | ||
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.LogiclanguagePackage | ||
13 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDefinition | ||
14 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicproblemPackage | ||
15 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult | ||
16 | import hu.bme.mit.inf.dslreasoner.viatra2logic.Viatra2Logic | ||
17 | import hu.bme.mit.inf.dslreasoner.viatra2logic.Viatra2LogicConfiguration | ||
18 | import hu.bme.mit.inf.dslreasoner.viatra2logic.ViatraQuerySetDescriptor | ||
19 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.Viatra2LogicAnnotationsPackage | ||
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod | ||
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedralScopePropagatorConstraints | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedralScopePropagatorSolver | ||
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic.InstanceModel2Logic | ||
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | ||
26 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
27 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage | ||
28 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretation2Gml | ||
29 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.StateCoderStrategy | ||
30 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasoner | ||
31 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration | ||
32 | import hu.bme.mit.inf.dslreasoner.visualisation.pi2graphviz.GraphvizVisualiser | ||
33 | import hu.bme.mit.inf.dslreasoner.workspace.FileSystemWorkspace | ||
34 | import java.util.List | ||
35 | import modes3.Modes3Factory | ||
36 | import modes3.Modes3Package | ||
37 | import modes3.queries.Modes3Queries | ||
38 | import org.eclipse.emf.ecore.EClass | ||
39 | import org.eclipse.emf.ecore.EObject | ||
40 | import org.eclipse.emf.ecore.resource.Resource | ||
41 | import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl | ||
42 | import org.eclipse.viatra.query.patternlanguage.emf.EMFPatternLanguageStandaloneSetup | ||
43 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions | ||
44 | import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchEMFBackendFactory | ||
45 | import org.eclipse.viatra.query.runtime.rete.matcher.ReteBackendFactory | ||
46 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
47 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition | ||
48 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink | ||
49 | |||
50 | @FinalFieldsConstructor | ||
51 | class Modes3ModelGenerator { | ||
52 | val MonitoringQuery monitoringQuery | ||
53 | val int modelSize | ||
54 | |||
55 | val ecore2Logic = new Ecore2Logic | ||
56 | val instanceModel2Logic = new InstanceModel2Logic | ||
57 | val viatra2Logic = new Viatra2Logic(ecore2Logic) | ||
58 | val solver = new ViatraReasoner | ||
59 | extension val LogicProblemBuilder = new LogicProblemBuilder | ||
60 | |||
61 | def generate() { | ||
62 | val metamodel = createMetamodelDescriptor() | ||
63 | val metamodelLogic = ecore2Logic.transformMetamodel(metamodel, new Ecore2LogicConfiguration) | ||
64 | val segment = ecore2Logic.TypeofEClass(metamodelLogic.trace, Modes3Package.eINSTANCE.segment) | ||
65 | val connectedTo = ecore2Logic.relationOfReference(metamodelLogic.trace, | ||
66 | Modes3Package.eINSTANCE.segment_ConnectedTo) | ||
67 | val connectedToIndicator = (metamodelLogic.trace. | ||
68 | referenceMapperTrace as EReferenceMapper_RelationsOverTypes_Trace).indicators.get( | ||
69 | Modes3Package.eINSTANCE.segment_ConnectedTo) | ||
70 | val inverseAssertion = Assertion( | ||
71 | '''oppositeReference «connectedTo.name» «connectedTo.name»''', | ||
72 | Forall[ | ||
73 | val src = addVar('''src''', segment) | ||
74 | val trg = addVar('''trg''', segment) | ||
75 | connectedToIndicator.call(src, trg) <=> connectedToIndicator.call(trg, src) | ||
76 | ] | ||
77 | ) | ||
78 | metamodelLogic.output.assertions += inverseAssertion | ||
79 | val inverseAnnotation = Ecore2logicannotationsFactory.eINSTANCE.createInverseRelationAssertion => [ | ||
80 | target = inverseAssertion | ||
81 | inverseA = connectedTo | ||
82 | inverseB = connectedTo | ||
83 | ] | ||
84 | metamodelLogic.output.annotations += inverseAnnotation | ||
85 | val initialModel = loadInitialModel() | ||
86 | val initialModelLogic = instanceModel2Logic.transform(metamodelLogic, initialModel) | ||
87 | val queries = loadQueries | ||
88 | val logic = viatra2Logic.transformQueries(queries, initialModelLogic, new Viatra2LogicConfiguration) | ||
89 | val config = new ViatraReasonerConfiguration => [ | ||
90 | runtimeLimit = 3600 | ||
91 | typeScopes => [ | ||
92 | minNewElements = modelSize | ||
93 | maxNewElements = modelSize | ||
94 | minNewElementsByType => [ | ||
95 | put(ecore2Logic.TypeofEClass(metamodelLogic.trace, Modes3Package.eINSTANCE.turnout), 1) | ||
96 | ] | ||
97 | maxNewElementsByType => [ | ||
98 | put(ecore2Logic.TypeofEClass(metamodelLogic.trace, Modes3Package.eINSTANCE.train), 5) | ||
99 | ] | ||
100 | ] | ||
101 | solutionScope.numberOfRequiredSolutions = 1 | ||
102 | nameNewElements = false | ||
103 | typeInferenceMethod = TypeInferenceMethod.PreliminaryAnalysis | ||
104 | stateCoderStrategy = StateCoderStrategy::Neighbourhood | ||
105 | scopePropagatorStrategy = new ScopePropagatorStrategy.Polyhedral( | ||
106 | PolyhedralScopePropagatorConstraints.Relational, PolyhedralScopePropagatorSolver.Clp) | ||
107 | // unitPropagationPatternGenerators += new Modes3UnitPropagationGenerator(ecore2Logic, metamodelLogic.trace) | ||
108 | debugConfiguration.partialInterpretatioVisualiser = null | ||
109 | ] | ||
110 | val workspace = new FileSystemWorkspace("output/", "") | ||
111 | val solution = solver.solve(logic.output, config, workspace) | ||
112 | if (solution instanceof ModelResult) { | ||
113 | println("Saving generated solutions") | ||
114 | val representations = solution.representation | ||
115 | for (representationIndex : 0 ..< representations.size) { | ||
116 | val representation = representations.get(representationIndex) | ||
117 | val representationNumber = representationIndex + 1 | ||
118 | if (representation instanceof PartialInterpretation) { | ||
119 | workspace.writeModel(representation, '''solution«representationNumber».partialinterpretation''') | ||
120 | val partialInterpretation2GML = new PartialInterpretation2Gml | ||
121 | val gml = partialInterpretation2GML.transform(representation) | ||
122 | workspace.writeText('''solution«representationNumber».gml''', gml) | ||
123 | if (representation.newElements.size < 160) { | ||
124 | if (representation instanceof PartialInterpretation) { | ||
125 | representation.problem.types.forEach[println(name)] | ||
126 | val rootType = (representation.problem.types.findFirst [ | ||
127 | name == "Modes3ModelRoot class DefinedPart" | ||
128 | ] as TypeDefinition) | ||
129 | val rootIntepretation = representation.partialtypeinterpratation.filter( | ||
130 | PartialComplexTypeInterpretation).findFirst [ | ||
131 | interpretationOf.name == "Modes3ModelRoot class" | ||
132 | ] | ||
133 | rootIntepretation.elements.removeAll(rootType.elements) | ||
134 | representation.problem.elements.removeAll(rootType.elements) | ||
135 | for (relationInterpretation : representation.partialrelationinterpretation) { | ||
136 | relationInterpretation.relationlinks.removeIf [ link | | ||
137 | if (link instanceof BinaryElementRelationLink) { | ||
138 | rootType.elements.contains(link.param1) || rootType.elements.contains(link.param2) | ||
139 | } else { | ||
140 | false | ||
141 | } | ||
142 | ] | ||
143 | } | ||
144 | rootType.elements.clear | ||
145 | } | ||
146 | val visualiser = new GraphvizVisualiser | ||
147 | val visualisation = visualiser.visualiseConcretization(representation) | ||
148 | visualisation.writeToFile(workspace, '''solution«representationNumber».png''') | ||
149 | } | ||
150 | } else { | ||
151 | workspace.writeText('''solution«representationNumber».txt''', representation.toString) | ||
152 | } | ||
153 | } | ||
154 | } else { | ||
155 | println("Failed to solver problem") | ||
156 | val partial = logic.output | ||
157 | workspace.writeModel(partial, "solution.partialinterpretation") | ||
158 | } | ||
159 | } | ||
160 | |||
161 | static def createMetamodelDescriptor() { | ||
162 | val eClasses = ImmutableList.copyOf(Modes3Package.eINSTANCE.EClassifiers.filter(EClass)) | ||
163 | new EcoreMetamodelDescriptor( | ||
164 | eClasses, | ||
165 | emptySet, | ||
166 | false, | ||
167 | emptyList, | ||
168 | emptyList, | ||
169 | ImmutableList.copyOf(eClasses.flatMap[EReferences]), | ||
170 | emptyList | ||
171 | ) | ||
172 | } | ||
173 | |||
174 | static def List<EObject> loadInitialModel() { | ||
175 | #[Modes3Factory.eINSTANCE.createModes3ModelRoot] | ||
176 | } | ||
177 | |||
178 | def loadQueries() { | ||
179 | val patternsBuilder = ImmutableList.builder | ||
180 | patternsBuilder.addAll(Modes3Queries.instance.specifications) | ||
181 | val patterns = patternsBuilder.build | ||
182 | val validationPatterns = ImmutableSet.copyOf(patterns.filter [ pattern | | ||
183 | pattern.allAnnotations.exists[name == "Constraint"] | ||
184 | ]) | ||
185 | new ViatraQuerySetDescriptor( | ||
186 | patterns, | ||
187 | validationPatterns, | ||
188 | emptyMap | ||
189 | ) | ||
190 | } | ||
191 | |||
192 | def static init() { | ||
193 | EMFPatternLanguageStandaloneSetup.doSetup | ||
194 | ViatraQueryEngineOptions.setSystemDefaultBackends(ReteBackendFactory.INSTANCE, ReteBackendFactory.INSTANCE, | ||
195 | LocalSearchEMFBackendFactory.INSTANCE) | ||
196 | LogiclanguagePackage.eINSTANCE.class | ||
197 | LogicproblemPackage.eINSTANCE.class | ||
198 | PartialinterpretationPackage.eINSTANCE.class | ||
199 | Ecore2logicannotationsPackage.eINSTANCE.class | ||
200 | Viatra2LogicAnnotationsPackage.eINSTANCE.class | ||
201 | Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put("ecore", new XMIResourceFactoryImpl) | ||
202 | Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put("logicproblem", new XMIResourceFactoryImpl) | ||
203 | Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put("partialinterpretation", | ||
204 | new XMIResourceFactoryImpl) | ||
205 | } | ||
206 | |||
207 | def static void main(String[] args) { | ||
208 | if (args.length != 2) { | ||
209 | System.err.println("Usage: <query> <model size>") | ||
210 | } | ||
211 | val monitoringQuery = MonitoringQuery.valueOf(args.get(0)) | ||
212 | val modelSize = Integer.parseInt(args.get(1)) | ||
213 | init() | ||
214 | val generator = new Modes3ModelGenerator(monitoringQuery, modelSize) | ||
215 | generator.generate() | ||
216 | } | ||
217 | |||
218 | private static enum MonitoringQuery { | ||
219 | closeTrains, | ||
220 | misalignedTurnout | ||
221 | } | ||
222 | } | ||
diff --git a/Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/run/Modes3UnitPropagationGenerator.xtend b/Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/run/Modes3UnitPropagationGenerator.xtend new file mode 100644 index 00000000..61bd2814 --- /dev/null +++ b/Domains/ca.mcgill.rtgmrt.example.modes3/src/modes3/run/Modes3UnitPropagationGenerator.xtend | |||
@@ -0,0 +1,205 @@ | |||
1 | package modes3.run | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic | ||
4 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic_Trace | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternGenerator | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.UnitPropagationPatternGenerator | ||
10 | import java.util.Map | ||
11 | import modes3.Modes3Package | ||
12 | import modes3.queries.ExtraInputOfTurnout | ||
13 | import modes3.queries.Output | ||
14 | import modes3.queries.TurnoutOutput | ||
15 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | ||
16 | import org.eclipse.xtend2.lib.StringConcatenationClient | ||
17 | |||
18 | class Modes3UnitPropagationGenerator implements UnitPropagationPatternGenerator { | ||
19 | static val MUST_NOT_CONNECTED_TO = "mustNotConnectedTo" | ||
20 | static val MUST_NOT_CONNECTED_TO_HELPER = "mustNotConnectedTo_helper" | ||
21 | static val MUST_NOT_TURNOUT_OUTPUT = "mustNotTurnoutOutput" | ||
22 | static val MUST_NOT_STRAIGHT = "mustNotStraight" | ||
23 | static val MUST_NOT_DIVERGENT = "mustNotDivergent" | ||
24 | |||
25 | val Type segmentType | ||
26 | val Type turnoutType | ||
27 | val Relation connectedToRelation | ||
28 | val Relation straightRelation | ||
29 | val Relation divergentRelation | ||
30 | |||
31 | new(extension Ecore2Logic ecore2Logic, Ecore2Logic_Trace ecore2LogicTrace) { | ||
32 | extension val Modes3Package = Modes3Package.eINSTANCE | ||
33 | segmentType = ecore2LogicTrace.TypeofEClass(segment) | ||
34 | turnoutType = ecore2LogicTrace.TypeofEClass(turnout) | ||
35 | connectedToRelation = ecore2LogicTrace.relationOfReference(segment_ConnectedTo) | ||
36 | straightRelation = ecore2LogicTrace.relationOfReference(turnout_Straight) | ||
37 | divergentRelation = ecore2LogicTrace.relationOfReference(turnout_Divergent) | ||
38 | } | ||
39 | |||
40 | override getMustPatterns() { | ||
41 | emptyMap | ||
42 | } | ||
43 | |||
44 | override getMustNotPatterns() { | ||
45 | #{ | ||
46 | connectedToRelation -> MUST_NOT_CONNECTED_TO, | ||
47 | straightRelation -> MUST_NOT_STRAIGHT, | ||
48 | divergentRelation -> MUST_NOT_DIVERGENT | ||
49 | } | ||
50 | } | ||
51 | |||
52 | override getAdditionalPatterns(extension PatternGenerator generator, Map<String, PQuery> fqnToPQuery) { | ||
53 | val StringConcatenationClient parameters = ''' | ||
54 | problem: LogicProblem, interpretation: PartialInterpretation, | ||
55 | source: DefinedElement, target: DefinedElement | ||
56 | ''' | ||
57 | |||
58 | val StringConcatenationClient commonParameterConstraints = ''' | ||
59 | find interpretation(problem, interpretation); | ||
60 | find mustExist(problem, interpretation, source); | ||
61 | find mustExist(problem, interpretation, target); | ||
62 | ''' | ||
63 | |||
64 | ''' | ||
65 | pattern «MUST_NOT_CONNECTED_TO_HELPER»(«parameters») { | ||
66 | // connectedToReflexive unit propagation | ||
67 | «commonParameterConstraints» | ||
68 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "source")» | ||
69 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
70 | source == target; | ||
71 | } or { | ||
72 | // tooManyInputsOfSegment unit propagation | ||
73 | «commonParameterConstraints» | ||
74 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "source")» | ||
75 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
76 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "input1")» | ||
77 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "input2")» | ||
78 | neg «typeIndexer.referInstanceOf(turnoutType, Modality.MAY, "source")» | ||
79 | «relationDefinitionIndexer.referPattern(fqnToPQuery.get(Output.instance.fullyQualifiedName), #["input1", "source"], Modality.MUST, true, false)» | ||
80 | «relationDefinitionIndexer.referPattern(fqnToPQuery.get(Output.instance.fullyQualifiedName), #["input2", "source"], Modality.MUST, true, false)» | ||
81 | input1 != input2; | ||
82 | input1 != target; | ||
83 | input2 != target; | ||
84 | } or { | ||
85 | // turnoutConnectedToBothOutputs unit propagation 1 | ||
86 | «commonParameterConstraints» | ||
87 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
88 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
89 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "divergent")» | ||
90 | «referRelation(straightRelation, "source", "target", Modality.MUST, fqnToPQuery)» | ||
91 | «referRelation(divergentRelation, "source", "divergent", Modality.MUST, fqnToPQuery)» | ||
92 | «referRelation(connectedToRelation, "source", "divergent", Modality.MUST, fqnToPQuery)» | ||
93 | } or { | ||
94 | // turnoutConnectedToBothOutputs unit propagation 2 | ||
95 | «commonParameterConstraints» | ||
96 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
97 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
98 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "straight")» | ||
99 | «referRelation(straightRelation, "source", "straight", Modality.MUST, fqnToPQuery)» | ||
100 | «referRelation(divergentRelation, "source", "target", Modality.MUST, fqnToPQuery)» | ||
101 | «referRelation(connectedToRelation, "source", "straight", Modality.MUST, fqnToPQuery)» | ||
102 | } or { | ||
103 | // tooManyExtraInputsOfTurnout unit propagation | ||
104 | «commonParameterConstraints» | ||
105 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
106 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
107 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "extraInput")» | ||
108 | «relationDefinitionIndexer.referPattern(fqnToPQuery.get(TurnoutOutput.instance.fullyQualifiedName), #["source", "target"], Modality.MAY, false, false)» | ||
109 | «relationDefinitionIndexer.referPattern(fqnToPQuery.get(ExtraInputOfTurnout.instance.fullyQualifiedName), #["source", "extraInput"], Modality.MUST, true, false)» | ||
110 | target != extraInput; | ||
111 | } | ||
112 | |||
113 | pattern «MUST_NOT_CONNECTED_TO»(«parameters») { | ||
114 | find «MUST_NOT_CONNECTED_TO_HELPER»(problem, interpretation, source, target); | ||
115 | } or { | ||
116 | find «MUST_NOT_CONNECTED_TO_HELPER»(problem, interpretation, target, source); | ||
117 | } | ||
118 | |||
119 | pattern «MUST_NOT_TURNOUT_OUTPUT»(«parameters») { | ||
120 | // outputReflexive unit propagation | ||
121 | «commonParameterConstraints» | ||
122 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
123 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "target")» | ||
124 | source == target; | ||
125 | } or { | ||
126 | // tooManyInputsOfSegment unit propagation | ||
127 | «commonParameterConstraints» | ||
128 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
129 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
130 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "input1")» | ||
131 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "input2")» | ||
132 | neg «typeIndexer.referInstanceOf(turnoutType, Modality.MAY, "target")» | ||
133 | «relationDefinitionIndexer.referPattern(fqnToPQuery.get(Output.instance.fullyQualifiedName), #["input1", "target"], Modality.MUST, true, false)» | ||
134 | «relationDefinitionIndexer.referPattern(fqnToPQuery.get(Output.instance.fullyQualifiedName), #["input2", "target"], Modality.MUST, true, false)» | ||
135 | input1 != input2; | ||
136 | input1 != source; | ||
137 | input2 != source; | ||
138 | } | ||
139 | |||
140 | pattern «MUST_NOT_STRAIGHT»(«parameters») { | ||
141 | find «MUST_NOT_TURNOUT_OUTPUT»(problem, interpretation, source, target); | ||
142 | } or { | ||
143 | // turnoutOutputsAreSame unit propagation | ||
144 | «commonParameterConstraints» | ||
145 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
146 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
147 | «referRelation(divergentRelation, "source", "target", Modality.MUST, fqnToPQuery)» | ||
148 | } or { | ||
149 | // turnoutConnectedToBothOutputs unit propagation | ||
150 | «commonParameterConstraints» | ||
151 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
152 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
153 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "divergent")» | ||
154 | «referRelation(connectedToRelation, "source", "target", Modality.MUST, fqnToPQuery)» | ||
155 | «referRelation(divergentRelation, "source", "divergent", Modality.MUST, fqnToPQuery)» | ||
156 | «referRelation(connectedToRelation, "source", "divergent", Modality.MUST, fqnToPQuery)» | ||
157 | } or { | ||
158 | // tooManyExtraInputsOfTurnout unit propagation | ||
159 | «commonParameterConstraints» | ||
160 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
161 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
162 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "extraInput")» | ||
163 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "potentialExtraInput")» | ||
164 | «relationDefinitionIndexer.referPattern(fqnToPQuery.get(ExtraInputOfTurnout.instance.fullyQualifiedName), #["source", "extraInput"], Modality.MUST, true, false)» | ||
165 | «referRelation(connectedToRelation, "source", "potentialExtraInput", Modality.MUST, fqnToPQuery)» | ||
166 | neg «referRelation(divergentRelation, "source", "potentialExtraInput", Modality.MAY, fqnToPQuery)» | ||
167 | extraInput != potentialExtraInput; | ||
168 | extraInput != target; | ||
169 | potentialExtraInput != target; | ||
170 | } | ||
171 | |||
172 | pattern «MUST_NOT_DIVERGENT»(«parameters») { | ||
173 | find «MUST_NOT_TURNOUT_OUTPUT»(problem, interpretation, source, target); | ||
174 | } or { | ||
175 | // turnoutOutputsAreSame unit propagation | ||
176 | «commonParameterConstraints» | ||
177 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
178 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
179 | «referRelation(straightRelation, "source", "target", Modality.MUST, fqnToPQuery)» | ||
180 | } or { | ||
181 | // turnoutConnectedToBothOutputs unit propagation | ||
182 | «commonParameterConstraints» | ||
183 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
184 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
185 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "straight")» | ||
186 | «referRelation(connectedToRelation, "source", "target", Modality.MUST, fqnToPQuery)» | ||
187 | «referRelation(straightRelation, "source", "straight", Modality.MUST, fqnToPQuery)» | ||
188 | «referRelation(connectedToRelation, "source", "straight", Modality.MUST, fqnToPQuery)» | ||
189 | } or { | ||
190 | // tooManyExtraInputsOfTurnout unit propagation | ||
191 | «commonParameterConstraints» | ||
192 | «typeIndexer.referInstanceOf(turnoutType, Modality.MUST, "source")» | ||
193 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "target")» | ||
194 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "extraInput")» | ||
195 | «typeIndexer.referInstanceOf(segmentType, Modality.MUST, "potentialExtraInput")» | ||
196 | «relationDefinitionIndexer.referPattern(fqnToPQuery.get(ExtraInputOfTurnout.instance.fullyQualifiedName), #["source", "extraInput"], Modality.MUST, true, false)» | ||
197 | «referRelation(connectedToRelation, "source", "potentialExtraInput", Modality.MUST, fqnToPQuery)» | ||
198 | neg «referRelation(straightRelation, "source", "potentialExtraInput", Modality.MAY, fqnToPQuery)» | ||
199 | extraInput != potentialExtraInput; | ||
200 | extraInput != target; | ||
201 | potentialExtraInput != target; | ||
202 | } | ||
203 | ''' | ||
204 | } | ||
205 | } | ||