aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java')
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java138
1 files changed, 137 insertions, 1 deletions
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java
index fbf8a7c9..ebe0d1b9 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java
@@ -5,5 +5,141 @@
5 */ 5 */
6package tools.refinery.store.reasoning.translator.typehierarchy; 6package tools.refinery.store.reasoning.translator.typehierarchy;
7 7
8sealed interface TypeAnalysisResult permits EliminatedType, PreservedType { 8import tools.refinery.store.reasoning.representation.PartialRelation;
9import tools.refinery.store.representation.TruthValue;
10
11import java.util.*;
12
13public final class TypeAnalysisResult {
14 private final ExtendedTypeInfo extendedTypeInfo;
15 private final List<PartialRelation> directSubtypes;
16 private final List<ExtendedTypeInfo> allExternalTypeInfoList;
17 private final InferredType inferredType;
18
19 public TypeAnalysisResult(ExtendedTypeInfo extendedTypeInfo, List<ExtendedTypeInfo> allExternalTypeInfoList) {
20 this.extendedTypeInfo = extendedTypeInfo;
21 directSubtypes = List.copyOf(extendedTypeInfo.getDirectSubtypes());
22 this.allExternalTypeInfoList = allExternalTypeInfoList;
23 inferredType = propagateMust(extendedTypeInfo.getAllSupertypesAndSelf(),
24 extendedTypeInfo.getConcreteSubtypesAndSelf());
25 }
26
27 public PartialRelation type() {
28 return extendedTypeInfo.getType();
29 }
30
31 public List<PartialRelation> getDirectSubtypes() {
32 return directSubtypes;
33 }
34
35 public boolean isAbstractType() {
36 return extendedTypeInfo.isAbstractType();
37 }
38
39 public boolean isVacuous() {
40 return isAbstractType() && directSubtypes.isEmpty();
41 }
42
43 public InferredType asInferredType() {
44 return inferredType;
45 }
46
47 public boolean isSubtypeOf(TypeAnalysisResult other) {
48 return extendedTypeInfo.getAllSubtypes().contains(other.type());
49 }
50
51 public InferredType merge(InferredType inferredType, TruthValue value) {
52 return switch (value) {
53 case UNKNOWN -> inferredType;
54 case TRUE -> addMust(inferredType);
55 case FALSE -> removeMay(inferredType);
56 case ERROR -> addError(inferredType);
57 };
58 }
59
60 private InferredType addMust(InferredType inferredType) {
61 var originalMustTypes = inferredType.mustTypes();
62 if (originalMustTypes.contains(type())) {
63 return inferredType;
64 }
65 var mustTypes = new HashSet<>(originalMustTypes);
66 extendedTypeInfo.addMust(mustTypes);
67 var originalMayConcreteTypes = inferredType.mayConcreteTypes();
68 var mayConcreteTypes = new LinkedHashSet<>(originalMayConcreteTypes);
69 Set<PartialRelation> mayConcreteTypesResult;
70 if (mayConcreteTypes.retainAll(extendedTypeInfo.getConcreteSubtypesAndSelf())) {
71 mayConcreteTypesResult = mayConcreteTypes;
72 } else {
73 mayConcreteTypesResult = originalMayConcreteTypes;
74 }
75 return propagateMust(mustTypes, mayConcreteTypesResult);
76 }
77
78 private InferredType removeMay(InferredType inferredType) {
79 var originalMayConcreteTypes = inferredType.mayConcreteTypes();
80 var mayConcreteTypes = new LinkedHashSet<>(originalMayConcreteTypes);
81 if (!mayConcreteTypes.removeAll(extendedTypeInfo.getConcreteSubtypesAndSelf())) {
82 return inferredType;
83 }
84 return propagateMust(inferredType.mustTypes(), mayConcreteTypes);
85 }
86
87 private InferredType addError(InferredType inferredType) {
88 var originalMustTypes = inferredType.mustTypes();
89 if (originalMustTypes.contains(type())) {
90 if (inferredType.mayConcreteTypes().isEmpty()) {
91 return inferredType;
92 }
93 return new InferredType(originalMustTypes, Set.of(), null);
94 }
95 var mustTypes = new HashSet<>(originalMustTypes);
96 extendedTypeInfo.addMust(mustTypes);
97 return new InferredType(mustTypes, Set.of(), null);
98 }
99
100 private InferredType propagateMust(Set<PartialRelation> originalMustTypes,
101 Set<PartialRelation> mayConcreteTypes) {
102 // It is possible that there is not type at all, do not force one by propagation.
103 var maybeUntyped = originalMustTypes.isEmpty();
104 // Para-consistent case, do not propagate must types to avoid logical explosion.
105 var paraConsistentOrSurelyUntyped = mayConcreteTypes.isEmpty();
106 if (maybeUntyped || paraConsistentOrSurelyUntyped) {
107 return new InferredType(originalMustTypes, mayConcreteTypes, null);
108 }
109 var currentType = computeCurrentType(mayConcreteTypes);
110 var mustTypes = new HashSet<>(originalMustTypes);
111 boolean changed = false;
112 for (var newMustExtendedTypeInfo : allExternalTypeInfoList) {
113 var newMustType = newMustExtendedTypeInfo.getType();
114 if (mustTypes.contains(newMustType)) {
115 continue;
116 }
117 if (newMustExtendedTypeInfo.allowsAllConcreteTypes(mayConcreteTypes)) {
118 newMustExtendedTypeInfo.addMust(mustTypes);
119 changed = true;
120 }
121 }
122 if (!changed) {
123 return new InferredType(originalMustTypes, mayConcreteTypes, currentType);
124 }
125 return new InferredType(mustTypes, mayConcreteTypes, currentType);
126 }
127
128 /**
129 * Returns a concrete type that is allowed by a (consistent, i.e., nonempty) set of <b>may</b> concrete types.
130 *
131 * @param mayConcreteTypes The set of allowed concrete types. Must not be empty.
132 * @return The first concrete type that is allowed by {@code matConcreteTypes}.
133 */
134 private PartialRelation computeCurrentType(Set<PartialRelation> mayConcreteTypes) {
135 for (var concreteExtendedTypeInfo : allExternalTypeInfoList) {
136 var concreteType = concreteExtendedTypeInfo.getType();
137 if (!concreteExtendedTypeInfo.isAbstractType() && mayConcreteTypes.contains(concreteType)) {
138 return concreteType;
139 }
140 }
141 // We have already filtered out the para-consistent case in {@link #propagateMust(Set<PartialRelation>,
142 // Set<PartialRelation>}.
143 throw new AssertionError("No concrete type in %s".formatted(mayConcreteTypes));
144 }
9} 145}