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