source: src/main/java/agents/anac/y2019/harddealer/math3/distribution/NormalDistribution.java

Last change on this file was 204, checked in by Katsuhide Fujita, 5 years ago

Fixed errors of ANAC2019 agents

  • Property svn:executable set to *
File size: 10.5 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package agents.anac.y2019.harddealer.math3.distribution;
19
20import agents.anac.y2019.harddealer.math3.exception.NotStrictlyPositiveException;
21import agents.anac.y2019.harddealer.math3.exception.NumberIsTooLargeException;
22import agents.anac.y2019.harddealer.math3.exception.OutOfRangeException;
23import agents.anac.y2019.harddealer.math3.exception.util.LocalizedFormats;
24import agents.anac.y2019.harddealer.math3.random.RandomGenerator;
25import agents.anac.y2019.harddealer.math3.random.Well19937c;
26import agents.anac.y2019.harddealer.math3.special.Erf;
27import agents.anac.y2019.harddealer.math3.util.FastMath;
28
29/**
30 * Implementation of the normal (gaussian) distribution.
31 *
32 * @see <a href="http://en.wikipedia.org/wiki/Normal_distribution">Normal distribution (Wikipedia)</a>
33 * @see <a href="http://mathworld.wolfram.com/NormalDistribution.html">Normal distribution (MathWorld)</a>
34 */
35public class NormalDistribution extends AbstractRealDistribution {
36 /**
37 * Default inverse cumulative probability accuracy.
38 * @since 2.1
39 */
40 public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
41 /** Serializable version identifier. */
42 private static final long serialVersionUID = 8589540077390120676L;
43 /** &radic;(2) */
44 private static final double SQRT2 = FastMath.sqrt(2.0);
45 /** Mean of this distribution. */
46 private final double mean;
47 /** Standard deviation of this distribution. */
48 private final double standardDeviation;
49 /** The value of {@code log(sd) + 0.5*log(2*pi)} stored for faster computation. */
50 private final double logStandardDeviationPlusHalfLog2Pi;
51 /** Inverse cumulative probability accuracy. */
52 private final double solverAbsoluteAccuracy;
53
54 /**
55 * Create a normal distribution with mean equal to zero and standard
56 * deviation equal to one.
57 * <p>
58 * <b>Note:</b> this constructor will implicitly create an instance of
59 * {@link Well19937c} as random generator to be used for sampling only (see
60 * {@link #sample()} and {@link #sample(int)}). In case no sampling is
61 * needed for the created distribution, it is advised to pass {@code null}
62 * as random generator via the appropriate constructors to avoid the
63 * additional initialisation overhead.
64 */
65 public NormalDistribution() {
66 this(0, 1);
67 }
68
69 /**
70 * Create a normal distribution using the given mean and standard deviation.
71 * <p>
72 * <b>Note:</b> this constructor will implicitly create an instance of
73 * {@link Well19937c} as random generator to be used for sampling only (see
74 * {@link #sample()} and {@link #sample(int)}). In case no sampling is
75 * needed for the created distribution, it is advised to pass {@code null}
76 * as random generator via the appropriate constructors to avoid the
77 * additional initialisation overhead.
78 *
79 * @param mean Mean for this distribution.
80 * @param sd Standard deviation for this distribution.
81 * @throws NotStrictlyPositiveException if {@code sd <= 0}.
82 */
83 public NormalDistribution(double mean, double sd)
84 throws NotStrictlyPositiveException {
85 this(mean, sd, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
86 }
87
88 /**
89 * Create a normal distribution using the given mean, standard deviation and
90 * inverse cumulative distribution accuracy.
91 * <p>
92 * <b>Note:</b> this constructor will implicitly create an instance of
93 * {@link Well19937c} as random generator to be used for sampling only (see
94 * {@link #sample()} and {@link #sample(int)}). In case no sampling is
95 * needed for the created distribution, it is advised to pass {@code null}
96 * as random generator via the appropriate constructors to avoid the
97 * additional initialisation overhead.
98 *
99 * @param mean Mean for this distribution.
100 * @param sd Standard deviation for this distribution.
101 * @param inverseCumAccuracy Inverse cumulative probability accuracy.
102 * @throws NotStrictlyPositiveException if {@code sd <= 0}.
103 * @since 2.1
104 */
105 public NormalDistribution(double mean, double sd, double inverseCumAccuracy)
106 throws NotStrictlyPositiveException {
107 this(new Well19937c(), mean, sd, inverseCumAccuracy);
108 }
109
110 /**
111 * Creates a normal distribution.
112 *
113 * @param rng Random number generator.
114 * @param mean Mean for this distribution.
115 * @param sd Standard deviation for this distribution.
116 * @throws NotStrictlyPositiveException if {@code sd <= 0}.
117 * @since 3.3
118 */
119 public NormalDistribution(RandomGenerator rng, double mean, double sd)
120 throws NotStrictlyPositiveException {
121 this(rng, mean, sd, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
122 }
123
124 /**
125 * Creates a normal distribution.
126 *
127 * @param rng Random number generator.
128 * @param mean Mean for this distribution.
129 * @param sd Standard deviation for this distribution.
130 * @param inverseCumAccuracy Inverse cumulative probability accuracy.
131 * @throws NotStrictlyPositiveException if {@code sd <= 0}.
132 * @since 3.1
133 */
134 public NormalDistribution(RandomGenerator rng,
135 double mean,
136 double sd,
137 double inverseCumAccuracy)
138 throws NotStrictlyPositiveException {
139 super(rng);
140
141 if (sd <= 0) {
142 throw new NotStrictlyPositiveException(LocalizedFormats.STANDARD_DEVIATION, sd);
143 }
144
145 this.mean = mean;
146 standardDeviation = sd;
147 logStandardDeviationPlusHalfLog2Pi = FastMath.log(sd) + 0.5 * FastMath.log(2 * FastMath.PI);
148 solverAbsoluteAccuracy = inverseCumAccuracy;
149 }
150
151 /**
152 * Access the mean.
153 *
154 * @return the mean for this distribution.
155 */
156 public double getMean() {
157 return mean;
158 }
159
160 /**
161 * Access the standard deviation.
162 *
163 * @return the standard deviation for this distribution.
164 */
165 public double getStandardDeviation() {
166 return standardDeviation;
167 }
168
169 /** {@inheritDoc} */
170 public double density(double x) {
171 return FastMath.exp(logDensity(x));
172 }
173
174 /** {@inheritDoc} */
175 @Override
176 public double logDensity(double x) {
177 final double x0 = x - mean;
178 final double x1 = x0 / standardDeviation;
179 return -0.5 * x1 * x1 - logStandardDeviationPlusHalfLog2Pi;
180 }
181
182 /**
183 * {@inheritDoc}
184 *
185 * If {@code x} is more than 40 standard deviations from the mean, 0 or 1
186 * is returned, as in these cases the actual value is within
187 * {@code Double.MIN_VALUE} of 0 or 1.
188 */
189 public double cumulativeProbability(double x) {
190 final double dev = x - mean;
191 if (FastMath.abs(dev) > 40 * standardDeviation) {
192 return dev < 0 ? 0.0d : 1.0d;
193 }
194 return 0.5 * Erf.erfc(-dev / (standardDeviation * SQRT2));
195 }
196
197 /** {@inheritDoc}
198 * @since 3.2
199 */
200 @Override
201 public double inverseCumulativeProbability(final double p) throws OutOfRangeException {
202 if (p < 0.0 || p > 1.0) {
203 throw new OutOfRangeException(p, 0, 1);
204 }
205 return mean + standardDeviation * SQRT2 * Erf.erfInv(2 * p - 1);
206 }
207
208 /**
209 * {@inheritDoc}
210 *
211 * @deprecated See {@link RealDistribution#cumulativeProbability(double,double)}
212 */
213 @Override@Deprecated
214 public double cumulativeProbability(double x0, double x1)
215 throws NumberIsTooLargeException {
216 return probability(x0, x1);
217 }
218
219 /** {@inheritDoc} */
220 @Override
221 public double probability(double x0,
222 double x1)
223 throws NumberIsTooLargeException {
224 if (x0 > x1) {
225 throw new NumberIsTooLargeException(LocalizedFormats.LOWER_ENDPOINT_ABOVE_UPPER_ENDPOINT,
226 x0, x1, true);
227 }
228 final double denom = standardDeviation * SQRT2;
229 final double v0 = (x0 - mean) / denom;
230 final double v1 = (x1 - mean) / denom;
231 return 0.5 * Erf.erf(v0, v1);
232 }
233
234 /** {@inheritDoc} */
235 @Override
236 protected double getSolverAbsoluteAccuracy() {
237 return solverAbsoluteAccuracy;
238 }
239
240 /**
241 * {@inheritDoc}
242 *
243 * For mean parameter {@code mu}, the mean is {@code mu}.
244 */
245 public double getNumericalMean() {
246 return getMean();
247 }
248
249 /**
250 * {@inheritDoc}
251 *
252 * For standard deviation parameter {@code s}, the variance is {@code s^2}.
253 */
254 public double getNumericalVariance() {
255 final double s = getStandardDeviation();
256 return s * s;
257 }
258
259 /**
260 * {@inheritDoc}
261 *
262 * The lower bound of the support is always negative infinity
263 * no matter the parameters.
264 *
265 * @return lower bound of the support (always
266 * {@code Double.NEGATIVE_INFINITY})
267 */
268 public double getSupportLowerBound() {
269 return Double.NEGATIVE_INFINITY;
270 }
271
272 /**
273 * {@inheritDoc}
274 *
275 * The upper bound of the support is always positive infinity
276 * no matter the parameters.
277 *
278 * @return upper bound of the support (always
279 * {@code Double.POSITIVE_INFINITY})
280 */
281 public double getSupportUpperBound() {
282 return Double.POSITIVE_INFINITY;
283 }
284
285 /** {@inheritDoc} */
286 public boolean isSupportLowerBoundInclusive() {
287 return false;
288 }
289
290 /** {@inheritDoc} */
291 public boolean isSupportUpperBoundInclusive() {
292 return false;
293 }
294
295 /**
296 * {@inheritDoc}
297 *
298 * The support of this distribution is connected.
299 *
300 * @return {@code true}
301 */
302 public boolean isSupportConnected() {
303 return true;
304 }
305
306 /** {@inheritDoc} */
307 @Override
308 public double sample() {
309 return standardDeviation * random.nextGaussian() + mean;
310 }
311}
Note: See TracBrowser for help on using the repository browser.