001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.math.distribution; 018 019 import org.apache.commons.math.MathException; 020 import org.apache.commons.math.special.Gamma; 021 import org.apache.commons.math.special.Beta; 022 023 /** 024 * Implements the Beta distribution. 025 * <p> 026 * References: 027 * <ul> 028 * <li><a href="http://en.wikipedia.org/wiki/Beta_distribution"> 029 * Beta distribution</a></li> 030 * </ul> 031 * </p> 032 * @version $Revision: 762087 $ $Date: 2009-04-05 10:20:18 -0400 (Sun, 05 Apr 2009) $ 033 * @since 2.0 034 */ 035 public class BetaDistributionImpl 036 extends AbstractContinuousDistribution implements BetaDistribution { 037 038 /** Serializable version identifier. */ 039 private static final long serialVersionUID = -1221965979403477668L; 040 041 /** First shape parameter. */ 042 private double alpha; 043 044 /** Second shape parameter. */ 045 private double beta; 046 047 /** Normalizing factor used in density computations. 048 * updated whenever alpha or beta are changed. 049 */ 050 private double z; 051 052 /** 053 * Build a new instance. 054 * @param alpha first shape parameter (must be positive) 055 * @param beta second shape parameter (must be positive) 056 */ 057 public BetaDistributionImpl(double alpha, double beta) { 058 this.alpha = alpha; 059 this.beta = beta; 060 z = Double.NaN; 061 } 062 063 /** {@inheritDoc} */ 064 public void setAlpha(double alpha) { 065 this.alpha = alpha; 066 z = Double.NaN; 067 } 068 069 /** {@inheritDoc} */ 070 public double getAlpha() { 071 return alpha; 072 } 073 074 /** {@inheritDoc} */ 075 public void setBeta(double beta) { 076 this.beta = beta; 077 z = Double.NaN; 078 } 079 080 /** {@inheritDoc} */ 081 public double getBeta() { 082 return beta; 083 } 084 085 /** 086 * Recompute the normalization factor. 087 */ 088 private void recomputeZ() { 089 if (Double.isNaN(z)) { 090 z = Gamma.logGamma(alpha) + Gamma.logGamma(beta) - Gamma.logGamma(alpha + beta); 091 } 092 } 093 094 /** {@inheritDoc} */ 095 public double density(Double x) throws MathException { 096 recomputeZ(); 097 if (x < 0 || x > 1) { 098 return 0; 099 } else if (x == 0) { 100 if (alpha < 1) { 101 throw new MathException("Cannot compute beta density at 0 when alpha = {0,number}", alpha); 102 } 103 return 0; 104 } else if (x == 1) { 105 if (beta < 1) { 106 throw new MathException("Cannot compute beta density at 1 when beta = %.3g", beta); 107 } 108 return 0; 109 } else { 110 double logX = Math.log(x); 111 double log1mX = Math.log1p(-x); 112 return Math.exp((alpha - 1) * logX + (beta - 1) * log1mX - z); 113 } 114 } 115 116 /** {@inheritDoc} */ 117 @Override 118 public double inverseCumulativeProbability(double p) throws MathException { 119 if (p == 0) { 120 return 0; 121 } else if (p == 1) { 122 return 1; 123 } else { 124 return super.inverseCumulativeProbability(p); 125 } 126 } 127 128 /** {@inheritDoc} */ 129 @Override 130 protected double getInitialDomain(double p) { 131 return p; 132 } 133 134 /** {@inheritDoc} */ 135 @Override 136 protected double getDomainLowerBound(double p) { 137 return 0; 138 } 139 140 /** {@inheritDoc} */ 141 @Override 142 protected double getDomainUpperBound(double p) { 143 return 1; 144 } 145 146 /** {@inheritDoc} */ 147 public double cumulativeProbability(double x) throws MathException { 148 if (x <= 0) { 149 return 0; 150 } else if (x >= 1) { 151 return 1; 152 } else { 153 return Beta.regularizedBeta(x, alpha, beta); 154 } 155 } 156 157 /** {@inheritDoc} */ 158 @Override 159 public double cumulativeProbability(double x0, double x1) throws MathException { 160 return cumulativeProbability(x1) - cumulativeProbability(x0); 161 } 162 }