From 7a310819cbbdd70767a9ed17e1bf84c2add9faed Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Tue, 27 Sep 2022 02:08:44 +0200 Subject: refactor: tuples in QueryableModel --- .../semantics/model/internal/DecisionTree.java | 2 +- .../model/internal/DecisionTreeCursor.java | 2 +- .../semantics/model/internal/DecisionTreeNode.java | 2 +- .../semantics/model/internal/IntermediateNode.java | 2 +- .../semantics/model/internal/TerminalNode.java | 2 +- .../semantics/model/tests/DecisionTreeTests.java | 2 +- .../store/query/viatra/ViatraTupleLike.java | 18 +++ .../query/viatra/internal/RawPatternMatcher.java | 48 ++++--- .../query/viatra/internal/RelationalScope.java | 2 +- .../viatra/internal/ViatraQueryableModel.java | 19 +-- .../internal/viewupdate/ModelUpdateListener.java | 2 +- .../internal/viewupdate/ViewUpdateBuffer.java | 2 +- .../internal/viewupdate/ViewUpdateTranslator.java | 2 +- .../store/query/viatra/tests/QueryTest.java | 82 ++++++------ .../query/viatra/tests/QueryTransactionTest.java | 2 +- .../tools/refinery/store/model/ModelStoreImpl.java | 1 + .../java/tools/refinery/store/model/Tuple.java | 148 --------------------- .../refinery/store/model/TupleHashProvider.java | 3 +- .../store/model/TupleHashProviderBitMagic.java | 7 +- .../internal/SimilarRelationEquivalenceClass.java | 4 +- .../store/model/representation/Relation.java | 2 +- .../tools/refinery/store/query/QueryableModel.java | 16 ++- .../refinery/store/query/QueryableModelStore.java | 9 +- .../query/view/AbstractFilteredRelationView.java | 6 +- .../store/query/view/FilteredRelationView.java | 2 +- .../store/query/view/FunctionalRelationView.java | 6 +- .../store/query/view/KeyOnlyRelationView.java | 2 +- .../refinery/store/query/view/RelationView.java | 2 +- .../java/tools/refinery/store/tuple/Tuple.java | 29 ++++ .../java/tools/refinery/store/tuple/Tuple0.java | 25 ++++ .../java/tools/refinery/store/tuple/Tuple1.java | 54 ++++++++ .../java/tools/refinery/store/tuple/Tuple2.java | 27 ++++ .../java/tools/refinery/store/tuple/TupleLike.java | 25 ++++ .../java/tools/refinery/store/tuple/TupleN.java | 52 ++++++++ .../refinery/store/map/tests/MapUnitTests.java | 2 +- .../store/model/hashTests/HashEfficiencyTest.java | 18 +-- .../refinery/store/model/tests/ModelTest.java | 2 +- 37 files changed, 364 insertions(+), 267 deletions(-) create mode 100644 subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraTupleLike.java delete mode 100644 subprojects/store/src/main/java/tools/refinery/store/model/Tuple.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java create mode 100644 subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java index 8c185509..d743ee2b 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java @@ -2,7 +2,7 @@ package tools.refinery.language.semantics.model.internal; import org.eclipse.collections.api.factory.primitive.IntObjectMaps; import tools.refinery.store.map.Cursor; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.TruthValue; public class DecisionTree { diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java index 8b02ba39..727a9528 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java @@ -2,7 +2,7 @@ package tools.refinery.language.semantics.model.internal; import tools.refinery.store.map.Cursor; import tools.refinery.store.map.VersionedMap; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.TruthValue; import java.util.ArrayDeque; diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java index 53954d62..7f38fc79 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java @@ -1,7 +1,7 @@ package tools.refinery.language.semantics.model.internal; import org.eclipse.collections.api.LazyIntIterable; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.TruthValue; abstract class DecisionTreeNode { diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java index acc53e73..7165197c 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java @@ -4,7 +4,7 @@ import org.eclipse.collections.api.LazyIntIterable; import org.eclipse.collections.api.factory.primitive.IntObjectMaps; import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; import org.eclipse.collections.api.tuple.primitive.IntObjectPair; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.TruthValue; final class IntermediateNode extends DecisionTreeNode { diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java index 20dd6b20..f3adea61 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java @@ -4,7 +4,7 @@ import org.eclipse.collections.api.LazyIntIterable; import org.eclipse.collections.api.factory.primitive.IntObjectMaps; import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; import org.eclipse.collections.api.tuple.primitive.IntObjectPair; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.TruthValue; class TerminalNode extends DecisionTreeNode { diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java index 8fe866af..5268eb8a 100644 --- a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java +++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java @@ -2,7 +2,7 @@ package tools.refinery.language.semantics.model.tests; import org.junit.jupiter.api.Test; import tools.refinery.language.semantics.model.internal.DecisionTree; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.TruthValue; import java.util.LinkedHashMap; diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraTupleLike.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraTupleLike.java new file mode 100644 index 00000000..46c28434 --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraTupleLike.java @@ -0,0 +1,18 @@ +package tools.refinery.store.query.viatra; + +import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; +import tools.refinery.store.tuple.Tuple1; +import tools.refinery.store.tuple.TupleLike; + +public record ViatraTupleLike(ITuple wrappedTuple) implements TupleLike { + @Override + public int getSize() { + return wrappedTuple.getSize(); + } + + @Override + public int get(int element) { + var wrappedValue = (Tuple1) wrappedTuple.get(element); + return wrappedValue.value0(); + } +} diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RawPatternMatcher.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RawPatternMatcher.java index be348a63..2c488319 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RawPatternMatcher.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RawPatternMatcher.java @@ -2,8 +2,9 @@ package tools.refinery.store.query.viatra.internal; import org.eclipse.viatra.query.runtime.api.GenericPatternMatcher; import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; -import org.eclipse.viatra.query.runtime.matchers.tuple.AbstractTuple; -import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; +import tools.refinery.store.query.viatra.ViatraTupleLike; +import tools.refinery.store.tuple.Tuple; +import tools.refinery.store.tuple.TupleLike; import java.util.Optional; import java.util.stream.Stream; @@ -13,39 +14,50 @@ public class RawPatternMatcher extends GenericPatternMatcher { public RawPatternMatcher(GenericQuerySpecification specification) { super(specification); - this.empty = new Object[specification.getParameterNames().size()]; + empty = new Object[specification.getParameterNames().size()]; } public boolean hasResult() { - return hasResult(empty); + return backend.hasMatch(empty); } - public boolean hasResult(Object[] parameters) { - return this.backend.hasMatch(parameters); + public boolean hasResult(Tuple parameters) { + return backend.hasMatch(toParametersArray(parameters)); } - public Optional oneResult() { - return oneResult(empty); + public Optional oneResult() { + return backend.getOneArbitraryMatch(empty).map(ViatraTupleLike::new); } - public Optional oneResult(Object[] parameters) { - Optional tuple = this.backend.getOneArbitraryMatch(parameters); - return tuple.map(AbstractTuple::getElements); + public Optional oneResult(Tuple parameters) { + return backend.getOneArbitraryMatch(toParametersArray(parameters)).map(ViatraTupleLike::new); } - public Stream allResults() { - return allResults(empty); + public Stream allResults() { + return backend.getAllMatches(empty).map(ViatraTupleLike::new); } - public Stream allResults(Object[] parameters) { - return this.backend.getAllMatches(parameters).map(AbstractTuple::getElements); + public Stream allResults(Tuple parameters) { + return backend.getAllMatches(toParametersArray(parameters)).map(ViatraTupleLike::new); } public int countResults() { - return countResults(empty); + return backend.countMatches(empty); } - public int countResults(Object[] parameters) { - return backend.countMatches(parameters); + public int countResults(Tuple parameters) { + return backend.countMatches(toParametersArray(parameters)); + } + + private Object[] toParametersArray(Tuple tuple) { + int size = tuple.getSize(); + var array = new Object[tuple.getSize()]; + for (int i = 0; i < size; i++) { + var value = tuple.get(i); + if (value >= 0) { + array[i] = Tuple.of(value); + } + } + return array; } } diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java index 8dfa22e0..5ddad67d 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java @@ -6,7 +6,7 @@ import org.eclipse.viatra.query.runtime.api.scope.IEngineContext; import org.eclipse.viatra.query.runtime.api.scope.IIndexingErrorListener; import org.eclipse.viatra.query.runtime.api.scope.QueryScope; import tools.refinery.store.model.Model; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; import tools.refinery.store.query.viatra.internal.context.RelationalEngineContext; import tools.refinery.store.query.viatra.internal.viewupdate.ModelUpdateListener; diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java index 3803702d..1c15e8f9 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraQueryableModel.java @@ -8,12 +8,13 @@ import tools.refinery.store.map.Cursor; import tools.refinery.store.map.DiffCursor; import tools.refinery.store.model.Model; import tools.refinery.store.model.ModelDiffCursor; -import tools.refinery.store.model.Tuple; import tools.refinery.store.model.representation.DataRepresentation; import tools.refinery.store.model.representation.Relation; import tools.refinery.store.query.QueryableModel; import tools.refinery.store.query.QueryableModelStore; import tools.refinery.store.query.building.DNFPredicate; +import tools.refinery.store.tuple.Tuple; +import tools.refinery.store.tuple.TupleLike; import java.util.HashMap; import java.util.Map; @@ -124,9 +125,9 @@ public class ViatraQueryableModel implements QueryableModel { return result; } - protected void validateParameters(DNFPredicate predicate, Object[] parameters) { + protected void validateParameters(DNFPredicate predicate, Tuple parameters) { int predicateArity = predicate.getVariables().size(); - int parameterArity = parameters.length; + int parameterArity = parameters.getSize(); if (parameterArity != predicateArity) { throw new IllegalArgumentException( "Predicate %s with %d arity called with different number of parameters (%d)" @@ -140,29 +141,29 @@ public class ViatraQueryableModel implements QueryableModel { } @Override - public boolean hasResult(DNFPredicate predicate, Object[] parameters) { + public boolean hasResult(DNFPredicate predicate, Tuple parameters) { validateParameters(predicate, parameters); return getMatcher(predicate).hasResult(parameters); } @Override - public Optional oneResult(DNFPredicate predicate) { + public Optional oneResult(DNFPredicate predicate) { return getMatcher(predicate).oneResult(); } @Override - public Optional oneResult(DNFPredicate predicate, Object[] parameters) { + public Optional oneResult(DNFPredicate predicate, Tuple parameters) { validateParameters(predicate, parameters); return getMatcher(predicate).oneResult(parameters); } @Override - public Stream allResults(DNFPredicate predicate) { + public Stream allResults(DNFPredicate predicate) { return getMatcher(predicate).allResults(); } @Override - public Stream allResults(DNFPredicate predicate, Object[] parameters) { + public Stream allResults(DNFPredicate predicate, Tuple parameters) { validateParameters(predicate, parameters); return getMatcher(predicate).allResults(parameters); } @@ -173,7 +174,7 @@ public class ViatraQueryableModel implements QueryableModel { } @Override - public int countResults(DNFPredicate predicate, Object[] parameters) { + public int countResults(DNFPredicate predicate, Tuple parameters) { validateParameters(predicate, parameters); return getMatcher(predicate).countResults(parameters); diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java index 5a0da315..1a2fcee7 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ModelUpdateListener.java @@ -3,7 +3,7 @@ package tools.refinery.store.query.viatra.internal.viewupdate; import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; import tools.refinery.store.query.view.RelationView; diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java index e13a9cb8..49f4c501 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateBuffer.java @@ -1,6 +1,6 @@ package tools.refinery.store.query.viatra.internal.viewupdate; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import java.util.ArrayList; import java.util.Arrays; diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java index 62a10e45..74d0b366 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/viewupdate/ViewUpdateTranslator.java @@ -4,7 +4,7 @@ import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.query.view.RelationView; import java.util.Objects; diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java index 4307ab6b..d6213b02 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTest.java @@ -1,7 +1,6 @@ package tools.refinery.store.query.viatra.tests; import org.junit.jupiter.api.Test; -import tools.refinery.store.model.Tuple; import tools.refinery.store.model.representation.Relation; import tools.refinery.store.model.representation.TruthValue; import tools.refinery.store.query.QueryableModel; @@ -11,6 +10,8 @@ import tools.refinery.store.query.viatra.ViatraQueryableModelStore; import tools.refinery.store.query.view.FilteredRelationView; import tools.refinery.store.query.view.KeyOnlyRelationView; import tools.refinery.store.query.view.RelationView; +import tools.refinery.store.tuple.Tuple; +import tools.refinery.store.tuple.TupleLike; import java.util.*; import java.util.stream.Stream; @@ -40,15 +41,16 @@ class QueryTest { model.flushChanges(); assertEquals(2, model.countResults(predicate)); - compareMatchSets(model.allResults(predicate), Set.of(List.of(Tuple.of(0)), List.of(Tuple.of(1)))); + compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0), Tuple.of(1))); } @Test void relationConstraintTest() { - Relation person = new Relation("Person", 1, false); + Relation person = new Relation<>("Person", 1, false); Relation friend = new Relation<>("friend", 2, TruthValue.FALSE); RelationView personView = new KeyOnlyRelationView(person); - RelationView friendMustView = new FilteredRelationView(friend, (k, v) -> v.must()); + RelationView friendMustView = new FilteredRelationView<>(friend, "must", + TruthValue::must); Variable p1 = new Variable("p1"); Variable p2 = new Variable("p2"); @@ -78,16 +80,16 @@ class QueryTest { model.flushChanges(); assertEquals(3, model.countResults(predicate)); - compareMatchSets(model.allResults(predicate), Set.of(List.of(Tuple.of(0), Tuple.of(1)), - List.of(Tuple.of(1), Tuple.of(0)), List.of(Tuple.of(1), Tuple.of(2)))); + compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 1), Tuple.of(1, 0), Tuple.of(1, 2))); } @Test void andTest() { - Relation person = new Relation("Person", 1, false); + Relation person = new Relation<>("Person", 1, false); Relation friend = new Relation<>("friend", 2, TruthValue.FALSE); RelationView personView = new KeyOnlyRelationView(person); - RelationView friendMustView = new FilteredRelationView(friend, (k, v) -> v.must()); + RelationView friendMustView = new FilteredRelationView<>(friend, "must", + TruthValue::must); Variable p1 = new Variable("p1"); Variable p2 = new Variable("p2"); @@ -120,23 +122,22 @@ class QueryTest { model.put(friend, Tuple.of(1, 0), TruthValue.TRUE); model.flushChanges(); assertEquals(2, model.countResults(predicate)); - compareMatchSets(model.allResults(predicate), - Set.of(List.of(Tuple.of(0), Tuple.of(1)), List.of(Tuple.of(1), Tuple.of(0)))); + compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 1), Tuple.of(1, 0))); model.put(friend, Tuple.of(2, 0), TruthValue.TRUE); model.flushChanges(); assertEquals(4, model.countResults(predicate)); - compareMatchSets(model.allResults(predicate), - Set.of(List.of(Tuple.of(0), Tuple.of(1)), List.of(Tuple.of(1), Tuple.of(0)), - List.of(Tuple.of(0), Tuple.of(2)), List.of(Tuple.of(2), Tuple.of(0)))); + compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 1), Tuple.of(1, 0), Tuple.of(0, 2), + Tuple.of(2, 0))); } @Test void existTest() { - Relation person = new Relation("Person", 1, false); + Relation person = new Relation<>("Person", 1, false); Relation friend = new Relation<>("friend", 2, TruthValue.FALSE); RelationView personView = new KeyOnlyRelationView(person); - RelationView friendMustView = new FilteredRelationView(friend, (k, v) -> v.must()); + RelationView friendMustView = new FilteredRelationView<>(friend, "must", + TruthValue::must); Variable p1 = new Variable("p1"); Variable p2 = new Variable("p2"); @@ -166,7 +167,7 @@ class QueryTest { model.flushChanges(); assertEquals(2, model.countResults(predicate)); - compareMatchSets(model.allResults(predicate), Set.of(List.of(Tuple.of(0)), List.of(Tuple.of(1)))); + compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0), Tuple.of(1))); } @Test @@ -176,7 +177,8 @@ class QueryTest { Relation friend = new Relation<>("friend", 2, TruthValue.FALSE); RelationView personView = new KeyOnlyRelationView(person); RelationView animalView = new KeyOnlyRelationView(animal); - RelationView friendMustView = new FilteredRelationView(friend, (k, v) -> v.must()); + RelationView friendMustView = new FilteredRelationView<>(friend, "must", + TruthValue::must); Variable p1 = new Variable("p1"); Variable p2 = new Variable("p2"); @@ -196,8 +198,7 @@ class QueryTest { DNFAnd clause2 = new DNFAnd(Collections.emptySet(), Arrays.asList(animalRelationAtom1, animalRelationAtom2, friendRelationAtom2)); - // No inter-species friendship - + // No friendship between species DNFPredicate predicate = new DNFPredicate("Or", parameters, Arrays.asList(clause1, clause2)); QueryableModelStore store = new ViatraQueryableModelStore(Set.of(person, animal, friend), @@ -215,13 +216,12 @@ class QueryTest { model.flushChanges(); assertEquals(2, model.countResults(predicate)); - compareMatchSets(model.allResults(predicate), - Set.of(List.of(Tuple.of(0), Tuple.of(1)), List.of(Tuple.of(2), Tuple.of(3)))); + compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 1), Tuple.of(2, 3))); } @Test void equalityTest() { - Relation person = new Relation("Person", 1, false); + Relation person = new Relation<>("Person", 1, false); RelationView personView = new KeyOnlyRelationView(person); Variable p1 = new Variable("p1"); @@ -244,16 +244,16 @@ class QueryTest { model.flushChanges(); assertEquals(3, model.countResults(predicate)); - compareMatchSets(model.allResults(predicate), Set.of(List.of(Tuple.of(0), Tuple.of(0)), - List.of(Tuple.of(1), Tuple.of(1)), List.of(Tuple.of(2), Tuple.of(2)))); + compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 0), Tuple.of(1, 1), Tuple.of(2, 2))); } @Test void inequalityTest() { - Relation person = new Relation("Person", 1, false); + Relation person = new Relation<>("Person", 1, false); Relation friend = new Relation<>("friend", 2, TruthValue.FALSE); RelationView personView = new KeyOnlyRelationView(person); - RelationView friendMustView = new FilteredRelationView(friend, (k, v) -> v.must()); + RelationView friendMustView = new FilteredRelationView<>(friend, "must", + TruthValue::must); Variable p1 = new Variable("p1"); Variable p2 = new Variable("p2"); @@ -281,16 +281,16 @@ class QueryTest { model.flushChanges(); assertEquals(2, model.countResults(predicate)); - compareMatchSets(model.allResults(predicate), - Set.of(List.of(Tuple.of(0), Tuple.of(1), Tuple.of(2)), List.of(Tuple.of(1), Tuple.of(0), Tuple.of(2)))); + compareMatchSets(model.allResults(predicate), Set.of(Tuple.of(0, 1, 2), Tuple.of(1, 0, 2))); } @Test void patternCallTest() { - Relation person = new Relation("Person", 1, false); + Relation person = new Relation<>("Person", 1, false); Relation friend = new Relation<>("friend", 2, TruthValue.FALSE); RelationView personView = new KeyOnlyRelationView(person); - RelationView friendMustView = new FilteredRelationView(friend, (k, v) -> v.must()); + RelationView friendMustView = new FilteredRelationView<>(friend, "must", + TruthValue::must); Variable p1 = new Variable("p1"); Variable p2 = new Variable("p2"); @@ -331,10 +331,11 @@ class QueryTest { @Test void negativePatternCallTest() { - Relation person = new Relation("Person", 1, false); + Relation person = new Relation<>("Person", 1, false); Relation friend = new Relation<>("friend", 2, TruthValue.FALSE); RelationView personView = new KeyOnlyRelationView(person); - RelationView friendMustView = new FilteredRelationView(friend, (k, v) -> v.must()); + RelationView friendMustView = new FilteredRelationView<>(friend, "must", + TruthValue::must); Variable p1 = new Variable("p1"); Variable p2 = new Variable("p2"); @@ -375,10 +376,11 @@ class QueryTest { @Test void transitivePatternCallTest() { - Relation person = new Relation("Person", 1, false); + Relation person = new Relation<>("Person", 1, false); Relation friend = new Relation<>("friend", 2, TruthValue.FALSE); RelationView personView = new KeyOnlyRelationView(person); - RelationView friendMustView = new FilteredRelationView(friend, (k, v) -> v.must()); + RelationView friendMustView = new FilteredRelationView<>(friend, "must", + TruthValue::must); Variable p1 = new Variable("p1"); Variable p2 = new Variable("p2"); @@ -415,18 +417,14 @@ class QueryTest { model.flushChanges(); assertEquals(3, model.countResults(predicate)); } - static void compareMatchSets(Stream matchSet, Set> expected) { - Set> translatedMatchSet = new HashSet<>(); + + static void compareMatchSets(Stream matchSet, Set expected) { + Set translatedMatchSet = new HashSet<>(); var iterator = matchSet.iterator(); while (iterator.hasNext()) { var element = iterator.next(); - List elementToTranslatedMatchSet = new ArrayList<>(); - for (Object o : element) { - elementToTranslatedMatchSet.add((Tuple) o); - } - translatedMatchSet.add(elementToTranslatedMatchSet); + translatedMatchSet.add(element.toTuple()); } - assertEquals(expected, translatedMatchSet); } } diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java index 613d0074..f57bca2b 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryTransactionTest.java @@ -1,7 +1,7 @@ package tools.refinery.store.query.viatra.tests; import org.junit.jupiter.api.Test; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; import tools.refinery.store.query.QueryableModel; import tools.refinery.store.query.QueryableModelStore; diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java index 97406cbb..b5e1c453 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreImpl.java @@ -16,6 +16,7 @@ import tools.refinery.store.model.internal.SimilarRelationEquivalenceClass; import tools.refinery.store.model.representation.AuxilaryData; import tools.refinery.store.model.representation.DataRepresentation; import tools.refinery.store.model.representation.Relation; +import tools.refinery.store.tuple.Tuple; import java.util.Set; diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/Tuple.java b/subprojects/store/src/main/java/tools/refinery/store/model/Tuple.java deleted file mode 100644 index 0aae3727..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/model/Tuple.java +++ /dev/null @@ -1,148 +0,0 @@ -package tools.refinery.store.model; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public abstract class Tuple { - private static final int CUSTOMTUPLESIZE = 2; - protected static final List tuple1Cash = new ArrayList<>(1024); - - public abstract int getSize(); - public abstract int get(int element); - public abstract int[] toArray(); - - @Override - public String toString() { - StringBuilder b = new StringBuilder(); - b.append("["); - for(int i = 0; i= tuple1Cash.size()) { - newlyCreated = new Tuple1(tuple1Cash.size()); - tuple1Cash.add(newlyCreated); - } - return newlyCreated; - } - } - - public static Tuple of(int... values) { - if(values.length == 0) { - return new Tuple0(); - } else if(values.length == 1) { - return of1(values[0]); - } else if(values.length == 2) { - return new Tuple2(values[0],values[1]); - } else return new TupleN(values); - } - - protected IllegalArgumentException doesNotContain(int element) { - return new IllegalArgumentException("Tuple does not contain element "+element); - } - - public static class Tuple0 extends Tuple{ - protected Tuple0() { } - @Override public int getSize() { return 0; } - @Override public int get(int element) { - throw doesNotContain(element); - } - @Override public int[] toArray() {return new int[]{};} - @Override public int hashCode() { return TupleHashProvider.singleton().getHash(this, 0); } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - return true; - } - } - public static class Tuple1 extends Tuple{ - final int value0; - protected Tuple1(int value0) { this.value0 = value0; } - @Override public int getSize() { return 1; } - @Override public int get(int element) { - if(element == 0) return value0; - throw doesNotContain(element); - } - @Override public int[] toArray() {return new int[]{ value0 };} - @Override public int hashCode() { return TupleHashProvider.singleton().getHash(this, 0); } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Tuple1 other = (Tuple1) obj; - return value0 == other.value0; - } - } - public static class Tuple2 extends Tuple{ - final int value0; - final int value1; - protected Tuple2(int value0, int value1) { this.value0 = value0; this.value1 = value1; } - @Override public int getSize() { return 2; } - @Override public int get(int element) { - if(element == 0) return value0; - else if(element == 1) return value1; - throw doesNotContain(element); - } - @Override public int[] toArray() {return new int[]{ value0,value1 };} - @Override public int hashCode() { return TupleHashProvider.singleton().getHash(this, 0); } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Tuple2 other = (Tuple2) obj; - return value0 == other.value0 && value1 == other.value1; - } - } - public static class TupleN extends Tuple{ - final int[] values; - protected TupleN(int[] values) { - if(values.length { protected static TupleHashProvider instance; @@ -39,7 +40,7 @@ public class TupleHashProvider implements ContinousHashProvider { 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911 }; - + protected static final long LARGESTPRIME30BITS = 1073741789; public TupleHashProvider() { diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java index 5b053229..33059a1b 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java @@ -1,6 +1,7 @@ package tools.refinery.store.model; import tools.refinery.store.map.ContinousHashProvider; +import tools.refinery.store.tuple.Tuple; public class TupleHashProviderBitMagic implements ContinousHashProvider { @@ -9,12 +10,12 @@ public class TupleHashProviderBitMagic implements ContinousHashProvider { if(key.getSize() == 1) { return key.get(0); } - + int result = 0; final int startBitIndex = index*30; final int finalBitIndex = startBitIndex+30; final int arity = key.getSize(); - + for(int i = startBitIndex; i<=finalBitIndex; i++) { final int selectedKey = key.get(i%arity); final int selectedPosition = 1<<(i/arity); @@ -22,7 +23,7 @@ public class TupleHashProviderBitMagic implements ContinousHashProvider { result |= 1<<(i%30); } } - + return result; } } diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/SimilarRelationEquivalenceClass.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/SimilarRelationEquivalenceClass.java index 9d1b1dd0..9939f17e 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/SimilarRelationEquivalenceClass.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/SimilarRelationEquivalenceClass.java @@ -3,7 +3,7 @@ package tools.refinery.store.model.internal; import java.util.Objects; import tools.refinery.store.map.ContinousHashProvider; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; public class SimilarRelationEquivalenceClass { @@ -29,5 +29,5 @@ public class SimilarRelationEquivalenceClass { return arity == other.arity && Objects.equals(defaultValue, other.defaultValue) && Objects.equals(hashProvider, other.hashProvider); } - + } diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java b/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java index fc2a3185..c0f31d08 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/representation/Relation.java @@ -1,6 +1,6 @@ package tools.refinery.store.model.representation; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.TupleHashProvider; public class Relation extends DataRepresentation { diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java index 187abbc2..648c3a36 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModel.java @@ -2,12 +2,14 @@ package tools.refinery.store.query; import tools.refinery.store.model.Model; import tools.refinery.store.query.building.DNFPredicate; +import tools.refinery.store.tuple.Tuple; +import tools.refinery.store.tuple.TupleLike; import java.util.Optional; import java.util.Set; import java.util.stream.Stream; -public interface QueryableModel extends Model{ +public interface QueryableModel extends Model { Set getPredicates(); boolean hasChanges(); @@ -16,17 +18,17 @@ public interface QueryableModel extends Model{ boolean hasResult(DNFPredicate predicate); - boolean hasResult(DNFPredicate predicate, Object[] parameters); + boolean hasResult(DNFPredicate predicate, Tuple parameters); - Optional oneResult(DNFPredicate predicate); + Optional oneResult(DNFPredicate predicate); - Optional oneResult(DNFPredicate predicate, Object[] parameters); + Optional oneResult(DNFPredicate predicate, Tuple parameters); - Stream allResults(DNFPredicate predicate); + Stream allResults(DNFPredicate predicate); - Stream allResults(DNFPredicate predicate, Object[] parameters); + Stream allResults(DNFPredicate predicate, Tuple parameters); int countResults(DNFPredicate predicate); - int countResults(DNFPredicate predicate, Object[] parameters); + int countResults(DNFPredicate predicate, Tuple parameters); } diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java index 08efe17c..878e1058 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/QueryableModelStore.java @@ -1,6 +1,5 @@ package tools.refinery.store.query; -import tools.refinery.store.model.ModelDiffCursor; import tools.refinery.store.model.ModelStore; import tools.refinery.store.model.representation.DataRepresentation; import tools.refinery.store.query.building.DNFPredicate; @@ -8,16 +7,16 @@ import tools.refinery.store.query.view.RelationView; import java.util.Set; -public interface QueryableModelStore extends ModelStore{ +public interface QueryableModelStore extends ModelStore { @SuppressWarnings("squid:S1452") Set> getDataRepresentations(); + @SuppressWarnings("squid:S1452") Set> getViews(); + Set getPredicates(); QueryableModel createModel(); - QueryableModel createModel(long state); - Set getStates(); - ModelDiffCursor getDiffCursor(long from, long to); + QueryableModel createModel(long state); } diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/AbstractFilteredRelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/AbstractFilteredRelationView.java index a21a38ba..79de1c4d 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/query/view/AbstractFilteredRelationView.java +++ b/subprojects/store/src/main/java/tools/refinery/store/query/view/AbstractFilteredRelationView.java @@ -1,8 +1,8 @@ package tools.refinery.store.query.view; import tools.refinery.store.model.Model; -import tools.refinery.store.model.Tuple; -import tools.refinery.store.model.Tuple.Tuple1; +import tools.refinery.store.tuple.Tuple; +import tools.refinery.store.tuple.Tuple1; import tools.refinery.store.model.representation.Relation; public abstract class AbstractFilteredRelationView extends RelationView { @@ -23,7 +23,7 @@ public abstract class AbstractFilteredRelationView extends RelationView { public boolean get(Model model, Object[] tuple) { int[] content = new int[tuple.length]; for (int i = 0; i < tuple.length; i++) { - content[i] = ((Tuple1) tuple[i]).get(0); + content[i] = ((Tuple1) tuple[i]).value0(); } Tuple key = Tuple.of(content); D value = model.get(getRepresentation(), key); 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 index bb5d0237..3b639979 100644 --- 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 @@ -1,6 +1,6 @@ package tools.refinery.store.query.view; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; import java.util.function.BiPredicate; 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 index 54baa050..ef3954a4 100644 --- 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 @@ -1,8 +1,8 @@ package tools.refinery.store.query.view; import tools.refinery.store.model.Model; -import tools.refinery.store.model.Tuple; -import tools.refinery.store.model.Tuple.Tuple1; +import tools.refinery.store.tuple.Tuple; +import tools.refinery.store.tuple.Tuple1; import tools.refinery.store.model.representation.Relation; public class FunctionalRelationView extends RelationView { @@ -28,7 +28,7 @@ public class FunctionalRelationView extends RelationView { public boolean get(Model model, Object[] tuple) { int[] content = new int[tuple.length - 1]; for (int i = 0; i < tuple.length - 1; i++) { - content[i] = ((Tuple1) tuple[i]).get(0); + content[i] = ((Tuple1) tuple[i]).value0(); } Tuple key = Tuple.of(content); @SuppressWarnings("unchecked") 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 index b9a9ed9f..c88af5a4 100644 --- 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 @@ -1,6 +1,6 @@ package tools.refinery.store.query.view; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; public class KeyOnlyRelationView extends AbstractFilteredRelationView { 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 index b8a54046..ceaf7d55 100644 --- 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 @@ -2,7 +2,7 @@ package tools.refinery.store.query.view; import tools.refinery.store.map.CursorAsIterator; import tools.refinery.store.model.Model; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.representation.Relation; import java.util.Objects; diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java new file mode 100644 index 00000000..bf844c6d --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java @@ -0,0 +1,29 @@ +package tools.refinery.store.tuple; + +public sealed interface Tuple extends TupleLike permits Tuple0, Tuple1, Tuple2, TupleN { + @Override + default Tuple toTuple() { + return this; + } + + static Tuple of() { + return Tuple0.INSTANCE; + } + + static Tuple of(int value) { + return Tuple1.Cache.INSTANCE.getOrCreate(value); + } + + static Tuple of(int value1, int value2) { + return new Tuple2(value1, value2); + } + + static Tuple of(int... values) { + return switch (values.length) { + case 0 -> of(); + case 1 -> of(values[0]); + case 2 -> of(values[0], values[1]); + default -> new TupleN(values); + }; + } +} diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java new file mode 100644 index 00000000..8eea5c3a --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java @@ -0,0 +1,25 @@ +package tools.refinery.store.tuple; + +public record Tuple0() implements Tuple { + public static Tuple0 INSTANCE = new Tuple0(); + + @Override + public int getSize() { + return 0; + } + + @Override + public int get(int element) { + throw new IndexOutOfBoundsException(element); + } + + @Override + public int[] toArray() { + return new int[]{}; + } + + @Override + public String toString() { + return "[]"; + } +} diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java new file mode 100644 index 00000000..95907ee1 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java @@ -0,0 +1,54 @@ +package tools.refinery.store.tuple; + +import java.util.ArrayList; + +public record Tuple1(int value0) implements Tuple { + @Override + public int getSize() { + return 1; + } + + @Override + public int get(int element) { + if (element == 0) { + return value0; + } + throw new IndexOutOfBoundsException(element); + } + + @Override + public int[] toArray() { + return new int[]{value0}; + } + + @Override + public String toString() { + return "[" + value0 + "]"; + } + + public static class Cache { + public static final Cache INSTANCE = new Cache(); + + private final ArrayList tuple1Cache = new ArrayList<>(1024); + + private Cache() { + } + + public Tuple1 getOrCreate(int value) { + if (value < 0) { + // Mask tuple for QueryableModelStore, doesn't refer to a model node. + return new Tuple1(value); + } + if (value < tuple1Cache.size()) { + return tuple1Cache.get(value); + } + Tuple1 newlyCreated = null; + tuple1Cache.ensureCapacity(value); + while (value >= tuple1Cache.size()) { + newlyCreated = new Tuple1(tuple1Cache.size()); + tuple1Cache.add(newlyCreated); + } + return newlyCreated; + } + } +} diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java new file mode 100644 index 00000000..0836a32d --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java @@ -0,0 +1,27 @@ +package tools.refinery.store.tuple; + +public record Tuple2(int value0, int value1) implements Tuple { + @Override + public int getSize() { + return 2; + } + + @Override + public int get(int element) { + return switch (element) { + case 0 -> value0; + case 1 -> value1; + default -> throw new ArrayIndexOutOfBoundsException(element); + }; + } + + @Override + public int[] toArray() { + return new int[]{value0, value1}; + } + + @Override + public String toString() { + return "[" + value0 + ", " + value1 + "]"; + } +} 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 new file mode 100644 index 00000000..470ca298 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java @@ -0,0 +1,25 @@ +package tools.refinery.store.tuple; + +public interface TupleLike { + int getSize(); + + int get(int element); + + default int[] toArray() { + int size = getSize(); + var array = new int[size]; + for (int i = 0; i < size; i++) { + array[i] = get(i); + } + return array; + } + + default Tuple toTuple() { + return switch (getSize()) { + case 0 -> Tuple.of(); + case 1 -> Tuple.of(get(0)); + case 2 -> Tuple.of(get(0), get(1)); + default -> Tuple.of(toArray()); + }; + } +} 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 new file mode 100644 index 00000000..15fd063b --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java @@ -0,0 +1,52 @@ +package tools.refinery.store.tuple; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public record TupleN(int[] values) implements Tuple { + static final int CUSTOM_TUPLE_SIZE = 2; + + public TupleN(int[] values) { + if (values.length < CUSTOM_TUPLE_SIZE) + throw new IllegalArgumentException(); + this.values = Arrays.copyOf(values, values.length); + } + + @Override + public int getSize() { + return values.length; + } + + @Override + public int get(int element) { + return values[element]; + } + + @Override + public int[] toArray() { + return values; + } + + @Override + public String toString() { + var valuesString = Arrays.stream(values).mapToObj(Integer::toString).collect(Collectors.joining(", ")); + return "[" + valuesString + "]"; + } + + @Override + public int hashCode() { + return Arrays.hashCode(values); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TupleN other = (TupleN) obj; + return Arrays.equals(values, other.values); + } +} diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java index f0d5d927..081112cc 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java @@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test; import tools.refinery.store.map.VersionedMapStore; import tools.refinery.store.map.VersionedMapStoreImpl; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.TupleHashProvider; class MapUnitTests { diff --git a/subprojects/store/src/test/java/tools/refinery/store/model/hashTests/HashEfficiencyTest.java b/subprojects/store/src/test/java/tools/refinery/store/model/hashTests/HashEfficiencyTest.java index 7d070380..ceec40f5 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/model/hashTests/HashEfficiencyTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/model/hashTests/HashEfficiencyTest.java @@ -10,7 +10,7 @@ import java.util.Random; import org.junit.jupiter.api.Test; import tools.refinery.store.map.ContinousHashProvider; -import tools.refinery.store.model.Tuple; +import tools.refinery.store.tuple.Tuple; import tools.refinery.store.model.TupleHashProvider; import tools.refinery.store.model.TupleHashProviderBitMagic; @@ -39,7 +39,7 @@ class HashEfficiencyTest { return result; } else throw new IllegalArgumentException(); } - + private static int amountToRange(int arity, int n) { int range = 1; while(Math.pow(range,arity) nPermutations(int arity, int n) { int range = amountToRange(arity, n); List permutations = permutations(range, arity); @@ -67,7 +67,7 @@ class HashEfficiencyTest { } return permutations; } - + @Test void permutationTest() { List p = permutations(10, 2); @@ -92,7 +92,7 @@ class HashEfficiencyTest { } private static double calculateHashClashes(List tuples, ContinousHashProvider chp) { int sumClashes = 0; - + for(int i = 0; i dataSourceNames = new LinkedList<>(); List> dataSources = new LinkedList<>(); - + // dataSourceNames.add("Permutation"); // dataSources.add(nPermutations(arity, size)); dataSourceNames.add("Random"); dataSources.add(nRandoms(arity, size, 0)); - + for(int dataSourceIndex = 0; dataSourceIndex