diff options
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.xtend | 133 |
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 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import com.google.common.collect.ImmutableSet | ||
5 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.InverseRelationAssertion | ||
6 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion | ||
7 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.UpperMultiplicityAssertion | ||
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | ||
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | ||
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
11 | import java.util.HashMap | ||
12 | import java.util.List | ||
13 | import org.eclipse.xtend.lib.annotations.Data | ||
14 | |||
15 | @Data | ||
16 | class RelationConstraints { | ||
17 | val List<RelationMultiplicityConstraint> multiplicityConstraints | ||
18 | } | ||
19 | |||
20 | @Data | ||
21 | class 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 | |||
81 | class 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 | } | ||