package test.beast.math.distributions;
import org.apache.commons.math.MathException;
import org.junit.Test;
import beast.core.parameter.RealParameter;
import beast.math.distributions.LogNormalDistributionModel;
import beast.util.Randomizer;
import beast.util.XMLParser;
import junit.framework.TestCase;
public class LogNormalDistributionModelTest extends TestCase {
@Test
public void testPDF() throws Exception {
System.out.println("Testing 10000 random pdf calls");
LogNormalDistributionModel logNormal = new LogNormalDistributionModel();
logNormal.init("1.0", "2.0");
for (int i = 0; i < 10000; i++) {
double M = Randomizer.nextDouble() * 10.0 - 5.0;
double S = Randomizer.nextDouble() * 10;
double x = -1;
while( x < 0 ) {
x = Math.log(Randomizer.nextDouble() * 10);
}
logNormal.MParameterInput.setValue(M + "", logNormal);
logNormal.SParameterInput.setValue(S + "", logNormal);
logNormal.initAndValidate();
double pdf = 1.0 / (x * S * Math.sqrt(2 * Math.PI)) * Math.exp(-Math.pow(Math.log(x) - M, 2) / (2 * S * S));
System.out.println("Testing logNormal[M=" + M + " S=" + S + "].pdf(" + x + ")");
double f = logNormal.density(x);
assertEquals(pdf, f, 1e-10);
}
}
@Test
public void testCalcLogP() throws Exception {
LogNormalDistributionModel logNormal = new LogNormalDistributionModel();
logNormal.hasMeanInRealSpaceInput.setValue("true", logNormal);
logNormal.offsetInput.setValue("1200", logNormal);
logNormal.MParameterInput.setValue("2000", logNormal);
logNormal.SParameterInput.setValue("0.6", logNormal);
logNormal.initAndValidate();
RealParameter p = new RealParameter(new Double[]{2952.6747000000014});
double f0 = logNormal.calcLogP(p);
assertEquals(-7.880210654973873, f0, 1e-10);
}
@Test
public void testCalcLogP2() throws Exception {
// does the same as testCalcLogP(), but with by constructing object through XML
String xml = "<input spec='beast.math.distributions.LogNormalDistributionModel' " +
"offset='1200' " +
"M='2000' " +
"S='0.6' " +
"meanInRealSpace='true'/>";
RealParameter p = new RealParameter(new Double[]{2952.6747000000014});
XMLParser parser = new XMLParser();
LogNormalDistributionModel logNormal = (LogNormalDistributionModel) parser.parseBareFragment(xml, true);
double f0 = logNormal.calcLogP(p);
assertEquals(-7.880210654973873, f0, 1e-10);
}
@Test
public void testCalcLogP3() throws Exception {
// does the same as testCalcLogP(), but with by constructing object through init
LogNormalDistributionModel logNormal = new LogNormalDistributionModel();
logNormal.init("2000", "0.6", true, "1200");
RealParameter p = new RealParameter(new Double[]{2952.6747000000014});
double f0 = logNormal.calcLogP(p);
assertEquals(-7.880210654973873, f0, 1e-10);
}
// remainder is adapted from Alexei's LogNormalDistributionTest from BEAST 1
LogNormalDistributionModel logNormal;
public void setUp() {
logNormal = new LogNormalDistributionModel();
logNormal.initByName("M", "1.0", "S", "2.0");
Randomizer.setSeed(123);
}
public void testPdf() {
System.out.println("Testing 10000 random pdf calls");
for (int i = 0; i < 10000; i++) {
double M = Randomizer.nextDouble() * 10.0 - 5.0;
double S = Randomizer.nextDouble() * 10;
double x = Math.log(Randomizer.nextDouble() * 10);
logNormal.MParameterInput.setValue(M + "", logNormal);
logNormal.SParameterInput.setValue(S + "", logNormal);
logNormal.initAndValidate();
double pdf = 1.0 / (x * S * Math.sqrt(2 * Math.PI)) * Math.exp(-Math.pow(Math.log(x) - M, 2) / (2 * S * S));
if (x <= 0) pdf = 0; // see logNormal.pdf(x)
//System.out.println("Testing logNormal[M=" + M + " S=" + S + "].pdf(" + x + ")");
assertEquals(pdf, logNormal.density(x), 1e-10);
}
}
public void testMean() {
for (int i = 0; i < 1000; i++) {
double M = Randomizer.nextDouble() * 10.0 - 5.0;
double S = Randomizer.nextDouble() * 10;
logNormal.MParameterInput.setValue(M + "", logNormal);
logNormal.SParameterInput.setValue(S + "", logNormal);
logNormal.initAndValidate();
double mean = Math.exp(M + S * S / 2);
//System.out.println("Testing logNormal[M=" + M + " S=" + S + "].mean()");
assertEquals(mean, logNormal.getMean(), 1e-10);
}
}
// public void testVariance() {
//
// for (int i = 0; i < 1000; i++) {
// double M = Randomizer.nextDouble() * 10.0 - 5.0;
// double S = Randomizer.nextDouble() * 10;
//
// logNormal.MParameterInput.setValue(M, logNormal);
// logNormal.SParameterInput.setValue(S, logNormal);
// logNormal.initAndValidate();
//
// double variance = (Math.exp(S * S) - 1) * Math.exp(2 * M + S * S);
//
// //System.out.println("Testing logNormal[M=" + M + " S=" + S + "].variance()");
//
// assertEquals(variance, logNormal.getVariance(), 1e-10);
// }
// }
public void testMedian() throws MathException {
System.out.println("Testing 10000 random quantile(0.5) calls");
for (int i = 0; i < 10000; i++) {
double M = Randomizer.nextDouble() * 10.0 - 5.0;
double S = Randomizer.nextDouble() * 10;
logNormal.MParameterInput.setValue(M + "", logNormal);
logNormal.SParameterInput.setValue(S + "", logNormal);
logNormal.initAndValidate();
double median = Math.exp(M);
//System.out.println("Testing logNormal[M=" + M + " S=" + S + "].median()");
assertEquals(median, logNormal.inverseCumulativeProbability(0.5), median / 1e6);
}
}
public void testCDFAndQuantile() throws MathException {
System.out.println("Testing 10000 random quantile/cdf pairs");
for (int i = 0; i < 10000; i++) {
double M = Randomizer.nextDouble() * 10.0 - 5.0;
double S = Randomizer.nextDouble() * 10;
logNormal.MParameterInput.setValue(M + "", logNormal);
logNormal.SParameterInput.setValue(S + "", logNormal);
logNormal.initAndValidate();
double p = Randomizer.nextDouble();
double quantile = logNormal.inverseCumulativeProbability(p);
double cdf = logNormal.cumulativeProbability(quantile);
assertEquals(p, cdf, 1e-7);
}
}
// public void testCDFAndQuantile2() {
//
// final LogNormalDistributionModel f = new LogNormalDistributionModel();
// logNormal.initByName("M", "1.0", "S", "1.0");
// for (double i = 0.01; i < 0.95; i += 0.01) {
// final double y = i;
//
// BisectionZeroFinder zeroFinder = new BisectionZeroFinder(new OneVariableFunction() {
// public double value(double x) {
// return f.cdf(x) - y;
// }
// }, 0.01, 100);
// zeroFinder.evaluate();
//
// assertEquals(f.quantile(i), zeroFinder.getResult(), 1e-6);
// }
// }
}