source: branches/3027-NormalDistribution/HeuristicLab.Random/3.3/NormalDistributedRandomPolar.cs @ 17244

Last change on this file since 17244 was 17244, checked in by gkronber, 11 months ago

#3027: added class to generate normally distributed numbers using the polar method.

File size: 5.0 KB
Line 
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
22using System;
23using HeuristicLab.Common;
24using HeuristicLab.Core;
25using HEAL.Attic;
26
27namespace 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  public sealed class NormalDistributedRandomPolar : Item, IRandom {
35    [Storable]
36    private double mu;
37    /// <summary>
38    /// Gets or sets the value for µ.
39    /// </summary>
40    public double Mu {
41      get { return mu; }
42      set { mu = value; }
43    }
44
45    [Storable]
46    private double sigma;
47    /// <summary>
48    /// Gets or sets the value for sigma.
49    /// </summary>
50    public double Sigma {
51      get { return sigma; }
52      set { sigma = value; }
53    }
54
55    [Storable]
56    private IRandom uniform;
57
58
59    [StorableConstructor]
60    private NormalDistributedRandomPolar(StorableConstructorFlag _) : base(_) { }
61
62    private NormalDistributedRandomPolar(NormalDistributedRandomPolar original, Cloner cloner)
63      : base(original, cloner) {
64      uniform = cloner.Clone(original.uniform);
65      mu = original.mu;
66      sigma = original.sigma;
67    }
68
69    /// <summary>
70    /// Initializes a new instance of <see cref="NormalDistributedRandomPolar"/> with µ = 0 and sigma = 1
71    /// and a new random number generator.
72    /// </summary>
73    public NormalDistributedRandomPolar() {
74      this.mu = 0.0;
75      this.sigma = 1.0;
76      this.uniform = new MersenneTwister();
77    }
78
79    /// <summary>
80    /// Initializes a new instance of <see cref="NormalDistributedRandomPolar"/> with the given parameters.
81    /// <note type="caution"> The random number generator is not copied!</note>
82    /// </summary>   
83    /// <param name="uniformRandom">The random number generator.</param>
84    /// <param name="mu">The value for µ.</param>
85    /// <param name="sigma">The value for sigma.</param>
86    public NormalDistributedRandomPolar(IRandom uniformRandom, double mu, double sigma) {
87      this.mu = mu;
88      this.sigma = sigma;
89      this.uniform = uniformRandom;
90    }
91
92    #region IRandom Members
93
94    /// <inheritdoc cref="IRandom.Reset()"/>
95    public void Reset() {
96      uniform.Reset();
97    }
98
99    /// <inheritdoc cref="IRandom.Reset(int)"/>
100    public void Reset(int seed) {
101      uniform.Reset(seed);
102    }
103
104    /// <summary>
105    /// This method is not implemented.
106    /// </summary>
107    public int Next() {
108      throw new NotImplementedException();
109    }
110
111    /// <summary>
112    /// This method is not implemented.
113    /// </summary>
114    public int Next(int maxVal) {
115      throw new NotImplementedException();
116    }
117
118    /// <summary>
119    /// This method is not implemented.
120    /// </summary>
121    public int Next(int minVal, int maxVal) {
122      throw new NotImplementedException();
123    }
124
125    /// <summary>
126    /// Generates a new double random number.
127    /// </summary>
128    /// <returns>A double random number.</returns>
129    public double NextDouble() {
130      return NormalDistributedRandomPolar.NextDouble(uniform, mu, sigma);
131    }
132
133    #endregion
134
135    /// <summary>
136    /// Clones the current instance (deep clone).
137    /// </summary>
138    /// <returns>The cloned object as <see cref="NormalDistributedRandomPolar"/>.</returns>
139    public override IDeepCloneable Clone(Cloner cloner) {
140      return new NormalDistributedRandomPolar(this, cloner);
141    }
142
143
144    /**
145     * Polar method due to Marsaglia.
146     *
147     * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag,
148     * New York, 1986, Ch. V, Sect. 4.4.
149     */
150    public static double NextDouble(IRandom uniformRandom, double mu, double sigma) {
151      // we don't use spare numbers (efficency loss but easier for multi-threaded code)
152      double u, v, s;
153      do {
154        u = uniformRandom.NextDouble() * 2 - 1;
155        v = uniformRandom.NextDouble() * 2 - 1;
156        s = u * u + v * v;
157      } while (s >= 1 || s == 0);
158      s = Math.Sqrt(-2.0 * Math.Log(s) / s);
159      return mu + sigma * u * s;
160    }
161  }
162}
Note: See TracBrowser for help on using the repository browser.