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 }