/* * BetaKDEDistribution.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.math.distributions; import dr.math.GammaFunction; import dr.stats.DiscreteStatistics; //import java.io.BufferedReader; //import java.io.FileReader; //import java.io.FileNotFoundException; //import java.io.IOException; //import java.util.StringTokenizer; /** * @author Marc Suchard */ public class BetaKDEDistribution extends KernelDensityEstimatorDistribution { public BetaKDEDistribution(Double[] sample, Double lowerBound, Double upperBound, Double bandWidth) { super(sample, lowerBound, upperBound, bandWidth); } protected void processBounds(Double lowerBound, Double upperBound) { if (lowerBound == null || upperBound == null || upperBound - lowerBound <= 0) { throw new RuntimeException("BetaKDEDistribution must be bounded"); } if (lowerBound > DiscreteStatistics.min(sample) || upperBound < DiscreteStatistics.max(sample)) throw new RuntimeException("Sample range outside bounds: "+DiscreteStatistics.min(sample)+" -> "+DiscreteStatistics.max(sample)); this.lowerBound = lowerBound; this.upperBound = upperBound; // Make a copy because we are translating values into [0,1) double[] oldSample = sample; sample = new double[sample.length]; range = upperBound - lowerBound; for(int i=0; i<N; i++) sample[i] = (oldSample[i] - this.lowerBound) / range; } protected void setBandWidth(Double bandWidth) { if (bandWidth == null) { // Default bandwidth double sigma = DiscreteStatistics.stdev(sample); this.bandWidth = sigma * Math.pow(N,-0.4); // Renault & Scaillet (2004); Chen (1999) } else this.bandWidth = bandWidth; } /* Beta kernel density estimator based on: * Chen SX (1999) Beta kernel estimators for density functions. Comp. Statist. Data. Anal. 31, 131-145. * */ protected double evaluateKernel(double x) { double xPrime = (x - lowerBound) / range; double alphaMinus1 = xPrime/bandWidth - 1.0; double betaMinus1 = (1.0 - xPrime)/bandWidth - 1.0; if (xPrime < 2*bandWidth) // Removing these two cases reduces the kernel to C1 alphaMinus1 = getRho(xPrime,bandWidth) - 1.0; else if (xPrime > 1 - 2*bandWidth) betaMinus1 = getRho(1.0-xPrime,bandWidth) - 1.0; double logK = GammaFunction.lnGamma(alphaMinus1+betaMinus1+2.0) - GammaFunction.lnGamma(alphaMinus1+1.0) - GammaFunction.lnGamma(betaMinus1+1.0); double pdf = 0; for(int i=0; i<N; i++) pdf += Math.pow(sample[i],alphaMinus1) * Math.pow(1.0-sample[i],betaMinus1); return pdf * Math.exp(logK) / (double)N / range; } private double getRho(double x, double bandWidth) { return 2*bandWidth*bandWidth + 2.5 - Math.sqrt(4*bandWidth*bandWidth*bandWidth*bandWidth + 6*bandWidth*bandWidth + 2.25 - x*x - x/bandWidth); } public double sampleMean() { return DiscreteStatistics.mean(sample); } private double range; // public static void main(String[] args) { // // String fileName = "out.txt"; // double[] values = null; // try { // // BufferedReader reader = new BufferedReader(new FileReader(fileName)); // // String line1 = reader.readLine(); // StringTokenizer st = new StringTokenizer(line1," "); // values = new double[st.countTokens()]; // for(int i=0; i<values.length; i++) // values[i] = Double.valueOf(st.nextToken()); // // reader.close(); // // } catch (FileNotFoundException e) { // System.err.println("File not found: "+fileName); // System.exit(-1); // } catch (IOException e) { // System.err.println("IO exception reading: "+fileName); // System.exit(-1); // } // //// System.err.println("v: "+new Vector(values)); // BetaKDEDistribution kde; // kde = new BetaKDEDistribution(values,0.0, 10.0, 0.1); // System.err.println("r: "+kde.pdf(3.0)); // // kde = new BetaKDEDistribution(values,1.0, 9.0, 0.25); // System.err.println("r: "+kde.pdf(7.0)); // // System.err.println("sm: "+kde.sampleMean()); // // } }