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.xtend156
1 files changed, 156 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..abf65be3
--- /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,156 @@
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 Relation inverseRelation
24 boolean containment
25 boolean container
26 int lowerBound
27 int upperBound
28 int inverseUpperBound
29
30 def isUpperBoundFinite() {
31 upperBound >= 0
32 }
33
34 private def isInverseUpperBoundFinite() {
35 inverseUpperBound >= 0
36 }
37
38 private def canHaveMultipleSourcesPerTarget() {
39 inverseUpperBound != 1
40 }
41
42 def constrainsUnfinished() {
43 lowerBound >= 1 && (!container || lowerBound >= 2)
44 }
45
46 def constrainsUnrepairable() {
47 // TODO Optimize the unrepairable matches computation,
48 // or come up with a heuristic when does computing unrepairables worth the overhead.
49 false && constrainsUnfinished && canHaveMultipleSourcesPerTarget && reference
50 }
51
52 def constrainsRemainingInverse() {
53 lowerBound >= 1 && !containment && !container && inverseUpperBoundFinite && reference
54 }
55
56 def constrainsRemainingContents() {
57 containment
58 }
59
60 def isActive() {
61 constrainsUnfinished || constrainsUnrepairable || constrainsRemainingInverse || constrainsRemainingContents
62 }
63
64 def isSourceTypeComplex() {
65 getParamTypeReference(0) instanceof ComplexTypeReference
66 }
67
68 def isTargetTypeComplex() {
69 getParamTypeReference(1) instanceof ComplexTypeReference
70 }
71
72 def isReference() {
73 sourceTypeComplex && targetTypeComplex
74 }
75
76 def getSourceType() {
77 getParamType(0)
78 }
79
80 def getTargetType() {
81 getParamType(1)
82 }
83
84 private def getParamTypeReference(int i) {
85 val parameters = relation.parameters
86 if (i < parameters.size) {
87 return parameters.get(i)
88 }
89 throw new IllegalArgumentException("Argument index out of range")
90 }
91
92 private def getParamType(int i) {
93 val reference = getParamTypeReference(i)
94 if (reference instanceof ComplexTypeReference) {
95 return reference.referred
96 }
97 throw new IllegalArgumentException("Constraint with primitive type")
98 }
99}
100
101class RelationConstraintCalculator {
102 def calculateRelationConstraints(LogicProblem problem) {
103 val containmentRelations = switch (problem.containmentHierarchies.size) {
104 case 0:
105 <Relation>emptySet
106 case 1:
107 ImmutableSet.copyOf(problem.containmentHierarchies.head.containmentRelations)
108 default:
109 throw new IllegalArgumentException("Only a single containment hierarchy is supported")
110 }
111 val inverseRelations = new HashMap<Relation, Relation>
112 val lowerMultiplicities = new HashMap<Relation, Integer>
113 val upperMultiplicities = new HashMap<Relation, Integer>
114 for (relation : problem.relations) {
115 lowerMultiplicities.put(relation, 0)
116 upperMultiplicities.put(relation, -1)
117 }
118 for (annotation : problem.annotations) {
119 switch (annotation) {
120 InverseRelationAssertion: {
121 inverseRelations.put(annotation.inverseA, annotation.inverseB)
122 inverseRelations.put(annotation.inverseB, annotation.inverseA)
123 }
124 LowerMultiplicityAssertion:
125 lowerMultiplicities.put(annotation.relation, annotation.lower)
126 UpperMultiplicityAssertion:
127 upperMultiplicities.put(annotation.relation, annotation.upper)
128 }
129 }
130 val multiplicityConstraintsBuilder = ImmutableList.builder()
131 for (relation : problem.relations) {
132 val containment = containmentRelations.contains(relation)
133 val lowerMultiplicity = lowerMultiplicities.get(relation)
134 val upperMultiplicity = upperMultiplicities.get(relation)
135 var container = false
136 var inverseUpperMultiplicity = -1
137 val inverseRelation = inverseRelations.get(relation)
138 if (inverseRelation !== null) {
139 inverseUpperMultiplicity = upperMultiplicities.get(inverseRelation)
140 container = containmentRelations.contains(inverseRelation)
141 }
142 if (containment) {
143 inverseUpperMultiplicity = 1
144 }
145 val constraint = new RelationMultiplicityConstraint(relation, inverseRelation, containment, container,
146 lowerMultiplicity, upperMultiplicity, inverseUpperMultiplicity)
147 if (constraint.isActive) {
148 if (relation.parameters.size != 2) {
149 throw new IllegalArgumentException('''Relation «relation.name» has multiplicity or containment constraints, but it is not binary''')
150 }
151 multiplicityConstraintsBuilder.add(constraint)
152 }
153 }
154 new RelationConstraints(multiplicityConstraintsBuilder.build)
155 }
156}