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 | 139 |
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 @@ | |||
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 | // 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 | |||
84 | class 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 | } | ||