1 | #region License Information
|
---|
2 | /* HeuristicLab
|
---|
3 | * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
|
---|
4 | *
|
---|
5 | * This file is part of HeuristicLab.
|
---|
6 | *
|
---|
7 | * HeuristicLab is free software: you can redistribute it and/or modify
|
---|
8 | * it under the terms of the GNU General Public License as published by
|
---|
9 | * the Free Software Foundation, either version 3 of the License, or
|
---|
10 | * (at your option) any later version.
|
---|
11 | *
|
---|
12 | * HeuristicLab is distributed in the hope that it will be useful,
|
---|
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
15 | * GNU General Public License for more details.
|
---|
16 | *
|
---|
17 | * You should have received a copy of the GNU General Public License
|
---|
18 | * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
|
---|
19 | */
|
---|
20 | #endregion
|
---|
21 |
|
---|
22 | using System;
|
---|
23 | using HeuristicLab.Common;
|
---|
24 | using HeuristicLab.Core;
|
---|
25 | using HEAL.Attic;
|
---|
26 |
|
---|
27 | namespace HeuristicLab.Random {
|
---|
28 |
|
---|
29 | /// <summary>
|
---|
30 | /// Normally distributed random variable.
|
---|
31 | /// Uses Marsaglia's polar method
|
---|
32 | /// </summary>
|
---|
33 | [Item("NormalDistributedRandomPolar", "A pseudo random number generator which uses Marsaglia's polar method to create normally distributed random numbers.")]
|
---|
34 | [StorableType("B17E35DB-1DC6-434A-8F08-4AD4AB224C59")]
|
---|
35 | public sealed class NormalDistributedRandomPolar : Item, IRandom {
|
---|
36 | [Storable]
|
---|
37 | private double mu;
|
---|
38 | /// <summary>
|
---|
39 | /// Gets or sets the value for µ.
|
---|
40 | /// </summary>
|
---|
41 | public double Mu {
|
---|
42 | get { return mu; }
|
---|
43 | set { mu = value; }
|
---|
44 | }
|
---|
45 |
|
---|
46 | [Storable]
|
---|
47 | private double sigma;
|
---|
48 | /// <summary>
|
---|
49 | /// Gets or sets the value for sigma.
|
---|
50 | /// </summary>
|
---|
51 | public double Sigma {
|
---|
52 | get { return sigma; }
|
---|
53 | set { sigma = value; }
|
---|
54 | }
|
---|
55 |
|
---|
56 | [Storable]
|
---|
57 | private IRandom uniform;
|
---|
58 |
|
---|
59 |
|
---|
60 | [StorableConstructor]
|
---|
61 | private NormalDistributedRandomPolar(StorableConstructorFlag _) : base(_) { }
|
---|
62 |
|
---|
63 | private NormalDistributedRandomPolar(NormalDistributedRandomPolar original, Cloner cloner)
|
---|
64 | : base(original, cloner) {
|
---|
65 | uniform = cloner.Clone(original.uniform);
|
---|
66 | mu = original.mu;
|
---|
67 | sigma = original.sigma;
|
---|
68 | }
|
---|
69 |
|
---|
70 | /// <summary>
|
---|
71 | /// Initializes a new instance of <see cref="NormalDistributedRandomPolar"/> with µ = 0 and sigma = 1
|
---|
72 | /// and a new random number generator.
|
---|
73 | /// </summary>
|
---|
74 | public NormalDistributedRandomPolar() {
|
---|
75 | this.mu = 0.0;
|
---|
76 | this.sigma = 1.0;
|
---|
77 | this.uniform = new MersenneTwister();
|
---|
78 | }
|
---|
79 |
|
---|
80 | /// <summary>
|
---|
81 | /// Initializes a new instance of <see cref="NormalDistributedRandomPolar"/> with the given parameters.
|
---|
82 | /// <note type="caution"> The random number generator is not copied!</note>
|
---|
83 | /// </summary>
|
---|
84 | /// <param name="uniformRandom">The random number generator.</param>
|
---|
85 | /// <param name="mu">The value for µ.</param>
|
---|
86 | /// <param name="sigma">The value for sigma.</param>
|
---|
87 | public NormalDistributedRandomPolar(IRandom uniformRandom, double mu, double sigma) {
|
---|
88 | this.mu = mu;
|
---|
89 | this.sigma = sigma;
|
---|
90 | this.uniform = uniformRandom;
|
---|
91 | }
|
---|
92 |
|
---|
93 | #region IRandom Members
|
---|
94 |
|
---|
95 | /// <inheritdoc cref="IRandom.Reset()"/>
|
---|
96 | public void Reset() {
|
---|
97 | uniform.Reset();
|
---|
98 | }
|
---|
99 |
|
---|
100 | /// <inheritdoc cref="IRandom.Reset(int)"/>
|
---|
101 | public void Reset(int seed) {
|
---|
102 | uniform.Reset(seed);
|
---|
103 | }
|
---|
104 |
|
---|
105 | /// <summary>
|
---|
106 | /// This method is not implemented.
|
---|
107 | /// </summary>
|
---|
108 | public int Next() {
|
---|
109 | throw new NotImplementedException();
|
---|
110 | }
|
---|
111 |
|
---|
112 | /// <summary>
|
---|
113 | /// This method is not implemented.
|
---|
114 | /// </summary>
|
---|
115 | public int Next(int maxVal) {
|
---|
116 | throw new NotImplementedException();
|
---|
117 | }
|
---|
118 |
|
---|
119 | /// <summary>
|
---|
120 | /// This method is not implemented.
|
---|
121 | /// </summary>
|
---|
122 | public int Next(int minVal, int maxVal) {
|
---|
123 | throw new NotImplementedException();
|
---|
124 | }
|
---|
125 |
|
---|
126 | /// <summary>
|
---|
127 | /// Generates a new double random number.
|
---|
128 | /// </summary>
|
---|
129 | /// <returns>A double random number.</returns>
|
---|
130 | public double NextDouble() {
|
---|
131 | return NormalDistributedRandomPolar.NextDouble(uniform, mu, sigma);
|
---|
132 | }
|
---|
133 |
|
---|
134 | #endregion
|
---|
135 |
|
---|
136 | /// <summary>
|
---|
137 | /// Clones the current instance (deep clone).
|
---|
138 | /// </summary>
|
---|
139 | /// <returns>The cloned object as <see cref="NormalDistributedRandomPolar"/>.</returns>
|
---|
140 | public override IDeepCloneable Clone(Cloner cloner) {
|
---|
141 | return new NormalDistributedRandomPolar(this, cloner);
|
---|
142 | }
|
---|
143 |
|
---|
144 |
|
---|
145 | /**
|
---|
146 | * Polar method due to Marsaglia.
|
---|
147 | *
|
---|
148 | * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag,
|
---|
149 | * New York, 1986, Ch. V, Sect. 4.4.
|
---|
150 | */
|
---|
151 | public static double NextDouble(IRandom uniformRandom, double mu, double sigma) {
|
---|
152 | // we don't use spare numbers (efficency loss but easier for multi-threaded code)
|
---|
153 | double u, v, s;
|
---|
154 | do {
|
---|
155 | u = uniformRandom.NextDouble() * 2 - 1;
|
---|
156 | v = uniformRandom.NextDouble() * 2 - 1;
|
---|
157 | s = u * u + v * v;
|
---|
158 | } while (s > 1 || s == 0);
|
---|
159 | s = Math.Sqrt(-2.0 * Math.Log(s) / s);
|
---|
160 | return mu + sigma * u * s;
|
---|
161 | }
|
---|
162 | }
|
---|
163 | }
|
---|