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 | 137 |
1 files changed, 137 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..c92260ea --- /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,137 @@ | |||
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 | 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 && false | ||
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 | |||
82 | class 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(inverseRelation) | ||
121 | container = containmentRelations.contains(inverseRelation) | ||
122 | } | ||
123 | if (containment) { | ||
124 | inverseUpperMultiplicity = 1 | ||
125 | } | ||
126 | val constraint = new RelationMultiplicityConstraint(relation, inverseRelation, containment, container, | ||
127 | lowerMultiplicity, upperMultiplicity, inverseUpperMultiplicity) | ||
128 | if (constraint.isActive) { | ||
129 | if (relation.parameters.size != 2) { | ||
130 | throw new IllegalArgumentException('''Relation «relation.name» has multiplicity or containment constraints, but it is not binary''') | ||
131 | } | ||
132 | multiplicityConstraintsBuilder.add(constraint) | ||
133 | } | ||
134 | } | ||
135 | new RelationConstraints(multiplicityConstraintsBuilder.build) | ||
136 | } | ||
137 | } | ||