diff options
author | Oszkar Semerath <Oszkar Semerath@DESKTOP-DNR7JQ7> | 2021-07-02 16:09:07 +0200 |
---|---|---|
committer | Oszkar Semerath <Oszkar Semerath@DESKTOP-DNR7JQ7> | 2021-07-02 16:09:07 +0200 |
commit | bd702e7964420c897799cd01ff658a2cc098c780 (patch) | |
tree | d8450dad2a497167273a5e88a37a4218507d6f63 /Solvers | |
parent | fixed bigdecimal <-> double casting error (diff) | |
download | VIATRA-Generator-bd702e7964420c897799cd01ff658a2cc098c780.tar.gz VIATRA-Generator-bd702e7964420c897799cd01ff658a2cc098c780.tar.zst VIATRA-Generator-bd702e7964420c897799cd01ff658a2cc098c780.zip |
First version of the versioned hashmap
Diffstat (limited to 'Solvers')
27 files changed, 960 insertions, 0 deletions
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/.classpath b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/.classpath new file mode 100644 index 00000000..0fa31827 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/.classpath | |||
@@ -0,0 +1,12 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <classpath> | ||
3 | <classpathentry kind="src" path="src"/> | ||
4 | <classpathentry kind="src" path="tests"/> | ||
5 | <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/> | ||
6 | <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"> | ||
7 | <attributes> | ||
8 | <attribute name="module" value="true"/> | ||
9 | </attributes> | ||
10 | </classpathentry> | ||
11 | <classpathentry kind="output" path="bin"/> | ||
12 | </classpath> | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/.project b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/.project new file mode 100644 index 00000000..464aef51 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/.project | |||
@@ -0,0 +1,23 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <projectDescription> | ||
3 | <name>org.eclipse.viatra.solver.data</name> | ||
4 | <comment></comment> | ||
5 | <projects> | ||
6 | </projects> | ||
7 | <buildSpec> | ||
8 | <buildCommand> | ||
9 | <name>org.eclipse.xtext.ui.shared.xtextBuilder</name> | ||
10 | <arguments> | ||
11 | </arguments> | ||
12 | </buildCommand> | ||
13 | <buildCommand> | ||
14 | <name>org.eclipse.jdt.core.javabuilder</name> | ||
15 | <arguments> | ||
16 | </arguments> | ||
17 | </buildCommand> | ||
18 | </buildSpec> | ||
19 | <natures> | ||
20 | <nature>org.eclipse.jdt.core.javanature</nature> | ||
21 | <nature>org.eclipse.xtext.ui.shared.xtextNature</nature> | ||
22 | </natures> | ||
23 | </projectDescription> | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/.settings/org.eclipse.jdt.core.prefs b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..f2525a8b --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/.settings/org.eclipse.jdt.core.prefs | |||
@@ -0,0 +1,14 @@ | |||
1 | eclipse.preferences.version=1 | ||
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled | ||
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 | ||
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve | ||
5 | org.eclipse.jdt.core.compiler.compliance=11 | ||
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate | ||
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate | ||
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate | ||
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error | ||
10 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled | ||
11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error | ||
12 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning | ||
13 | org.eclipse.jdt.core.compiler.release=enabled | ||
14 | org.eclipse.jdt.core.compiler.source=11 | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/bin/.gitignore b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/bin/.gitignore new file mode 100644 index 00000000..cf1db2ee --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/bin/.gitignore | |||
@@ -0,0 +1 @@ | |||
/org/ | |||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/BooleanValue.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/BooleanValue.java new file mode 100644 index 00000000..7b0e565b --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/BooleanValue.java | |||
@@ -0,0 +1,17 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | public class BooleanValue implements TruthValue { | ||
4 | private final boolean value; | ||
5 | protected BooleanValue(final boolean value) { | ||
6 | this.value = value; | ||
7 | } | ||
8 | public static final BooleanValue trueValue = new BooleanValue(true); | ||
9 | public static final BooleanValue falseValue = new BooleanValue(false); | ||
10 | |||
11 | @Override | ||
12 | public String getName() { | ||
13 | // TODO Auto-generated method stub | ||
14 | return Boolean.toString(value); | ||
15 | } | ||
16 | |||
17 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/DataSymbol.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/DataSymbol.java new file mode 100644 index 00000000..74624db6 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/DataSymbol.java | |||
@@ -0,0 +1,5 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | public class DataSymbol { | ||
4 | |||
5 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/DefinedSymbol.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/DefinedSymbol.java new file mode 100644 index 00000000..40d01721 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/DefinedSymbol.java | |||
@@ -0,0 +1,11 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | public class DefinedSymbol extends Symbol { | ||
4 | private final String name; | ||
5 | public DefinedSymbol(String name) { | ||
6 | this.name = name; | ||
7 | } | ||
8 | public String getName() { | ||
9 | return name; | ||
10 | } | ||
11 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Logic2Valued.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Logic2Valued.java new file mode 100644 index 00000000..7a807155 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Logic2Valued.java | |||
@@ -0,0 +1,9 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | public class Logic2Valued { | ||
4 | protected static final String trueName = "true"; | ||
5 | protected static final String falseName = "false"; | ||
6 | |||
7 | public static final TruthValue trueValue = new NamedTruthValue(trueName); | ||
8 | public static final TruthValue falseValue = new NamedTruthValue(falseName); | ||
9 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Logic4Valued.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Logic4Valued.java new file mode 100644 index 00000000..5f1e2bd8 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Logic4Valued.java | |||
@@ -0,0 +1,22 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | public class Logic4Valued extends Logic2Valued { | ||
4 | protected static final String unknownName = "unknown"; | ||
5 | protected static final String errorName = "error"; | ||
6 | |||
7 | public static final TruthValue unknownValue = new NamedTruthValue(unknownName); | ||
8 | public static final TruthValue errorValue = new NamedTruthValue(errorName); | ||
9 | |||
10 | // public TruthValue getImplMin(TruthValue a, TruthValue b) { | ||
11 | // | ||
12 | // } | ||
13 | // public TruthValue getImplMax(TruthValue a, TruthValue b) { | ||
14 | // | ||
15 | // } | ||
16 | // public TruthValue getInfoMin(TruthValue a, TruthValue b) { | ||
17 | // | ||
18 | // } | ||
19 | // public TruthValue getInfoMax(TruthValue a, TruthValue b) { | ||
20 | // | ||
21 | // } | ||
22 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Model.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Model.java new file mode 100644 index 00000000..6f5c58ce --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Model.java | |||
@@ -0,0 +1,10 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | import java.util.List; | ||
4 | import java.util.Map; | ||
5 | import java.util.Set; | ||
6 | |||
7 | public class Model { | ||
8 | Set<ModelObject> objects; | ||
9 | Map<String,Map<List<ModelObject>,TruthValue>> interpretation; | ||
10 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/ModelObject.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/ModelObject.java new file mode 100644 index 00000000..73607f82 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/ModelObject.java | |||
@@ -0,0 +1,5 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | public class ModelObject { | ||
4 | |||
5 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/NamedTruthValue.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/NamedTruthValue.java new file mode 100644 index 00000000..be3a2351 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/NamedTruthValue.java | |||
@@ -0,0 +1,13 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | public class NamedTruthValue implements TruthValue { | ||
4 | private final String name; | ||
5 | public NamedTruthValue(String name) { | ||
6 | this.name = name; | ||
7 | } | ||
8 | @Override | ||
9 | public String getName() { | ||
10 | return this.name; | ||
11 | } | ||
12 | |||
13 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/PrimitiveSymbol.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/PrimitiveSymbol.java new file mode 100644 index 00000000..6bf0b195 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/PrimitiveSymbol.java | |||
@@ -0,0 +1,5 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | public class PrimitiveSymbol { | ||
4 | |||
5 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Symbol.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Symbol.java new file mode 100644 index 00000000..d403e181 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/Symbol.java | |||
@@ -0,0 +1,5 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | public class Symbol { | ||
4 | |||
5 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/TruthValue.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/TruthValue.java new file mode 100644 index 00000000..5dbde11c --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/TruthValue.java | |||
@@ -0,0 +1,5 @@ | |||
1 | package org.eclipse.viatra.solver.data; | ||
2 | |||
3 | interface TruthValue { | ||
4 | public String getName(); | ||
5 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/ContinousHashProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/ContinousHashProvider.java new file mode 100644 index 00000000..c4567458 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/ContinousHashProvider.java | |||
@@ -0,0 +1,34 @@ | |||
1 | package org.eclipse.viatra.solver.data.map; | ||
2 | |||
3 | /** | ||
4 | * A class representing an equivalence relation for a type {@code KEY} with a continuous hash function. | ||
5 | * @author Oszkar Semerath | ||
6 | * | ||
7 | * @param <KEY> Target java type. | ||
8 | */ | ||
9 | public interface ContinousHashProvider<KEY> { | ||
10 | /** | ||
11 | * Provides a hash code for a object {@code key} with a given {@code index}. It has the following contracts: | ||
12 | * <ul> | ||
13 | * <li>If {@link #equals}{@code (key1,key2)}, then {@code getHash(key1, index) == getHash(key2, index)} for all values of {@code index}.</li> | ||
14 | * <li>If {@code getHash(key1,index) == getHash(key2, index)} for all values of {@code index}, then {@link #equals}{@code (key1, key2)}</li> | ||
15 | * </ul> | ||
16 | * Check {@link #equals} for further details. | ||
17 | * @param key The target data object. | ||
18 | * @param index The depth of the the hash code. Needs to be non-negative. | ||
19 | * @return A hash code. | ||
20 | */ | ||
21 | public int getHash(KEY key, int index); | ||
22 | /** | ||
23 | * Compares the equivalnce of two objects {@code key1} and {@code key2}. It has the contracts of a equivalence relation: | ||
24 | * <ul> | ||
25 | * <li> Reflexive: {@code equals(key,key) == true}.</li> | ||
26 | * <li> Symmetric: {@code equals(key1,key2) == equals(key2,key1)}.</li> | ||
27 | * <li> Transitive: {@code equals(key1,key2) == true} and {@code equals(key2,key3) == true} then {@code equals(key1,key3) == true}.</li> | ||
28 | * </ul> | ||
29 | * @param key1 First data object. | ||
30 | * @param key2 Second data object. | ||
31 | * @return whether {@code key1} and {@code key2} are equivalent with respect to an equivalence relation represented by the given . | ||
32 | */ | ||
33 | public boolean equals(KEY key1, KEY key2); | ||
34 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/Versioned.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/Versioned.java new file mode 100644 index 00000000..d58c458e --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/Versioned.java | |||
@@ -0,0 +1,6 @@ | |||
1 | package org.eclipse.viatra.solver.data.map; | ||
2 | |||
3 | public interface Versioned { | ||
4 | public long commit(); | ||
5 | public void restore(long state); | ||
6 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMap.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMap.java new file mode 100644 index 00000000..41fd55b7 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMap.java | |||
@@ -0,0 +1,63 @@ | |||
1 | package org.eclipse.viatra.solver.data.map; | ||
2 | |||
3 | import java.util.Iterator; | ||
4 | import java.util.Map; | ||
5 | |||
6 | import org.eclipse.viatra.solver.data.map.internal.MutableNode; | ||
7 | import org.eclipse.viatra.solver.data.map.internal.Node; | ||
8 | import org.eclipse.viatra.solver.data.map.internal.NodeIterator; | ||
9 | |||
10 | public class VersionedMap<KEY,VALUE> implements Versioned{ | ||
11 | |||
12 | protected final ContinousHashProvider<? super KEY> hashProvider; | ||
13 | protected final VALUE defaultValue; | ||
14 | protected Node<KEY,VALUE> root = null; | ||
15 | |||
16 | protected VersionedMap(ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue) { | ||
17 | this.hashProvider = hashProvider; | ||
18 | this.defaultValue = defaultValue; | ||
19 | } | ||
20 | |||
21 | public VALUE getDefaultValue() { | ||
22 | return defaultValue; | ||
23 | } | ||
24 | public ContinousHashProvider<? super KEY> getHashProvider() { | ||
25 | return hashProvider; | ||
26 | } | ||
27 | |||
28 | public void put(KEY key, VALUE value) { | ||
29 | if(root!=null) { | ||
30 | root = root.putValue(key, value, hashProvider, defaultValue, hashProvider.getHash(key, 0), 0); | ||
31 | } else { | ||
32 | root = MutableNode.initialize(key, value, hashProvider, defaultValue); | ||
33 | } | ||
34 | } | ||
35 | public VALUE get(KEY key) { | ||
36 | if(root!=null) { | ||
37 | return root.getValue(key, hashProvider, defaultValue, hashProvider.getHash(key, 0), 0); | ||
38 | } else { | ||
39 | return defaultValue; | ||
40 | } | ||
41 | } | ||
42 | public int getSize() { | ||
43 | if(root == null) { | ||
44 | return 0; | ||
45 | } else { | ||
46 | return root.getSize(); | ||
47 | } | ||
48 | } | ||
49 | Iterator<Map.Entry<KEY,VALUE>> getIterator() { | ||
50 | return new NodeIterator<KEY, VALUE>(this.root); | ||
51 | } | ||
52 | |||
53 | @Override | ||
54 | public long commit() { | ||
55 | // TODO Auto-generated method stub | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public void restore(long state) { | ||
61 | // TODO Auto-generated method stub | ||
62 | } | ||
63 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java new file mode 100644 index 00000000..e2bc06a9 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java | |||
@@ -0,0 +1,215 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.internal; | ||
2 | |||
3 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
4 | |||
5 | public class ImmutableNode<KEY, VALUE> extends Node<KEY, VALUE> { | ||
6 | /** | ||
7 | * Bitmap defining the stored key and values. | ||
8 | */ | ||
9 | int dataMap; | ||
10 | /** | ||
11 | * Bitmap defining the positions of further nodes. | ||
12 | */ | ||
13 | int nodeMap; | ||
14 | /** | ||
15 | * Stores Keys, Values, and subnodes. Structure: (KEY,VALUE)*,NODE; NODES are stored backwards. | ||
16 | */ | ||
17 | Object[] content; | ||
18 | |||
19 | /** | ||
20 | * Constructor with given content | ||
21 | */ | ||
22 | protected ImmutableNode(int dataMap, int nodeMap, Object[] content) { | ||
23 | this.dataMap = dataMap; | ||
24 | this.nodeMap = nodeMap; | ||
25 | this.content = content; | ||
26 | } | ||
27 | |||
28 | /** | ||
29 | * Constructor that copies a mutable node to an immutable. | ||
30 | * @param node | ||
31 | */ | ||
32 | @SuppressWarnings("unchecked") | ||
33 | protected ImmutableNode(MutableNode<KEY,VALUE> node) { | ||
34 | int size = 0; | ||
35 | for(int i = 0; i<factor; i++) { | ||
36 | if(node.content[i]!=null) { | ||
37 | size++; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | int datas = 0; | ||
42 | int nodes = 0; | ||
43 | this.dataMap = 0; | ||
44 | this.nodeMap = 0; | ||
45 | this.content = new Object[size]; | ||
46 | int bitposition = 1; | ||
47 | for(int i = 0; i<factor; i++) { | ||
48 | Object key = node.content[i*2]; | ||
49 | if(key != null) { | ||
50 | dataMap |= bitposition; | ||
51 | content[datas*2] = key; | ||
52 | content[datas*2+1] = node.content[i*2+1]; | ||
53 | datas++; | ||
54 | } else { | ||
55 | Node<KEY,VALUE> subnode = (Node<KEY, VALUE>) node.content[i*2+1]; | ||
56 | if(subnode != null) { | ||
57 | ImmutableNode<KEY, VALUE> immutableSubnode = subnode.toImmutable(); | ||
58 | nodeMap |=bitposition; | ||
59 | content[size-1-nodes] = immutableSubnode; | ||
60 | nodes++; | ||
61 | } | ||
62 | } | ||
63 | bitposition<<=1; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | private int index(int bitmap, int bitpos) { | ||
68 | return Integer.bitCount(bitmap & (bitpos-1)); | ||
69 | } | ||
70 | |||
71 | @SuppressWarnings("unchecked") | ||
72 | @Override | ||
73 | public VALUE getValue(KEY key, ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue, int hash, int depth) { | ||
74 | int selectedHashFragment = hashFragment(hash,shiftDepth(depth)); | ||
75 | int bitposition = 1 << selectedHashFragment; | ||
76 | // If the key is stored as a data | ||
77 | if((dataMap & bitposition) != 0) { | ||
78 | int keyIndex = 2*index(dataMap, bitposition); | ||
79 | KEY keyCandidate = (KEY) content[keyIndex]; | ||
80 | if(hashProvider.equals(keyCandidate, key)) { | ||
81 | return (VALUE) content[keyIndex+1]; | ||
82 | } else { | ||
83 | return defaultValue; | ||
84 | } | ||
85 | } | ||
86 | // the key is stored as a node | ||
87 | else if((nodeMap & bitposition) != 0) { | ||
88 | int keyIndex = content.length-1-index(nodeMap, bitposition); | ||
89 | ImmutableNode<KEY,VALUE> subNode = (ImmutableNode<KEY,VALUE>) content[keyIndex]; | ||
90 | int newHash = depth%numberOfFactors == 0? | ||
91 | hashProvider.getHash(key, hashDepth(depth)) : | ||
92 | hash; | ||
93 | int newDepth = depth+1; | ||
94 | return subNode.getValue(key, hashProvider, defaultValue, newHash, newDepth); | ||
95 | } | ||
96 | // the key is not stored at all | ||
97 | else { | ||
98 | return defaultValue; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | @SuppressWarnings("unchecked") | ||
103 | @Override | ||
104 | public Node<KEY,VALUE> putValue(KEY key, VALUE value, ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue, int hash, int depth) { | ||
105 | int selectedHashFragment = hashFragment(hash,shiftDepth(depth)); | ||
106 | int bitposition = 1 << selectedHashFragment; | ||
107 | if((dataMap & bitposition) != 0) { | ||
108 | int keyIndex = 2*index(dataMap, bitposition); | ||
109 | KEY keyCandidate = (KEY) content[keyIndex]; | ||
110 | if(hashProvider.equals(keyCandidate, key)) { | ||
111 | if(value == defaultValue) { | ||
112 | // delete | ||
113 | MutableNode<KEY, VALUE> mutable = this.toMutable(); | ||
114 | mutable.removeEntry(selectedHashFragment); | ||
115 | return mutable; | ||
116 | } else if(value == content[keyIndex+1]) { | ||
117 | // dont change | ||
118 | return this; | ||
119 | } else { | ||
120 | // update existing value | ||
121 | MutableNode<KEY, VALUE> mutable = this.toMutable(); | ||
122 | mutable.updateValue(value, selectedHashFragment); | ||
123 | return mutable; | ||
124 | } | ||
125 | } else { | ||
126 | if(value == defaultValue) { | ||
127 | // dont change | ||
128 | return this; | ||
129 | } else { | ||
130 | // add new key + value | ||
131 | MutableNode<KEY, VALUE> mutable = this.toMutable(); | ||
132 | mutable.putValue(key, value, hashProvider, defaultValue, selectedHashFragment, depth); | ||
133 | return mutable; | ||
134 | } | ||
135 | } | ||
136 | } else if((nodeMap & bitposition)!=0) { | ||
137 | |||
138 | int keyIndex = content.length-1-index(dataMap, bitposition); | ||
139 | ImmutableNode<KEY,VALUE> subNode = (ImmutableNode<KEY,VALUE>) content[keyIndex]; | ||
140 | int newHash = newHash(hashProvider, key, selectedHashFragment, depth); | ||
141 | int newDepth = depth+1; | ||
142 | Node<KEY,VALUE> newsubNode = subNode.putValue(key, value, hashProvider, defaultValue, newHash, newDepth); | ||
143 | |||
144 | if(subNode == newsubNode) { | ||
145 | // nothing changed | ||
146 | return this; | ||
147 | } else { | ||
148 | MutableNode<KEY, VALUE> result = toMutable(); | ||
149 | result.updateSubNode(selectedHashFragment, newsubNode); | ||
150 | return result; | ||
151 | } | ||
152 | } else { | ||
153 | // add new key + value | ||
154 | MutableNode<KEY, VALUE> mutable = this.toMutable(); | ||
155 | mutable.putValue(key, value, hashProvider, defaultValue, selectedHashFragment, depth); | ||
156 | return mutable; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | |||
161 | @Override | ||
162 | public int getSize() { | ||
163 | throw new UnsupportedOperationException(); | ||
164 | } | ||
165 | |||
166 | @Override | ||
167 | protected MutableNode<KEY,VALUE> toMutable() { | ||
168 | return new MutableNode<KEY,VALUE>(this); | ||
169 | } | ||
170 | |||
171 | @Override | ||
172 | protected ImmutableNode<KEY,VALUE> toImmutable() { | ||
173 | return this; | ||
174 | } | ||
175 | |||
176 | @Override | ||
177 | protected void prettyPrint(StringBuilder builder, int depth, int code) { | ||
178 | for(int i = 0; i<depth; i++) { | ||
179 | builder.append("\t"); | ||
180 | } | ||
181 | if(code>=0) { | ||
182 | builder.append(code); | ||
183 | builder.append(":"); | ||
184 | } | ||
185 | builder.append("Immutable("); | ||
186 | boolean hadContent = false; | ||
187 | int dataMask = 1; | ||
188 | for(int i = 0; i<factor; i++) { | ||
189 | if((dataMask & dataMap) != 0) { | ||
190 | if(hadContent) { | ||
191 | builder.append(","); | ||
192 | } | ||
193 | builder.append(i); | ||
194 | builder.append(":["); | ||
195 | builder.append(content[2*index(dataMap, dataMask)].toString()); | ||
196 | builder.append("]->["); | ||
197 | builder.append(content[2*index(dataMap, dataMask)+1].toString()); | ||
198 | builder.append("]"); | ||
199 | hadContent = true; | ||
200 | } | ||
201 | dataMask<<=1; | ||
202 | } | ||
203 | builder.append(")"); | ||
204 | int nodeMask = 1; | ||
205 | for(int i = 0; i<factor; i++) { | ||
206 | if((nodeMask & nodeMap)!=0) { | ||
207 | @SuppressWarnings("unchecked") | ||
208 | Node<KEY,VALUE> subNode = (Node<KEY, VALUE>) content[content.length-1-index(nodeMap, nodeMask)]; | ||
209 | builder.append("\n"); | ||
210 | subNode.prettyPrint(builder, depth+1, i); | ||
211 | } | ||
212 | nodeMask<<=1; | ||
213 | } | ||
214 | } | ||
215 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/ImmutableNodeIterator.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/ImmutableNodeIterator.java new file mode 100644 index 00000000..7715bc72 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/ImmutableNodeIterator.java | |||
@@ -0,0 +1,5 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.internal; | ||
2 | |||
3 | public class ImmutableNodeIterator { | ||
4 | |||
5 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MutableNode.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MutableNode.java new file mode 100644 index 00000000..f6d0323e --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MutableNode.java | |||
@@ -0,0 +1,241 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.internal; | ||
2 | |||
3 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
4 | |||
5 | public class MutableNode<KEY,VALUE> extends Node<KEY,VALUE> { | ||
6 | Object[] content; | ||
7 | protected MutableNode() { | ||
8 | this.content = new Object[2*factor]; | ||
9 | } | ||
10 | public static <KEY,VALUE> MutableNode<KEY,VALUE> initialize( | ||
11 | KEY key, VALUE value, | ||
12 | ContinousHashProvider<? super KEY> hashProvider, | ||
13 | VALUE defaultValue) | ||
14 | { | ||
15 | if(value == defaultValue) { | ||
16 | return null; | ||
17 | } else { | ||
18 | int hash = hashProvider.getHash(key, 0); | ||
19 | int fragment = hashFragment(hash, 0); | ||
20 | MutableNode<KEY, VALUE> res = new MutableNode<KEY, VALUE>(); | ||
21 | res.content[2*fragment] = key; | ||
22 | res.content[2*fragment+1] = value; | ||
23 | return res; | ||
24 | } | ||
25 | } | ||
26 | |||
27 | protected MutableNode(ImmutableNode<KEY,VALUE> node) { | ||
28 | this.content = new Object[2*factor]; | ||
29 | int dataUsed=0; | ||
30 | int nodeUsed=0; | ||
31 | for(int i=0; i<factor; i++) { | ||
32 | int bitposition = 1 << i; | ||
33 | if((node.dataMap & bitposition) != 0) { | ||
34 | content[2*i] = this.content[dataUsed*2]; | ||
35 | content[2*i+1] = this.content[dataUsed*2+1]; | ||
36 | dataUsed++; | ||
37 | } else if((node.nodeMap & bitposition) != 0) { | ||
38 | content[2*i+1] = this.content[this.content.length-1-nodeUsed]; | ||
39 | nodeUsed++; | ||
40 | } | ||
41 | } | ||
42 | } | ||
43 | |||
44 | @SuppressWarnings("unchecked") | ||
45 | @Override | ||
46 | public VALUE getValue(KEY key, ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue, int hash, int depth) { | ||
47 | int selectedHashFragment = hashFragment(hash,shiftDepth(depth)); | ||
48 | KEY keyCandidate = (KEY) content[2*selectedHashFragment]; | ||
49 | if(keyCandidate != null) { | ||
50 | if(hashProvider.equals(keyCandidate, key)) { | ||
51 | return (VALUE) content[2*selectedHashFragment+1]; | ||
52 | } else { | ||
53 | return defaultValue; | ||
54 | } | ||
55 | } else { | ||
56 | Node<KEY,VALUE> nodeCandidate = (Node<KEY,VALUE>) content[2*selectedHashFragment+1]; | ||
57 | if(nodeCandidate != null) { | ||
58 | int newHash = newHash(hashProvider, key, hash, depth); | ||
59 | int newDepth = depth+1; | ||
60 | return (VALUE) nodeCandidate.getValue(key, hashProvider, defaultValue, newHash, newDepth); | ||
61 | } else { | ||
62 | return defaultValue; | ||
63 | } | ||
64 | } | ||
65 | } | ||
66 | |||
67 | private boolean hasContent() { | ||
68 | for(Object element : this.content) { | ||
69 | if(element != null) return true; | ||
70 | } | ||
71 | return false; | ||
72 | } | ||
73 | |||
74 | private MutableNode<KEY,VALUE> createNewNode( | ||
75 | ContinousHashProvider<? super KEY> hashProvider, | ||
76 | KEY key1, VALUE value1, int oldHash1, | ||
77 | KEY key2, VALUE value2, int oldHash2, | ||
78 | int newdepth) | ||
79 | { | ||
80 | int newHash1 = newHash(hashProvider, key1, oldHash1, newdepth); | ||
81 | int newHash2 = newHash(hashProvider, key2, oldHash2, newdepth); | ||
82 | int newFragment1 = hashFragment(newHash1, newdepth); | ||
83 | int newFragment2 = hashFragment(newHash2, newdepth); | ||
84 | |||
85 | MutableNode<KEY,VALUE> subNode = new MutableNode<KEY,VALUE>(); | ||
86 | if(newFragment1 != newFragment2) { | ||
87 | subNode.content[newFragment1*2]=key1; | ||
88 | subNode.content[newFragment1*2+1]=value1; | ||
89 | |||
90 | subNode.content[newFragment2*2]=key2; | ||
91 | subNode.content[newFragment2*2+1]=value2; | ||
92 | return subNode; | ||
93 | } else { | ||
94 | MutableNode<KEY,VALUE> subSubNode = createNewNode( | ||
95 | hashProvider, | ||
96 | key1, value1, newHash1, | ||
97 | key2, value2, newHash2, | ||
98 | newdepth+1); | ||
99 | subNode.content[newFragment1*2+1] = subSubNode; | ||
100 | return subNode; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | @SuppressWarnings("unchecked") | ||
105 | @Override | ||
106 | public Node<KEY,VALUE> putValue(KEY key, VALUE value, ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue, int hash, int depth) { | ||
107 | int selectedHashFragment = hashFragment(hash,shiftDepth(depth)); | ||
108 | KEY keyCandidate = (KEY) content[2*selectedHashFragment]; | ||
109 | if(keyCandidate != null) { | ||
110 | if(hashProvider.equals(keyCandidate,key)) { | ||
111 | // Update entry | ||
112 | if(value == defaultValue) { | ||
113 | return removeEntry(selectedHashFragment); | ||
114 | } else { | ||
115 | return updateValue(value, selectedHashFragment); | ||
116 | } | ||
117 | } else { | ||
118 | if(value == defaultValue) { | ||
119 | // dont need to add new node | ||
120 | return this; | ||
121 | } else { | ||
122 | // Split entry: data -> node | ||
123 | return moveDown(key, value, hashProvider, hash, depth, selectedHashFragment, keyCandidate); | ||
124 | } | ||
125 | } | ||
126 | } else { | ||
127 | Node<KEY,VALUE> nodeCandidate = (Node<KEY,VALUE>) content[2*selectedHashFragment+1]; | ||
128 | if(nodeCandidate != null) { | ||
129 | Node<KEY, VALUE> newNode = nodeCandidate.putValue(key, value, hashProvider, defaultValue, newHash(hashProvider, key, hash, depth+1), depth+1); | ||
130 | return updateSubNode(selectedHashFragment,newNode); | ||
131 | } else { | ||
132 | content[2*selectedHashFragment] = key; | ||
133 | return updateValue(value, selectedHashFragment); | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | Node<KEY, VALUE> updateSubNode(int selectedHashFragment, Node<KEY, VALUE> newNode) { | ||
139 | content[2*selectedHashFragment+1] = newNode; | ||
140 | for(int i = 0; i<this.content.length; i++) { | ||
141 | if(content[i]!=null) return this; | ||
142 | } | ||
143 | return null; | ||
144 | } | ||
145 | |||
146 | @SuppressWarnings("unchecked") | ||
147 | Node<KEY, VALUE> moveDown( | ||
148 | KEY key, VALUE value, | ||
149 | ContinousHashProvider<? super KEY> hashProvider, int hash, | ||
150 | int depth, int selectedHashFragment, KEY keyCandidate) { | ||
151 | KEY previousKey = keyCandidate; | ||
152 | VALUE previousValue = (VALUE) content[2*selectedHashFragment+1]; | ||
153 | |||
154 | MutableNode<KEY,VALUE> subNode = createNewNode( | ||
155 | hashProvider, | ||
156 | previousKey, previousValue, hashProvider.getHash(previousKey, hashDepth(depth)), | ||
157 | key, value, hash, | ||
158 | depth+1); | ||
159 | |||
160 | content[2*selectedHashFragment] = null; | ||
161 | content[2*selectedHashFragment+1] = subNode; | ||
162 | return this; | ||
163 | } | ||
164 | |||
165 | Node<KEY, VALUE> updateValue(VALUE value, int selectedHashFragment) { | ||
166 | content[2*selectedHashFragment+1] = value; | ||
167 | return this; | ||
168 | } | ||
169 | Node<KEY, VALUE> removeEntry(int selectedHashFragment) { | ||
170 | content[2*selectedHashFragment] = null; | ||
171 | content[2*selectedHashFragment+1] = null; | ||
172 | if(hasContent()) { | ||
173 | return this; | ||
174 | } else { | ||
175 | return null; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | @SuppressWarnings("unchecked") | ||
180 | @Override | ||
181 | public int getSize() { | ||
182 | int size = 0; | ||
183 | for(int i=0; i<factor; i++) { | ||
184 | if(content[i*2]!=null) { | ||
185 | size++; | ||
186 | } else{ | ||
187 | Node<KEY,VALUE> nodeCandidate = (Node<KEY, VALUE>) content[i*2+1]; | ||
188 | if(nodeCandidate!=null) { | ||
189 | size+=nodeCandidate.getSize(); | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | return size; | ||
194 | } | ||
195 | |||
196 | @Override | ||
197 | protected MutableNode<KEY,VALUE> toMutable() { | ||
198 | return this; | ||
199 | } | ||
200 | |||
201 | @Override | ||
202 | protected ImmutableNode<KEY,VALUE> toImmutable() { | ||
203 | return new ImmutableNode<KEY,VALUE>(this); | ||
204 | } | ||
205 | |||
206 | @Override | ||
207 | protected void prettyPrint(StringBuilder builder, int depth, int code) { | ||
208 | for(int i = 0; i<depth; i++) { | ||
209 | builder.append("\t"); | ||
210 | } | ||
211 | if(code>=0) { | ||
212 | builder.append(code); | ||
213 | builder.append(":"); | ||
214 | } | ||
215 | builder.append("Mutable("); | ||
216 | boolean hadContent = false; | ||
217 | for(int i = 0; i<factor; i++) { | ||
218 | if(content[2*i] != null) { | ||
219 | if(hadContent) { | ||
220 | builder.append(","); | ||
221 | } | ||
222 | builder.append(i); | ||
223 | builder.append(":["); | ||
224 | builder.append(content[2*i].toString()); | ||
225 | builder.append("]->["); | ||
226 | builder.append(content[2*i+1].toString()); | ||
227 | builder.append("]"); | ||
228 | hadContent = true; | ||
229 | } | ||
230 | } | ||
231 | builder.append(")"); | ||
232 | for(int i = 0; i<factor; i++) { | ||
233 | if(content[2*i] == null || content[2*i+1]!=null) { | ||
234 | @SuppressWarnings("unchecked") | ||
235 | Node<KEY,VALUE> subNode = (Node<KEY, VALUE>) content[2*i+1]; | ||
236 | builder.append("\n"); | ||
237 | subNode.prettyPrint(builder, depth+1, i); | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MutableNodeIterator.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MutableNodeIterator.java new file mode 100644 index 00000000..619eb3b2 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MutableNodeIterator.java | |||
@@ -0,0 +1,29 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.internal; | ||
2 | |||
3 | import java.util.Map.Entry; | ||
4 | |||
5 | public class MutableNodeIterator<KEY,VALUE> extends NodeIterator<MutableNode<KEY,VALUE>,KEY, VALUE>{ | ||
6 | |||
7 | public MutableNodeIterator(MutableNode<KEY, VALUE> node) { | ||
8 | super(node); | ||
9 | } | ||
10 | |||
11 | /** | ||
12 | * Index of the last result value; | ||
13 | */ | ||
14 | int index = -1; | ||
15 | NodeIterator<KEY,VALUE> actualSubNode = null; | ||
16 | |||
17 | @Override | ||
18 | public boolean hasNext() { | ||
19 | for(int i = index; i<node.factor; i++) { | ||
20 | |||
21 | } | ||
22 | return false; | ||
23 | } | ||
24 | @Override | ||
25 | public Entry<KEY, VALUE> next() { | ||
26 | // TODO Auto-generated method stub | ||
27 | return null; | ||
28 | } | ||
29 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/Node.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/Node.java new file mode 100644 index 00000000..89c52f7f --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/Node.java | |||
@@ -0,0 +1,69 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.internal; | ||
2 | |||
3 | import org.eclipse.viatra.solver.data.map.ContinousHashProvider; | ||
4 | |||
5 | public abstract class Node<KEY,VALUE>{ | ||
6 | protected static final int branchingFactorBit = 5; | ||
7 | protected static final int factor = 1<<branchingFactorBit; | ||
8 | protected static final int numberOfFactors = Integer.SIZE / branchingFactorBit; | ||
9 | protected static final int factorMask = factor-1; | ||
10 | |||
11 | /** | ||
12 | * Calculates the index for the continuous hash. | ||
13 | * @param depth The depth of the node in the tree. | ||
14 | * @return The index of the continuous hash. | ||
15 | */ | ||
16 | protected static int hashDepth(int depth) { | ||
17 | return depth/numberOfFactors; | ||
18 | } | ||
19 | |||
20 | /** | ||
21 | * Calculates the which segment of a single hash should be used. | ||
22 | * @param depth The depth of the node in the tree. | ||
23 | * @return The segment of a hash code. | ||
24 | */ | ||
25 | protected static int shiftDepth(int depth) { | ||
26 | return depth%numberOfFactors; | ||
27 | } | ||
28 | /** | ||
29 | * Selects a segments from a complete hash for a given depth. | ||
30 | * @param hash A complete hash. | ||
31 | * @param shiftDepth The index of the segment. | ||
32 | * @return The segment as an integer. | ||
33 | */ | ||
34 | protected static int hashFragment(int hash, int shiftDepth) { | ||
35 | return (hash >>> shiftDepth*branchingFactorBit) & factorMask; | ||
36 | } | ||
37 | /** | ||
38 | * Returns the hash code for a given depth. It may calculate new hash code, or reuse a hash code calculated for depth-1. | ||
39 | * @param key The key. | ||
40 | * @param hash Hash code for depth-1 | ||
41 | * @param depth The depth. | ||
42 | * @return The new hash code. | ||
43 | */ | ||
44 | protected int newHash(final ContinousHashProvider<? super KEY> hashProvider, KEY key, int hash, int depth) { | ||
45 | return depth%numberOfFactors == 0? | ||
46 | hashProvider.getHash(key, hashDepth(depth)) : | ||
47 | hash; | ||
48 | } | ||
49 | |||
50 | |||
51 | abstract public VALUE getValue(KEY key, ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue, int hash, int depth); | ||
52 | abstract public Node<KEY,VALUE> putValue(KEY key, VALUE value, ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue, int hash, int depth); | ||
53 | abstract public int getSize(); | ||
54 | |||
55 | abstract protected MutableNode<KEY, VALUE> toMutable(); | ||
56 | abstract protected ImmutableNode<KEY, VALUE> toImmutable(); | ||
57 | |||
58 | ///////// For iterators | ||
59 | //abstract boolean moveIteratorToNextData(NodeIterator<KEY,VALUE> iterator, int currentIndex); | ||
60 | //abstract boolean moveIteratorToNextNode(NodeIterator<KEY,VALUE> iterator, int currentIndex); | ||
61 | ///////// FOR printing | ||
62 | abstract protected void prettyPrint(StringBuilder builder, int depth, int code); | ||
63 | @Override | ||
64 | public String toString() { | ||
65 | StringBuilder stringBuilder = new StringBuilder(); | ||
66 | prettyPrint(stringBuilder, 0, -1); | ||
67 | return stringBuilder.toString(); | ||
68 | } | ||
69 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/NodeIterator.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/NodeIterator.java new file mode 100644 index 00000000..4c426b1e --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/NodeIterator.java | |||
@@ -0,0 +1,13 @@ | |||
1 | package org.eclipse.viatra.solver.data.map.internal; | ||
2 | |||
3 | import java.util.Iterator; | ||
4 | import java.util.Map; | ||
5 | |||
6 | public abstract class NodeIterator<NODETYPE extends Node<KEY,VALUE>,KEY,VALUE> | ||
7 | implements Iterator<Map.Entry<KEY,VALUE>> | ||
8 | { | ||
9 | protected NODETYPE node; | ||
10 | public NodeIterator(NODETYPE node) { | ||
11 | this.node = node; | ||
12 | } | ||
13 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/tests/org/eclipse/viatra/solver/data/map/MapSmokeTest.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/tests/org/eclipse/viatra/solver/data/map/MapSmokeTest.java new file mode 100644 index 00000000..e1a7a39b --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/tests/org/eclipse/viatra/solver/data/map/MapSmokeTest.java | |||
@@ -0,0 +1,82 @@ | |||
1 | package org.eclipse.viatra.solver.data.map; | ||
2 | |||
3 | import java.util.Random; | ||
4 | |||
5 | import org.junit.jupiter.api.Test; | ||
6 | |||
7 | public class MapSmokeTest { | ||
8 | |||
9 | private void runTest(int seed, int steps, int maxKey, int maxValue) { | ||
10 | String[] values = new String[maxValue]; | ||
11 | for(int i = 0; i<values.length; i++) { | ||
12 | values[i] = "VALUE-"+i; | ||
13 | } | ||
14 | ContinousHashProvider<Integer> chp = new ContinousHashProvider<Integer>() { | ||
15 | |||
16 | @Override | ||
17 | public int getHash(Integer key, int index) { | ||
18 | int result = 1; | ||
19 | final int prime = 31; | ||
20 | result = prime*result + key; | ||
21 | result = prime*result + index; | ||
22 | return result; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public boolean equals(Integer key1, Integer key2) { | ||
27 | return key1.equals(key2); | ||
28 | } | ||
29 | }; | ||
30 | |||
31 | VersionedMap<Integer, String> sut = new VersionedMap<Integer, String>(chp, values[0]); | ||
32 | MapTestEnvironment<Integer, String> e = new MapTestEnvironment<Integer, String>(sut); | ||
33 | |||
34 | Random r = new Random(seed); | ||
35 | |||
36 | iterativeCall(steps, maxKey, maxValue, values, e, r); | ||
37 | } | ||
38 | |||
39 | void recursiveCall( | ||
40 | int steps, | ||
41 | int maxKey, | ||
42 | int maxValue, | ||
43 | String[] values, | ||
44 | MapTestEnvironment<Integer, String> e, | ||
45 | Random r) | ||
46 | { | ||
47 | if(steps<=0) { | ||
48 | return; | ||
49 | } else { | ||
50 | e.put(r.nextInt(maxKey), values[r.nextInt(maxValue)]); | ||
51 | e.checkEquivalence(); | ||
52 | |||
53 | recursiveCall(steps-1, maxKey, maxValue, values, e, r); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | void iterativeCall(int steps, | ||
58 | int maxKey, | ||
59 | int maxValue, | ||
60 | String[] values, | ||
61 | MapTestEnvironment<Integer, String> e, | ||
62 | Random r) | ||
63 | { | ||
64 | for(int i=0; i<steps; i++) { | ||
65 | e.put(r.nextInt(maxKey), values[r.nextInt(maxValue)]); | ||
66 | e.checkEquivalence(); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | @Test | ||
71 | void runTest1() { | ||
72 | runTest(0, 100000, 3, 2); | ||
73 | } | ||
74 | @Test | ||
75 | void runTest2() { | ||
76 | runTest(1, 100000, 3, 2); | ||
77 | } | ||
78 | @Test | ||
79 | void runTest3() { | ||
80 | runTest(1, 32*32*32*32, 32*32-1, 2); | ||
81 | } | ||
82 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/tests/org/eclipse/viatra/solver/data/map/MapTestEnvironment.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/tests/org/eclipse/viatra/solver/data/map/MapTestEnvironment.java new file mode 100644 index 00000000..5e9b2e5f --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/tests/org/eclipse/viatra/solver/data/map/MapTestEnvironment.java | |||
@@ -0,0 +1,41 @@ | |||
1 | package org.eclipse.viatra.solver.data.map; | ||
2 | |||
3 | import static org.junit.Assert.fail; | ||
4 | import static org.junit.jupiter.api.Assertions.assertEquals; | ||
5 | |||
6 | import java.util.HashMap; | ||
7 | import java.util.Map; | ||
8 | import java.util.Map.Entry; | ||
9 | |||
10 | import junit.framework.AssertionFailedError; | ||
11 | |||
12 | public class MapTestEnvironment<KEY,VALUE> { | ||
13 | VersionedMap<KEY, VALUE> sut; | ||
14 | Map<KEY,VALUE> oracle = new HashMap<KEY, VALUE>(); | ||
15 | |||
16 | public MapTestEnvironment(VersionedMap<KEY, VALUE> sut) { | ||
17 | this.sut = sut; | ||
18 | } | ||
19 | |||
20 | public void put(KEY key, VALUE value) { | ||
21 | sut.put(key, value); | ||
22 | oracle.put(key, value); | ||
23 | } | ||
24 | |||
25 | public void checkEquivalence() { | ||
26 | int nonDefault = 0; | ||
27 | for(Entry<KEY, VALUE> entry : oracle.entrySet()) { | ||
28 | VALUE sutAnswer = sut.get(entry.getKey()); | ||
29 | VALUE oracleAnswer1 = entry.getValue(); | ||
30 | VALUE oracleAnswer2 = (oracleAnswer1 == null)?sut.getDefaultValue():oracleAnswer1; | ||
31 | if(sutAnswer!=oracleAnswer2) { | ||
32 | fail("Non-equivalent gets: " + sutAnswer + " != " + oracleAnswer2 + "<-[oracle]") ; | ||
33 | } | ||
34 | if(entry.getValue() != sut.getDefaultValue()) { | ||
35 | nonDefault++; | ||
36 | } | ||
37 | } | ||
38 | int sutNonDefault = sut.getSize(); | ||
39 | assertEquals(sutNonDefault, nonDefault); | ||
40 | } | ||
41 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/tests/org/eclipse/viatra/solver/data/map/MapTests.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/tests/org/eclipse/viatra/solver/data/map/MapTests.java new file mode 100644 index 00000000..28a49380 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/tests/org/eclipse/viatra/solver/data/map/MapTests.java | |||
@@ -0,0 +1,5 @@ | |||
1 | package org.eclipse.viatra.solver.data.map; | ||
2 | |||
3 | public class MapTests { | ||
4 | |||
5 | } | ||