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.xtend134
1 files changed, 134 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..52a390a8
--- /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,134 @@
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 constrainsUnfinished && canHaveMultipleSourcesPerTarget
48 }
49
50 def constrainsRemainingInverse() {
51 lowerBound >= 1 && !containment && inverseUpperBoundFinite
52 }
53
54 def constrainsRemainingContents() {
55 containment
56 }
57
58 def isActive() {
59 constrainsUnfinished || constrainsUnrepairable || constrainsRemainingInverse || constrainsRemainingContents
60 }
61
62 def getSourceType() {
63 getParamType(0)
64 }
65
66 def getTargetType() {
67 getParamType(1)
68 }
69
70 private def getParamType(int i) {
71 val parameters = relation.parameters
72 if (i < parameters.size) {
73 val firstParam = parameters.get(i)
74 if (firstParam instanceof ComplexTypeReference) {
75 return firstParam.referred
76 }
77 }
78 throw new IllegalArgumentException("Constraint with unknown source type")
79 }
80}
81
82class RelationConstraintCalculator {
83 def calculateRelationConstraints(LogicProblem problem) {
84 val containmentRelations = switch (problem.containmentHierarchies.size) {
85 case 0:
86 <Relation>emptySet
87 case 1:
88 ImmutableSet.copyOf(problem.containmentHierarchies.head.containmentRelations)
89 default:
90 throw new IllegalArgumentException("Only a single containment hierarchy is supported")
91 }
92 val inverseRelations = new HashMap<Relation, Relation>
93 val lowerMultiplicities = new HashMap<Relation, Integer>
94 val upperMultiplicities = new HashMap<Relation, Integer>
95 for (relation : problem.relations) {
96 lowerMultiplicities.put(relation, 0)
97 upperMultiplicities.put(relation, -1)
98 }
99 for (annotation : problem.annotations) {
100 switch (annotation) {
101 InverseRelationAssertion: {
102 inverseRelations.put(annotation.inverseA, annotation.inverseB)
103 inverseRelations.put(annotation.inverseB, annotation.inverseA)
104 }
105 LowerMultiplicityAssertion:
106 lowerMultiplicities.put(annotation.relation, annotation.lower)
107 UpperMultiplicityAssertion:
108 upperMultiplicities.put(annotation.relation, annotation.upper)
109 }
110 }
111 val multiplicityConstraintsBuilder = ImmutableList.builder()
112 for (relation : problem.relations) {
113 val containment = containmentRelations.contains(relation)
114 val lowerMultiplicity = lowerMultiplicities.get(relation)
115 val upperMultiplicity = upperMultiplicities.get(relation)
116 var container = false
117 var inverseUpperMultiplicity = -1
118 val inverseRelation = inverseRelations.get(relation)
119 if (inverseRelation !== null) {
120 inverseUpperMultiplicity = upperMultiplicities.get(relation)
121 container = containmentRelations.contains(inverseRelation)
122 }
123 val constraint = new RelationMultiplicityConstraint(relation, inverseRelation, containment, container,
124 lowerMultiplicity, upperMultiplicity, inverseUpperMultiplicity)
125 if (constraint.isActive) {
126 if (relation.parameters.size != 2) {
127 throw new IllegalArgumentException('''Relation «relation.name» has multiplicity or containment constraints, but it is not binary''')
128 }
129 multiplicityConstraintsBuilder.add(constraint)
130 }
131 }
132 new RelationConstraints(multiplicityConstraintsBuilder.build)
133 }
134}