package com.k13n.soliton;

import java.util.Random;

public class RobustSolitonGenerator implements SolitonGenerator {
  private Random random;
  private int k;
  private double c, delta, R, beta;

  public RobustSolitonGenerator(int k, double c, double delta, long seed) {
    this.k = k;
    this.c = c;
    this.delta = delta;
    random = new Random(seed);
    R = computeR();
    beta = computeBeta();
  }

  public RobustSolitonGenerator(int k, double c, double delta) {
    this(k, c, delta, new Random().nextLong());
  }

  private double computeR() {
    return c * Math.log(k / delta) * Math.sqrt(k);
  }

  private double computeBeta() {
    double sum = 0;
    for (int i = 1; i <= k; i++)
      sum += idealSoliton(i) + unnormalizedRobustSoliton(i);
    return sum;
  }

  @Override
  public int next() {
    double u = random.nextDouble();
    return inverseTransformSampling(u);
  }

  private int inverseTransformSampling(double u) {
     double sum = 0;
     int index = 1;
     while (sum <= u)
       sum += normalizedRobustSoliton(index++);
     return index - 1;
  }

  private double normalizedRobustSoliton(int i) {
    return (idealSoliton(i) + unnormalizedRobustSoliton(i)) / beta;
  }

  private double unnormalizedRobustSoliton(int i) {
    if (1 <= i && i <= Math.floor(k/R)-1)
      return R / (i*k);
    else if (i == Math.floor(k / R))
      return R * Math.log(R / delta) / k;
    else
      return 0;
  }

  private double idealSoliton(int i) {
    if (i == 1)
      return 1.0 / k;
    else
      return 1.0 / (i * (i-1));
  }

}

@@ -152,18 +152,21 @@
 te int k
+, M
 ;%0A
-
   privat
@@ -373,24 +373,44 @@
 computeR();%0A
+    M = computeM();%0A
     beta = c
@@ -624,32 +624,434 @@
 h.sqrt(k);%0A  %7D%0A%0A
+  private int computeM() %7B%0A    return (int) Math.floor(k / R);%0A  %7D%0A%0A%0A  public RobustSolitonGenerator(int k, int M, double delta, long seed) %7B%0A    this.k = k;%0A    this.M = M;%0A    this.delta = delta;%0A    random = new Random(seed);%0A    R = k / ((double) M);%0A    beta = computeBeta();%0A  %7D%0A%0A  public RobustSolitonGenerator(int k, int M, double delta) %7B%0A    this(k, M, delta, new Random().nextLong());%0A  %7D%0A%0A%0A
   private double
@@ -1710,22 +1710,8 @@
 %3C= M
-ath.floor(k/R)
 -1)%0A
@@ -1727,16 +1727,18 @@
 urn 
-R
+1.0
  / (i*
-k
+M
 );%0A 
@@ -1755,32 +1755,16 @@
  (i == M
-ath.floor(k / R)
 )%0A      
@@ -1773,12 +1773,8 @@
 turn
- R *
  Mat
@@ -1792,17 +1792,17 @@
 elta) / 
-k
+M
 ;%0A    el

Add a constructor to fix the position of the last spike