From 36550e2be2146b290210cb12c76d0341e499f849 Mon Sep 17 00:00:00 2001 From: OszkarSemerath Date: Mon, 7 Aug 2023 16:07:09 +0200 Subject: Tests + small changes for AbstractNeighbourhoodCalculator and StateEquivalenceCheckerImpl --- .../AbstractNeighbourhoodCalculator.java | 15 +- .../statecoding/neighbourhood/ObjectCodeImpl.java | 3 +- .../StateEquivalenceCheckerImpl.java | 19 +- .../store/statecoding/EquivalenceTest.java | 178 +++++++++++++++++++ .../store/statecoding/StateCoderUnitTest.java | 195 +++++++++++++++++++++ 5 files changed, 390 insertions(+), 20 deletions(-) create mode 100644 subprojects/store/src/test/java/tools/refinery/store/statecoding/EquivalenceTest.java create mode 100644 subprojects/store/src/test/java/tools/refinery/store/statecoding/StateCoderUnitTest.java (limited to 'subprojects/store') 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 index 0de76519..c3f8a586 100644 --- 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 @@ -13,10 +13,7 @@ import tools.refinery.store.statecoding.ObjectCode; import tools.refinery.store.tuple.Tuple; import tools.refinery.store.tuple.Tuple0; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Random; +import java.util.*; public abstract class AbstractNeighbourhoodCalculator { protected final List> nullImpactValues; @@ -56,13 +53,13 @@ public abstract class AbstractNeighbourhoodCalculator { } protected long getTupleHash1(Tuple tuple, Object value, ObjectCode objectCodeImpl) { - long result = value.hashCode(); + long result = Objects.hashCode(value); result = result * 31 + objectCodeImpl.get(tuple.get(0)); return result; } protected long getTupleHash2(Tuple tuple, Object value, ObjectCode objectCodeImpl) { - long result = value.hashCode(); + long result = Objects.hashCode(value); result = result * 31 + objectCodeImpl.get(tuple.get(0)); result = result * 31 + objectCodeImpl.get(tuple.get(1)); if (tuple.get(0) == tuple.get(1)) { @@ -72,7 +69,7 @@ public abstract class AbstractNeighbourhoodCalculator { } protected long getTupleHashN(Tuple tuple, Object value, ObjectCode objectCodeImpl) { - long result = value.hashCode(); + long result = Objects.hashCode(value); for (int i = 0; i < tuple.getSize(); i++) { result = result * 31 + objectCodeImpl.get(tuple.get(i)); } @@ -85,9 +82,9 @@ public abstract class AbstractNeighbourhoodCalculator { } protected long calculateModelCode(long lastSum) { - long result = 1; + long result = 0; for (var nullImpactValue : nullImpactValues) { - result = result * 31 + nullImpactValue.get(Tuple0.INSTANCE).hashCode(); + result = result * 31 + Objects.hashCode(nullImpactValue.get(Tuple0.INSTANCE)); } result += lastSum; return result; diff --git a/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/ObjectCodeImpl.java b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/ObjectCodeImpl.java index 08e3a90b..c4d86cf1 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/ObjectCodeImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/statecoding/neighbourhood/ObjectCodeImpl.java @@ -50,7 +50,8 @@ public class ObjectCodeImpl implements ObjectCode { public void set(int object, long value) { ensureSize(object); - vector[object]=value; + final long valueToPut = value == 0 ? 1 : value; + vector[object]=valueToPut; } public int getSize() { 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 e58a2502..34dba34e 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 @@ -29,11 +29,8 @@ public class StateEquivalenceCheckerImpl implements StateEquivalenceChecker { List> interpretations1, ObjectCode code1, List> interpretations2, - ObjectCode code2) { - if (code1.getSize() != code2.getSize()) { - return EquivalenceResult.DIFFERENT; - } - + ObjectCode code2) + { IntIntHashMap object2PermutationGroup = new IntIntHashMap(); List> permutationsGroups = new ArrayList<>(); @@ -69,12 +66,14 @@ public class StateEquivalenceCheckerImpl implements StateEquivalenceChecker { for (int o = 0; o < code.getSize(); o++) { if(! individuals.contains(o)){ long hash = code.get(o); - var equivalenceClass = result.get(hash); - if (equivalenceClass == null) { - equivalenceClass = new IntHashSet(); - result.put(hash, equivalenceClass); + if(hash != 0) { + var equivalenceClass = result.get(hash); + if (equivalenceClass == null) { + equivalenceClass = new IntHashSet(); + result.put(hash, equivalenceClass); + } + equivalenceClass.add(o); } - equivalenceClass.add(o); } } return result; diff --git a/subprojects/store/src/test/java/tools/refinery/store/statecoding/EquivalenceTest.java b/subprojects/store/src/test/java/tools/refinery/store/statecoding/EquivalenceTest.java new file mode 100644 index 00000000..8a9c0e9b --- /dev/null +++ b/subprojects/store/src/test/java/tools/refinery/store/statecoding/EquivalenceTest.java @@ -0,0 +1,178 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.statecoding; + +import org.junit.jupiter.api.Test; +import tools.refinery.store.map.Version; +import tools.refinery.store.model.Model; +import tools.refinery.store.model.ModelStore; +import tools.refinery.store.representation.Symbol; +import tools.refinery.store.tuple.Tuple; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class EquivalenceTest { + Symbol person = new Symbol<>("Person", 1, Boolean.class, false); + Symbol age = new Symbol<>("age", 1, Integer.class, null); + Symbol friend = new Symbol<>("friend", 2, Boolean.class, false); + Symbol parents = new Symbol<>("parents", 3, Boolean.class, false); + Symbol population = new Symbol<>("population", 0, Integer.class, 0); + + private ModelStore createStore() { + return ModelStore.builder() + .symbols(person, age, friend, parents, population) + .with(StateCoderAdapter.builder()) + .build(); + } + + @Test + void emptyModelCode0() { + ModelStore store = createStore(); + var stateCoder = store.getAdapter(StateCoderStoreAdapter.class); + Model model = createStore().createEmptyModel(); + Version v1 = model.commit(); + Version v2 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.ISOMORPHIC, stateCoder.checkEquivalence(v1, v2)); + + var personI = model.getInterpretation(person); + var friendI = model.getInterpretation(friend); + + personI.put(Tuple.of(1), true); + personI.put(Tuple.of(2), true); + friendI.put(Tuple.of(1, 2), true); + + Version v3 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v1, v3)); + } + + @Test + void nullRelationTest() { + ModelStore store = createStore(); + var stateCoder = store.getAdapter(StateCoderStoreAdapter.class); + Model model = createStore().createEmptyModel(); + + var populationI = model.getInterpretation(population); + + Version v1 = model.commit(); + + populationI.put(Tuple.of(), 1); + Version v2 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v1, v2)); + + populationI.put(Tuple.of(), 2); + Version v3 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v2, v3)); + } + + @Test + void unaryBooleanTest() { + ModelStore store = createStore(); + var stateCoder = store.getAdapter(StateCoderStoreAdapter.class); + Model model = createStore().createEmptyModel(); + + var personI = model.getInterpretation(person); + + Version v1 = model.commit(); + + personI.put(Tuple.of(1), true); + Version v2 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v1, v2)); + + personI.put(Tuple.of(2), true); + Version v3 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v2, v3)); + + personI.put(Tuple.of(1), false); + Version v4 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.ISOMORPHIC, stateCoder.checkEquivalence(v2, v4)); + } + + @Test + void unaryIntTest() { + ModelStore store = createStore(); + var stateCoder = store.getAdapter(StateCoderStoreAdapter.class); + Model model = createStore().createEmptyModel(); + + var ageI = model.getInterpretation(age); + + ageI.put(Tuple.of(1), 3); + Version v1 = model.commit(); + + ageI.put(Tuple.of(1), 4); + Version v2 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v1, v2)); + + ageI.put(Tuple.of(2), 4); + Version v3 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v2, v3)); + + ageI.put(Tuple.of(1), null); + Version v4 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.ISOMORPHIC, stateCoder.checkEquivalence(v2, v4)); + } + + @Test + void binaryTest() { + ModelStore store = createStore(); + var stateCoder = store.getAdapter(StateCoderStoreAdapter.class); + Model model = createStore().createEmptyModel(); + + var friendI = model.getInterpretation(friend); + + Version v1 = model.commit(); + + friendI.put(Tuple.of(1, 2), true); + Version v2 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v1, v2)); + + friendI.put(Tuple.of(2, 1), true); + Version v3 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v2, v3)); + + friendI.put(Tuple.of(1, 2), false); + Version v4 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.ISOMORPHIC, stateCoder.checkEquivalence(v2, v4)); + } + + @Test + void NaryTest() { + ModelStore store = createStore(); + var stateCoder = store.getAdapter(StateCoderStoreAdapter.class); + Model model = createStore().createEmptyModel(); + + var parentsI = model.getInterpretation(parents); + + Version v1 = model.commit(); + + parentsI.put(Tuple.of(3, 1, 2), true); + Version v2 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v1, v2)); + + parentsI.put(Tuple.of(4, 1, 2), true); + Version v3 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.DIFFERENT, stateCoder.checkEquivalence(v2, v3)); + + parentsI.put(Tuple.of(3, 1, 2), false); + Version v4 = model.commit(); + + assertEquals(StateEquivalenceChecker.EquivalenceResult.ISOMORPHIC, stateCoder.checkEquivalence(v2, v4)); + } +} diff --git a/subprojects/store/src/test/java/tools/refinery/store/statecoding/StateCoderUnitTest.java b/subprojects/store/src/test/java/tools/refinery/store/statecoding/StateCoderUnitTest.java new file mode 100644 index 00000000..d94df841 --- /dev/null +++ b/subprojects/store/src/test/java/tools/refinery/store/statecoding/StateCoderUnitTest.java @@ -0,0 +1,195 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.statecoding; + +import org.junit.jupiter.api.Test; +import tools.refinery.store.model.Model; +import tools.refinery.store.model.ModelStore; +import tools.refinery.store.representation.Symbol; +import tools.refinery.store.tuple.Tuple; + +import java.util.Objects; + +import static org.junit.jupiter.api.Assertions.*; + +class StateCoderUnitTest { + Symbol person = new Symbol<>("Person", 1, Boolean.class, false); + Symbol age = new Symbol<>("age", 1, Integer.class, null); + Symbol friend = new Symbol<>("friend", 2, Boolean.class, false); + Symbol parents = new Symbol<>("parents", 3, Boolean.class, false); + Symbol population = new Symbol<>("population", 0, Integer.class, 0); + + private Model createEmptyModel() { + var store = ModelStore.builder() + .symbols(person, age, friend, parents, population) + .with(StateCoderAdapter.builder()) + .build(); + + return store.createEmptyModel(); + } + + @Test + void emptyModelCode0() { + Model model = createEmptyModel(); + var stateCoder = model.getAdapter(StateCoderAdapter.class); + + assertEquals(0, stateCoder.calculateModelCode()); + + var personI = model.getInterpretation(person); + var friendI = model.getInterpretation(friend); + + personI.put(Tuple.of(1), true); + personI.put(Tuple.of(2), true); + friendI.put(Tuple.of(1, 2), true); + + assertNotEquals(0, stateCoder.calculateModelCode()); + } + + @Test + void emptyObjectCode0() { + Model model = createEmptyModel(); + var stateCoder = model.getAdapter(StateCoderAdapter.class); + + var personI = model.getInterpretation(person); + var friendI = model.getInterpretation(friend); + + assertEquals(0, stateCoder.calculateObjectCode().get(1)); + assertEquals(0, stateCoder.calculateObjectCode().get(17)); + + personI.put(Tuple.of(1), true); + personI.put(Tuple.of(2), true); + friendI.put(Tuple.of(1, 2), true); + + assertNotEquals(0, stateCoder.calculateObjectCode().get(1)); + assertEquals(0, stateCoder.calculateObjectCode().get(17)); + } + + @Test + void nullRelationTest() { + Model model = createEmptyModel(); + var stateCoder = model.getAdapter(StateCoderAdapter.class); + + var populationI = model.getInterpretation(population); + + final int hashOf0 = Objects.hashCode(0); + + assertEquals(hashOf0, stateCoder.calculateModelCode()); + + populationI.put(Tuple.of(), 1); + int code1 = stateCoder.calculateModelCode(); + + assertNotEquals(hashOf0, stateCoder.calculateModelCode()); + + populationI.put(Tuple.of(), 2); + int code2 = stateCoder.calculateModelCode(); + + assertNotEquals(code1, code2); + + populationI.put(Tuple.of(), 1); + assertEquals(code1, stateCoder.calculateModelCode()); + } + + @Test + void unaryBooleanTest() { + Model model = createEmptyModel(); + var stateCoder = model.getAdapter(StateCoderAdapter.class); + + var personI = model.getInterpretation(person); + + assertEquals(0, stateCoder.calculateModelCode()); + + personI.put(Tuple.of(1), true); + int code1 = stateCoder.calculateModelCode(); + + assertNotEquals(0, stateCoder.calculateModelCode()); + + personI.put(Tuple.of(2), true); + int code2 = stateCoder.calculateModelCode(); + + assertNotEquals(code1, code2); + + personI.put(Tuple.of(1), false); + assertEquals(code1, stateCoder.calculateModelCode()); + } + + @Test + void unaryIntTest() { + Model model = createEmptyModel(); + var stateCoder = model.getAdapter(StateCoderAdapter.class); + + var ageI = model.getInterpretation(age); + + assertEquals(0, stateCoder.calculateModelCode()); + + ageI.put(Tuple.of(1), 4); + int code0 = stateCoder.calculateModelCode(); + + assertNotEquals(0, code0); + + ageI.put(Tuple.of(1), 5); + int code1 = stateCoder.calculateModelCode(); + + assertNotEquals(code0, code1); + + ageI.put(Tuple.of(2), 5); + int code2 = stateCoder.calculateModelCode(); + + assertNotEquals(code1, code2); + + ageI.put(Tuple.of(1), null); + assertEquals(code1, stateCoder.calculateModelCode()); + } + + @Test + void binaryTest() { + Model model = createEmptyModel(); + var stateCoder = model.getAdapter(StateCoderAdapter.class); + + var friendI = model.getInterpretation(friend); + + assertEquals(0, stateCoder.calculateModelCode()); + + friendI.put(Tuple.of(1, 2), true); + int code1 = stateCoder.calculateModelCode(); + + assertNotEquals(0, code1); + + friendI.put(Tuple.of(2, 1), true); + int code2 = stateCoder.calculateModelCode(); + + assertNotEquals(code1, code2); + + friendI.put(Tuple.of(1, 2), false); + int code3 = stateCoder.calculateModelCode(); + + assertEquals(code1, code3); + } + + @Test + void NaryTest() { + Model model = createEmptyModel(); + var stateCoder = model.getAdapter(StateCoderAdapter.class); + + var parentsI = model.getInterpretation(parents); + + assertEquals(0, stateCoder.calculateModelCode()); + + parentsI.put(Tuple.of(3, 1, 2), true); + int code1 = stateCoder.calculateModelCode(); + + assertNotEquals(0, code1); + + parentsI.put(Tuple.of(4, 1, 2), true); + int code2 = stateCoder.calculateModelCode(); + + assertNotEquals(code1, code2); + + parentsI.put(Tuple.of(3, 1, 2), false); + int code3 = stateCoder.calculateModelCode(); + + assertEquals(code1, code3); + } +} -- cgit v1.2.3-70-g09d2