aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store
diff options
context:
space:
mode:
authorLibravatar OszkarSemerath <semerath@mit.bme.hu>2023-08-07 02:45:57 +0200
committerLibravatar OszkarSemerath <semerath@mit.bme.hu>2023-08-07 02:45:57 +0200
commit8eb1b7a14972e52018a1bb69a53f2878e96b581e (patch)
treeddab1d27e8354d5d2c847c3473303a1f2bf549fa /subprojects/store
parentMerge pull request #34 from OszkarSemerath/datastructure (diff)
downloadrefinery-8eb1b7a14972e52018a1bb69a53f2878e96b581e.tar.gz
refinery-8eb1b7a14972e52018a1bb69a53f2878e96b581e.tar.zst
refinery-8eb1b7a14972e52018a1bb69a53f2878e96b581e.zip
StateCoderBuilder improvement with individuals, and customizable calculators.
Diffstat (limited to 'subprojects/store')
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCodeCalculatorFactory.java15
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderBuilder.java16
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/StateEquivalenceChecker.java2
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderAdapterImpl.java12
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderBuilderImpl.java34
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/internal/StateCoderStoreAdapterImpl.java29
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/AbstractNeighbourhoodCalculator.java95
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/LazyNeighbourhoodCalculator.java100
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/LazyNeighbourhoodCalculatorFactory.java20
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/NeighbourhoodCalculator.java132
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/statecoding/stateequivalence/StateEquivalenceCheckerImpl.java42
-rw-r--r--subprojects/store/src/test/java/tools/refinery/store/statecoding/StateCoderBuildTest.java51
12 files changed, 297 insertions, 251 deletions
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCodeCalculatorFactory.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCodeCalculatorFactory.java
new file mode 100644
index 00000000..04e17a13
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCodeCalculatorFactory.java
@@ -0,0 +1,15 @@
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 org.eclipse.collections.api.set.primitive.IntSet;
9import tools.refinery.store.model.Interpretation;
10
11import java.util.List;
12
13public interface StateCodeCalculatorFactory {
14 StateCodeCalculator create(List<? extends Interpretation<?>> interpretations, IntSet individuals);
15}
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
index 2f37584f..54650825 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderBuilder.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateCoderBuilder.java
@@ -8,7 +8,9 @@ package tools.refinery.store.statecoding;
8import tools.refinery.store.adapter.ModelAdapterBuilder; 8import tools.refinery.store.adapter.ModelAdapterBuilder;
9import tools.refinery.store.model.ModelStore; 9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.representation.AnySymbol; 10import tools.refinery.store.representation.AnySymbol;
11import tools.refinery.store.tuple.Tuple1;
11 12
13import java.util.Arrays;
12import java.util.Collection; 14import java.util.Collection;
13import java.util.List; 15import java.util.List;
14 16
@@ -24,6 +26,20 @@ public interface StateCoderBuilder extends ModelAdapterBuilder {
24 return excludeAll(List.of(symbols)); 26 return excludeAll(List.of(symbols));
25 } 27 }
26 28
29 StateCoderBuilder individual(Tuple1 tuple);
30 default StateCoderBuilder individual(Collection<Tuple1> tuple1s) {
31 for(Tuple1 tuple : tuple1s){
32 individual(tuple);
33 }
34 return this;
35 }
36 default StateCoderBuilder individuals(Tuple1... tuple1s) {
37 return individual(Arrays.stream(tuple1s).toList());
38 }
39
40 StateCoderBuilder stateCodeCalculatorFactory(StateCodeCalculatorFactory codeCalculatorFactory);
41 StateCoderBuilder stateEquivalenceChecker(StateEquivalenceChecker stateEquivalenceChecker);
42
27 @Override 43 @Override
28 StateCoderStoreAdapter build(ModelStore store); 44 StateCoderStoreAdapter build(ModelStore store);
29} 45}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateEquivalenceChecker.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateEquivalenceChecker.java
index 6d8dc6c7..3fd8c8d8 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateEquivalenceChecker.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/StateEquivalenceChecker.java
@@ -5,6 +5,7 @@
5 */ 5 */
6package tools.refinery.store.statecoding; 6package tools.refinery.store.statecoding;
7 7
8import org.eclipse.collections.api.set.primitive.IntSet;
8import tools.refinery.store.model.Interpretation; 9import tools.refinery.store.model.Interpretation;
9 10
10import java.util.List; 11import java.util.List;
@@ -15,6 +16,7 @@ public interface StateEquivalenceChecker {
15 } 16 }
16 17
17 EquivalenceResult constructMorphism( 18 EquivalenceResult constructMorphism(
19 IntSet individuals,
18 List<? extends Interpretation<?>> interpretations1, 20 List<? extends Interpretation<?>> interpretations1,
19 ObjectCode code1, List<? 21 ObjectCode code1, List<?
20 extends Interpretation<?>> interpretations2, 22 extends Interpretation<?>> interpretations2,
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
index b66fc86d..a2471916 100644
--- 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
@@ -6,28 +6,20 @@
6package tools.refinery.store.statecoding.internal; 6package tools.refinery.store.statecoding.internal;
7 7
8import tools.refinery.store.adapter.ModelStoreAdapter; 8import tools.refinery.store.adapter.ModelStoreAdapter;
9import tools.refinery.store.model.Interpretation;
10import tools.refinery.store.model.Model; 9import tools.refinery.store.model.Model;
11import tools.refinery.store.representation.Symbol;
12import tools.refinery.store.statecoding.StateCodeCalculator; 10import tools.refinery.store.statecoding.StateCodeCalculator;
13import tools.refinery.store.statecoding.StateCoderAdapter; 11import tools.refinery.store.statecoding.StateCoderAdapter;
14import tools.refinery.store.statecoding.StateCoderResult; 12import tools.refinery.store.statecoding.StateCoderResult;
15import tools.refinery.store.statecoding.neighbourhood.LazyNeighbourhoodCalculator;
16
17import java.util.Collection;
18import java.util.List;
19 13
20public class StateCoderAdapterImpl implements StateCoderAdapter { 14public class StateCoderAdapterImpl implements StateCoderAdapter {
21 final ModelStoreAdapter storeAdapter; 15 final ModelStoreAdapter storeAdapter;
22 final Model model; 16 final Model model;
23 final StateCodeCalculator calculator; 17 final StateCodeCalculator calculator;
24 18
25 StateCoderAdapterImpl(ModelStoreAdapter storeAdapter, Model model, Collection<Symbol<?>> symbols) { 19 StateCoderAdapterImpl(ModelStoreAdapter storeAdapter, StateCodeCalculator calculator, Model model) {
26 this.storeAdapter = storeAdapter; 20 this.storeAdapter = storeAdapter;
27 this.model = model; 21 this.model = model;
28 22 this.calculator = calculator;
29 List<? extends Interpretation<?>> interpretations = symbols.stream().map(model::getInterpretation).toList();
30 calculator = new LazyNeighbourhoodCalculator(interpretations);
31 } 23 }
32 24
33 @Override 25 @Override
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
index 700723f4..8268a826 100644
--- 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
@@ -5,19 +5,27 @@
5 */ 5 */
6package tools.refinery.store.statecoding.internal; 6package tools.refinery.store.statecoding.internal;
7 7
8import org.eclipse.collections.impl.set.mutable.primitive.IntHashSet;
8import tools.refinery.store.model.ModelStore; 9import tools.refinery.store.model.ModelStore;
9import tools.refinery.store.model.ModelStoreBuilder; 10import tools.refinery.store.model.ModelStoreBuilder;
10import tools.refinery.store.representation.AnySymbol; 11import tools.refinery.store.representation.AnySymbol;
11import tools.refinery.store.representation.Symbol; 12import tools.refinery.store.representation.Symbol;
13import tools.refinery.store.statecoding.StateCodeCalculatorFactory;
12import tools.refinery.store.statecoding.StateCoderBuilder; 14import tools.refinery.store.statecoding.StateCoderBuilder;
13import tools.refinery.store.statecoding.StateCoderStoreAdapter; 15import tools.refinery.store.statecoding.StateCoderStoreAdapter;
16import tools.refinery.store.statecoding.StateEquivalenceChecker;
17import tools.refinery.store.statecoding.neighbourhood.LazyNeighbourhoodCalculatorFactory;
18import tools.refinery.store.statecoding.stateequivalence.StateEquivalenceCheckerImpl;
19import tools.refinery.store.tuple.Tuple1;
14 20
15import java.util.HashSet; 21import java.util.*;
16import java.util.LinkedHashSet;
17import java.util.Set;
18 22
19public class StateCoderBuilderImpl implements StateCoderBuilder { 23public class StateCoderBuilderImpl implements StateCoderBuilder {
20 Set<AnySymbol> excluded = new HashSet<>(); 24 Set<AnySymbol> excluded = new HashSet<>();
25 IntHashSet individuals = new IntHashSet();
26
27 StateCodeCalculatorFactory calculator = new LazyNeighbourhoodCalculatorFactory();
28 StateEquivalenceChecker checker = new StateEquivalenceCheckerImpl();
21 29
22 @Override 30 @Override
23 public StateCoderBuilder exclude(AnySymbol symbol) { 31 public StateCoderBuilder exclude(AnySymbol symbol) {
@@ -26,6 +34,24 @@ public class StateCoderBuilderImpl implements StateCoderBuilder {
26 } 34 }
27 35
28 @Override 36 @Override
37 public StateCoderBuilder individual(Tuple1 tuple) {
38 individuals.add(tuple.get(0));
39 return this;
40 }
41
42 @Override
43 public StateCoderBuilder stateEquivalenceChecker(StateEquivalenceChecker stateEquivalenceChecker) {
44 this.checker = stateEquivalenceChecker;
45 return this;
46 }
47
48 @Override
49 public StateCoderBuilder stateCodeCalculatorFactory(StateCodeCalculatorFactory codeCalculatorFactory) {
50 this.calculator = codeCalculatorFactory;
51 return this;
52 }
53
54 @Override
29 public boolean isConfigured() { 55 public boolean isConfigured() {
30 return true; 56 return true;
31 } 57 }
@@ -43,6 +69,6 @@ public class StateCoderBuilderImpl implements StateCoderBuilder {
43 symbols.add(typed); 69 symbols.add(typed);
44 } 70 }
45 } 71 }
46 return new StateCoderStoreAdapterImpl(store, symbols); 72 return new StateCoderStoreAdapterImpl(store, calculator, checker, symbols, individuals);
47 } 73 }
48} 74}
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
index 5374755d..89586bfb 100644
--- 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
@@ -5,14 +5,15 @@
5 */ 5 */
6package tools.refinery.store.statecoding.internal; 6package tools.refinery.store.statecoding.internal;
7 7
8import org.eclipse.collections.api.set.primitive.IntSet;
8import tools.refinery.store.map.Version; 9import tools.refinery.store.map.Version;
9import tools.refinery.store.model.Model; 10import tools.refinery.store.model.Model;
10import tools.refinery.store.model.ModelStore; 11import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.representation.Symbol; 12import tools.refinery.store.representation.Symbol;
13import tools.refinery.store.statecoding.StateCodeCalculatorFactory;
12import tools.refinery.store.statecoding.StateCoderAdapter; 14import tools.refinery.store.statecoding.StateCoderAdapter;
13import tools.refinery.store.statecoding.StateCoderStoreAdapter; 15import tools.refinery.store.statecoding.StateCoderStoreAdapter;
14import tools.refinery.store.statecoding.StateEquivalenceChecker; 16import tools.refinery.store.statecoding.StateEquivalenceChecker;
15import tools.refinery.store.statecoding.stateequivalence.StateEquivalenceCheckerImpl;
16 17
17import java.util.Collection; 18import java.util.Collection;
18import java.util.Objects; 19import java.util.Objects;
@@ -20,12 +21,22 @@ import java.util.Objects;
20public class StateCoderStoreAdapterImpl implements StateCoderStoreAdapter { 21public class StateCoderStoreAdapterImpl implements StateCoderStoreAdapter {
21 final ModelStore store; 22 final ModelStore store;
22 final Collection<Symbol<?>> symbols; 23 final Collection<Symbol<?>> symbols;
24 final IntSet individuals;
23 25
24 final StateEquivalenceChecker equivalenceChecker = new StateEquivalenceCheckerImpl(); 26 final StateEquivalenceChecker equivalenceChecker;
27 final StateCodeCalculatorFactory codeCalculatorFactory;
25 28
26 StateCoderStoreAdapterImpl(ModelStore store, Collection<Symbol<?>> symbols) { 29 StateCoderStoreAdapterImpl(ModelStore store,
30 StateCodeCalculatorFactory codeCalculatorFactory,
31 StateEquivalenceChecker equivalenceChecker,
32 Collection<Symbol<?>> symbols,
33 IntSet individuals)
34 {
35 this.codeCalculatorFactory = codeCalculatorFactory;
36 this.equivalenceChecker = equivalenceChecker;
27 this.store = store; 37 this.store = store;
28 this.symbols = symbols; 38 this.symbols = symbols;
39 this.individuals = individuals;
29 } 40 }
30 41
31 @Override 42 @Override
@@ -35,7 +46,7 @@ public class StateCoderStoreAdapterImpl implements StateCoderStoreAdapter {
35 46
36 @Override 47 @Override
37 public StateEquivalenceChecker.EquivalenceResult checkEquivalence(Version v1, Version v2) { 48 public StateEquivalenceChecker.EquivalenceResult checkEquivalence(Version v1, Version v2) {
38 if(Objects.equals(v1,v2)) { 49 if (Objects.equals(v1, v2)) {
39 return StateEquivalenceChecker.EquivalenceResult.ISOMORPHIC; 50 return StateEquivalenceChecker.EquivalenceResult.ISOMORPHIC;
40 } 51 }
41 var model1 = this.getStore().createModelForState(v1); 52 var model1 = this.getStore().createModelForState(v1);
@@ -44,20 +55,20 @@ public class StateCoderStoreAdapterImpl implements StateCoderStoreAdapter {
44 var s1 = model1.getAdapter(StateCoderAdapter.class).calculateStateCode(); 55 var s1 = model1.getAdapter(StateCoderAdapter.class).calculateStateCode();
45 var s2 = model2.getAdapter(StateCoderAdapter.class).calculateStateCode(); 56 var s2 = model2.getAdapter(StateCoderAdapter.class).calculateStateCode();
46 57
47 if(s1.modelCode() != s2.modelCode()) { 58 if (s1.modelCode() != s2.modelCode()) {
48 return StateEquivalenceChecker.EquivalenceResult.DIFFERENT; 59 return StateEquivalenceChecker.EquivalenceResult.DIFFERENT;
49 } 60 }
50 61
51 var i1 = symbols.stream().map(model1::getInterpretation).toList(); 62 var i1 = symbols.stream().map(model1::getInterpretation).toList();
52 var i2 = symbols.stream().map(model2::getInterpretation).toList(); 63 var i2 = symbols.stream().map(model2::getInterpretation).toList();
53 64
54 return equivalenceChecker.constructMorphism(i1,s1.objectCode(),i2,s2.objectCode()); 65 return equivalenceChecker.constructMorphism(individuals, i1, s1.objectCode(), i2, s2.objectCode());
55 } 66 }
56 67
57 @Override 68 @Override
58 public StateCoderAdapter createModelAdapter(Model model) { 69 public StateCoderAdapter createModelAdapter(Model model) {
59 return new StateCoderAdapterImpl(this,model,symbols); 70 var interpretations = symbols.stream().map(model::getInterpretation).toList();
71 var coder = codeCalculatorFactory.create(interpretations, individuals);
72 return new StateCoderAdapterImpl(this, coder, model);
60 } 73 }
61
62
63} 74}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/AbstractNeighbourhoodCalculator.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/AbstractNeighbourhoodCalculator.java
new file mode 100644
index 00000000..0de76519
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/AbstractNeighbourhoodCalculator.java
@@ -0,0 +1,95 @@
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.IntSet;
9import org.eclipse.collections.impl.map.mutable.primitive.IntLongHashMap;
10import org.eclipse.collections.impl.map.mutable.primitive.LongIntHashMap;
11import tools.refinery.store.model.Interpretation;
12import tools.refinery.store.statecoding.ObjectCode;
13import tools.refinery.store.tuple.Tuple;
14import tools.refinery.store.tuple.Tuple0;
15
16import java.util.ArrayList;
17import java.util.LinkedHashMap;
18import java.util.List;
19import java.util.Random;
20
21public abstract class AbstractNeighbourhoodCalculator {
22 protected final List<Interpretation<?>> nullImpactValues;
23 protected final LinkedHashMap<Interpretation<?>, long[]> impactValues;
24 protected final IntLongHashMap individualHashValues;
25
26 protected AbstractNeighbourhoodCalculator(List<? extends Interpretation<?>> interpretations, IntSet individuals) {
27 this.nullImpactValues = new ArrayList<>();
28 this.impactValues = new LinkedHashMap<>();
29 Random random = new Random(1);
30
31 individualHashValues = new IntLongHashMap();
32 var individualsInOrder = individuals.toSortedList(Integer::compare);
33 for(int i = 0; i<individualsInOrder.size(); i++) {
34 individualHashValues.put(individualsInOrder.get(i), random.nextLong());
35 }
36
37 for (Interpretation<?> interpretation : interpretations) {
38 int arity = interpretation.getSymbol().arity();
39 if (arity == 0) {
40 nullImpactValues.add(interpretation);
41 } else {
42 long[] impact = new long[arity];
43 for (int i = 0; i < arity; i++) {
44 impact[i] = random.nextInt();
45 }
46 impactValues.put(interpretation, impact);
47 }
48 }
49 }
50
51 protected void initializeWithIndividuals(ObjectCodeImpl previous, LongIntHashMap hash2Amount) {
52 for (var entry : individualHashValues.keyValuesView()) {
53 previous.set(entry.getOne(), entry.getTwo());
54 hash2Amount.put(entry.getTwo(), 1);
55 }
56 }
57
58 protected long getTupleHash1(Tuple tuple, Object value, ObjectCode objectCodeImpl) {
59 long result = value.hashCode();
60 result = result * 31 + objectCodeImpl.get(tuple.get(0));
61 return result;
62 }
63
64 protected long getTupleHash2(Tuple tuple, Object value, ObjectCode objectCodeImpl) {
65 long result = value.hashCode();
66 result = result * 31 + objectCodeImpl.get(tuple.get(0));
67 result = result * 31 + objectCodeImpl.get(tuple.get(1));
68 if (tuple.get(0) == tuple.get(1)) {
69 result *= 31;
70 }
71 return result;
72 }
73
74 protected long getTupleHashN(Tuple tuple, Object value, ObjectCode objectCodeImpl) {
75 long result = value.hashCode();
76 for (int i = 0; i < tuple.getSize(); i++) {
77 result = result * 31 + objectCodeImpl.get(tuple.get(i));
78 }
79 return result;
80 }
81
82 protected void addHash(ObjectCodeImpl objectCodeImpl, int o, long impact, long tupleHash) {
83 long x = tupleHash * impact;
84 objectCodeImpl.set(o, objectCodeImpl.get(o) + x);
85 }
86
87 protected long calculateModelCode(long lastSum) {
88 long result = 1;
89 for (var nullImpactValue : nullImpactValues) {
90 result = result * 31 + nullImpactValue.get(Tuple0.INSTANCE).hashCode();
91 }
92 result += lastSum;
93 return result;
94 }
95}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/LazyNeighbourhoodCalculator.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/LazyNeighbourhoodCalculator.java
index 79317679..98a75e08 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/LazyNeighbourhoodCalculator.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/LazyNeighbourhoodCalculator.java
@@ -6,74 +6,48 @@
6package tools.refinery.store.statecoding.neighbourhood; 6package tools.refinery.store.statecoding.neighbourhood;
7 7
8import org.eclipse.collections.api.map.primitive.LongIntMap; 8import org.eclipse.collections.api.map.primitive.LongIntMap;
9import org.eclipse.collections.api.set.primitive.IntSet;
9import org.eclipse.collections.impl.map.mutable.primitive.LongIntHashMap; 10import org.eclipse.collections.impl.map.mutable.primitive.LongIntHashMap;
10import tools.refinery.store.map.Cursor; 11import tools.refinery.store.map.Cursor;
11import tools.refinery.store.model.Interpretation; 12import tools.refinery.store.model.Interpretation;
12import tools.refinery.store.statecoding.StateCodeCalculator; 13import tools.refinery.store.statecoding.StateCodeCalculator;
13import tools.refinery.store.statecoding.StateCoderResult; 14import tools.refinery.store.statecoding.StateCoderResult;
14import tools.refinery.store.tuple.Tuple; 15import tools.refinery.store.tuple.Tuple;
15import tools.refinery.store.tuple.Tuple0;
16 16
17import java.util.ArrayList;
18import java.util.LinkedHashMap;
19import java.util.List; 17import java.util.List;
20import java.util.Random;
21 18
22public class LazyNeighbourhoodCalculator implements StateCodeCalculator { 19public class LazyNeighbourhoodCalculator extends AbstractNeighbourhoodCalculator implements StateCodeCalculator {
23 protected final List<Interpretation<?>> nullImpactValues; 20 public LazyNeighbourhoodCalculator(List<? extends Interpretation<?>> interpretations, IntSet individuals) {
24 protected final LinkedHashMap<Interpretation<?>, long[]> impactValues; 21 super(interpretations, individuals);
25
26 public LazyNeighbourhoodCalculator(List<? extends Interpretation<?>> interpretations) {
27 this.nullImpactValues = new ArrayList<>();
28 this.impactValues = new LinkedHashMap<>();
29 Random random = new Random(1);
30
31 for (Interpretation<?> interpretation : interpretations) {
32 int arity = interpretation.getSymbol().arity();
33 if (arity == 0) {
34 nullImpactValues.add(interpretation);
35 } else {
36 long[] impact = new long[arity];
37 for (int i = 0; i < arity; i++) {
38 impact[i] = random.nextInt();
39 }
40 impactValues.put(interpretation, impact);
41 }
42 }
43 } 22 }
44 23
45 public StateCoderResult calculateCodes() { 24 public StateCoderResult calculateCodes() {
46 ObjectCodeImpl previous = new ObjectCodeImpl(); 25 ObjectCodeImpl previous = new ObjectCodeImpl();
47 ObjectCodeImpl next = new ObjectCodeImpl(); 26 LongIntHashMap hash2Amount = new LongIntHashMap();
48 LongIntMap hash2Amount = new LongIntHashMap(); 27
28 initializeWithIndividuals(previous, hash2Amount);
49 29
50 long lastSum; 30 long lastSum;
51 int lastSize = 1; 31 // All hash code is 0, except to the individuals.
52 boolean grows; 32 int lastSize = hash2Amount.size() + 1;
53 33
34 boolean grows;
54 do { 35 do {
36 ObjectCodeImpl next = new ObjectCodeImpl();
55 constructNextObjectCodes(previous, next, hash2Amount); 37 constructNextObjectCodes(previous, next, hash2Amount);
56 38
57 LongIntHashMap nextHash2Amount = new LongIntHashMap(); 39 LongIntHashMap nextHash2Amount = new LongIntHashMap();
58 lastSum = calculateLastSum(previous, next, hash2Amount, nextHash2Amount); 40 lastSum = calculateLastSum(previous, next, hash2Amount, nextHash2Amount);
59 41
60 previous = next;
61 next = null;
62
63 int nextSize = nextHash2Amount.size(); 42 int nextSize = nextHash2Amount.size();
64 grows = nextSize > lastSize; 43 grows = nextSize > lastSize;
65 lastSize = nextSize; 44 lastSize = nextSize;
66 45
67 if (grows) { 46 previous = next;
68 next = new ObjectCodeImpl(previous); 47 hash2Amount = nextHash2Amount;
69 }
70 } while (grows); 48 } while (grows);
71 49
72 long result = 1; 50 long result = calculateModelCode(lastSum);
73 for (var nullImpactValue : nullImpactValues) {
74 result = result * 31 + nullImpactValue.get(Tuple0.INSTANCE).hashCode();
75 }
76 result += lastSum;
77 51
78 return new StateCoderResult((int) result, previous); 52 return new StateCoderResult((int) result, previous);
79 } 53 }
@@ -96,7 +70,7 @@ public class LazyNeighbourhoodCalculator implements StateCodeCalculator {
96 final long shifted1 = hash >>> 8; 70 final long shifted1 = hash >>> 8;
97 final long shifted2 = hash << 8; 71 final long shifted2 = hash << 8;
98 final long shifted3 = hash >> 2; 72 final long shifted3 = hash >> 2;
99 lastSum += shifted1*shifted3 + shifted2; 73 lastSum += shifted1 * shifted3 + shifted2;
100 } 74 }
101 return lastSum; 75 return lastSum;
102 } 76 }
@@ -126,7 +100,7 @@ public class LazyNeighbourhoodCalculator implements StateCodeCalculator {
126 100
127 private boolean isUnique(LongIntMap hash2Amount, ObjectCodeImpl objectCodeImpl, int object) { 101 private boolean isUnique(LongIntMap hash2Amount, ObjectCodeImpl objectCodeImpl, int object) {
128 final long hash = objectCodeImpl.get(object); 102 final long hash = objectCodeImpl.get(object);
129 if(hash == 0) { 103 if (hash == 0) {
130 return false; 104 return false;
131 } 105 }
132 final int amount = hash2Amount.get(hash); 106 final int amount = hash2Amount.get(hash);
@@ -149,12 +123,12 @@ public class LazyNeighbourhoodCalculator implements StateCodeCalculator {
149 } 123 }
150 124
151 private void lazyImpactCalculation2(LongIntMap hash2Amount, ObjectCodeImpl previous, ObjectCodeImpl next, long[] impactValues, Cursor<Tuple, ?> cursor) { 125 private void lazyImpactCalculation2(LongIntMap hash2Amount, ObjectCodeImpl previous, ObjectCodeImpl next, long[] impactValues, Cursor<Tuple, ?> cursor) {
152 Tuple tuple = cursor.getKey(); 126 final Tuple tuple = cursor.getKey();
153 int o1 = tuple.get(0); 127 final int o1 = tuple.get(0);
154 int o2 = tuple.get(1); 128 final int o2 = tuple.get(1);
155 129
156 boolean u1 = isUnique(hash2Amount, previous, o1); 130 final boolean u1 = isUnique(hash2Amount, previous, o1);
157 boolean u2 = isUnique(hash2Amount, previous, o2); 131 final boolean u2 = isUnique(hash2Amount, previous, o2);
158 132
159 if (u1 && u2) { 133 if (u1 && u2) {
160 next.ensureSize(o1); 134 next.ensureSize(o1);
@@ -175,9 +149,9 @@ public class LazyNeighbourhoodCalculator implements StateCodeCalculator {
175 } 149 }
176 150
177 private void lazyImpactCalculationN(LongIntMap hash2Amount, ObjectCodeImpl previous, ObjectCodeImpl next, long[] impactValues, Cursor<Tuple, ?> cursor) { 151 private void lazyImpactCalculationN(LongIntMap hash2Amount, ObjectCodeImpl previous, ObjectCodeImpl next, long[] impactValues, Cursor<Tuple, ?> cursor) {
178 Tuple tuple = cursor.getKey(); 152 final Tuple tuple = cursor.getKey();
179 153
180 boolean[] uniques = new boolean[tuple.getSize()]; 154 final boolean[] uniques = new boolean[tuple.getSize()];
181 boolean allUnique = true; 155 boolean allUnique = true;
182 for (int i = 0; i < tuple.getSize(); i++) { 156 for (int i = 0; i < tuple.getSize(); i++) {
183 final boolean isUnique = isUnique(hash2Amount, previous, tuple.get(i)); 157 final boolean isUnique = isUnique(hash2Amount, previous, tuple.get(i));
@@ -204,32 +178,4 @@ public class LazyNeighbourhoodCalculator implements StateCodeCalculator {
204 } 178 }
205 } 179 }
206 180
207 private long getTupleHash1(Tuple tuple, Object value, ObjectCodeImpl objectCodeImpl) {
208 long result = value.hashCode();
209 result = result * 31 + objectCodeImpl.get(tuple.get(0));
210 return result;
211 }
212
213 private long getTupleHash2(Tuple tuple, Object value, ObjectCodeImpl objectCodeImpl) {
214 long result = value.hashCode();
215 result = result * 31 + objectCodeImpl.get(tuple.get(0));
216 result = result * 31 + objectCodeImpl.get(tuple.get(1));
217 if (tuple.get(0) == tuple.get(1)) {
218 result*=31;
219 }
220 return result;
221 }
222
223 private long getTupleHashN(Tuple tuple, Object value, ObjectCodeImpl objectCodeImpl) {
224 long result = value.hashCode();
225 for (int i = 0; i < tuple.getSize(); i++) {
226 result = result * 31 + objectCodeImpl.get(tuple.get(i));
227 }
228 return result;
229 }
230
231 protected void addHash(ObjectCodeImpl objectCodeImpl, int o, long impact, long tupleHash) {
232 long x = tupleHash * impact;
233 objectCodeImpl.set(o, objectCodeImpl.get(o) + x);
234 }
235} 181}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/LazyNeighbourhoodCalculatorFactory.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/LazyNeighbourhoodCalculatorFactory.java
new file mode 100644
index 00000000..2e499f95
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/LazyNeighbourhoodCalculatorFactory.java
@@ -0,0 +1,20 @@
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.IntSet;
9import tools.refinery.store.model.Interpretation;
10import tools.refinery.store.statecoding.StateCodeCalculator;
11import tools.refinery.store.statecoding.StateCodeCalculatorFactory;
12
13import java.util.List;
14
15public class LazyNeighbourhoodCalculatorFactory implements StateCodeCalculatorFactory {
16 @Override
17 public StateCodeCalculator create(List<? extends Interpretation<?>> interpretations, IntSet individuals) {
18 return new LazyNeighbourhoodCalculator(interpretations,individuals);
19 }
20}
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
deleted file mode 100644
index 212291c3..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/NeighbourhoodCalculator.java
+++ /dev/null
@@ -1,132 +0,0 @@
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.statecoding.StateCodeCalculator;
12import tools.refinery.store.statecoding.StateCoderResult;
13import tools.refinery.store.tuple.Tuple;
14import tools.refinery.store.tuple.Tuple0;
15
16import java.util.ArrayList;
17import java.util.LinkedHashMap;
18import java.util.List;
19import java.util.Random;
20
21public class NeighbourhoodCalculator implements StateCodeCalculator {
22 protected final List<Interpretation<?>> nullImpactValues;
23 protected final LinkedHashMap<Interpretation<?>, long[]> impactValues;
24
25 public NeighbourhoodCalculator(List<? extends Interpretation<?>> interpretations) {
26 this.nullImpactValues = new ArrayList<>();
27 this.impactValues = new LinkedHashMap<>();
28 Random random = new Random(1);
29
30 for (Interpretation<?> interpretation : interpretations) {
31 int arity = interpretation.getSymbol().arity();
32 if (arity == 0) {
33 nullImpactValues.add(interpretation);
34 } else {
35 long[] impact = new long[arity];
36 for (int i = 0; i < arity; i++) {
37 impact[i] = random.nextLong();
38 }
39 impactValues.put(interpretation, impact);
40 }
41 }
42 }
43
44 @Override
45 public StateCoderResult calculateCodes() {
46 ObjectCodeImpl previous = new ObjectCodeImpl();
47 ObjectCodeImpl next = new ObjectCodeImpl();
48
49 int previousSize = 1;
50 long lastSum;
51 boolean grows;
52
53 do{
54 for (var impactValueEntry : this.impactValues.entrySet()) {
55 Interpretation<?> interpretation = impactValueEntry.getKey();
56 long[] impact = impactValueEntry.getValue();
57 var cursor = interpretation.getAll();
58 while (cursor.move()) {
59 Tuple tuple = cursor.getKey();
60 Object value = cursor.getValue();
61 long tupleHash = getTupleHash(tuple, value, previous);
62 addHash(next, tuple, impact, tupleHash);
63 }
64 }
65
66 previous = next;
67 next = null;
68 lastSum = 0;
69 MutableLongSet codes = new LongHashSet();
70 for (int i = 0; i < previous.getSize(); i++) {
71 long objectHash = previous.get(i);
72 codes.add(objectHash);
73
74 final long shifted1 = objectHash>>> 32;
75 final long shifted2 = objectHash << 32;
76 lastSum += shifted1 + shifted2;
77 }
78 int nextSize = codes.size();
79 grows = previousSize < nextSize;
80 previousSize = nextSize;
81
82 if(grows) {
83 next = new ObjectCodeImpl(previous);
84 }
85 } while (grows);
86
87 long result = 1;
88 for (var nullImpactValue : nullImpactValues) {
89 result = result * 31 + nullImpactValue.get(Tuple0.INSTANCE).hashCode();
90 }
91 result += lastSum;
92
93 return new StateCoderResult((int) result, previous);
94 }
95
96 protected long getTupleHash(Tuple tuple, Object value, ObjectCodeImpl objectCodeImpl) {
97 long result = value.hashCode();
98 int arity = tuple.getSize();
99 if (arity == 1) {
100 result = result * 31 + objectCodeImpl.get(tuple.get(0));
101 } else if (arity == 2) {
102 result = result * 31 + objectCodeImpl.get(tuple.get(0));
103 result = result * 31 + objectCodeImpl.get(tuple.get(1));
104 if (tuple.get(0) == tuple.get(1)) {
105 result++;
106 }
107 } else if (arity > 2) {
108 for (int i = 0; i < arity; i++) {
109 result = result * 31 + objectCodeImpl.get(tuple.get(i));
110 }
111 }
112 return result;
113 }
114
115 protected void addHash(ObjectCodeImpl objectCodeImpl, Tuple tuple, long[] impact, long tupleHashCode) {
116 if (tuple.getSize() == 1) {
117 addHash(objectCodeImpl, tuple.get(0), impact[0], tupleHashCode);
118 } else if (tuple.getSize() == 2) {
119 addHash(objectCodeImpl, tuple.get(0), impact[0], tupleHashCode);
120 addHash(objectCodeImpl, tuple.get(1), impact[1], tupleHashCode);
121 } else if (tuple.getSize() > 2) {
122 for (int i = 0; i < tuple.getSize(); i++) {
123 addHash(objectCodeImpl, tuple.get(i), impact[i], tupleHashCode);
124 }
125 }
126 }
127
128 protected void addHash(ObjectCodeImpl objectCodeImpl, int o, long impact, long tupleHash) {
129 objectCodeImpl.set(o, objectCodeImpl.get(o) + tupleHash * impact);
130 }
131
132}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/stateequivalence/StateEquivalenceCheckerImpl.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/stateequivalence/StateEquivalenceCheckerImpl.java
index fd704086..e58a2502 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/statecoding/stateequivalence/StateEquivalenceCheckerImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/stateequivalence/StateEquivalenceCheckerImpl.java
@@ -5,7 +5,9 @@
5 */ 5 */
6package tools.refinery.store.statecoding.stateequivalence; 6package tools.refinery.store.statecoding.stateequivalence;
7 7
8import org.eclipse.collections.api.factory.primitive.IntIntMaps;
8import org.eclipse.collections.api.map.primitive.IntIntMap; 9import org.eclipse.collections.api.map.primitive.IntIntMap;
10import org.eclipse.collections.api.set.primitive.IntSet;
9import org.eclipse.collections.impl.map.mutable.primitive.IntIntHashMap; 11import org.eclipse.collections.impl.map.mutable.primitive.IntIntHashMap;
10import org.eclipse.collections.impl.map.mutable.primitive.LongObjectHashMap; 12import org.eclipse.collections.impl.map.mutable.primitive.LongObjectHashMap;
11import org.eclipse.collections.impl.set.mutable.primitive.IntHashSet; 13import org.eclipse.collections.impl.set.mutable.primitive.IntHashSet;
@@ -23,7 +25,8 @@ public class StateEquivalenceCheckerImpl implements StateEquivalenceChecker {
23 public static final int LIMIT = 1000; 25 public static final int LIMIT = 1000;
24 26
25 @Override 27 @Override
26 public EquivalenceResult constructMorphism(List<? extends Interpretation<?>> interpretations1, 28 public EquivalenceResult constructMorphism(IntSet individuals,
29 List<? extends Interpretation<?>> interpretations1,
27 ObjectCode code1, 30 ObjectCode code1,
28 List<? extends Interpretation<?>> interpretations2, 31 List<? extends Interpretation<?>> interpretations2,
29 ObjectCode code2) { 32 ObjectCode code2) {
@@ -34,7 +37,8 @@ public class StateEquivalenceCheckerImpl implements StateEquivalenceChecker {
34 IntIntHashMap object2PermutationGroup = new IntIntHashMap(); 37 IntIntHashMap object2PermutationGroup = new IntIntHashMap();
35 List<List<IntIntMap>> permutationsGroups = new ArrayList<>(); 38 List<List<IntIntMap>> permutationsGroups = new ArrayList<>();
36 39
37 final EquivalenceResult permutations = constructPermutationNavigation(indexByHash(code1), indexByHash(code2), 40 final EquivalenceResult permutations = constructPermutationNavigation(individuals,
41 indexByHash(code1, individuals), indexByHash(code2, individuals),
38 object2PermutationGroup, permutationsGroups); 42 object2PermutationGroup, permutationsGroups);
39 43
40 if (permutations == EquivalenceResult.DIFFERENT) { 44 if (permutations == EquivalenceResult.DIFFERENT) {
@@ -60,24 +64,27 @@ public class StateEquivalenceCheckerImpl implements StateEquivalenceChecker {
60 return EquivalenceResult.DIFFERENT; 64 return EquivalenceResult.DIFFERENT;
61 } 65 }
62 66
63 private LongObjectHashMap<IntHashSet> indexByHash(ObjectCode code) { 67 private LongObjectHashMap<IntHashSet> indexByHash(ObjectCode code, IntSet individuals) {
64 LongObjectHashMap<IntHashSet> result = new LongObjectHashMap<>(); 68 LongObjectHashMap<IntHashSet> result = new LongObjectHashMap<>();
65 for (int o = 0; o < code.getSize(); o++) { 69 for (int o = 0; o < code.getSize(); o++) {
66 long hash = code.get(o); 70 if(! individuals.contains(o)){
67 var equivalenceClass = result.get(hash); 71 long hash = code.get(o);
68 if (equivalenceClass == null) { 72 var equivalenceClass = result.get(hash);
69 equivalenceClass = new IntHashSet(); 73 if (equivalenceClass == null) {
70 result.put(hash, equivalenceClass); 74 equivalenceClass = new IntHashSet();
75 result.put(hash, equivalenceClass);
76 }
77 equivalenceClass.add(o);
71 } 78 }
72 equivalenceClass.add(o);
73 } 79 }
74 return result; 80 return result;
75 } 81 }
76 82
77 private EquivalenceResult constructPermutationNavigation(LongObjectHashMap<IntHashSet> map1, 83 private EquivalenceResult constructPermutationNavigation(IntSet individuals,
78 LongObjectHashMap<IntHashSet> map2, 84 LongObjectHashMap<IntHashSet> map1,
79 IntIntHashMap emptyMapToListOfOptions, 85 LongObjectHashMap<IntHashSet> map2,
80 List<List<IntIntMap>> emptyListOfOptions) { 86 IntIntHashMap object2OptionIndex,
87 List<List<IntIntMap>> listOfOptions) {
81 if (map1.size() != map2.size()) { 88 if (map1.size() != map2.size()) {
82 return EquivalenceResult.DIFFERENT; 89 return EquivalenceResult.DIFFERENT;
83 } 90 }
@@ -101,10 +108,13 @@ public class StateEquivalenceCheckerImpl implements StateEquivalenceChecker {
101 108
102 allComplete &= pairing.isComplete(); 109 allComplete &= pairing.isComplete();
103 110
104 final int optionIndex = emptyListOfOptions.size(); 111 final int optionIndex = listOfOptions.size();
105 set1.forEach(key -> emptyMapToListOfOptions.put(key, optionIndex)); 112 set1.forEach(key -> object2OptionIndex.put(key, optionIndex));
106 emptyListOfOptions.add(pairing.permutations()); 113 listOfOptions.add(pairing.permutations());
107 } 114 }
115
116 individuals.forEach(o -> listOfOptions.add(o,List.of(IntIntMaps.immutable.of(o,o))));
117
108 if(allComplete) { 118 if(allComplete) {
109 return EquivalenceResult.ISOMORPHIC; 119 return EquivalenceResult.ISOMORPHIC;
110 } else { 120 } else {
diff --git a/subprojects/store/src/test/java/tools/refinery/store/statecoding/StateCoderBuildTest.java b/subprojects/store/src/test/java/tools/refinery/store/statecoding/StateCoderBuildTest.java
index b0b80af7..a4e953ea 100644
--- a/subprojects/store/src/test/java/tools/refinery/store/statecoding/StateCoderBuildTest.java
+++ b/subprojects/store/src/test/java/tools/refinery/store/statecoding/StateCoderBuildTest.java
@@ -19,11 +19,10 @@ class StateCoderBuildTest {
19 Symbol<Boolean> friend = new Symbol<>("friend", 2, Boolean.class, false); 19 Symbol<Boolean> friend = new Symbol<>("friend", 2, Boolean.class, false);
20 20
21 @Test 21 @Test
22 void simpleStateCoderTest() { 22 void simpleStateCoderBuildTest() {
23 var store = ModelStore.builder() 23 var store = ModelStore.builder()
24 .symbols(person, age, friend) 24 .symbols(person, age, friend)
25 .with(StateCoderAdapter 25 .with(StateCoderAdapter.builder())
26 .builder())
27 .build(); 26 .build();
28 27
29 var model = store.createEmptyModel(); 28 var model = store.createEmptyModel();
@@ -33,6 +32,7 @@ class StateCoderBuildTest {
33 var personI = model.getInterpretation(person); 32 var personI = model.getInterpretation(person);
34 var friendI = model.getInterpretation(friend); 33 var friendI = model.getInterpretation(friend);
35 var ageI = model.getInterpretation(age); 34 var ageI = model.getInterpretation(age);
35
36 fill(personI, friendI, ageI); 36 fill(personI, friendI, ageI);
37 37
38 stateCoder.calculateStateCode(); 38 stateCoder.calculateStateCode();
@@ -68,6 +68,51 @@ class StateCoderBuildTest {
68 assertEquals(code,stateCoder.calculateStateCode().modelCode()); 68 assertEquals(code,stateCoder.calculateStateCode().modelCode());
69 } 69 }
70 70
71 @Test
72 void notIndividualTest() {
73 var store = ModelStore.builder()
74 .symbols(friend)
75 .with(StateCoderAdapter.builder())
76 .build();
77
78 var model = store.createEmptyModel();
79 var stateCoder = model.getAdapter(StateCoderAdapter.class);
80
81 var friendI = model.getInterpretation(friend);
82
83 friendI.put(Tuple.of(1,2),true);
84 int code1 = stateCoder.calculateModelCode();
85
86 friendI.put(Tuple.of(1,2),false);
87 friendI.put(Tuple.of(2,1),true);
88 int code2 = stateCoder.calculateModelCode();
89
90 assertEquals(code1,code2);
91 }
92
93 @Test
94 void individualTest() {
95 var store = ModelStore.builder()
96 .symbols(friend)
97 .with(StateCoderAdapter.builder()
98 .individual(Tuple.of(1)))
99 .build();
100
101 var model = store.createEmptyModel();
102 var stateCoder = model.getAdapter(StateCoderAdapter.class);
103
104 var friendI = model.getInterpretation(friend);
105
106 friendI.put(Tuple.of(1,2),true);
107 int code1 = stateCoder.calculateModelCode();
108
109 friendI.put(Tuple.of(1,2),false);
110 friendI.put(Tuple.of(2,1),true);
111 int code2 = stateCoder.calculateModelCode();
112
113 assertNotEquals(code1,code2);
114 }
115
71 private static void fill(Interpretation<Boolean> personI, Interpretation<Boolean> friendI, Interpretation<Integer> ageI) { 116 private static void fill(Interpretation<Boolean> personI, Interpretation<Boolean> friendI, Interpretation<Integer> ageI) {
72 personI.put(Tuple.of(1), true); 117 personI.put(Tuple.of(1), true);
73 personI.put(Tuple.of(2), true); 118 personI.put(Tuple.of(2), true);