aboutsummaryrefslogtreecommitdiffstats
path: root/store/src/test/java/org/eclipse/viatra/solver/data/model/hashTests/HashEfficiencyTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'store/src/test/java/org/eclipse/viatra/solver/data/model/hashTests/HashEfficiencyTest.java')
-rw-r--r--store/src/test/java/org/eclipse/viatra/solver/data/model/hashTests/HashEfficiencyTest.java160
1 files changed, 160 insertions, 0 deletions
diff --git a/store/src/test/java/org/eclipse/viatra/solver/data/model/hashTests/HashEfficiencyTest.java b/store/src/test/java/org/eclipse/viatra/solver/data/model/hashTests/HashEfficiencyTest.java
new file mode 100644
index 00000000..c4d98a43
--- /dev/null
+++ b/store/src/test/java/org/eclipse/viatra/solver/data/model/hashTests/HashEfficiencyTest.java
@@ -0,0 +1,160 @@
1package org.eclipse.viatra.solver.data.model.hashTests;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4
5import java.util.ArrayList;
6import java.util.LinkedList;
7import java.util.List;
8import java.util.Random;
9
10import org.eclipse.viatra.solver.data.map.ContinousHashProvider;
11import org.eclipse.viatra.solver.data.model.Tuple;
12import org.eclipse.viatra.solver.data.model.TupleHashProvider;
13import org.eclipse.viatra.solver.data.model.TupleHashProviderBitMagic;
14import org.junit.jupiter.api.Test;
15
16class HashEfficiencyTest {
17
18 private static List<Tuple> permutations(int range, int arity) {
19 if(arity == 1) {
20 List<Tuple> result = new ArrayList<>(range);
21 for(int i=0; i<range; i++) {
22 result.add(Tuple.of(i));
23 }
24 return result;
25 } else if(arity > 1) {
26 List<Tuple> smallers = permutations(range, arity-1);
27 List<Tuple> result = new ArrayList<>(range*smallers.size());
28 for(Tuple smaller : smallers) {
29 for(int i=0; i<range; i++) {
30 int[] larger = new int[arity];
31 for(int x = 0; x<smaller.getSize(); x++) {
32 larger[x] = smaller.get(x);
33 }
34 larger[arity-1] = i;
35 result.add(Tuple.of(larger));
36 }
37 }
38 return result;
39 } else throw new IllegalArgumentException();
40 }
41
42 private static int amountToRange(int arity, int n) {
43 int range = 1;
44 while(Math.pow(range,arity)<n+0.1) {
45 range++;
46 }
47 return 1024;
48 }
49
50 public static List<Tuple> nPermutations(int arity, int n) {
51 int range = amountToRange(arity, n);
52 List<Tuple> permutations = permutations(range, arity);
53 return permutations.subList(0, n);
54 }
55
56 public static List<Tuple> nRandoms(int arity, int n, int seed) {
57 int range = amountToRange(arity, n);
58 List<Tuple> permutations = new ArrayList<>(n);
59 Random r = new Random(seed);
60 for(int i = 0; i<n; i++) {
61 int[] tuple = new int[arity];
62 for(int j=0; j<arity; j++) {
63 tuple[j] = r.nextInt(range);
64 }
65 permutations.add(Tuple.of(tuple));
66 }
67 return permutations;
68 }
69
70 @Test
71 void permutationTest() {
72 List<Tuple> p = permutations(10, 2);
73 assertEquals(p.size(),10*10);
74 }
75// private void printTuples(List<Tuple> p) {
76// for(Tuple element : p) {
77// System.out.println(element);
78// }
79// }
80 @Test
81 void nPermutationTest() {
82 final int amount = 500;
83 List<Tuple> p = nPermutations(2, amount);
84 assertEquals(amount,p.size());
85 }
86 @Test
87 void nRandomTest() {
88 final int amount = 500;
89 List<Tuple> p = nRandoms(2, amount, 1);;
90 assertEquals(amount,p.size());
91 }
92 private static double calculateHashClashes(List<Tuple> tuples, ContinousHashProvider<Tuple> chp) {
93 int sumClashes = 0;
94
95 for(int i = 0; i<tuples.size(); i++) {
96 int height = 0;
97 for(int j=0; j<tuples.size(); j++) {
98 int clashes = calculateHashClash(chp, tuples.get(i), tuples.get(j));
99 height = Math.max(height, clashes);
100 }
101 sumClashes += height;
102 }
103 return (sumClashes+0.0) / tuples.size();
104 }
105 private static int calculateHashClash(ContinousHashProvider<Tuple> chp, Tuple a, Tuple b) {
106 if(a.equals(b)) return 0;
107 final int bits = 5;
108 final int segments = Integer.SIZE/bits;
109 final int mask = (1<<bits)-1;
110 for(int i = 0;;i++) {
111 int index = i/segments;
112 int depth = i%segments;
113 int aHash = (chp.getHash(a, index)>>(depth*5))&mask;
114 int bHash = (chp.getHash(b, index)>>(depth*5))&mask;
115 if(aHash != bHash) {
116 return i+1;
117 }
118 if(i>400) {
119 throw new IllegalStateException(a+" vs "+b);
120 }
121 }
122 }
123 private static double caclulateOptimalHashClash(int size) {
124 return (Math.log(size)/Math.log(32));
125 }
126 public static void main(String[] args) {
127 List<String> hashNames = new LinkedList<>();
128 List<ContinousHashProvider<Tuple>> hashes = new LinkedList<>();
129 hashNames.add("PrimeGroup");
130 hashes.add(new TupleHashProvider());
131 hashNames.add("BitMagic");
132 hashes.add(new TupleHashProviderBitMagic());
133
134 int[] arities = new int[] {2,3,4,5};
135 int[] sizes = new int[] {32*32,32*32*8};
136
137 System.out.println("Size,Arity,DataSource,Hash,Chashes,Optimal,Badness");
138 for(int size : sizes) {
139 double optimalClashes = caclulateOptimalHashClash(size);
140 for(int arity : arities) {
141 List<String> dataSourceNames = new LinkedList<>();
142 List<List<Tuple>> dataSources = new LinkedList<>();
143
144// dataSourceNames.add("Permutation");
145// dataSources.add(nPermutations(arity, size));
146 dataSourceNames.add("Random");
147 dataSources.add(nRandoms(arity, size, 0));
148
149 for(int dataSourceIndex = 0; dataSourceIndex<dataSourceNames.size(); dataSourceIndex++) {
150 for(int hashIndex = 0; hashIndex<hashNames.size(); hashIndex++) {
151 double clashes = calculateHashClashes(dataSources.get(dataSourceIndex),hashes.get(hashIndex));
152 System.out.println(
153 size+","+arity+","+dataSourceNames.get(dataSourceIndex)+","+hashNames.get(hashIndex)+","+
154 clashes+","+optimalClashes+","+(clashes+0.0)/optimalClashes);
155 }
156 }
157 }
158 }
159 }
160}