package edu.cmu.graphchi.walks; import edu.cmu.graphchi.ChiVertex; import edu.cmu.graphchi.engine.auxdata.VertexDegree; import org.junit.Test; import java.util.Random; import static junit.framework.Assert.*; /** */ public class TestWeightedHopper { private float[] initWeights(int n) { float[] weights = new float[n]; Random rinit = new Random(4091982); for(int i=0; i <weights.length; i++) { weights[i] = rinit.nextFloat() * 10.0f; } return weights; } @Test public void testBasicMethod() { final float[] weights = initWeights(1000); ChiVertex<Integer, Float> vert = new ChiVertex<Integer, Float>(0, new VertexDegree(0, weights.length)) { public Float getOutEdgeValue(int i) { return weights[i]; } @Override public int getOutEdgeId(int i) { return i; } @Override public int numOutEdges() { return weights.length; } }; int n = 10000000; int[] hops = WeightedHopper.generateRandomHopsOut(new Random(260379), vert, n); assertEquals(hops.length, n); /* Now check the distribution makes sense */ int[] counts = new int[weights.length]; for(int i=0; i < hops.length; i++) { assertTrue(hops[i] >= 0 && hops[i] < weights.length); counts[hops[i]]++; } float totalWeight = 0.0f; for(int j=0; j < weights.length; j++) totalWeight += weights[j]; for(int j=0; j < weights.length; j++) { int expected = (int) (n * weights[j] / totalWeight); assertTrue(Math.abs(expected - counts[j]) < n / weights.length); // dubious } } @Test public void testBasicMethodSmall() { final float[] weights = initWeights(18); ChiVertex<Integer, Float> vert = new ChiVertex<Integer, Float>(0, new VertexDegree(0, weights.length)) { public Float getOutEdgeValue(int i) { return weights[i]; } @Override public int getOutEdgeId(int i) { return i; } @Override public int numOutEdges() { return weights.length; } }; int n = 10000000; int[] hops = WeightedHopper.generateRandomHopsOut(new Random(260379), vert, n); assertEquals(hops.length, n); /* Now check the distribution makes sense */ int[] counts = new int[weights.length]; for(int i=0; i < hops.length; i++) { assertTrue(hops[i] >= 0 && hops[i] < weights.length); counts[hops[i]]++; } float totalWeight = 0.0f; for(int j=0; j < weights.length; j++) totalWeight += weights[j]; for(int j=0; j < weights.length; j++) { int expected = (int) (n * weights[j] / totalWeight); assertTrue(Math.abs(expected - counts[j]) < n / weights.length); // dubious } } @Test public void testAliasMethod() { final float[] weights = initWeights(1000); ChiVertex<Integer, Float> vert = new ChiVertex<Integer, Float>(0, new VertexDegree(0, weights.length)) { public Float getOutEdgeValue(int i) { return weights[i]; } @Override public int getOutEdgeId(int i) { return i; } @Override public int numOutEdges() { return weights.length; } }; int n = 10000000; int[] hops = WeightedHopper.generateRandomHopsAliasMethodOut(new Random(260379), vert, n); assertEquals(hops.length, n); /* Now check the distribution makes sense */ int[] counts = new int[weights.length]; for(int i=0; i < hops.length; i++) { assertTrue(hops[i] >= 0 && hops[i] < weights.length); counts[hops[i]]++; } float totalWeight = 0.0f; for(int j=0; j < weights.length; j++) totalWeight += weights[j]; for(int j=0; j < weights.length; j++) { int expected = (int) (n * weights[j] / totalWeight); assertTrue(Math.abs(expected - counts[j]) < n / weights.length); // dubious } } @Test public void testBoth() { long t1 = System.currentTimeMillis(); testBasicMethod(); long t2 = System.currentTimeMillis(); testAliasMethod(); long tt = System.currentTimeMillis(); System.out.println("Timings: basic=" + (t2 - t1) + " ms, alias=" + (tt - t2)); } }