Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Random/UniformRandomizer.cs @ 1364

Last change on this file since 1364 was 1157, checked in by vdorfer, 16 years ago

Created API documentation for HeuristicLab.IntVector namespace and changed some comments in HeuristicLab.Random and HeuristicLab.Selection.Offspring namespace(#331)

File size: 9.4 KB
RevLine 
[2]1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 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 System.Collections.Generic;
24using System.Text;
25using HeuristicLab.Core;
26using HeuristicLab.Data;
27using HeuristicLab.Constraints;
28
29namespace HeuristicLab.Random {
[1153]30  /// <summary>
31  /// Uniformly distributed random number generator.
32  /// </summary>
[2]33  public class UniformRandomizer : OperatorBase {
34    private static int MAX_NUMBER_OF_TRIES = 100;
[1153]35    /// <inheritdoc select="summary"/>
[2]36    public override string Description {
37      get { return "Initializes the value of variable 'Value' to a random value uniformly distributed between 'Min' and 'Max' (exclusive)"; }
38    }
39
[1153]40    /// <summary>
41    /// Gets or sets the maximum value of the random number generator (exclusive).
42    /// </summary>
43    /// <remarks>Gets or sets the variable with name <c>Max</c> through the
44    /// <see cref="OperatorBase.GetVariable"/> method of class <see cref="OperatorBase"/>.</remarks>
[426]45    public double Max {
46      get { return ((DoubleData)GetVariable("Max").Value).Data; }
47      set { ((DoubleData)GetVariable("Max").Value).Data = value; }
48    }
[1153]49    /// <summary>
50    /// Gets or sets the minimum value of the random number generator.
51    /// </summary>
52    /// <remarks>Gets or sets the variable with name <c>Min</c> through the
53    /// <see cref="OperatorBase.GetVariable"/> method of class <see cref="OperatorBase"/>.</remarks>
[426]54    public double Min {
55      get { return ((DoubleData)GetVariable("Min").Value).Data; }
56      set { ((DoubleData)GetVariable("Min").Value).Data = value; }
57    }
58
[1153]59    /// <summary>
60    /// Initializes a new instance of <see cref="UniformRandomizer"/> with four variable infos
61    /// (<c>Value</c>, <c>Random</c>, <c>Max</c> and <c>Min</c>), being a random number generator
62    /// between 0.0 and 1.0.
63    /// </summary>
[2]64    public UniformRandomizer() {
65      AddVariableInfo(new VariableInfo("Value", "The value to manipulate (type is one of: IntData, ConstrainedIntData, DoubleData, ConstrainedDoubleData)", typeof(IObjectData), VariableKind.In));
66      AddVariableInfo(new VariableInfo("Random", "The random generator to use", typeof(MersenneTwister), VariableKind.In));
[469]67      AddVariableInfo(new VariableInfo("Min", "Lower bound of the uniform distribution (inclusive)", typeof(DoubleData), VariableKind.None));
[2]68      GetVariableInfo("Min").Local = true;
69      AddVariable(new Variable("Min", new DoubleData(0.0)));
70
[469]71      AddVariableInfo(new VariableInfo("Max", "Upper bound of the uniform distribution (exclusive)", typeof(DoubleData), VariableKind.None));
[2]72      GetVariableInfo("Max").Local = true;
73      AddVariable(new Variable("Max", new DoubleData(1.0)));
74    }
75
[1153]76    /// <summary>
77    /// Generates a new uniformly distributed random variable.
78    /// </summary>
79    /// <param name="scope">The scope where to apply the random number generator.</param>
[1157]80    /// <returns><c>null</c>.</returns>
[2]81    public override IOperation Apply(IScope scope) {
82      IObjectData value = GetVariableValue<IObjectData>("Value", scope, false);
83      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
[719]84      double min = GetVariableValue<DoubleData>("Min", scope, true).Data;
85      double max = GetVariableValue<DoubleData>("Max", scope, true).Data;
[2]86
[763]87      RandomizeUniform(value, mt, min, max);
[2]88      return null;
89    }
90
[1153]91    /// <summary>
92    /// Generates a new random number depending on the type of the <paramref name="value"/>.
93    /// </summary>
94    /// <exception cref="ArgumentException">Thrown when an unhandleable type appears.</exception>
95    /// <param name="value">The object whose data should be a new randomly generated number.</param>
96    /// <param name="mt">The MersenneTwister to generate a new random number.</param>
97    /// <param name="min">The left border of the interval in which the next random number has to lie.</param>
98    /// <param name="max">The right border (exclusive) of the interval in which the next random number
99    /// has to lie.</param>
[763]100    private void RandomizeUniform(IObjectData value, MersenneTwister mt, double min, double max) {
101      // Dispatch manually based on dynamic type,
102      // a bit awkward but necessary until we create a better type hierarchy for numeric types (gkronber 15.11.2008).
103      if (value is DoubleData)
104        RandomizeUniform((DoubleData)value, mt, min, max);
105      else if (value is ConstrainedDoubleData)
106        RandomizeUniform((ConstrainedDoubleData)value, mt, min, max);
107      else if (value is IntData)
108        RandomizeUniform((IntData)value, mt, min, max);
109      else if (value is ConstrainedIntData)
110        RandomizeUniform((ConstrainedIntData)value, mt, min, max);
111      else throw new ArgumentException("Can't handle type " + value.GetType().Name);
112    }
[2]113
[1153]114      /// <summary>
115      /// Generates a new double random number.
116      /// </summary>
117      /// <param name="data">The double object which the new value is assigned to.</param>
118      /// <param name="mt">The random number generator.</param>
119      /// <param name="min">The left border of the interval in which the next random number has to lie.</param>
120      /// <param name="max">The right border (exclusive) of the interval in which the next random number
121      /// has to lie.</param>
[763]122      public void RandomizeUniform(DoubleData data, MersenneTwister mt, double min, double max) {
[2]123        data.Data = mt.NextDouble() * (max - min) + min;
124      }
125
[1153]126      /// <summary>
127      /// Generates a new int random number.
128      /// </summary>
129      /// <param name="data">The int object which the new value is assigned to.</param>
130      /// <param name="mt">The random number generator.</param>
131      /// <param name="min">The left border of the interval in which the next random number has to lie.</param>
132      /// <param name="max">The right border (exclusive) of the interval in which the next random number
133      /// has to lie.</param>
[763]134      public void RandomizeUniform(IntData data, MersenneTwister mt, double min, double max) {
[469]135        data.Data = (int)Math.Floor(mt.NextDouble() * (max - min) + min);
[2]136      }
137
[1153]138      /// <summary>
139      /// Generates a new double random number, being restricted to some constraints.
140      /// </summary>
141      /// <exception cref="InvalidOperationException">Thrown when no valid value could be found.</exception>
142      /// <param name="data">The double object which the new value is assigned to and whose constraints
143      /// must be fulfilled.</param>
144      /// <param name="mt">The random number generator.</param>
145      /// <param name="min">The left border of the interval in which the next random number has to lie.</param>
146      /// <param name="max">The right border (exclusive) of the interval in which the next random number
147      /// has to lie.</param>
[763]148      public void RandomizeUniform(ConstrainedDoubleData data, MersenneTwister mt, double min, double max) {
[2]149        for(int tries = MAX_NUMBER_OF_TRIES; tries >= 0; tries--) {
150          double r = mt.NextDouble() * (max - min) + min;
151          if(IsIntegerConstrained(data)) {
[469]152            r = Math.Floor(r);
[2]153          }
154          if(data.TrySetData(r)) {
155            return;
156          }
157        }
[763]158        throw new InvalidOperationException("Couldn't find a valid value");
[2]159      }
[1153]160      /// <summary>
161      /// Generates a new int random number, being restricted to some constraints.
162      /// </summary>
163      /// <exception cref="InvalidOperationException">Thrown when no valid value could be found.</exception>
164      /// <param name="data">The int object which the new value is assigned to and whose constraints
165      /// must be fulfilled.</param>
166      /// <param name="mt">The random number generator.</param>
167      /// <param name="min">The left border of the interval in which the next random number has to lie.</param>
168      /// <param name="max">The right border (exclusive) of the interval in which the next random number
169      /// has to lie.</param>
[763]170      public void RandomizeUniform(ConstrainedIntData data, MersenneTwister mt, double min, double max) {
[2]171        for(int tries = MAX_NUMBER_OF_TRIES; tries >= 0; tries--) {
[469]172          int r = (int)Math.Floor(mt.NextDouble() * (max - min) + min);
[2]173          if(data.TrySetData(r)) {
174            return;
175          }
176        }
[763]177        throw new InvalidOperationException("Couldn't find a valid value");
[2]178      }
179
180      private bool IsIntegerConstrained(ConstrainedDoubleData data) {
181        foreach(IConstraint constraint in data.Constraints) {
182          if(constraint is IsIntegerConstraint) {
183            return true;
184          }
185        }
186        return false;
187      }
188    }
189}
Note: See TracBrowser for help on using the repository browser.