Distributions
- added all distributions required - introduced tests
This commit is contained in:
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"java.configuration.updateBuildConfiguration": "automatic"
|
||||
}
|
||||
14
pom.xml
14
pom.xml
@@ -13,4 +13,18 @@
|
||||
<maven.compiler.target>23</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-runner</artifactId>
|
||||
<version>1.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -10,7 +10,7 @@ public interface Distribution {
|
||||
* Represents an exponential distribution.
|
||||
*/
|
||||
public static class Exponential implements Distribution {
|
||||
private final double lambda;
|
||||
public final double lambda;
|
||||
|
||||
/**
|
||||
* Creates a new exponential distribution with the given rate.
|
||||
@@ -31,8 +31,8 @@ public interface Distribution {
|
||||
* Represents a normal distribution.
|
||||
*/
|
||||
public static class Normal implements Distribution {
|
||||
private final double mean;
|
||||
private final double sigma;
|
||||
public final double mean;
|
||||
public final double sigma;
|
||||
|
||||
/**
|
||||
* Creates a new normal distribution with the given mean and standard deviation.
|
||||
@@ -56,8 +56,8 @@ public interface Distribution {
|
||||
* Represents a normal distribution using the Box-Muller transform.
|
||||
*/
|
||||
public static class NormalBoxMuller implements Distribution {
|
||||
private final double mean;
|
||||
private final double sigma;
|
||||
public final double mean;
|
||||
public final double sigma;
|
||||
|
||||
/**
|
||||
* Creates a new normal distribution with the given mean and standard deviation.
|
||||
@@ -74,9 +74,102 @@ public interface Distribution {
|
||||
public double sample(Rng rng) {
|
||||
var sample1 = rng.random();
|
||||
var sample2 = rng.random();
|
||||
//remove the other value for thread safety
|
||||
//next = mean + sigma * Math.sqrt(-2 * Math.log(sample1)) * Math.sin(2 * Math.PI * sample2);
|
||||
// remove the other value for thread safety
|
||||
// next = mean + sigma * Math.sqrt(-2 * Math.log(sample1)) * Math.sin(2 *
|
||||
// Math.PI * sample2);
|
||||
return mean + sigma * Math.sqrt(-2 * Math.log(sample1)) * Math.cos(2 * Math.PI * sample2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent a uniform distribution.
|
||||
*/
|
||||
public static class Uniform implements Distribution {
|
||||
public final double min;
|
||||
public final double max;
|
||||
|
||||
/**
|
||||
* Creates a new uniform distribution with the given min value and max value.
|
||||
*
|
||||
* @param min the minimum value possible
|
||||
* @param max the maximum value possible
|
||||
*/
|
||||
public Uniform(double min, double max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sample(Rng rng) {
|
||||
return min + rng.random() * (max - min);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent an Erlang distribution.
|
||||
*/
|
||||
public static class Erlang implements Distribution {
|
||||
public final int k;
|
||||
public final double lambda;
|
||||
|
||||
/**
|
||||
* Creates a new erlang distribution with the given K exponentials, all with the
|
||||
* same lambda.
|
||||
*
|
||||
* @param k the number of exponentials
|
||||
* @param lambda the lambda of the exponentials
|
||||
*/
|
||||
public Erlang(int k, double lambda) {
|
||||
this.k = k;
|
||||
this.lambda = lambda;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sample(Rng rng) {
|
||||
var product = 1.0;
|
||||
for (int i = 0; i < this.k; i++) {
|
||||
product *= rng.random();
|
||||
}
|
||||
return -Math.log(product) / this.lambda;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent a HyperExponential distribution.
|
||||
*/
|
||||
public static class HyperExponential implements Distribution {
|
||||
private final double[] lambdas;
|
||||
private final double[] probabilities;
|
||||
|
||||
/**
|
||||
* Creates a new hyperexponential distribution with the given lambdas and their
|
||||
* corresponding probabilities.
|
||||
*
|
||||
* @param lambdas the array of lambda values for the exponential
|
||||
* distributions
|
||||
* @param probabilities the array of probabilities for each lambda
|
||||
*/
|
||||
public HyperExponential(double[] lambdas, double[] probabilities) {
|
||||
if (lambdas.length != probabilities.length) {
|
||||
throw new IllegalArgumentException("Lambdas and probabilities must have the same length");
|
||||
}
|
||||
this.lambdas = lambdas;
|
||||
this.probabilities = probabilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sample(Rng rng) {
|
||||
var randomValue = rng.random();
|
||||
var i = 0;
|
||||
|
||||
while (i < probabilities.length) {
|
||||
randomValue -= probabilities[i];
|
||||
if (randomValue <= 0.0d)
|
||||
break;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return -Math.log(rng.random()) / lambdas[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public class Statistics {
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
*
|
||||
* @param save
|
||||
* @param val1
|
||||
|
||||
29
src/test/java/net/berack/upo/valpre/rand/TestRandom.java
Normal file
29
src/test/java/net/berack/upo/valpre/rand/TestRandom.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package net.berack.upo.valpre.rand;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class TestRandom {
|
||||
@Test
|
||||
public void testRng() {
|
||||
var numbers = new int[5000];
|
||||
var rng = new Rng(4656);
|
||||
|
||||
for (var i = 0; i < 1000000; i++) {
|
||||
var sample = rng.random();
|
||||
var index = (int) (sample * numbers.length);
|
||||
numbers[index] += 1;
|
||||
}
|
||||
|
||||
var avg = (double) Arrays.stream(numbers).sum() / numbers.length;
|
||||
var variance = Arrays.stream(numbers).mapToDouble(num -> Math.pow(num - avg, 2)).sum() / numbers.length;
|
||||
var stdDev = Math.sqrt(variance);
|
||||
var expected = Math.sqrt((double) numbers.length / 12);
|
||||
expected *= 1.1; // adding a bit of margin
|
||||
|
||||
assertTrue("Standard Dev must be less than [" + expected + "] -> [" + stdDev + "]", stdDev < expected);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user