package org.streaminer.util.distribution;
import java.util.Random;
/**
*
* @author Maycon Viana Bordin <mayconbordin@gmail.com>
*/
public class ZipfDistribution {
private double theta;
private double alpha;
private double eta;
private double zetan;
private long n;
private Random random = new Random();
public ZipfDistribution(double theta, long n) {
this(theta, n, n);
}
public ZipfDistribution(double theta, long n, long length) {
this.theta = theta;
this.n = n;
alpha = 1. / (1. - theta);
zetan = zeta(length, theta);
eta = (1. - Math.pow(2.0/n, 1.0 - theta)) / (1.0 - zeta(2, theta)/zetan);
}
public double nextDouble() {
double val;
double u = random.nextDouble();
double uz = u * zetan;
if (uz < 1) val = 1;
else if (uz < (1. + Math.pow(0.5, theta))) val = 2;
else val = 1 + (long)(n * Math.pow(eta*u - eta + 1.0, alpha));
return val;
}
public static double zeta(long n, double theta) {
double ans=0.0;
for (int i=1; i <= n; i++)
ans += Math.pow(1./(double)i, theta);
return ans;
}
}