1  #region License Information


2  /* HeuristicLab


3  * Copyright (C) 20022008 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 System.Collections.Generic;


24  using System.Text;


25  using HeuristicLab.Core;


26  using HeuristicLab.Data;


27  using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;


28 


29  namespace HeuristicLab.Random {


30  /// <summary>


31  /// Uniformly distributed random number generator.


32  /// </summary>


33  [EmptyStorableClass]


34  public class UniformRandomizer : OperatorBase {


35  private static int MAX_NUMBER_OF_TRIES = 100;


36  /// <inheritdoc select="summary"/>


37  public override string Description {


38  get { return "Initializes the value of variable 'Value' to a random value uniformly distributed between 'Min' and 'Max' (exclusive)"; }


39  }


40 


41  /// <summary>


42  /// Gets or sets the maximum value of the random number generator (exclusive).


43  /// </summary>


44  /// <remarks>Gets or sets the variable with name <c>Max</c> through the


45  /// <see cref="OperatorBase.GetVariable"/> method of class <see cref="OperatorBase"/>.</remarks>


46  public double Max {


47  get { return ((DoubleData)GetVariable("Max").Value).Data; }


48  set { ((DoubleData)GetVariable("Max").Value).Data = value; }


49  }


50  /// <summary>


51  /// Gets or sets the minimum value of the random number generator.


52  /// </summary>


53  /// <remarks>Gets or sets the variable with name <c>Min</c> through the


54  /// <see cref="OperatorBase.GetVariable"/> method of class <see cref="OperatorBase"/>.</remarks>


55  public double Min {


56  get { return ((DoubleData)GetVariable("Min").Value).Data; }


57  set { ((DoubleData)GetVariable("Min").Value).Data = value; }


58  }


59 


60  /// <summary>


61  /// Initializes a new instance of <see cref="UniformRandomizer"/> with four variable infos


62  /// (<c>Value</c>, <c>Random</c>, <c>Max</c> and <c>Min</c>), being a random number generator


63  /// between 0.0 and 1.0.


64  /// </summary>


65  public UniformRandomizer() {


66  AddVariableInfo(new VariableInfo("Value", "The value to manipulate (type is one of: IntData, ConstrainedIntData, DoubleData, ConstrainedDoubleData)", typeof(IObjectData), VariableKind.In));


67  AddVariableInfo(new VariableInfo("Random", "The random generator to use", typeof(MersenneTwister), VariableKind.In));


68  AddVariableInfo(new VariableInfo("Min", "Lower bound of the uniform distribution (inclusive)", typeof(DoubleData), VariableKind.None));


69  GetVariableInfo("Min").Local = true;


70  AddVariable(new Variable("Min", new DoubleData(0.0)));


71 


72  AddVariableInfo(new VariableInfo("Max", "Upper bound of the uniform distribution (exclusive)", typeof(DoubleData), VariableKind.None));


73  GetVariableInfo("Max").Local = true;


74  AddVariable(new Variable("Max", new DoubleData(1.0)));


75  }


76 


77  /// <summary>


78  /// Generates a new uniformly distributed random variable.


79  /// </summary>


80  /// <param name="scope">The scope where to apply the random number generator.</param>


81  /// <returns><c>null</c>.</returns>


82  public override IOperation Apply(IScope scope) {


83  IObjectData value = GetVariableValue<IObjectData>("Value", scope, false);


84  MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);


85  double min = GetVariableValue<DoubleData>("Min", scope, true).Data;


86  double max = GetVariableValue<DoubleData>("Max", scope, true).Data;


87 


88  RandomizeUniform(value, mt, min, max);


89  return null;


90  }


91 


92  /// <summary>


93  /// Generates a new random number depending on the type of the <paramref name="value"/>.


94  /// </summary>


95  /// <exception cref="ArgumentException">Thrown when an unhandleable type appears.</exception>


96  /// <param name="value">The object whose data should be a new randomly generated number.</param>


97  /// <param name="mt">The MersenneTwister to generate a new random number.</param>


98  /// <param name="min">The left border of the interval in which the next random number has to lie.</param>


99  /// <param name="max">The right border (exclusive) of the interval in which the next random number


100  /// has to lie.</param>


101  private void RandomizeUniform(IObjectData value, MersenneTwister mt, double min, double max) {


102  // Dispatch manually based on dynamic type,


103  // a bit awkward but necessary until we create a better type hierarchy for numeric types (gkronber 15.11.2008).


104  if (value is DoubleData)


105  RandomizeUniform((DoubleData)value, mt, min, max);


106  else if (value is IntData)


107  RandomizeUniform((IntData)value, mt, min, max);


108  else throw new ArgumentException("Can't handle type " + value.GetType().Name);


109  }


110 


111  /// <summary>


112  /// Generates a new double random number.


113  /// </summary>


114  /// <param name="data">The double object which the new value is assigned to.</param>


115  /// <param name="mt">The random number generator.</param>


116  /// <param name="min">The left border of the interval in which the next random number has to lie.</param>


117  /// <param name="max">The right border (exclusive) of the interval in which the next random number


118  /// has to lie.</param>


119  public void RandomizeUniform(DoubleData data, MersenneTwister mt, double min, double max) {


120  data.Data = mt.NextDouble() * (max  min) + min;


121  }


122 


123  /// <summary>


124  /// Generates a new int random number.


125  /// </summary>


126  /// <param name="data">The int object which the new value is assigned to.</param>


127  /// <param name="mt">The random number generator.</param>


128  /// <param name="min">The left border of the interval in which the next random number has to lie.</param>


129  /// <param name="max">The right border (exclusive) of the interval in which the next random number


130  /// has to lie.</param>


131  public void RandomizeUniform(IntData data, MersenneTwister mt, double min, double max) {


132  data.Data = (int)Math.Floor(mt.NextDouble() * (max  min) + min);


133  }


134  }


135  }

