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  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. NonUniform Random Variates Generation. SpringerVerlag,


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 multithreaded 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  }

