View Javadoc

1   /*
2    * @(#)DistGamma.java Apr 3, 2003
3    * 
4    * Copyright (c) 2003 Delft University of Technology Jaffalaan 5, 2628 BX Delft,
5    * the Netherlands All rights reserved.
6    * 
7    * This software is proprietary information of Delft University of Technology
8    * The code is published under the General Public License
9    */
10  package nl.tudelft.simulation.jstats.distributions;
11  
12  import cern.jet.stat.Gamma;
13  import nl.tudelft.simulation.jstats.streams.StreamInterface;
14  
15  /***
16   * The Gamma distribution. For more information on this distribution see <a
17   * href="http://mathworld.wolfram.com/GammaDistribution.html">
18   * http://mathworld.wolfram.com/GammaDistribution.html </a>
19   * <p>
20   * (c) copyright 2002-2004 <a href="http://www.simulation.tudelft.nl">Delft
21   * University of Technology </a>, the Netherlands. <br>
22   * See for project information <a href="http://www.simulation.tudelft.nl">
23   * www.simulation.tudelft.nl </a> <br>
24   * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
25   * License (GPL) </a>, no warranty <br>
26   * 
27   * @author <a href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">
28   *         Alexander Verbraeck </a> <br>
29   *         <a href="http://www.tbm.tudelft.nl/webstaf/peterja/index.htm"> Peter
30   *         Jacobs </a>
31   * @version 1.11 2004-03-22
32   * @since 1.2
33   */
34  public class DistGamma extends DistContinuous
35  {
36  	/*** alpha is the alpha parameter of the distribution */
37  	private double alpha;
38  
39  	/*** beta is the beta parameter of the distribution */
40  	private double beta;
41  
42  	/***
43  	 * constructs a new gamma distribution. The gamma distribution represents
44  	 * the time to complete some task, e.g. customer service or machine repair
45  	 * 
46  	 * @param stream the numberstream
47  	 * @param alpha is the shape parameter alpha>0
48  	 * @param beta is the scale parameter beta>0
49  	 */
50  	public DistGamma(final StreamInterface stream, final double alpha,
51  			final double beta)
52  	{
53  		super(stream);
54  		if ((alpha > 0.0) && (beta > 0.0))
55  		{
56  			this.alpha = alpha;
57  			this.beta = beta;
58  		} else
59  		{
60  			throw new IllegalArgumentException(
61  					"Error Gamma - alpha <= 0.0 or beta <= 0.0");
62  		}
63  	}
64  
65  	/***
66  	 * @see DistContinuous#draw()
67  	 */
68  	public double draw()
69  	{
70  		// according to Law and Kelton, Simulation Modeling and Analysis, 1991
71  		// pages 488-489
72  		if (this.alpha < 1.0)
73  		{
74  			double b = (Math.E + this.alpha) / Math.E;
75  			long counter = 0;
76  			while (counter < 1000)
77  			{
78  				// step 1.
79  				double p = b * this.stream.nextDouble();
80  				if (p <= 1.0d)
81  				{
82  					// step 2.
83  					double y = Math.pow(p, 1.0d / this.alpha);
84  					double u2 = this.stream.nextDouble();
85  					if (u2 <= Math.exp(-y))
86  					{
87  						return this.beta * y;
88  					}
89  				} else
90  				{
91  					// step 3.
92  					double y = -Math.log((b - p) / this.alpha);
93  					double u2 = this.stream.nextDouble();
94  					if (u2 <= Math.pow(y, this.alpha - 1.0d))
95  					{
96  						return this.beta * y;
97  					}
98  				}
99  			}
100 			new IllegalArgumentException("1000 tries for alpha<1.0");
101 			return 1.0d;
102 		} else if (this.alpha > 1.0)
103 		{
104 			// according to Law and Kelton, Simulation Modeling and
105 			// Analysis, 1991, pages 488-489
106 			double a = 1.0d / Math.sqrt(2.0d * this.alpha - 1.0d);
107 			double b = this.alpha - Math.log(4.0d);
108 			double q = this.alpha + (1.0d / a);
109 			double theta = 4.5d;
110 			double d = 1.0d + Math.log(theta);
111 			long counter = 0;
112 			while (counter < 1000)
113 			{
114 				// step 1.
115 				double u1 = this.stream.nextDouble();
116 				double u2 = this.stream.nextDouble();
117 				// step 2.
118 				double v = a * Math.log(u1 / (1.0d - u1));
119 				double y = this.alpha * Math.exp(v);
120 				double z = u1 * u1 * u2;
121 				double w = b + q * v - y;
122 				// step 3.
123 				if ((w + d - theta * z) >= 0.0d)
124 				{
125 					return this.beta * y;
126 				}
127 				// step 4.
128 				if (w > Math.log(z))
129 				{
130 					return this.beta * y;
131 				}
132 			}
133 			new IllegalArgumentException("1000 tries for alpha>1.0");
134 			return 1.0d;
135 		} else
136 		// alpha == 1.0
137 		{
138 			// Gamma(1.0, beta) ~ exponential with mean = beta
139 			return -this.beta * Math.log(this.stream.nextDouble());
140 		}
141 	}
142 
143 	/***
144 	 * @see nl.tudelft.simulation.jstats.distributions.DistContinuous
145 	 *      #probDensity(double)
146 	 */
147 	public double probDensity(final double observation)
148 	{
149 		if (observation <= 0)
150 		{
151 			return 0.0;
152 		}
153 		return (Math.pow(this.beta, -this.alpha)
154 				* Math.pow(observation, this.alpha - 1) * Math.exp(-1
155 				* observation / this.beta))
156 				/ Gamma.gamma(this.alpha);
157 	}
158 
159 	/***
160 	 * @see java.lang.Object#toString()
161 	 */
162 	public String toString()
163 	{
164 		return "Gamma(" + this.alpha + "," + this.beta + ")";
165 	}
166 }