aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar OszkarSemerath <semerath@mit.bme.hu>2023-07-29 16:16:02 +0200
committerLibravatar OszkarSemerath <semerath@mit.bme.hu>2023-07-29 16:16:02 +0200
commit64f8706af45647b3015abc1bb1378c6be22a515c (patch)
treea4b776a846634d69f6a256eb4755f62abd1bb248
parentMerge pull request #31 from OszkarSemerath/datastructure (diff)
downloadrefinery-64f8706af45647b3015abc1bb1378c6be22a515c.tar.gz
refinery-64f8706af45647b3015abc1bb1378c6be22a515c.tar.zst
refinery-64f8706af45647b3015abc1bb1378c6be22a515c.zip
Initial prototype of the StateCoderAdapter based on NeighbourhoodCalculator.
No tests yet.
-rw-r--r--subprojects/store/build.gradle.kts5
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCodeCalculator.java10
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderAdapter.java12
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderBuilder.java29
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderStoreAdapter.java14
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderAdapterImpl.java47
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderBuilderImpl.java48
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderStoreAdapterImpl.java34
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/NeighbourhoodCalculator.java129
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/ObjectCode.java55
10 files changed, 383 insertions, 0 deletions
diff --git a/subprojects/store/build.gradle.kts b/subprojects/store/build.gradle.kts
index 2c485020..d653f01d 100644
--- a/subprojects/store/build.gradle.kts
+++ b/subprojects/store/build.gradle.kts
@@ -8,3 +8,8 @@ plugins {
8 id("tools.refinery.gradle.java-library") 8 id("tools.refinery.gradle.java-library")
9 id("tools.refinery.gradle.jmh") 9 id("tools.refinery.gradle.jmh")
10} 10}
11
12dependencies {
13 implementation(libs.eclipseCollections)
14 implementation(libs.eclipseCollections.api)
15}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCodeCalculator.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCodeCalculator.java
new file mode 100644
index 00000000..479b61ed
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCodeCalculator.java
@@ -0,0 +1,10 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.statecoding;
7
8public interface StateCodeCalculator {
9
10}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderAdapter.java
new file mode 100644
index 00000000..8795fb68
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderAdapter.java
@@ -0,0 +1,12 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.statecoding;
7
8import tools.refinery.store.adapter.ModelAdapter;
9
10public interface StateCoderAdapter extends ModelAdapter {
11 int calculateHashCode();
12}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderBuilder.java
new file mode 100644
index 00000000..2f37584f
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderBuilder.java
@@ -0,0 +1,29 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.statecoding;
7
8import tools.refinery.store.adapter.ModelAdapterBuilder;
9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.representation.AnySymbol;
11
12import java.util.Collection;
13import java.util.List;
14
15public interface StateCoderBuilder extends ModelAdapterBuilder {
16 StateCoderBuilder exclude(AnySymbol symbol);
17 default StateCoderBuilder excludeAll(Collection<? extends AnySymbol> symbols) {
18 for(var symbol : symbols) {
19 exclude(symbol);
20 }
21 return this;
22 }
23 default StateCoderBuilder excludeAll(AnySymbol... symbols) {
24 return excludeAll(List.of(symbols));
25 }
26
27 @Override
28 StateCoderStoreAdapter build(ModelStore store);
29}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderStoreAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderStoreAdapter.java
new file mode 100644
index 00000000..5946a162
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderStoreAdapter.java
@@ -0,0 +1,14 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.statecoding;
7
8import tools.refinery.store.adapter.ModelStoreAdapter;
9import tools.refinery.store.model.Model;
10
11public interface StateCoderStoreAdapter extends ModelStoreAdapter {
12 @Override
13 StateCoderAdapter createModelAdapter(Model model);
14}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderAdapterImpl.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderAdapterImpl.java
new file mode 100644
index 00000000..689db2e3
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderAdapterImpl.java
@@ -0,0 +1,47 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.statecoding.internal;
7
8import tools.refinery.store.adapter.ModelStoreAdapter;
9import tools.refinery.store.model.Interpretation;
10import tools.refinery.store.model.Model;
11import tools.refinery.store.representation.Symbol;
12import tools.refinery.store.statecoding.StateCoderAdapter;
13import tools.refinery.store.statecoding.neighbourhood.NeighbourhoodCalculator;
14
15import java.util.Collection;
16import java.util.List;
17
18public class StateCoderAdapterImpl implements StateCoderAdapter {
19 final ModelStoreAdapter storeAdapter;
20 final Model model;
21 final NeighbourhoodCalculator calculator;
22
23 StateCoderAdapterImpl(ModelStoreAdapter storeAdapter, Model model, Collection<Symbol<?>> symbols) {
24 this.storeAdapter = storeAdapter;
25 this.model = model;
26
27 List<? extends Interpretation<?>> interpretations = symbols.stream().map(model::getInterpretation).toList();
28 calculator = new NeighbourhoodCalculator(interpretations);
29 }
30
31 @Override
32 public Model getModel() {
33 return model;
34 }
35
36 @Override
37 public ModelStoreAdapter getStoreAdapter() {
38 return storeAdapter;
39 }
40
41 @Override
42 public int calculateHashCode() {
43 return calculator.calculate();
44 }
45
46
47}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderBuilderImpl.java
new file mode 100644
index 00000000..700723f4
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderBuilderImpl.java
@@ -0,0 +1,48 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.statecoding.internal;
7
8import tools.refinery.store.model.ModelStore;
9import tools.refinery.store.model.ModelStoreBuilder;
10import tools.refinery.store.representation.AnySymbol;
11import tools.refinery.store.representation.Symbol;
12import tools.refinery.store.statecoding.StateCoderBuilder;
13import tools.refinery.store.statecoding.StateCoderStoreAdapter;
14
15import java.util.HashSet;
16import java.util.LinkedHashSet;
17import java.util.Set;
18
19public class StateCoderBuilderImpl implements StateCoderBuilder {
20 Set<AnySymbol> excluded = new HashSet<>();
21
22 @Override
23 public StateCoderBuilder exclude(AnySymbol symbol) {
24 excluded.add(symbol);
25 return this;
26 }
27
28 @Override
29 public boolean isConfigured() {
30 return true;
31 }
32
33 @Override
34 public void configure(ModelStoreBuilder storeBuilder) {
35 // It does not modify the build process
36 }
37
38 @Override
39 public StateCoderStoreAdapter build(ModelStore store) {
40 Set<Symbol<?>> symbols = new LinkedHashSet<>();
41 for (AnySymbol symbol : store.getSymbols()) {
42 if (!excluded.contains(symbol) && (symbol instanceof Symbol<?> typed)) {
43 symbols.add(typed);
44 }
45 }
46 return new StateCoderStoreAdapterImpl(store, symbols);
47 }
48}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderStoreAdapterImpl.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderStoreAdapterImpl.java
new file mode 100644
index 00000000..77d36e96
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderStoreAdapterImpl.java
@@ -0,0 +1,34 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.statecoding.internal;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.representation.Symbol;
11import tools.refinery.store.statecoding.StateCoderAdapter;
12import tools.refinery.store.statecoding.StateCoderStoreAdapter;
13
14import java.util.Collection;
15
16public class StateCoderStoreAdapterImpl implements StateCoderStoreAdapter {
17 final ModelStore store;
18 final Collection<Symbol<?>> symbols;
19
20 StateCoderStoreAdapterImpl(ModelStore store, Collection<Symbol<?>> symbols) {
21 this.store = store;
22 this.symbols = symbols;
23 }
24
25 @Override
26 public ModelStore getStore() {
27 return store;
28 }
29
30 @Override
31 public StateCoderAdapter createModelAdapter(Model model) {
32 return new StateCoderAdapterImpl(this,model,symbols);
33 }
34}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/NeighbourhoodCalculator.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/NeighbourhoodCalculator.java
new file mode 100644
index 00000000..24a7122e
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/NeighbourhoodCalculator.java
@@ -0,0 +1,129 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.statecoding.neighbourhood;
7
8import org.eclipse.collections.api.set.primitive.MutableLongSet;
9import org.eclipse.collections.impl.set.mutable.primitive.LongHashSet;
10import tools.refinery.store.model.Interpretation;
11import tools.refinery.store.tuple.Tuple;
12import tools.refinery.store.tuple.Tuple0;
13
14import java.util.ArrayList;
15import java.util.LinkedHashMap;
16import java.util.List;
17import java.util.Random;
18
19public class NeighbourhoodCalculator {
20 final List<Interpretation<?>> nullImpactValues;
21 final LinkedHashMap<Interpretation<?>, long[]> impactValues;
22
23 public NeighbourhoodCalculator(List<? extends Interpretation<?>> interpretations) {
24 this.nullImpactValues = new ArrayList<>();
25 this.impactValues = new LinkedHashMap<>();
26 Random random = new Random(1);
27
28 for (Interpretation<?> interpretation : interpretations) {
29 int arity = interpretation.getSymbol().arity();
30 if (arity == 0) {
31 nullImpactValues.add(interpretation);
32 } else {
33 long[] impact = new long[arity];
34 for (int i = 0; i < arity; i++) {
35 impact[i] = random.nextLong();
36 }
37 impactValues.put(interpretation, impact);
38 }
39 }
40 }
41
42 public int calculate() {
43 ObjectCode previous = new ObjectCode();
44 ObjectCode next = new ObjectCode();
45
46 int previousSize = 1;
47 long lastSum;
48 boolean grows;
49
50 do{
51 for (var impactValueEntry : this.impactValues.entrySet()) {
52 Interpretation<?> interpretation = impactValueEntry.getKey();
53 long[] impact = impactValueEntry.getValue();
54 var cursor = interpretation.getAll();
55 while (cursor.move()) {
56 Tuple tuple = cursor.getKey();
57 Object value = cursor.getValue();
58 long tupleHash = getTupleHash(tuple, value, previous);
59 addHash(next, tuple, impact, tupleHash);
60 }
61 }
62
63 previous = next;
64 next = null;
65 lastSum = 0;
66 MutableLongSet codes = new LongHashSet();
67 for (int i = 0; i < previous.getSize(); i++) {
68 long objectHash = previous.get(i);
69 codes.add(objectHash);
70
71 final long shifted1 = objectHash>>> 32;
72 final long shifted2 = objectHash << 32;
73 lastSum += shifted1 + shifted2;
74 }
75 int nextSize = codes.size();
76 grows = previousSize < nextSize;
77 previousSize = nextSize;
78
79 if(grows) {
80 next = new ObjectCode(previous);
81 }
82 } while (grows);
83
84 long result = 1;
85 for (var nullImpactValue : nullImpactValues) {
86 result = result * 31 + nullImpactValue.get(Tuple0.INSTANCE).hashCode();
87 }
88 result += lastSum;
89
90 return (int) result;
91 }
92
93 protected long getTupleHash(Tuple tuple, Object value, ObjectCode objectCode) {
94 long result = (long) value;
95 int arity = tuple.getSize();
96 if (arity == 1) {
97 result = result * 31 + objectCode.get(tuple.get(0));
98 } else if (arity == 2) {
99 result = result * 31 + objectCode.get(tuple.get(0));
100 result = result * 31 + objectCode.get(tuple.get(1));
101 if (tuple.get(0) == tuple.get(1)) {
102 result++;
103 }
104 } else if (arity > 2) {
105 for (int i = 0; i < arity; i++) {
106 result = result * 31 + objectCode.get(tuple.get(i));
107 }
108 }
109 return result;
110 }
111
112 protected void addHash(ObjectCode objectCode, Tuple tuple, long[] impact, long tupleHashCode) {
113 if (tuple.getSize() == 1) {
114 addHash(objectCode, tuple.get(0), impact[0], tupleHashCode);
115 } else if (tuple.getSize() == 2) {
116 addHash(objectCode, tuple.get(0), impact[0], tupleHashCode);
117 addHash(objectCode, tuple.get(1), impact[1], tupleHashCode);
118 } else if (tuple.getSize() > 2) {
119 for (int i = 0; i < tuple.getSize(); i++) {
120 addHash(objectCode, tuple.get(i), impact[i], tupleHashCode);
121 }
122 }
123 }
124
125 protected void addHash(ObjectCode objectCode, int o, long impact, long tupleHash) {
126 objectCode.set(o, objectCode.get(o) + tupleHash * impact);
127 }
128
129}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/ObjectCode.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/ObjectCode.java
new file mode 100644
index 00000000..594d2b3a
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/ObjectCode.java
@@ -0,0 +1,55 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.statecoding.neighbourhood;
7
8public class ObjectCode {
9 private long[] vector;
10 private int size;
11
12 public ObjectCode() {
13 vector = new long[10];
14 size = 0;
15 }
16
17 public ObjectCode(ObjectCode sameSize) {
18 this.vector = new long[sameSize.size];
19 this.size = sameSize.size;
20 }
21
22 private void ensureSize(int object) {
23 if(object >= size) {
24 size = object+1;
25 }
26
27 if(object >= vector.length) {
28 int newLength = vector.length*2;
29 while(object >= newLength) {
30 newLength*=2;
31 }
32
33 long[] newVector = new long[newLength];
34 System.arraycopy(vector, 0, newVector, 0, vector.length);
35 this.vector = newVector;
36 }
37 }
38
39 public long get(int object) {
40 if(object < vector.length) {
41 return vector[object];
42 } else {
43 return 0;
44 }
45 }
46
47 public void set(int object, long value) {
48 ensureSize(object);
49 vector[object]=value;
50 }
51
52 public int getSize() {
53 return this.size;
54 }
55}