/* Copyright (C) 2001 Kyle Siegrist, Dawn Duehring This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package distributions; /**This class models the distribution of the number of distinct sample values when a sample of a specified size is chosen with replacement from a finite population of a specified size*/ public class BirthdayDistribution extends Distribution{ private int popSize, sampleSize; private double[][] prob; /**This general constructor creates a new birthday distribution with a specified population size and sample size*/ public BirthdayDistribution(int n, int k){ setParameters(n, k); } /**This default constructor creates a new birthday distribution with population size 365 and sample size 20*/ public BirthdayDistribution(){ this(365, 20); } /**This method sets the parameters: the population size and the sample size. Also, the probabilities are computed and stored in an array*/ public void setParameters(int n, int k){ //Correct for invalid parameters if (n < 1) n = 1; if (k < 1) k = 1; int upperIndex; popSize = n; sampleSize = k; super.setParameters(1, Math.min(popSize, sampleSize), 1, DISCRETE); prob = new double[sampleSize + 1][popSize + 1]; prob[0][0] = 1; prob[1][1] = 1; for (int j = 1; j < sampleSize; j++){ if (j < popSize) upperIndex = j + 1; else upperIndex = (int)popSize; for (int m = 1; m <= upperIndex; m++){ prob[j+1][m] = prob[j][m] * ((double)m / popSize) + prob[j][m - 1] * ((double)(popSize - m + 1) / popSize); } } } /**This method computes the getDensity function*/ public double getDensity(double x){ int m = (int)(Math.rint(x)); return prob[sampleSize][m]; } /**This method computes the mean*/ public double getMean(){ return popSize * (1 - Math.pow(1 - 1.0 / popSize, sampleSize)); } /**This method computes the variance*/ public double getVariance(){ return popSize * (popSize - 1) * Math.pow(1 - 2.0 / popSize, sampleSize) + popSize * Math.pow(1 - 1.0 / popSize, sampleSize) - popSize * popSize * Math.pow(1 - 1.0 / popSize, 2 * sampleSize); } /**This method returns the population size*/ public double getPopSize(){ return popSize; } /**This method sets the population size*/ public void setPopSize(int n){ setParameters(n, sampleSize); } /**This method returns the sample size*/ public double getSampleSize(){ return sampleSize; } /**This method sets the sample size*/ public void setSampleSize(int k){ setParameters(popSize, k); } /**This method simulates a value from the distribution, as the number of distinct sample values*/ public double simulate(){ int[] count = new int[popSize]; double distinct = 0; for (int i = 1; i <= sampleSize; i++){ int j = (int)(popSize * Math.random()); if (count[j] == 0) distinct++; count[j] = count[j]++; } return distinct; } }