aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-reasoning-scope/src/main/java/tools/refinery/store/reasoning/scope/ScopePropagator.java
diff options
context:
space:
mode:
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.java102
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 */
6package tools.refinery.store.reasoning.scope;
7
8import com.google.ortools.Loader;
9import tools.refinery.store.dse.propagation.PropagationBuilder;
10import tools.refinery.store.model.ModelStoreBuilder;
11import tools.refinery.store.model.ModelStoreConfiguration;
12import tools.refinery.store.reasoning.representation.PartialRelation;
13import tools.refinery.store.reasoning.translator.TranslationException;
14import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator;
15import tools.refinery.store.representation.Symbol;
16import tools.refinery.store.representation.cardinality.CardinalityInterval;
17import tools.refinery.store.representation.cardinality.FiniteUpperCardinality;
18
19import java.util.*;
20
21public 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}