aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend
diff options
context:
space:
mode:
Diffstat (limited to 'Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend')
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend133
1 files changed, 133 insertions, 0 deletions
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend
new file mode 100644
index 00000000..ffa9e6e6
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend
@@ -0,0 +1,133 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import com.google.common.collect.ImmutableList
4import com.google.common.collect.ImmutableSet
5import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.InverseRelationAssertion
6import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion
7import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.UpperMultiplicityAssertion
8import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference
9import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
10import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
11import java.util.HashMap
12import java.util.List
13import org.eclipse.xtend.lib.annotations.Data
14
15@Data
16class RelationConstraints {
17 val List<RelationMultiplicityConstraint> multiplicityConstraints
18}
19
20@Data
21class RelationMultiplicityConstraint {
22 Relation relation
23 boolean containment
24 boolean container
25 int lowerBound
26 int upperBound
27 int inverseUpperBound
28
29 def isUpperBoundFinite() {
30 upperBound >= 0
31 }
32
33 private def isInverseUpperBoundFinite() {
34 inverseUpperBound >= 0
35 }
36
37 private def canHaveMultipleSourcesPerTarget() {
38 inverseUpperBound != 1
39 }
40
41 def constrainsUnfinished() {
42 lowerBound >= 1 && (!container || lowerBound >= 2)
43 }
44
45 def constrainsUnrepairable() {
46 constrainsUnfinished && canHaveMultipleSourcesPerTarget
47 }
48
49 def constrainsRemainingInverse() {
50 !containment && inverseUpperBoundFinite
51 }
52
53 def constrainsRemainingContents() {
54 containment
55 }
56
57 def isActive() {
58 constrainsUnfinished || constrainsUnrepairable || constrainsRemainingInverse || constrainsRemainingContents
59 }
60
61 def getSourceType() {
62 getParamType(0)
63 }
64
65 def getTargetType() {
66 getParamType(1)
67 }
68
69 private def getParamType(int i) {
70 val parameters = relation.parameters
71 if (i < parameters.size) {
72 val firstParam = parameters.get(i)
73 if (firstParam instanceof ComplexTypeReference) {
74 return firstParam.referred
75 }
76 }
77 throw new IllegalArgumentException("Constraint with unknown source type")
78 }
79}
80
81class RelationConstraintCalculator {
82 def calculateRelationConstraints(LogicProblem problem) {
83 val containmentRelations = switch (problem.containmentHierarchies.size) {
84 case 0:
85 <Relation>emptySet
86 case 1:
87 ImmutableSet.copyOf(problem.containmentHierarchies.head.containmentRelations)
88 default:
89 throw new IllegalArgumentException("Only a single containment hierarchy is supported")
90 }
91 val inverseRelations = new HashMap<Relation, Relation>
92 val lowerMultiplicities = new HashMap<Relation, Integer>
93 val upperMultiplicities = new HashMap<Relation, Integer>
94 for (relation : problem.relations) {
95 lowerMultiplicities.put(relation, 0)
96 upperMultiplicities.put(relation, -1)
97 }
98 for (annotation : problem.annotations) {
99 switch (annotation) {
100 InverseRelationAssertion: {
101 inverseRelations.put(annotation.inverseA, annotation.inverseB)
102 inverseRelations.put(annotation.inverseB, annotation.inverseA)
103 }
104 LowerMultiplicityAssertion:
105 lowerMultiplicities.put(annotation.relation, annotation.lower)
106 UpperMultiplicityAssertion:
107 upperMultiplicities.put(annotation.relation, annotation.upper)
108 }
109 }
110 val multiplicityConstraintsBuilder = ImmutableList.builder()
111 for (relation : problem.relations) {
112 val containment = containmentRelations.contains(relation)
113 val lowerMultiplicity = lowerMultiplicities.get(relation)
114 val upperMultiplicity = upperMultiplicities.get(relation)
115 var container = false
116 var inverseUpperMultiplicity = -1
117 val inverseRelation = inverseRelations.get(relation)
118 if (inverseRelation !== null) {
119 inverseUpperMultiplicity = upperMultiplicities.get(relation)
120 container = containmentRelations.contains(inverseRelation)
121 }
122 val constraint = new RelationMultiplicityConstraint(relation, containment, container, lowerMultiplicity,
123 upperMultiplicity, inverseUpperMultiplicity)
124 if (constraint.isActive) {
125 if (relation.parameters.size != 2) {
126 throw new IllegalArgumentException('''Relation «relation.name» has multiplicity or containment constraints, but it is not binary''')
127 }
128 multiplicityConstraintsBuilder.add(constraint)
129 }
130 }
131 new RelationConstraints(multiplicityConstraintsBuilder.build)
132 }
133}