diff options
Diffstat (limited to 'subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/ScopePropagator.java')
-rw-r--r-- | subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/ScopePropagator.java | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/ScopePropagator.java b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/ScopePropagator.java new file mode 100644 index 00000000..25b1966c --- /dev/null +++ b/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/ScopePropagator.java | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.reasoning.scope; | ||
7 | |||
8 | import com.google.ortools.Loader; | ||
9 | import tools.refinery.store.dse.propagation.PropagationBuilder; | ||
10 | import tools.refinery.store.model.ModelStoreBuilder; | ||
11 | import tools.refinery.store.model.ModelStoreConfiguration; | ||
12 | import tools.refinery.store.reasoning.representation.PartialRelation; | ||
13 | import tools.refinery.store.reasoning.translator.TranslationException; | ||
14 | import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; | ||
15 | import tools.refinery.store.representation.Symbol; | ||
16 | import tools.refinery.store.representation.cardinality.CardinalityInterval; | ||
17 | import tools.refinery.store.representation.cardinality.FiniteUpperCardinality; | ||
18 | |||
19 | import java.util.*; | ||
20 | |||
21 | public class ScopePropagator implements ModelStoreConfiguration { | ||
22 | private final Symbol<CardinalityInterval> countSymbol; | ||
23 | private final Map<PartialRelation, CardinalityInterval> scopes = new LinkedHashMap<>(); | ||
24 | private final List<TypeScopePropagator.Factory> typeScopePropagatorFactories = new ArrayList<>(); | ||
25 | |||
26 | public ScopePropagator() { | ||
27 | this(MultiObjectTranslator.COUNT_STORAGE); | ||
28 | } | ||
29 | |||
30 | public ScopePropagator(Symbol<CardinalityInterval> countSymbol) { | ||
31 | if (countSymbol.arity() != 1) { | ||
32 | throw new IllegalArgumentException("Count symbol must have arty 1, got %s with arity %d instead" | ||
33 | .formatted(countSymbol, countSymbol.arity())); | ||
34 | } | ||
35 | if (!countSymbol.valueType().equals(CardinalityInterval.class)) { | ||
36 | throw new IllegalArgumentException("Count symbol must have CardinalityInterval values"); | ||
37 | } | ||
38 | if (countSymbol.defaultValue() != null) { | ||
39 | throw new IllegalArgumentException("Count symbol must default value null"); | ||
40 | } | ||
41 | this.countSymbol = countSymbol; | ||
42 | } | ||
43 | |||
44 | public ScopePropagator scope(PartialRelation type, CardinalityInterval interval) { | ||
45 | if (type.arity() != 1) { | ||
46 | throw new TranslationException(type, "Only types with arity 1 may have scopes, got %s with arity %d" | ||
47 | .formatted(type, type.arity())); | ||
48 | } | ||
49 | var newValue = scopes.compute(type, (ignoredKey, oldValue) -> | ||
50 | oldValue == null ? interval : oldValue.meet(interval)); | ||
51 | if (newValue.isEmpty()) { | ||
52 | throw new TranslationException(type, "Unsatisfiable scope for type %s".formatted(type)); | ||
53 | } | ||
54 | return this; | ||
55 | } | ||
56 | |||
57 | public ScopePropagator scopes(Map<PartialRelation, CardinalityInterval> scopes) { | ||
58 | return scopes(scopes.entrySet()); | ||
59 | } | ||
60 | |||
61 | public ScopePropagator scopes(Collection<Map.Entry<PartialRelation, CardinalityInterval>> scopes) { | ||
62 | for (var entry : scopes) { | ||
63 | scope(entry.getKey(), entry.getValue()); | ||
64 | } | ||
65 | return this; | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public void apply(ModelStoreBuilder storeBuilder) { | ||
70 | createTypeScopePropagatorFactories(); | ||
71 | Loader.loadNativeLibraries(); | ||
72 | for (var factory : typeScopePropagatorFactories) { | ||
73 | factory.configure(storeBuilder); | ||
74 | } | ||
75 | storeBuilder.getAdapter(PropagationBuilder.class) | ||
76 | .propagator(model -> new BoundScopePropagator(model, this)); | ||
77 | } | ||
78 | |||
79 | private void createTypeScopePropagatorFactories() { | ||
80 | for (var entry : scopes.entrySet()) { | ||
81 | var type = entry.getKey(); | ||
82 | var bounds = entry.getValue(); | ||
83 | if (bounds.lowerBound() > 0) { | ||
84 | var lowerFactory = new LowerTypeScopePropagator.Factory(type, bounds.lowerBound()); | ||
85 | typeScopePropagatorFactories.add(lowerFactory); | ||
86 | } | ||
87 | if (bounds.upperBound() instanceof FiniteUpperCardinality finiteUpperCardinality) { | ||
88 | var upperFactory = new UpperTypeScopePropagator.Factory(type, | ||
89 | finiteUpperCardinality.finiteUpperBound()); | ||
90 | typeScopePropagatorFactories.add(upperFactory); | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | Symbol<CardinalityInterval> getCountSymbol() { | ||
96 | return countSymbol; | ||
97 | } | ||
98 | |||
99 | List<TypeScopePropagator.Factory> getTypeScopePropagatorFactories() { | ||
100 | return typeScopePropagatorFactories; | ||
101 | } | ||
102 | } | ||