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