package org.eclipse.viatra.solver.data.model.hashTests; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Random; import org.eclipse.viatra.solver.data.map.ContinousHashProvider; import org.eclipse.viatra.solver.data.model.Tuple; import org.eclipse.viatra.solver.data.model.TupleHashProvider; import org.eclipse.viatra.solver.data.model.TupleHashProviderBitMagic; import org.junit.jupiter.api.Test; class HashEfficiencyTest { private static List permutations(int range, int arity) { if(arity == 1) { List result = new ArrayList<>(range); for(int i=0; i 1) { List smallers = permutations(range, arity-1); List result = new ArrayList<>(range*smallers.size()); for(Tuple smaller : smallers) { for(int i=0; i nPermutations(int arity, int n) { int range = amountToRange(arity, n); List permutations = permutations(range, arity); return permutations.subList(0, n); } public static List nRandoms(int arity, int n, int seed) { int range = amountToRange(arity, n); List permutations = new ArrayList<>(n); Random r = new Random(seed); for(int i = 0; i p = permutations(10, 2); assertEquals(p.size(),10*10); } // private void printTuples(List p) { // for(Tuple element : p) { // System.out.println(element); // } // } @Test void nPermutationTest() { final int amount = 500; List p = nPermutations(2, amount); assertEquals(amount,p.size()); } @Test void nRandomTest() { final int amount = 500; List p = nRandoms(2, amount, 1);; assertEquals(amount,p.size()); } private static double calculateHashClashes(List tuples, ContinousHashProvider chp) { int sumClashes = 0; for(int i = 0; i chp, Tuple a, Tuple b) { if(a.equals(b)) return 0; final int bits = 5; final int segments = Integer.SIZE/bits; final int mask = (1<>(depth*5))&mask; int bHash = (chp.getHash(b, index)>>(depth*5))&mask; if(aHash != bHash) { return i+1; } if(i>400) { throw new IllegalStateException(a+" vs "+b); } } } private static double caclulateOptimalHashClash(int size) { return (Math.log(size)/Math.log(32)); } public static void main(String[] args) { List hashNames = new LinkedList<>(); List> hashes = new LinkedList<>(); hashNames.add("PrimeGroup"); hashes.add(new TupleHashProvider()); hashNames.add("BitMagic"); hashes.add(new TupleHashProviderBitMagic()); int[] arities = new int[] {2,3,4,5}; int[] sizes = new int[] {32*32,32*32*8}; System.out.println("Size,Arity,DataSource,Hash,Chashes,Optimal,Badness"); for(int size : sizes) { double optimalClashes = caclulateOptimalHashClash(size); for(int arity : arities) { List 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