aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2023-03-31 17:31:46 +0200
committerLibravatar GitHub <noreply@github.com>2023-03-31 17:31:46 +0200
commit93f1d439f33a5139039fe93280bbfcae61a904ab (patch)
treee98eae681a866d2d0cd728885ed6c8f8fa65e9a2 /subprojects/store
parentrefactor: PartialInterpretation adapter naming (diff)
parentbuild: try to fix secret detection in workflow (diff)
downloadrefinery-93f1d439f33a5139039fe93280bbfcae61a904ab.tar.gz
refinery-93f1d439f33a5139039fe93280bbfcae61a904ab.tar.zst
refinery-93f1d439f33a5139039fe93280bbfcae61a904ab.zip
Merge pull request #24 from kris7t/partial-interpretation
Changes for supporting partial interpretation
Diffstat (limited to 'subprojects/store')
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java36
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretation.java19
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationAdapter.java9
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationBuilder.java9
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationStoreAdapter.java9
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationAdapterImpl.java24
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationBuilderImpl.java17
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationStoreAdapterImpl.java23
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/DNF.java169
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java9
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java19
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/FunctionalDependency.java15
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/ModelQuery.java11
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java13
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java23
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java16
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/RelationLike.java11
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/ResultSet.java25
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/Variable.java43
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java80
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java28
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/ConstantAtom.java12
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java9
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java32
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java17
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java22
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java32
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java24
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java49
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java71
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java36
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java62
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java19
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java44
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java29
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java7
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java6
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java60
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java10
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java52
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java2
42 files changed, 196 insertions, 1011 deletions
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java b/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java
new file mode 100644
index 00000000..fc8e628b
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java
@@ -0,0 +1,36 @@
1package tools.refinery.store.map;
2
3public final class Cursors {
4 private Cursors() {
5 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
6 }
7
8 public static <K, V> Cursor<K, V> empty() {
9 return new Empty<>();
10 }
11
12 private static class Empty<K, V> implements Cursor<K, V> {
13 private boolean terminated = false;
14
15 @Override
16 public K getKey() {
17 return null;
18 }
19
20 @Override
21 public V getValue() {
22 return null;
23 }
24
25 @Override
26 public boolean isTerminated() {
27 return terminated;
28 }
29
30 @Override
31 public boolean move() {
32 terminated = true;
33 return false;
34 }
35 }
36}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretation.java
deleted file mode 100644
index 331fa294..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretation.java
+++ /dev/null
@@ -1,19 +0,0 @@
1package tools.refinery.store.partial;
2
3import tools.refinery.store.adapter.ModelAdapterBuilderFactory;
4import tools.refinery.store.model.ModelStoreBuilder;
5import tools.refinery.store.partial.internal.PartialInterpretationBuilderImpl;
6
7public final class PartialInterpretation extends ModelAdapterBuilderFactory<PartialInterpretationAdapter,
8 PartialInterpretationStoreAdapter, PartialInterpretationBuilder> {
9 public static final PartialInterpretation ADAPTER = new PartialInterpretation();
10
11 private PartialInterpretation() {
12 super(PartialInterpretationAdapter.class, PartialInterpretationStoreAdapter.class, PartialInterpretationBuilder.class);
13 }
14
15 @Override
16 public PartialInterpretationBuilder createBuilder(ModelStoreBuilder storeBuilder) {
17 return new PartialInterpretationBuilderImpl(storeBuilder);
18 }
19}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationAdapter.java
deleted file mode 100644
index 2c83a200..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationAdapter.java
+++ /dev/null
@@ -1,9 +0,0 @@
1package tools.refinery.store.partial;
2
3import tools.refinery.store.adapter.ModelAdapter;
4
5public interface PartialInterpretationAdapter extends ModelAdapter {
6 @Override
7 PartialInterpretationStoreAdapter getStoreAdapter();
8}
9
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationBuilder.java
deleted file mode 100644
index 0ec13836..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationBuilder.java
+++ /dev/null
@@ -1,9 +0,0 @@
1package tools.refinery.store.partial;
2
3import tools.refinery.store.adapter.ModelAdapterBuilder;
4import tools.refinery.store.model.ModelStore;
5
6public interface PartialInterpretationBuilder extends ModelAdapterBuilder {
7 @Override
8 PartialInterpretationStoreAdapter createStoreAdapter(ModelStore store);
9}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationStoreAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationStoreAdapter.java
deleted file mode 100644
index d4eb770d..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/partial/PartialInterpretationStoreAdapter.java
+++ /dev/null
@@ -1,9 +0,0 @@
1package tools.refinery.store.partial;
2
3import tools.refinery.store.adapter.ModelStoreAdapter;
4import tools.refinery.store.model.Model;
5
6public interface PartialInterpretationStoreAdapter extends ModelStoreAdapter {
7 @Override
8 PartialInterpretationAdapter createModelAdapter(Model model);
9}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationAdapterImpl.java b/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationAdapterImpl.java
deleted file mode 100644
index 4b3977c0..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationAdapterImpl.java
+++ /dev/null
@@ -1,24 +0,0 @@
1package tools.refinery.store.partial.internal;
2
3import tools.refinery.store.model.Model;
4import tools.refinery.store.partial.PartialInterpretationAdapter;
5
6public class PartialInterpretationAdapterImpl implements PartialInterpretationAdapter {
7 private final Model model;
8 private final PartialInterpretationStoreAdapterImpl storeAdapter;
9
10 PartialInterpretationAdapterImpl(Model model, PartialInterpretationStoreAdapterImpl storeAdapter) {
11 this.model = model;
12 this.storeAdapter = storeAdapter;
13 }
14
15 @Override
16 public Model getModel() {
17 return model;
18 }
19
20 @Override
21 public PartialInterpretationStoreAdapterImpl getStoreAdapter() {
22 return storeAdapter;
23 }
24}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationBuilderImpl.java
deleted file mode 100644
index 4609dc32..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationBuilderImpl.java
+++ /dev/null
@@ -1,17 +0,0 @@
1package tools.refinery.store.partial.internal;
2
3import tools.refinery.store.adapter.AbstractModelAdapterBuilder;
4import tools.refinery.store.model.ModelStore;
5import tools.refinery.store.model.ModelStoreBuilder;
6import tools.refinery.store.partial.PartialInterpretationBuilder;
7
8public class PartialInterpretationBuilderImpl extends AbstractModelAdapterBuilder implements PartialInterpretationBuilder {
9 public PartialInterpretationBuilderImpl(ModelStoreBuilder storeBuilder) {
10 super(storeBuilder);
11 }
12
13 @Override
14 public PartialInterpretationStoreAdapterImpl createStoreAdapter(ModelStore store) {
15 return null;
16 }
17}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationStoreAdapterImpl.java b/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationStoreAdapterImpl.java
deleted file mode 100644
index 970b802b..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/partial/internal/PartialInterpretationStoreAdapterImpl.java
+++ /dev/null
@@ -1,23 +0,0 @@
1package tools.refinery.store.partial.internal;
2
3import tools.refinery.store.model.Model;
4import tools.refinery.store.model.ModelStore;
5import tools.refinery.store.partial.PartialInterpretationStoreAdapter;
6
7public class PartialInterpretationStoreAdapterImpl implements PartialInterpretationStoreAdapter {
8 private final ModelStore store;
9
10 PartialInterpretationStoreAdapterImpl(ModelStore store) {
11 this.store = store;
12 }
13
14 @Override
15 public ModelStore getStore() {
16 return store;
17 }
18
19 @Override
20 public PartialInterpretationAdapterImpl createModelAdapter(Model model) {
21 return new PartialInterpretationAdapterImpl(model, this);
22 }
23}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java
deleted file mode 100644
index 95c5d787..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/DNF.java
+++ /dev/null
@@ -1,169 +0,0 @@
1package tools.refinery.store.query;
2
3import tools.refinery.store.query.atom.DNFAtom;
4
5import java.util.*;
6
7public final class DNF implements RelationLike {
8 private final String name;
9
10 private final String uniqueName;
11
12 private final List<Variable> parameters;
13
14 private final List<FunctionalDependency<Variable>> functionalDependencies;
15
16 private final List<DNFAnd> clauses;
17
18 private DNF(String name, List<Variable> parameters, List<FunctionalDependency<Variable>> functionalDependencies,
19 List<DNFAnd> clauses) {
20 validateFunctionalDependencies(parameters, functionalDependencies);
21 this.name = name;
22 this.uniqueName = DNFUtils.generateUniqueName(name);
23 this.parameters = parameters;
24 this.functionalDependencies = functionalDependencies;
25 this.clauses = clauses;
26 }
27
28 private static void validateFunctionalDependencies(
29 Collection<Variable> parameters, Collection<FunctionalDependency<Variable>> functionalDependencies) {
30 var parameterSet = new HashSet<>(parameters);
31 for (var functionalDependency : functionalDependencies) {
32 validateParameters(parameters, parameterSet, functionalDependency.forEach(), functionalDependency);
33 validateParameters(parameters, parameterSet, functionalDependency.unique(), functionalDependency);
34 }
35 }
36
37 private static void validateParameters(Collection<Variable> parameters, Set<Variable> parameterSet,
38 Collection<Variable> toValidate,
39 FunctionalDependency<Variable> functionalDependency) {
40 for (var variable : toValidate) {
41 if (!parameterSet.contains(variable)) {
42 throw new IllegalArgumentException(
43 "Variable %s of functional dependency %s does not appear in the parameter list %s"
44 .formatted(variable, functionalDependency, parameters));
45 }
46 }
47 }
48
49 @Override
50 public String name() {
51 return name;
52 }
53
54 public String getUniqueName() {
55 return uniqueName;
56 }
57
58 public List<Variable> getParameters() {
59 return parameters;
60 }
61
62 public List<FunctionalDependency<Variable>> getFunctionalDependencies() {
63 return functionalDependencies;
64 }
65
66 @Override
67 public int arity() {
68 return parameters.size();
69 }
70
71 public List<DNFAnd> getClauses() {
72 return clauses;
73 }
74
75 public static Builder builder() {
76 return builder(null);
77 }
78
79 public static Builder builder(String name) {
80 return new Builder(name);
81 }
82
83 @SuppressWarnings("UnusedReturnValue")
84 public static class Builder {
85 private final String name;
86
87 private final List<Variable> parameters = new ArrayList<>();
88
89 private final List<FunctionalDependency<Variable>> functionalDependencies = new ArrayList<>();
90
91 private final List<List<DNFAtom>> clauses = new ArrayList<>();
92
93 private Builder(String name) {
94 this.name = name;
95 }
96
97 public Builder parameter(Variable variable) {
98 parameters.add(variable);
99 return this;
100 }
101
102 public Builder parameters(Variable... variables) {
103 return parameters(List.of(variables));
104 }
105
106 public Builder parameters(Collection<Variable> variables) {
107 parameters.addAll(variables);
108 return this;
109 }
110
111 public Builder functionalDependencies(Collection<FunctionalDependency<Variable>> functionalDependencies) {
112 this.functionalDependencies.addAll(functionalDependencies);
113 return this;
114 }
115
116 public Builder functionalDependency(FunctionalDependency<Variable> functionalDependency) {
117 functionalDependencies.add(functionalDependency);
118 return this;
119 }
120
121 public Builder functionalDependency(Set<Variable> forEach, Set<Variable> unique) {
122 return functionalDependency(new FunctionalDependency<>(forEach, unique));
123 }
124
125 public Builder clause(DNFAtom... atoms) {
126 clauses.add(List.of(atoms));
127 return this;
128 }
129
130 public Builder clause(Collection<DNFAtom> atoms) {
131 clauses.add(List.copyOf(atoms));
132 return this;
133 }
134
135 public Builder clause(DNFAnd clause) {
136 return clause(clause.constraints());
137 }
138
139 public Builder clauses(DNFAnd... clauses) {
140 for (var clause : clauses) {
141 this.clause(clause);
142 }
143 return this;
144 }
145
146 public Builder clauses(Collection<DNFAnd> clauses) {
147 for (var clause : clauses) {
148 this.clause(clause);
149 }
150 return this;
151 }
152
153 public DNF build() {
154 var postProcessedClauses = new ArrayList<DNFAnd>();
155 for (var constraints : clauses) {
156 var variables = new HashSet<Variable>();
157 for (var constraint : constraints) {
158 constraint.collectAllVariables(variables);
159 }
160 parameters.forEach(variables::remove);
161 postProcessedClauses.add(new DNFAnd(Collections.unmodifiableSet(variables),
162 Collections.unmodifiableList(constraints)));
163 }
164 return new DNF(name, Collections.unmodifiableList(parameters),
165 Collections.unmodifiableList(functionalDependencies),
166 Collections.unmodifiableList(postProcessedClauses));
167 }
168 }
169}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java
deleted file mode 100644
index 8c3bf05d..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/DNFAnd.java
+++ /dev/null
@@ -1,9 +0,0 @@
1package tools.refinery.store.query;
2
3import tools.refinery.store.query.atom.DNFAtom;
4
5import java.util.List;
6import java.util.Set;
7
8public record DNFAnd(Set<Variable> quantifiedVariables, List<DNFAtom> constraints) {
9}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java b/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java
deleted file mode 100644
index 0ef77d49..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/DNFUtils.java
+++ /dev/null
@@ -1,19 +0,0 @@
1package tools.refinery.store.query;
2
3import java.util.UUID;
4
5public final class DNFUtils {
6 private DNFUtils() {
7 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
8 }
9
10 public static String generateUniqueName(String originalName) {
11 UUID uuid = UUID.randomUUID();
12 String uniqueString = "_" + uuid.toString().replace('-', '_');
13 if (originalName == null) {
14 return uniqueString;
15 } else {
16 return originalName + uniqueString;
17 }
18 }
19}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/FunctionalDependency.java b/subprojects/store/src/main/java/tools/refinery/store/query/FunctionalDependency.java
deleted file mode 100644
index 63a81713..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/FunctionalDependency.java
+++ /dev/null
@@ -1,15 +0,0 @@
1package tools.refinery.store.query;
2
3import java.util.HashSet;
4import java.util.Set;
5
6public record FunctionalDependency<T>(Set<T> forEach, Set<T> unique) {
7 public FunctionalDependency {
8 var uniqueForEach = new HashSet<>(unique);
9 uniqueForEach.retainAll(forEach);
10 if (!uniqueForEach.isEmpty()) {
11 throw new IllegalArgumentException("Variables %s appear on both sides of the functional dependency"
12 .formatted(uniqueForEach));
13 }
14 }
15}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQuery.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQuery.java
deleted file mode 100644
index 6a1aeabb..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQuery.java
+++ /dev/null
@@ -1,11 +0,0 @@
1package tools.refinery.store.query;
2
3import tools.refinery.store.adapter.ModelAdapterType;
4
5public final class ModelQuery extends ModelAdapterType<ModelQueryAdapter, ModelQueryStoreAdapter, ModelQueryBuilder> {
6 public static final ModelQuery ADAPTER = new ModelQuery();
7
8 private ModelQuery() {
9 super(ModelQueryAdapter.class, ModelQueryStoreAdapter.class, ModelQueryBuilder.class);
10 }
11}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java
deleted file mode 100644
index 7449e39b..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java
+++ /dev/null
@@ -1,13 +0,0 @@
1package tools.refinery.store.query;
2
3import tools.refinery.store.adapter.ModelAdapter;
4
5public interface ModelQueryAdapter extends ModelAdapter {
6 ModelQueryStoreAdapter getStoreAdapter();
7
8 ResultSet getResultSet(DNF query);
9
10 boolean hasPendingChanges();
11
12 void flushChanges();
13}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java
deleted file mode 100644
index 4364d844..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java
+++ /dev/null
@@ -1,23 +0,0 @@
1package tools.refinery.store.query;
2
3import tools.refinery.store.adapter.ModelAdapterBuilder;
4import tools.refinery.store.model.ModelStore;
5
6import java.util.Collection;
7import java.util.List;
8
9public interface ModelQueryBuilder extends ModelAdapterBuilder {
10 default ModelQueryBuilder queries(DNF... queries) {
11 return queries(List.of(queries));
12 }
13
14 default ModelQueryBuilder queries(Collection<DNF> queries) {
15 queries.forEach(this::query);
16 return this;
17 }
18
19 ModelQueryBuilder query(DNF query);
20
21 @Override
22 ModelQueryStoreAdapter createStoreAdapter(ModelStore store);
23}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java
deleted file mode 100644
index ef5a4587..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java
+++ /dev/null
@@ -1,16 +0,0 @@
1package tools.refinery.store.query;
2
3import tools.refinery.store.adapter.ModelStoreAdapter;
4import tools.refinery.store.model.Model;
5import tools.refinery.store.query.view.AnyRelationView;
6
7import java.util.Collection;
8
9public interface ModelQueryStoreAdapter extends ModelStoreAdapter {
10 Collection<AnyRelationView> getRelationViews();
11
12 Collection<DNF> getQueries();
13
14 @Override
15 ModelQueryAdapter createModelAdapter(Model model);
16}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/RelationLike.java b/subprojects/store/src/main/java/tools/refinery/store/query/RelationLike.java
deleted file mode 100644
index 8c784d8b..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/RelationLike.java
+++ /dev/null
@@ -1,11 +0,0 @@
1package tools.refinery.store.query;
2
3public interface RelationLike {
4 String name();
5
6 int arity();
7
8 default boolean invalidIndex(int i) {
9 return i < 0 || i >= arity();
10 }
11}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/ResultSet.java b/subprojects/store/src/main/java/tools/refinery/store/query/ResultSet.java
deleted file mode 100644
index 3542e252..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/ResultSet.java
+++ /dev/null
@@ -1,25 +0,0 @@
1package tools.refinery.store.query;
2
3import tools.refinery.store.tuple.Tuple;
4import tools.refinery.store.tuple.TupleLike;
5
6import java.util.Optional;
7import java.util.stream.Stream;
8
9public interface ResultSet {
10 boolean hasResult();
11
12 boolean hasResult(Tuple parameters);
13
14 Optional<TupleLike> oneResult();
15
16 Optional<TupleLike> oneResult(Tuple parameters);
17
18 Stream<TupleLike> allResults();
19
20 Stream<TupleLike> allResults(Tuple parameters);
21
22 int countResults();
23
24 int countResults(Tuple parameters);
25}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java b/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java
deleted file mode 100644
index 3632f3c5..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java
+++ /dev/null
@@ -1,43 +0,0 @@
1package tools.refinery.store.query;
2
3import java.util.Objects;
4
5public class Variable {
6 private final String name;
7 private final String uniqueName;
8
9 public Variable() {
10 this(null);
11 }
12
13 public Variable(String name) {
14 super();
15 this.name = name;
16 this.uniqueName = DNFUtils.generateUniqueName(name);
17
18 }
19 public String getName() {
20 return name;
21 }
22
23 public String getUniqueName() {
24 return uniqueName;
25 }
26
27 public boolean isNamed() {
28 return name != null;
29 }
30
31 @Override
32 public boolean equals(Object o) {
33 if (this == o) return true;
34 if (o == null || getClass() != o.getClass()) return false;
35 Variable variable = (Variable) o;
36 return Objects.equals(uniqueName, variable.uniqueName);
37 }
38
39 @Override
40 public int hashCode() {
41 return Objects.hash(uniqueName);
42 }
43}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java
deleted file mode 100644
index 47121870..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallAtom.java
+++ /dev/null
@@ -1,80 +0,0 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.query.Variable;
4import tools.refinery.store.query.RelationLike;
5
6import java.util.List;
7import java.util.Objects;
8import java.util.Set;
9
10public abstract class CallAtom<T extends RelationLike> implements DNFAtom {
11 private final CallPolarity polarity;
12 private final T target;
13 private final List<Variable> substitution;
14
15 protected CallAtom(CallPolarity polarity, T target, List<Variable> substitution) {
16 if (substitution.size() != target.arity()) {
17 throw new IllegalArgumentException("%s needs %d arguments, but got %s".formatted(target.name(),
18 target.arity(), substitution.size()));
19 }
20 if (polarity.isTransitive() && target.arity() != 2) {
21 throw new IllegalArgumentException("Transitive closures can only take binary relations");
22 }
23 this.polarity = polarity;
24 this.target = target;
25 this.substitution = substitution;
26 }
27
28 protected CallAtom(CallPolarity polarity, T target, Variable... substitution) {
29 this(polarity, target, List.of(substitution));
30 }
31
32 protected CallAtom(boolean positive, T target, List<Variable> substitution) {
33 this(CallPolarity.fromBoolean(positive), target, substitution);
34 }
35
36 protected CallAtom(boolean positive, T target, Variable... substitution) {
37 this(positive, target, List.of(substitution));
38 }
39
40 protected CallAtom(T target, List<Variable> substitution) {
41 this(true, target, substitution);
42 }
43
44 protected CallAtom(T target, Variable... substitution) {
45 this(target, List.of(substitution));
46 }
47
48 public CallPolarity getPolarity() {
49 return polarity;
50 }
51
52 public T getTarget() {
53 return target;
54 }
55
56 public List<Variable> getSubstitution() {
57 return substitution;
58 }
59
60 @Override
61 public void collectAllVariables(Set<Variable> variables) {
62 if (polarity.isPositive()) {
63 variables.addAll(substitution);
64 }
65 }
66
67 @Override
68 public boolean equals(Object o) {
69 if (this == o) return true;
70 if (o == null || getClass() != o.getClass()) return false;
71 CallAtom<?> callAtom = (CallAtom<?>) o;
72 return polarity == callAtom.polarity && Objects.equals(target, callAtom.target) && Objects.equals(substitution
73 , callAtom.substitution);
74 }
75
76 @Override
77 public int hashCode() {
78 return Objects.hash(polarity, target, substitution);
79 }
80}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java
deleted file mode 100644
index 957e9b7b..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/CallPolarity.java
+++ /dev/null
@@ -1,28 +0,0 @@
1package tools.refinery.store.query.atom;
2
3public enum CallPolarity {
4 POSITIVE(true, false),
5 NEGATIVE(false, false),
6 TRANSITIVE(true, true);
7
8 private final boolean positive;
9
10 private final boolean transitive;
11
12 CallPolarity(boolean positive, boolean transitive) {
13 this.positive = positive;
14 this.transitive = transitive;
15 }
16
17 public boolean isPositive() {
18 return positive;
19 }
20
21 public boolean isTransitive() {
22 return transitive;
23 }
24
25 public static CallPolarity fromBoolean(boolean positive) {
26 return positive ? POSITIVE : NEGATIVE;
27 }
28}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/ConstantAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/ConstantAtom.java
deleted file mode 100644
index 13dae7d0..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/ConstantAtom.java
+++ /dev/null
@@ -1,12 +0,0 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.query.Variable;
4
5import java.util.Set;
6
7public record ConstantAtom(Variable variable, int nodeId) implements DNFAtom {
8 @Override
9 public void collectAllVariables(Set<Variable> variables) {
10 variables.add(variable);
11 }
12}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java
deleted file mode 100644
index ebf71236..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFAtom.java
+++ /dev/null
@@ -1,9 +0,0 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.query.Variable;
4
5import java.util.Set;
6
7public interface DNFAtom {
8 void collectAllVariables(Set<Variable> variables);
9}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java
deleted file mode 100644
index 3b4f5cd1..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/DNFCallAtom.java
+++ /dev/null
@@ -1,32 +0,0 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.query.DNF;
4import tools.refinery.store.query.Variable;
5
6import java.util.List;
7
8public class DNFCallAtom extends CallAtom<DNF> {
9 public DNFCallAtom(CallPolarity polarity, DNF target, List<Variable> substitution) {
10 super(polarity, target, substitution);
11 }
12
13 public DNFCallAtom(CallPolarity polarity, DNF target, Variable... substitution) {
14 super(polarity, target, substitution);
15 }
16
17 public DNFCallAtom(boolean positive, DNF target, List<Variable> substitution) {
18 super(positive, target, substitution);
19 }
20
21 public DNFCallAtom(boolean positive, DNF target, Variable... substitution) {
22 super(positive, target, substitution);
23 }
24
25 public DNFCallAtom(DNF target, List<Variable> substitution) {
26 super(target, substitution);
27 }
28
29 public DNFCallAtom(DNF target, Variable... substitution) {
30 super(target, substitution);
31 }
32}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java
deleted file mode 100644
index b1b3a6f7..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/EquivalenceAtom.java
+++ /dev/null
@@ -1,17 +0,0 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.query.Variable;
4
5import java.util.Set;
6
7public record EquivalenceAtom(boolean positive, Variable left, Variable right) implements DNFAtom {
8 public EquivalenceAtom(Variable left, Variable right) {
9 this(true, left, right);
10 }
11
12 @Override
13 public void collectAllVariables(Set<Variable> variables) {
14 variables.add(left);
15 variables.add(right);
16 }
17}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java
deleted file mode 100644
index e389f563..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/Modality.java
+++ /dev/null
@@ -1,22 +0,0 @@
1package tools.refinery.store.query.atom;
2
3import java.util.Locale;
4
5public enum Modality {
6 MUST,
7 MAY,
8 CURRENT;
9
10 public Modality negate() {
11 return switch(this) {
12 case MUST -> MAY;
13 case MAY -> MUST;
14 case CURRENT -> CURRENT;
15 };
16 }
17
18 @Override
19 public String toString() {
20 return name().toLowerCase(Locale.ROOT);
21 }
22}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java b/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java
deleted file mode 100644
index a2b176c4..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/atom/RelationViewAtom.java
+++ /dev/null
@@ -1,32 +0,0 @@
1package tools.refinery.store.query.atom;
2
3import tools.refinery.store.query.Variable;
4import tools.refinery.store.query.view.AnyRelationView;
5
6import java.util.List;
7
8public final class RelationViewAtom extends CallAtom<AnyRelationView> {
9 public RelationViewAtom(CallPolarity polarity, AnyRelationView target, List<Variable> substitution) {
10 super(polarity, target, substitution);
11 }
12
13 public RelationViewAtom(CallPolarity polarity, AnyRelationView target, Variable... substitution) {
14 super(polarity, target, substitution);
15 }
16
17 public RelationViewAtom(boolean positive, AnyRelationView target, List<Variable> substitution) {
18 super(positive, target, substitution);
19 }
20
21 public RelationViewAtom(boolean positive, AnyRelationView target, Variable... substitution) {
22 super(positive, target, substitution);
23 }
24
25 public RelationViewAtom(AnyRelationView target, List<Variable> substitution) {
26 super(target, substitution);
27 }
28
29 public RelationViewAtom(AnyRelationView target, Variable... substitution) {
30 super(target, substitution);
31 }
32}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java
deleted file mode 100644
index 328cde3a..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/view/AnyRelationView.java
+++ /dev/null
@@ -1,24 +0,0 @@
1package tools.refinery.store.query.view;
2
3import tools.refinery.store.model.Model;
4import tools.refinery.store.query.FunctionalDependency;
5import tools.refinery.store.representation.AnySymbol;
6import tools.refinery.store.query.RelationLike;
7
8import java.util.Set;
9
10public sealed interface AnyRelationView extends RelationLike permits RelationView {
11 AnySymbol getSymbol();
12
13 default Set<FunctionalDependency<Integer>> getFunctionalDependencies() {
14 return Set.of();
15 }
16
17 default Set<RelationViewImplication> getImpliedRelationViews() {
18 return Set.of();
19 }
20
21 boolean get(Model model, Object[] tuple);
22
23 Iterable<Object[]> getAll(Model model);
24}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java
deleted file mode 100644
index 64c601bb..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java
+++ /dev/null
@@ -1,49 +0,0 @@
1package tools.refinery.store.query.view;
2
3import tools.refinery.store.tuple.Tuple;
4import tools.refinery.store.representation.Symbol;
5
6import java.util.Objects;
7import java.util.function.BiPredicate;
8import java.util.function.Predicate;
9
10public class FilteredRelationView<T> extends TuplePreservingRelationView<T> {
11 private final BiPredicate<Tuple, T> predicate;
12
13 public FilteredRelationView(Symbol<T> symbol, String name, BiPredicate<Tuple, T> predicate) {
14 super(symbol, name);
15 this.predicate = predicate;
16 }
17
18 public FilteredRelationView(Symbol<T> symbol, BiPredicate<Tuple, T> predicate) {
19 super(symbol);
20 this.predicate = predicate;
21 }
22
23 public FilteredRelationView(Symbol<T> symbol, String name, Predicate<T> predicate) {
24 this(symbol, name, (k, v) -> predicate.test(v));
25 }
26
27 public FilteredRelationView(Symbol<T> symbol, Predicate<T> predicate) {
28 this(symbol, (k, v) -> predicate.test(v));
29 }
30
31 @Override
32 public boolean filter(Tuple key, T value) {
33 return this.predicate.test(key, value);
34 }
35
36 @Override
37 public boolean equals(Object o) {
38 if (this == o) return true;
39 if (o == null || getClass() != o.getClass()) return false;
40 if (!super.equals(o)) return false;
41 FilteredRelationView<?> that = (FilteredRelationView<?>) o;
42 return Objects.equals(predicate, that.predicate);
43 }
44
45 @Override
46 public int hashCode() {
47 return Objects.hash(super.hashCode(), predicate);
48 }
49}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java
deleted file mode 100644
index 3d278a8b..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java
+++ /dev/null
@@ -1,71 +0,0 @@
1package tools.refinery.store.query.view;
2
3import tools.refinery.store.model.Model;
4import tools.refinery.store.query.FunctionalDependency;
5import tools.refinery.store.representation.Symbol;
6import tools.refinery.store.tuple.Tuple;
7import tools.refinery.store.tuple.Tuple1;
8
9import java.util.Set;
10import java.util.stream.Collectors;
11import java.util.stream.IntStream;
12
13public final class FunctionalRelationView<T> extends RelationView<T> {
14 public FunctionalRelationView(Symbol<T> symbol, String name) {
15 super(symbol, name);
16 }
17
18 public FunctionalRelationView(Symbol<T> symbol) {
19 super(symbol);
20 }
21
22 @Override
23 public Set<FunctionalDependency<Integer>> getFunctionalDependencies() {
24 var arity = getSymbol().arity();
25 var forEach = IntStream.range(0, arity).boxed().collect(Collectors.toUnmodifiableSet());
26 var unique = Set.of(arity);
27 return Set.of(new FunctionalDependency<>(forEach, unique));
28 }
29
30 @Override
31 public Set<RelationViewImplication> getImpliedRelationViews() {
32 var symbol = getSymbol();
33 var impliedIndices = IntStream.range(0, symbol.arity()).boxed().toList();
34 var keyOnlyRelationView = new KeyOnlyRelationView<>(symbol);
35 return Set.of(new RelationViewImplication(this, keyOnlyRelationView, impliedIndices));
36 }
37
38 @Override
39 public boolean filter(Tuple key, T value) {
40 return true;
41 }
42
43 @Override
44 public Object[] forwardMap(Tuple key, T value) {
45 int size = key.getSize();
46 Object[] result = new Object[size + 1];
47 for (int i = 0; i < size; i++) {
48 result[i] = Tuple.of(key.get(i));
49 }
50 result[key.getSize()] = value;
51 return result;
52 }
53
54 @Override
55 public boolean get(Model model, Object[] tuple) {
56 int[] content = new int[tuple.length - 1];
57 for (int i = 0; i < tuple.length - 1; i++) {
58 content[i] = ((Tuple1) tuple[i]).value0();
59 }
60 Tuple key = Tuple.of(content);
61 @SuppressWarnings("unchecked")
62 T valueInTuple = (T) tuple[tuple.length - 1];
63 T valueInMap = model.getInterpretation(getSymbol()).get(key);
64 return valueInTuple.equals(valueInMap);
65 }
66
67 @Override
68 public int arity() {
69 return getSymbol().arity() + 1;
70 }
71}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java
deleted file mode 100644
index e1b2e45b..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java
+++ /dev/null
@@ -1,36 +0,0 @@
1package tools.refinery.store.query.view;
2
3import tools.refinery.store.representation.Symbol;
4import tools.refinery.store.tuple.Tuple;
5
6import java.util.Objects;
7
8public final class KeyOnlyRelationView<T> extends TuplePreservingRelationView<T> {
9 public static final String VIEW_NAME = "key";
10
11 private final T defaultValue;
12
13 public KeyOnlyRelationView(Symbol<T> symbol) {
14 super(symbol, VIEW_NAME);
15 defaultValue = symbol.defaultValue();
16 }
17
18 @Override
19 public boolean filter(Tuple key, T value) {
20 return !Objects.equals(value, defaultValue);
21 }
22
23 @Override
24 public boolean equals(Object o) {
25 if (this == o) return true;
26 if (o == null || getClass() != o.getClass()) return false;
27 if (!super.equals(o)) return false;
28 KeyOnlyRelationView<?> that = (KeyOnlyRelationView<?>) o;
29 return Objects.equals(defaultValue, that.defaultValue);
30 }
31
32 @Override
33 public int hashCode() {
34 return Objects.hash(super.hashCode(), defaultValue);
35 }
36}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java
deleted file mode 100644
index bbec1e73..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java
+++ /dev/null
@@ -1,62 +0,0 @@
1package tools.refinery.store.query.view;
2
3import tools.refinery.store.map.CursorAsIterator;
4import tools.refinery.store.model.Model;
5import tools.refinery.store.representation.Symbol;
6import tools.refinery.store.tuple.Tuple;
7
8import java.util.Objects;
9import java.util.UUID;
10
11/**
12 * Represents a view of a {@link Symbol} that can be queried.
13 *
14 * @param <T>
15 * @author Oszkar Semerath
16 */
17public abstract non-sealed class RelationView<T> implements AnyRelationView {
18 private final Symbol<T> symbol;
19
20 private final String name;
21
22 protected RelationView(Symbol<T> symbol, String name) {
23 this.symbol = symbol;
24 this.name = name;
25 }
26
27 protected RelationView(Symbol<T> representation) {
28 this(representation, UUID.randomUUID().toString());
29 }
30
31 @Override
32 public Symbol<T> getSymbol() {
33 return symbol;
34 }
35
36 @Override
37 public String name() {
38 return symbol.name() + "#" + name;
39 }
40
41 public abstract boolean filter(Tuple key, T value);
42
43 public abstract Object[] forwardMap(Tuple key, T value);
44
45 @Override
46 public Iterable<Object[]> getAll(Model model) {
47 return (() -> new CursorAsIterator<>(model.getInterpretation(symbol).getAll(), this::forwardMap, this::filter));
48 }
49
50 @Override
51 public boolean equals(Object o) {
52 if (this == o) return true;
53 if (o == null || getClass() != o.getClass()) return false;
54 RelationView<?> that = (RelationView<?>) o;
55 return Objects.equals(symbol, that.symbol) && Objects.equals(name, that.name);
56 }
57
58 @Override
59 public int hashCode() {
60 return Objects.hash(symbol, name);
61 }
62}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java
deleted file mode 100644
index 2ba1fcc4..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java
+++ /dev/null
@@ -1,19 +0,0 @@
1package tools.refinery.store.query.view;
2
3import java.util.List;
4
5public record RelationViewImplication(AnyRelationView implyingRelationView, AnyRelationView impliedRelationView,
6 List<Integer> impliedIndices) {
7 public RelationViewImplication {
8 if (impliedIndices.size() != impliedRelationView.arity()) {
9 throw new IllegalArgumentException("Expected %d implied indices for %s, but %d are provided"
10 .formatted(impliedRelationView.arity(), impliedRelationView, impliedIndices.size()));
11 }
12 for (var index : impliedIndices) {
13 if (impliedRelationView.invalidIndex(index)) {
14 throw new IllegalArgumentException("%d is not a valid index for %s".formatted(index,
15 implyingRelationView));
16 }
17 }
18 }
19}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java
deleted file mode 100644
index 8cc4986e..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java
+++ /dev/null
@@ -1,44 +0,0 @@
1package tools.refinery.store.query.view;
2
3import tools.refinery.store.model.Model;
4import tools.refinery.store.tuple.Tuple;
5import tools.refinery.store.tuple.Tuple1;
6import tools.refinery.store.representation.Symbol;
7
8public abstract class TuplePreservingRelationView<T> extends RelationView<T> {
9 protected TuplePreservingRelationView(Symbol<T> symbol, String name) {
10 super(symbol, name);
11 }
12
13 protected TuplePreservingRelationView(Symbol<T> symbol) {
14 super(symbol);
15 }
16
17 public Object[] forwardMap(Tuple key) {
18 Object[] result = new Object[key.getSize()];
19 for (int i = 0; i < key.getSize(); i++) {
20 result[i] = Tuple.of(key.get(i));
21 }
22 return result;
23 }
24
25 @Override
26 public Object[] forwardMap(Tuple key, T value) {
27 return forwardMap(key);
28 }
29
30 @Override
31 public boolean get(Model model, Object[] tuple) {
32 int[] content = new int[tuple.length];
33 for (int i = 0; i < tuple.length; i++) {
34 content[i] = ((Tuple1) tuple[i]).value0();
35 }
36 Tuple key = Tuple.of(content);
37 T value = model.getInterpretation(getSymbol()).get(key);
38 return filter(key, value);
39 }
40
41 public int arity() {
42 return this.getSymbol().arity();
43 }
44}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java
new file mode 100644
index 00000000..18903ead
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java
@@ -0,0 +1,29 @@
1package tools.refinery.store.representation;
2
3import java.util.Optional;
4
5public non-sealed interface AbstractDomain<A, C> extends AnyAbstractDomain {
6 @Override
7 Class<A> abstractType();
8
9 @Override
10 Class<C> concreteType();
11
12 A toAbstract(C concreteValue);
13
14 Optional<C> toConcrete(A abstractValue);
15
16 default boolean isConcrete(A abstractValue) {
17 return toConcrete(abstractValue).isPresent();
18 }
19
20 boolean isRefinement(A originalValue, A refinedValue);
21
22 A commonRefinement(A leftValue, A rightValue);
23
24 A commonAncestor(A leftValue, A rightValue);
25
26 A unknown();
27
28 boolean isError(A abstractValue);
29}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java
new file mode 100644
index 00000000..4c428a1e
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java
@@ -0,0 +1,7 @@
1package tools.refinery.store.representation;
2
3public sealed interface AnyAbstractDomain permits AbstractDomain {
4 Class<?> abstractType();
5
6 Class<?> concreteType();
7}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java b/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java
index 85ea15f4..30b1c03f 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java
@@ -1,12 +1,6 @@
1package tools.refinery.store.representation; 1package tools.refinery.store.representation;
2 2
3import java.util.Objects;
4
5public record Symbol<T>(String name, int arity, Class<T> valueType, T defaultValue) implements AnySymbol { 3public record Symbol<T>(String name, int arity, Class<T> valueType, T defaultValue) implements AnySymbol {
6 public boolean isDefaultValue(T value) {
7 return Objects.equals(defaultValue, value);
8 }
9
10 @Override 4 @Override
11 public boolean equals(Object o) { 5 public boolean equals(Object o) {
12 return this == o; 6 return this == o;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java
new file mode 100644
index 00000000..29858bce
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java
@@ -0,0 +1,60 @@
1package tools.refinery.store.representation;
2
3import java.util.Optional;
4
5public final class TruthValueDomain implements AbstractDomain<TruthValue, Boolean> {
6 public static final TruthValueDomain INSTANCE = new TruthValueDomain();
7
8 private TruthValueDomain() {
9 }
10
11 @Override
12 public Class<TruthValue> abstractType() {
13 return null;
14 }
15
16 @Override
17 public Class<Boolean> concreteType() {
18 return null;
19 }
20
21 @Override
22 public TruthValue toAbstract(Boolean concreteValue) {
23 return null;
24 }
25
26 @Override
27 public Optional<Boolean> toConcrete(TruthValue abstractValue) {
28 return Optional.empty();
29 }
30
31 @Override
32 public boolean isConcrete(TruthValue abstractValue) {
33 return AbstractDomain.super.isConcrete(abstractValue);
34 }
35
36 @Override
37 public boolean isRefinement(TruthValue originalValue, TruthValue refinedValue) {
38 return false;
39 }
40
41 @Override
42 public TruthValue commonRefinement(TruthValue leftValue, TruthValue rightValue) {
43 return null;
44 }
45
46 @Override
47 public TruthValue commonAncestor(TruthValue leftValue, TruthValue rightValue) {
48 return null;
49 }
50
51 @Override
52 public TruthValue unknown() {
53 return null;
54 }
55
56 @Override
57 public boolean isError(TruthValue abstractValue) {
58 return false;
59 }
60}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java
index 470ca298..953ea9f8 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java
@@ -1,5 +1,8 @@
1package tools.refinery.store.tuple; 1package tools.refinery.store.tuple;
2 2
3import java.util.stream.Collectors;
4import java.util.stream.IntStream;
5
3public interface TupleLike { 6public interface TupleLike {
4 int getSize(); 7 int getSize();
5 8
@@ -22,4 +25,11 @@ public interface TupleLike {
22 default -> Tuple.of(toArray()); 25 default -> Tuple.of(toArray());
23 }; 26 };
24 } 27 }
28
29 static String toString(TupleLike tuple) {
30 var valuesString = IntStream.range(0, tuple.getSize())
31 .mapToObj(i -> Integer.toString(tuple.get(i)))
32 .collect(Collectors.joining(", "));
33 return "[" + valuesString + "]";
34 }
25} 35}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java
index 15fd063b..c3aed847 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java
@@ -1,7 +1,6 @@
1package tools.refinery.store.tuple; 1package tools.refinery.store.tuple;
2 2
3import java.util.Arrays; 3import java.util.Arrays;
4import java.util.stream.Collectors;
5 4
6public record TupleN(int[] values) implements Tuple { 5public record TupleN(int[] values) implements Tuple {
7 static final int CUSTOM_TUPLE_SIZE = 2; 6 static final int CUSTOM_TUPLE_SIZE = 2;
@@ -29,8 +28,7 @@ public record TupleN(int[] values) implements Tuple {
29 28
30 @Override 29 @Override
31 public String toString() { 30 public String toString() {
32 var valuesString = Arrays.stream(values).mapToObj(Integer::toString).collect(Collectors.joining(", ")); 31 return TupleLike.toString(this);
33 return "[" + valuesString + "]";
34 } 32 }
35 33
36 @Override 34 @Override
diff --git a/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java b/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java
new file mode 100644
index 00000000..8a151d01
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java
@@ -0,0 +1,52 @@
1package tools.refinery.store.util;
2
3import java.util.*;
4import java.util.function.Function;
5import java.util.stream.Collectors;
6
7public class CycleDetectingMapper<T, R> {
8 private static final String SEPARATOR = " -> ";
9
10 private final Function<T, String> getName;
11
12 private final Function<T, R> doMap;
13
14 private final Set<T> inProgress = new LinkedHashSet<>();
15
16 private final Map<T, R> results = new HashMap<>();
17
18 public CycleDetectingMapper(Function<T, String> getName, Function<T, R> doMap) {
19 this.getName = getName;
20 this.doMap = doMap;
21 }
22
23 public R map(T input) {
24 if (inProgress.contains(input)) {
25 var path = inProgress.stream().map(getName).collect(Collectors.joining(SEPARATOR));
26 throw new IllegalArgumentException("Circular reference %s%s%s detected".formatted(path, SEPARATOR,
27 getName.apply(input)));
28 }
29 // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant
30 // way, which would cause a ConcurrentModificationException with computeIfAbsent.
31 @SuppressWarnings("squid:S3824")
32 var result = results.get(input);
33 if (result == null) {
34 inProgress.add(input);
35 try {
36 result = doMap.apply(input);
37 results.put(input, result);
38 } finally {
39 inProgress.remove(input);
40 }
41 }
42 return result;
43 }
44
45 public List<T> getInProgress() {
46 return List.copyOf(inProgress);
47 }
48
49 public R getAlreadyMapped(T input) {
50 return results.get(input);
51 }
52}
diff --git a/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java b/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java
index 371b5e47..9536a444 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java
@@ -49,7 +49,7 @@ class ModelTest {
49 49
50 assertEquals(3, ageInterpretation.get(Tuple.of(0))); 50 assertEquals(3, ageInterpretation.get(Tuple.of(0)));
51 assertEquals(1, ageInterpretation.get(Tuple.of(1))); 51 assertEquals(1, ageInterpretation.get(Tuple.of(1)));
52 assertNull(ageInterpretation.get( Tuple.of(2))); 52 assertNull(ageInterpretation.get(Tuple.of(2)));
53 53
54 assertTrue(friendInterpretation.get(Tuple.of(0, 1))); 54 assertTrue(friendInterpretation.get(Tuple.of(0, 1)));
55 assertFalse(friendInterpretation.get(Tuple.of(0, 5))); 55 assertFalse(friendInterpretation.get(Tuple.of(0, 5)));