aboutsummaryrefslogtreecommitdiffstats
path: root/Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend
diff options
context:
space:
mode:
Diffstat (limited to 'Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend')
-rw-r--r--Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend335
1 files changed, 69 insertions, 266 deletions
diff --git a/Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend b/Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend
index 3b828170..74e03f71 100644
--- a/Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend
+++ b/Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend
@@ -4,48 +4,36 @@ import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic
4import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic_Trace 4import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic_Trace
5import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicProblemBuilder 5import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicProblemBuilder
6import hu.bme.mit.inf.dslreasoner.logic.model.builder.TracedOutput 6import hu.bme.mit.inf.dslreasoner.logic.model.builder.TracedOutput
7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference
8import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.PrimitiveTypeReference
9import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition 7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition
10import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
11import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeReference
12import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Variable 8import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Variable
13import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem 9import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
14import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery 10import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery
15import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.Viatra2LogicAnnotationsFactory 11import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.Viatra2LogicAnnotationsFactory
16import java.util.ArrayList 12import java.util.ArrayList
17import java.util.HashMap 13import java.util.HashMap
18import java.util.HashSet
19import java.util.LinkedList 14import java.util.LinkedList
20import java.util.List 15import java.util.List
21import java.util.Map 16import java.util.Map
22import java.util.Set 17import java.util.Set
23import org.eclipse.emf.ecore.EAttribute 18import org.eclipse.emf.ecore.EAttribute
24import org.eclipse.emf.ecore.EClassifier
25import org.eclipse.emf.ecore.EEnum
26import org.eclipse.emf.ecore.EReference 19import org.eclipse.emf.ecore.EReference
27import org.eclipse.emf.ecore.EStructuralFeature 20import org.eclipse.emf.ecore.EStructuralFeature
28import org.eclipse.emf.ecore.EcorePackage 21import org.eclipse.emf.ecore.util.EcoreUtil
29import org.eclipse.viatra.query.runtime.api.IQuerySpecification 22import org.eclipse.viatra.query.runtime.api.IQuerySpecification
30import org.eclipse.viatra.query.runtime.emf.EMFQueryMetaContext 23import org.eclipse.viatra.query.runtime.emf.EMFQueryMetaContext
31import org.eclipse.viatra.query.runtime.emf.types.BaseEMFTypeKey
32import org.eclipse.viatra.query.runtime.emf.types.EClassTransitiveInstancesKey
33import org.eclipse.viatra.query.runtime.emf.types.EDataTypeInSlotsKey
34import org.eclipse.viatra.query.runtime.matchers.context.IInputKey
35import org.eclipse.viatra.query.runtime.matchers.context.common.JavaTransitiveInstancesKey
36import org.eclipse.viatra.query.runtime.matchers.planning.helpers.TypeHelper
37import org.eclipse.viatra.query.runtime.matchers.psystem.PBody 24import org.eclipse.viatra.query.runtime.matchers.psystem.PBody
25import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint
38import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable 26import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable
27import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.AggregatorConstraint
39import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall 28import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall
29import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.PatternMatchCounter
30import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PDisjunction
40import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter 31import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter
41import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery 32import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
42import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.PBodyNormalizer 33import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.PBodyNormalizer
43import org.eclipse.xtend.lib.annotations.Data 34import org.eclipse.xtend.lib.annotations.Data
44 35
45import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* 36import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
46import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PDisjunction
47import org.eclipse.emf.ecore.util.EcoreUtil
48import org.eclipse.viatra.query.runtime.emf.types.EClassUnscopedTransitiveInstancesKey
49 37
50@Data class ViatraQuerySetDescriptor { 38@Data class ViatraQuerySetDescriptor {
51 val List<? extends IQuerySpecification<?>> patterns 39 val List<? extends IQuerySpecification<?>> patterns
@@ -57,24 +45,24 @@ class Viatra2LogicTrace {
57 public val Map<PQuery, RelationDefinition> query2Relation = new HashMap 45 public val Map<PQuery, RelationDefinition> query2Relation = new HashMap
58 public val Map<PQuery, TransfomedViatraQuery> query2Annotation = new HashMap 46 public val Map<PQuery, TransfomedViatraQuery> query2Annotation = new HashMap
59 public val Map<Pair<PQuery,PParameter>, Variable> parameter2Variable = new HashMap 47 public val Map<Pair<PQuery,PParameter>, Variable> parameter2Variable = new HashMap
60 //public val Map<PVariable, Variable> variable2Variable = new HashMap
61} 48}
62class Viatra2LogicConfiguration { 49class Viatra2LogicConfiguration {
63 public var normalize = true 50 public var normalize = true
64 public var transitiveClosureDepth = 3
65} 51}
66 52
67class Viatra2Logic { 53class Viatra2Logic {
68 val extension LogicProblemBuilder builder = new LogicProblemBuilder 54 val extension LogicProblemBuilder builder = new LogicProblemBuilder
69 val extension Viatra2LogicAnnotationsFactory factory = Viatra2LogicAnnotationsFactory.eINSTANCE 55 val extension Viatra2LogicAnnotationsFactory factory = Viatra2LogicAnnotationsFactory.eINSTANCE
70 val normalizer = new PBodyNormalizer(EMFQueryMetaContext.DEFAULT) 56 val normalizer = new PBodyNormalizer(EMFQueryMetaContext.DEFAULT)
57 val Viatra2LogicTypeInferer typeInferer
71 58
72 val Ecore2Logic ecore2Logic 59 val Ecore2Logic ecore2Logic
73 Constraint2Logic constraint2Logic 60 Constraint2Logic constraint2Logic
74 61
75 new(Ecore2Logic ecore2Logic) { 62 new(Ecore2Logic ecore2Logic) {
76 this.ecore2Logic = ecore2Logic 63 this.ecore2Logic = ecore2Logic
77 constraint2Logic = new Constraint2Logic(ecore2Logic) 64 this.typeInferer = new Viatra2LogicTypeInferer(ecore2Logic)
65 this.constraint2Logic = new Constraint2Logic(ecore2Logic)
78 } 66 }
79 67
80 def TracedOutput<LogicProblem,Viatra2LogicTrace> transformQueries( 68 def TracedOutput<LogicProblem,Viatra2LogicTrace> transformQueries(
@@ -82,65 +70,55 @@ class Viatra2Logic {
82 TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, 70 TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace,
83 Viatra2LogicConfiguration config) 71 Viatra2LogicConfiguration config)
84 { 72 {
73 // Create trace
85 val viatra2LogicTrace = new Viatra2LogicTrace 74 val viatra2LogicTrace = new Viatra2LogicTrace
86 val typeAlanysis = new HashMap 75
76 // Translation works on PQueries. QuerySpecification -> PQuery.
87 val pQueries = queries.patterns.map[it.internalQueryRepresentation] 77 val pQueries = queries.patterns.map[it.internalQueryRepresentation]
88 78
89 for(query: pQueries) { 79 // If requested, the queries are normalized
90 val disjunction = normalizer.rewrite(query) 80 for(query: pQueries) {
81 val disjunction = normalizer.rewrite(query)
91 viatra2LogicTrace.query2Disjunction.put(query,disjunction) 82 viatra2LogicTrace.query2Disjunction.put(query,disjunction)
92 } 83 }
93 84
94 for(query: pQueries) { 85 // The types are calculated
95 val types = query.lookup(viatra2LogicTrace.query2Disjunction).bodies.toInvertedMap[ 86 val types = typeInferer.inferTypes(pQueries,ecore2LogicTrace,viatra2LogicTrace)
96 TypeHelper::inferUnaryTypesFor(it.uniqueVariables,it.constraints,EMFQueryMetaContext.DEFAULT)
97 ]
98// for(m : types.values) {
99// for(n: m.entrySet) {
100// val variable = n.key
101// println(''' - «variable.name»''')
102// for(type : n.value) {
103// println('''«variable.name» - «type»''')
104// }
105// }
106//
107// }
108
109 typeAlanysis.put(query,types)
110 }
111 87
88 // First, the signature of the queries are translated, ...
112 for(query: pQueries) { 89 for(query: pQueries) {
113 try { 90 try {
114 this.transformQueryHeader(query,query.lookup(typeAlanysis),ecore2LogicTrace,viatra2LogicTrace,config) 91 this.transformQueryHeader(query,types,ecore2LogicTrace,viatra2LogicTrace,config)
115 } catch(IllegalArgumentException e) { 92 } catch(IllegalArgumentException e) {
116 throw new IllegalArgumentException(''' 93 throw new IllegalArgumentException('''
117 Unable to translate query "«query.fullyQualifiedName»". 94 Unable to translate query "«query.fullyQualifiedName»".
118 Reason: «e.class.simpleName», «e.message»''',e) 95 Reason: «e.class.simpleName», «e.message»''',e)
119 } 96 }
120 } 97 }
98
99 // ...then the bodies, ...
121 for(query: pQueries) { 100 for(query: pQueries) {
122 try { 101 try {
123 this.transformQuerySpecification(query,query.lookup(typeAlanysis),ecore2LogicTrace,viatra2LogicTrace,config) 102 this.transformQuerySpecification(query,types,ecore2LogicTrace,viatra2LogicTrace,config)
124 } catch (IllegalArgumentException e){ 103 } catch (IllegalArgumentException e){
125 throw new IllegalArgumentException(''' 104 throw new IllegalArgumentException('''
126 Unable to translate query "«query.fullyQualifiedName»". 105 Unable to translate query "«query.fullyQualifiedName»".
127 Reason: «e.class.simpleName», «e.message»''',e) 106 Reason: «e.class.simpleName», «e.message»''',e)
128 } 107 }
129 } 108 }
130 /*for(d : viatra2LogicTrace.query2Relation.values) {
131 checkDefinition(d)
132 }*/
133 109
110 // ... and finally, the annotations.
134 transformQueryConstraints( 111 transformQueryConstraints(
135 queries.validationPatterns.map[internalQueryRepresentation], 112 queries.validationPatterns.map[internalQueryRepresentation],
136 queries.derivedFeatures, 113 queries.derivedFeatures,
137 ecore2LogicTrace,viatra2LogicTrace) 114 ecore2LogicTrace,viatra2LogicTrace)
115
138 return new TracedOutput(ecore2LogicTrace.output,viatra2LogicTrace) 116 return new TracedOutput(ecore2LogicTrace.output,viatra2LogicTrace)
139 } 117 }
140 118
141 def protected transformQueryHeader( 119 def protected transformQueryHeader(
142 PQuery pquery, 120 PQuery pquery,
143 Map<PBody, Map<PVariable, Set<IInputKey>>> types, 121 Viatra2LogicTypeResult types,
144 TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, 122 TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace,
145 Viatra2LogicTrace viatra2LogicTrace, 123 Viatra2LogicTrace viatra2LogicTrace,
146 Viatra2LogicConfiguration config) 124 Viatra2LogicConfiguration config)
@@ -149,7 +127,7 @@ class Viatra2Logic {
149 val parameters = new ArrayList<Variable>(pquery.parameters.size) 127 val parameters = new ArrayList<Variable>(pquery.parameters.size)
150 for(vParam: pquery.parameters) { 128 for(vParam: pquery.parameters) {
151 val parameterName = '''parameter «vParam.name»''' 129 val parameterName = '''parameter «vParam.name»'''
152 val parameterType = getType(vParam,types,ecore2LogicTrace) 130 val parameterType = types.getType(pquery,vParam)
153 if(parameterType === null) { 131 if(parameterType === null) {
154 throw new AssertionError('''null type for parameter «vParam.name» in pattern «pquery.fullyQualifiedName»''') 132 throw new AssertionError('''null type for parameter «vParam.name» in pattern «pquery.fullyQualifiedName»''')
155 } 133 }
@@ -166,6 +144,7 @@ class Viatra2Logic {
166 it.target = lRelation 144 it.target = lRelation
167 it.patternFullyQualifiedName = pquery.fullyQualifiedName 145 it.patternFullyQualifiedName = pquery.fullyQualifiedName
168 it.patternPQuery = pquery 146 it.patternPQuery = pquery
147 it.optimizedDisjunction = viatra2LogicTrace.query2Disjunction.get(pquery)
169 ] 148 ]
170 viatra2LogicTrace.query2Annotation.put(pquery,annotation) 149 viatra2LogicTrace.query2Annotation.put(pquery,annotation)
171 ecore2LogicTrace.output.annotations += annotation 150 ecore2LogicTrace.output.annotations += annotation
@@ -175,7 +154,7 @@ class Viatra2Logic {
175 154
176 def protected transformQuerySpecification( 155 def protected transformQuerySpecification(
177 PQuery pquery, 156 PQuery pquery,
178 Map<PBody, Map<PVariable, Set<IInputKey>>> types, 157 Viatra2LogicTypeResult types,
179 TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, 158 TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace,
180 Viatra2LogicTrace viatra2LogicTrace, 159 Viatra2LogicTrace viatra2LogicTrace,
181 Viatra2LogicConfiguration config) 160 Viatra2LogicConfiguration config)
@@ -233,7 +212,7 @@ class Viatra2Logic {
233 } 212 }
234 213
235 def transformBody(PBody body, 214 def transformBody(PBody body,
236 Map<PBody, Map<PVariable, Set<IInputKey>>> types, 215 Viatra2LogicTypeResult types,
237 TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, 216 TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace,
238 Viatra2LogicTrace viatra2LogicTrace, 217 Viatra2LogicTrace viatra2LogicTrace,
239 Viatra2LogicConfiguration config) 218 Viatra2LogicConfiguration config)
@@ -248,19 +227,33 @@ class Viatra2Logic {
248 // Inner Variables 227 // Inner Variables
249 val innerPositiveVariables = new LinkedList 228 val innerPositiveVariables = new LinkedList
250 val innerNegativeVariables = new LinkedList 229 val innerNegativeVariables = new LinkedList
230 val innerAggreatedVariables = new LinkedList
231 //println(body.uniqueVariables)
251 for(innerVariable : body.uniqueVariables) { 232 for(innerVariable : body.uniqueVariables) {
252 233
253 if(!variable2Variable.containsKey(innerVariable)) { 234 if(!variable2Variable.containsKey(innerVariable)) {
254 val name = '''variable «innerVariable.name.normalizeName»''' 235 if(innerVariable.aggregateOnly) {
255 //println(body.pattern.fullyQualifiedName + "-") 236 // do not create variable
256 val logicType = getType(innerVariable,types,ecore2LogicTrace) 237 innerAggreatedVariables.add(innerVariable)
257 val logicVariable = createVar(name,logicType) 238 variable2Variable.put(innerVariable,null)
258 if(innerVariable.isPositiveVariable) {
259 innerPositiveVariables += logicVariable
260 } else { 239 } else {
261 innerNegativeVariables += logicVariable 240 val name = '''variable «innerVariable.name.normalizeName»'''
241 val logicType = types.getType(body,innerVariable)
242 if(logicType === null) {
243 throw new IllegalArgumentException('''Variable «innerVariable.name.normalizeName» has no type!''')
244 }
245 val logicVariable = createVar(name,logicType)
246 if(innerVariable.negativeOnly) {
247 innerNegativeVariables += logicVariable
248 } else {
249 innerPositiveVariables += logicVariable
250 }
251 variable2Variable.put(innerVariable,logicVariable)
252 body.pattern.lookup(viatra2LogicTrace.query2Annotation).variableTrace += createVariableMapping=>[
253 it.sourcePVariable = innerVariable
254 it.targetLogicVariable = logicVariable
255 ]
262 } 256 }
263 variable2Variable.put(innerVariable,logicVariable)
264 } 257 }
265 } 258 }
266 259
@@ -279,229 +272,39 @@ class Viatra2Logic {
279 } else { 272 } else {
280 Exists(innerPositiveVariables,allNegativeVariablesAreSatisfied); 273 Exists(innerPositiveVariables,allNegativeVariablesAreSatisfied);
281 } 274 }
282 275
283 return allVariablesAreExisting 276 return allVariablesAreExisting
284 } 277 }
285// def toTypeJudgement(PVariable v, IInputKey key) {
286// new TypeJudgement(key,new Tuple1)
287// }
288 278
289 def private normalizeName(String variableName) { 279 def private normalizeName(String variableName) {
290 return variableName.replaceAll("[\\W]|_", "") 280 return variableName.replaceAll("[\\W]|_", "")
291 } 281 }
292
293 /**
294 * Translates the type of a parameter variable in a pattern
295 */
296 def TypeReference getType(PParameter v, Map<PBody, Map<PVariable, Set<IInputKey>>> types, TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) {
297 // If parameter type is specified then the specified type is used
298 if(v.declaredUnaryType !== null) {
299 val res = transformTypeReference(v.declaredUnaryType,ecore2LogicTrace)
300 if(res === null) {
301 throw new AssertionError('''
302 Unable to translate declared type «v.declaredUnaryType».
303 ''')
304 } else {
305 return res
306 }
307 }
308 // Otherwise, calculate the type based on the type of the variable in the bodies
309 else {
310 val bodies = types.keySet
311 val typesFromBodies = new ArrayList(bodies.size)
312 for(body : bodies) {
313 // collect the variable in the body
314 val exported = body.symbolicParameters.filter[it.patternParameter === v]
315 if(exported.size !== 1) {
316 throw new AssertionError('''Parameter «v.name» has no reference in body!''')
317 }
318 val variable = exported.head.parameterVariable
319 typesFromBodies+=variable.getType(types,ecore2LogicTrace)
320 }
321 return typesFromBodies.calculateCommonSupertype
322 }
323 }
324
325 /**
326 * Translates the type of a variable in a pattern body
327 */
328 def TypeReference getType(PVariable v, Map<PBody, Map<PVariable, Set<IInputKey>>> types ,TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) {
329 if (v.isPositiveVariable) {
330 val keys = getTypesFromCollection(v,types)
331 val logicTypes = keys.map[transformTypeReference(it,ecore2LogicTrace)].filterNull
332 return logicTypes.calculateCommonSubtype
333 } else {
334 val onlyConstraint = v.referringConstraints.head as NegativePatternCall
335 val indexOfVariable = v.lookup(onlyConstraint.actualParametersTuple.invertIndex)
336 val parameter = onlyConstraint.referredQuery.parameters.get(indexOfVariable)
337 val declaredUnaryType = parameter.declaredUnaryType as BaseEMFTypeKey<? extends EClassifier>
338 if (declaredUnaryType === null) {
339 throw new UnsupportedOperationException(
340 '''parameter «parameter.name» in pattern «onlyConstraint.referredQuery.fullyQualifiedName» does not have type!''')
341 } else
342 return declaredUnaryType.transformTypeReference(ecore2LogicTrace)
343 }
344 }
345
346 def getTypesFromCollection(PVariable v, Map<PBody, Map<PVariable, Set<IInputKey>>> types) {
347 for(entry : types.entrySet) {
348 if(entry.key.uniqueVariables.contains(v)) {
349 return v.lookup(entry.value)
350 }
351 }
352 throw new IllegalArgumentException('''Variable «v.name» is not present in neither of the bodies!''')
353 }
354
355 282
356 def TypeReference calculateCommonSubtype(Iterable<TypeReference> types) { 283 def isNegativeOnly(PVariable variable) {
357 val primitiveTypeReferences = types.filter(PrimitiveTypeReference) 284 if(variable.referringConstraints.size == 1) {
358 val complexTypeReferences = types.filter(ComplexTypeReference) 285 val PConstraint onlyConstraint = variable.referringConstraints.head
359 if(complexTypeReferences.isEmpty) { 286 if(onlyConstraint instanceof NegativePatternCall) {
360 val head = primitiveTypeReferences.head 287 return true
361 if(primitiveTypeReferences.exists[it.eClass !== head.eClass]) { 288 } else {
362 throw new IllegalArgumentException('''Inconsistent types: «primitiveTypeReferences.map[eClass.name].toSet.toList»''') 289 return false
363 }
364 return head
365 } else if(primitiveTypeReferences.isEmpty) {
366 val complexTypes = complexTypeReferences.map[it.referred].toSet
367 if(complexTypes.size === 1) {
368 return builder.toTypeReference(complexTypes.head)
369 }
370 // Collect possible subtypes
371 val subtypeSets = complexTypes.map[it.transitiveClosureStar[it.subtypes].toSet]
372 val commonTypeSet = new HashSet(subtypeSets.head)
373 val otherSets = subtypeSets.tail
374 for(otherSet : otherSets) {
375 commonTypeSet.retainAll(otherSet)
376 }
377 if(commonTypeSet.empty) {
378 throw new IllegalArgumentException('''Inconsistent types: «complexTypes.map[name].toList»''')
379 }
380
381 return calculateCommonComplexSupertype(commonTypeSet)
382
383 } else {
384 throw new IllegalArgumentException('''
385 Inconsistent types, mixing primitive and complex types:
386 «primitiveTypeReferences.map[eClass.name].toSet.toList»
387 and
388 «complexTypeReferences.map[it.referred].toSet.map[name].toList»''')
389
390 }
391 }
392 def TypeReference calculateCommonSupertype(Iterable<TypeReference> types) {
393 val primitiveTypeReferences = types.filter(PrimitiveTypeReference)
394 val complexTypeReferences = types.filter(ComplexTypeReference)
395 if(complexTypeReferences.isEmpty) {
396 val head = primitiveTypeReferences.head
397 if(primitiveTypeReferences.exists[it.eClass !== head.eClass]) {
398 throw new IllegalArgumentException('''Inconsistent types: «primitiveTypeReferences.map[eClass.name].toSet.toList»''')
399 }
400 return head
401 } else if(primitiveTypeReferences.isEmpty) {
402 val complexTypes = complexTypeReferences.map[it.referred].toSet
403 return calculateCommonComplexSupertype(complexTypes)
404
405 } else {
406 throw new IllegalArgumentException('''
407 Inconsistent types, mixing primitive and complex types:
408 «primitiveTypeReferences.map[eClass.name].toSet.toList»
409 and
410 «complexTypeReferences.map[it.referred].toSet.map[name].toList»''')
411
412 }
413 }
414 def TypeReference calculateCommonComplexSupertype(Set<Type> complexTypes) {
415 if(complexTypes.size === 1) {
416 return builder.toTypeReference(complexTypes.head)
417 }
418 // Collect possible supertypes
419 val supertypeSets = complexTypes.map[it.transitiveClosureStar[it.supertypes].toSet]
420 val commonTypeSet = new HashSet(supertypeSets.head)
421 val otherSets = supertypeSets.tail
422 for(otherSet : otherSets) {
423 commonTypeSet.retainAll(otherSet)
424 }
425 if(commonTypeSet.empty) {
426 throw new IllegalArgumentException('''Inconsistent types: «complexTypes.map[name].toList»''')
427 }
428 // Remove type that already have covered
429 val coveredTypes = commonTypeSet.map[it.supertypes].flatten
430 commonTypeSet.removeAll(coveredTypes)
431 return builder.toTypeReference(commonTypeSet.head)
432 }
433
434 /**
435 * Transforms a Viatra type reference to a logic type.
436 */
437 def dispatch TypeReference transformTypeReference(EDataTypeInSlotsKey k,TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) {
438 val w = k.wrappedKey
439 if(w == EcorePackage.Literals.EINT || w == EcorePackage.Literals.ESHORT || w == EcorePackage.Literals.ELONG) {
440 return builder.LogicInt
441 } else if(w == EcorePackage.Literals.EDOUBLE || w == EcorePackage.Literals.EFLOAT) {
442 return builder.LogicReal
443 } else if(w == EcorePackage.Literals.EBOOLEAN) {
444 return builder.LogicBool
445 } else if(w == EcorePackage.Literals.ESTRING) {
446 return builder.LogicString
447 } else if(w instanceof EEnum) {
448 val c = this.ecore2Logic.TypeofEEnum(ecore2LogicTrace.trace,w)
449 return builder.toTypeReference(c);
450 } else throw new UnsupportedOperationException('''Unknown reference type «w.class.name»''')
451 }
452 def dispatch TypeReference transformTypeReference(JavaTransitiveInstancesKey k,TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) {
453 val c = k.wrapperInstanceClass
454 if(c == Integer || c == Long || c == Short) {
455 return LogicInt
456 } else if(c == Float || c == Double) {
457 return LogicReal
458 } else if(c == Boolean) {
459 return LogicBool
460 } else if(c == String) {
461 return LogicString
462 } else if(c.superclass == java.lang.Enum){
463 val enums = ecore2Logic.allEnumsInScope(ecore2LogicTrace.trace)
464 for(enum : enums) {
465 if(c == enum.instanceClass) {
466 return builder.toTypeReference(ecore2Logic.TypeofEEnum(ecore2LogicTrace.trace,enum))
467 }
468 } 290 }
469 throw new IllegalArgumentException('''Enum type «c.simpleName» is not mapped to logic!''')
470 }
471 return null
472 }
473 def dispatch TypeReference transformTypeReference(EClassTransitiveInstancesKey k,TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) {
474 val c = k.wrappedKey
475
476 if(this.ecore2Logic.allClassesInScope(ecore2LogicTrace.trace).toList.contains(c)) {
477 return builder.toTypeReference(this.ecore2Logic.TypeofEClass(ecore2LogicTrace.trace,k.wrappedKey))
478 } else { 291 } else {
479 return null 292 return false
480 } 293 }
481 } 294 }
482 def dispatch TypeReference transformTypeReference(EClassUnscopedTransitiveInstancesKey k, TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) {
483 val c = k.wrappedKey
484
485 if(this.ecore2Logic.allClassesInScope(ecore2LogicTrace.trace).toList.contains(c)) {
486 return builder.toTypeReference(this.ecore2Logic.TypeofEClass(ecore2LogicTrace.trace,k.wrappedKey))
487 } else {
488 return null
489 }
490 }
491
492 def dispatch TypeReference transformTypeReference(IInputKey k,TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) {
493 //println(k)
494 throw new IllegalArgumentException('''Unsupported type: «k.class.simpleName»''')
495 }
496 295
497 def boolean isPositiveVariable(PVariable v) { 296 def isAggregateOnly(PVariable variable) {
498 val constraints = v.referringConstraints 297 if(variable.referringConstraints.size == 1) {
499 if(constraints.size == 1) { 298 val PConstraint onlyConstraint = variable.referringConstraints.head
500 val onlyConstraint = constraints.head 299 if(onlyConstraint instanceof AggregatorConstraint) {
501 if(onlyConstraint instanceof NegativePatternCall) { 300 return true
301 } else if(onlyConstraint instanceof PatternMatchCounter) {
302 return true
303 } else {
502 return false 304 return false
503 } 305 }
306 } else {
307 return false
504 } 308 }
505 return true
506 } 309 }
507} \ No newline at end of file 310} \ No newline at end of file