Advertisement
mrkarp

Untitled

Mar 28th, 2014
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.42 KB | None | 0 0
  1. 001/*
  2. 002 * Licensed to the Apache Software Foundation (ASF) under one or more
  3. 003 * contributor license agreements. See the NOTICE file distributed with
  4. 004 * this work for additional information regarding copyright ownership.
  5. 005 * The ASF licenses this file to You under the Apache License, Version 2.0
  6. 006 * (the "License"); you may not use this file except in compliance with
  7. 007 * the License. You may obtain a copy of the License at
  8. 008 *
  9. 009 * http://www.apache.org/licenses/LICENSE-2.0
  10. 010 *
  11. 011 * Unless required by applicable law or agreed to in writing, software
  12. 012 * distributed under the License is distributed on an "AS IS" BASIS,
  13. 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. 014 * See the License for the specific language governing permissions and
  15. 015 * limitations under the License.
  16. 016 */
  17. 017
  18. 018package org.apache.commons.math3.distribution;
  19. 019
  20. 020import org.apache.commons.math3.exception.NotStrictlyPositiveException;
  21. 021import org.apache.commons.math3.exception.NumberIsTooLargeException;
  22. 022import org.apache.commons.math3.exception.OutOfRangeException;
  23. 023import org.apache.commons.math3.exception.util.LocalizedFormats;
  24. 024import org.apache.commons.math3.special.Erf;
  25. 025import org.apache.commons.math3.util.FastMath;
  26. 026import org.apache.commons.math3.random.RandomGenerator;
  27. 027import org.apache.commons.math3.random.Well19937c;
  28. 028
  29. 029/**
  30. 030 * Implementation of the normal (gaussian) distribution.
  31. 031 *
  32. 032 * @see <a href="http://en.wikipedia.org/wiki/Normal_distribution">Normal distribution (Wikipedia)</a>
  33. 033 * @see <a href="http://mathworld.wolfram.com/NormalDistribution.html">Normal distribution (MathWorld)</a>
  34. 034 * @version $Id: NormalDistribution.java 1535290 2013-10-24 06:58:32Z luc $
  35. 035 */
  36. 036public class NormalDistribution extends AbstractRealDistribution {
  37. 037 /**
  38. 038 * Default inverse cumulative probability accuracy.
  39. 039 * @since 2.1
  40. 040 */
  41. 041 public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
  42. 042 /** Serializable version identifier. */
  43. 043 private static final long serialVersionUID = 8589540077390120676L;
  44. 044 /** &radic;(2) */
  45. 045 private static final double SQRT2 = FastMath.sqrt(2.0);
  46. 046 /** Mean of this distribution. */
  47. 047 private final double mean;
  48. 048 /** Standard deviation of this distribution. */
  49. 049 private final double standardDeviation;
  50. 050 /** The value of {@code log(sd) + 0.5*log(2*pi)} stored for faster computation. */
  51. 051 private final double logStandardDeviationPlusHalfLog2Pi;
  52. 052 /** Inverse cumulative probability accuracy. */
  53. 053 private final double solverAbsoluteAccuracy;
  54. 054
  55. 055 /**
  56. 056 * Create a normal distribution with mean equal to zero and standard
  57. 057 * deviation equal to one.
  58. 058 */
  59. 059 public NormalDistribution() {
  60. 060 this(0, 1);
  61. 061 }
  62. 062
  63. 063 /**
  64. 064 * Create a normal distribution using the given mean and standard deviation.
  65. 065 *
  66. 066 * @param mean Mean for this distribution.
  67. 067 * @param sd Standard deviation for this distribution.
  68. 068 * @throws NotStrictlyPositiveException if {@code sd <= 0}.
  69. 069 */
  70. 070 public NormalDistribution(double mean, double sd)
  71. 071 throws NotStrictlyPositiveException {
  72. 072 this(mean, sd, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
  73. 073 }
  74. 074
  75. 075 /**
  76. 076 * Create a normal distribution using the given mean, standard deviation and
  77. 077 * inverse cumulative distribution accuracy.
  78. 078 *
  79. 079 * @param mean Mean for this distribution.
  80. 080 * @param sd Standard deviation for this distribution.
  81. 081 * @param inverseCumAccuracy Inverse cumulative probability accuracy.
  82. 082 * @throws NotStrictlyPositiveException if {@code sd <= 0}.
  83. 083 * @since 2.1
  84. 084 */
  85. 085 public NormalDistribution(double mean, double sd, double inverseCumAccuracy)
  86. 086 throws NotStrictlyPositiveException {
  87. 087 this(new Well19937c(), mean, sd, inverseCumAccuracy);
  88. 088 }
  89. 089
  90. 090 /**
  91. 091 * Creates a normal distribution.
  92. 092 *
  93. 093 * @param rng Random number generator.
  94. 094 * @param mean Mean for this distribution.
  95. 095 * @param sd Standard deviation for this distribution.
  96. 096 * @throws NotStrictlyPositiveException if {@code sd <= 0}.
  97. 097 * @since 3.3
  98. 098 */
  99. 099 public NormalDistribution(RandomGenerator rng, double mean, double sd)
  100. 100 throws NotStrictlyPositiveException {
  101. 101 this(rng, mean, sd, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
  102. 102 }
  103. 103
  104. 104 /**
  105. 105 * Creates a normal distribution.
  106. 106 *
  107. 107 * @param rng Random number generator.
  108. 108 * @param mean Mean for this distribution.
  109. 109 * @param sd Standard deviation for this distribution.
  110. 110 * @param inverseCumAccuracy Inverse cumulative probability accuracy.
  111. 111 * @throws NotStrictlyPositiveException if {@code sd <= 0}.
  112. 112 * @since 3.1
  113. 113 */
  114. 114 public NormalDistribution(RandomGenerator rng,
  115. 115 double mean,
  116. 116 double sd,
  117. 117 double inverseCumAccuracy)
  118. 118 throws NotStrictlyPositiveException {
  119. 119 super(rng);
  120. 120
  121. 121 if (sd <= 0) {
  122. 122 throw new NotStrictlyPositiveException(LocalizedFormats.STANDARD_DEVIATION, sd);
  123. 123 }
  124. 124
  125. 125 this.mean = mean;
  126. 126 standardDeviation = sd;
  127. 127 logStandardDeviationPlusHalfLog2Pi = FastMath.log(sd) + 0.5 * FastMath.log(2 * FastMath.PI);
  128. 128 solverAbsoluteAccuracy = inverseCumAccuracy;
  129. 129 }
  130. 130
  131. 131 /**
  132. 132 * Access the mean.
  133. 133 *
  134. 134 * @return the mean for this distribution.
  135. 135 */
  136. 136 public double getMean() {
  137. 137 return mean;
  138. 138 }
  139. 139
  140. 140 /**
  141. 141 * Access the standard deviation.
  142. 142 *
  143. 143 * @return the standard deviation for this distribution.
  144. 144 */
  145. 145 public double getStandardDeviation() {
  146. 146 return standardDeviation;
  147. 147 }
  148. 148
  149. 149 /** {@inheritDoc} */
  150. 150 public double density(double x) {
  151. 151 return FastMath.exp(logDensity(x));
  152. 152 }
  153. 153
  154. 154 /** {@inheritDoc} */
  155. 155 @Override
  156. 156 public double logDensity(double x) {
  157. 157 final double x0 = x - mean;
  158. 158 final double x1 = x0 / standardDeviation;
  159. 159 return -0.5 * x1 * x1 - logStandardDeviationPlusHalfLog2Pi;
  160. 160 }
  161. 161
  162. 162 /**
  163. 163 * {@inheritDoc}
  164. 164 *
  165. 165 * If {@code x} is more than 40 standard deviations from the mean, 0 or 1
  166. 166 * is returned, as in these cases the actual value is within
  167. 167 * {@code Double.MIN_VALUE} of 0 or 1.
  168. 168 */
  169. 169 public double cumulativeProbability(double x) {
  170. 170 final double dev = x - mean;
  171. 171 if (FastMath.abs(dev) > 40 * standardDeviation) {
  172. 172 return dev < 0 ? 0.0d : 1.0d;
  173. 173 }
  174. 174 return 0.5 * (1 + Erf.erf(dev / (standardDeviation * SQRT2)));
  175. 175 }
  176. 176
  177. 177 /** {@inheritDoc}
  178. 178 * @since 3.2
  179. 179 */
  180. 180 @Override
  181. 181 public double inverseCumulativeProbability(final double p) throws OutOfRangeException {
  182. 182 if (p < 0.0 || p > 1.0) {
  183. 183 throw new OutOfRangeException(p, 0, 1);
  184. 184 }
  185. 185 return mean + standardDeviation * SQRT2 * Erf.erfInv(2 * p - 1);
  186. 186 }
  187. 187
  188. 188 /**
  189. 189 * {@inheritDoc}
  190. 190 *
  191. 191 * @deprecated See {@link RealDistribution#cumulativeProbability(double,double)}
  192. 192 */
  193. 193 @Override@Deprecated
  194. 194 public double cumulativeProbability(double x0, double x1)
  195. 195 throws NumberIsTooLargeException {
  196. 196 return probability(x0, x1);
  197. 197 }
  198. 198
  199. 199 /** {@inheritDoc} */
  200. 200 @Override
  201. 201 public double probability(double x0,
  202. 202 double x1)
  203. 203 throws NumberIsTooLargeException {
  204. 204 if (x0 > x1) {
  205. 205 throw new NumberIsTooLargeException(LocalizedFormats.LOWER_ENDPOINT_ABOVE_UPPER_ENDPOINT,
  206. 206 x0, x1, true);
  207. 207 }
  208. 208 final double denom = standardDeviation * SQRT2;
  209. 209 final double v0 = (x0 - mean) / denom;
  210. 210 final double v1 = (x1 - mean) / denom;
  211. 211 return 0.5 * Erf.erf(v0, v1);
  212. 212 }
  213. 213
  214. 214 /** {@inheritDoc} */
  215. 215 @Override
  216. 216 protected double getSolverAbsoluteAccuracy() {
  217. 217 return solverAbsoluteAccuracy;
  218. 218 }
  219. 219
  220. 220 /**
  221. 221 * {@inheritDoc}
  222. 222 *
  223. 223 * For mean parameter {@code mu}, the mean is {@code mu}.
  224. 224 */
  225. 225 public double getNumericalMean() {
  226. 226 return getMean();
  227. 227 }
  228. 228
  229. 229 /**
  230. 230 * {@inheritDoc}
  231. 231 *
  232. 232 * For standard deviation parameter {@code s}, the variance is {@code s^2}.
  233. 233 */
  234. 234 public double getNumericalVariance() {
  235. 235 final double s = getStandardDeviation();
  236. 236 return s * s;
  237. 237 }
  238. 238
  239. 239 /**
  240. 240 * {@inheritDoc}
  241. 241 *
  242. 242 * The lower bound of the support is always negative infinity
  243. 243 * no matter the parameters.
  244. 244 *
  245. 245 * @return lower bound of the support (always
  246. 246 * {@code Double.NEGATIVE_INFINITY})
  247. 247 */
  248. 248 public double getSupportLowerBound() {
  249. 249 return Double.NEGATIVE_INFINITY;
  250. 250 }
  251. 251
  252. 252 /**
  253. 253 * {@inheritDoc}
  254. 254 *
  255. 255 * The upper bound of the support is always positive infinity
  256. 256 * no matter the parameters.
  257. 257 *
  258. 258 * @return upper bound of the support (always
  259. 259 * {@code Double.POSITIVE_INFINITY})
  260. 260 */
  261. 261 public double getSupportUpperBound() {
  262. 262 return Double.POSITIVE_INFINITY;
  263. 263 }
  264. 264
  265. 265 /** {@inheritDoc} */
  266. 266 public boolean isSupportLowerBoundInclusive() {
  267. 267 return false;
  268. 268 }
  269. 269
  270. 270 /** {@inheritDoc} */
  271. 271 public boolean isSupportUpperBoundInclusive() {
  272. 272 return false;
  273. 273 }
  274. 274
  275. 275 /**
  276. 276 * {@inheritDoc}
  277. 277 *
  278. 278 * The support of this distribution is connected.
  279. 279 *
  280. 280 * @return {@code true}
  281. 281 */
  282. 282 public boolean isSupportConnected() {
  283. 283 return true;
  284. 284 }
  285. 285
  286. 286 /** {@inheritDoc} */
  287. 287 @Override
  288. 288 public double sample() {
  289. 289 return standardDeviation * random.nextGaussian() + mean;
  290. 290 }
  291. 291}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement