Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Random/3.2/UniformRandomAdder.cs @ 3381

Last change on this file since 3381 was 1530, checked in by gkronber, 16 years ago

Moved source files of plugins Hive ... Visualization.Test into version-specific sub-folders. #576

File size: 8.7 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 that adds the generated value to the existing one.
32  /// </summary>
[2]33  public class UniformRandomAdder : OperatorBase {
34
35    private static int MAX_NUMBER_OF_TRIES = 100;
36
[1153]37    /// <inheritdoc select="summary"/>
[2]38    public override string Description {
[763]39      get {
40        return @"Samples a uniformly distributed random variable 'U' with range = [min,max] and E(u) = (max-min)/2
[2]41and adds the result to the variable 'Value'. ShakingFactor influences the effective range of U.
42If r=(max-min) then the effective range of U is [E(u) - shakingFactor * r/2, E(u) + shakingFactor * r/2].
43
44If a constraint for the allowed range of 'Value' is defined and the result of the operation would be smaller then
[763]45the smallest allowed value then 'Value' is set to the lower bound and vice versa for the upper bound.";
46      }
[2]47    }
48
[1153]49    /// <summary>
50    /// Initializes a new instance of <see cref="UniformRandomAdder"/> with five variable infos
51    /// (<c>Value</c>, <c>ShakingFactor</c>, <c>Random</c>, <c>Min</c> and <c>Max</c>), having an interval
52    /// of -1.0 to 1.0.
53    /// </summary>
[2]54    public UniformRandomAdder() {
55      AddVariableInfo(new VariableInfo("Value", "The value to manipulate (type is one of: IntData, ConstrainedIntData, DoubleData, ConstrainedDoubleData)", typeof(IObjectData), VariableKind.In));
[469]56      AddVariableInfo(new VariableInfo("ShakingFactor", "Determines the force of the shaking factor", typeof(DoubleData), VariableKind.In));
[2]57      AddVariableInfo(new VariableInfo("Random", "The random generator to use", typeof(MersenneTwister), VariableKind.In));
[469]58      AddVariableInfo(new VariableInfo("Min", "Lower bound of the uniform distribution (inclusive)", typeof(DoubleData), VariableKind.None));
[2]59      GetVariableInfo("Min").Local = true;
60      AddVariable(new Variable("Min", new DoubleData(-1.0)));
61
[469]62      AddVariableInfo(new VariableInfo("Max", "Upper bound of the uniform distribution (exclusive)", typeof(DoubleData), VariableKind.None));
[2]63      GetVariableInfo("Max").Local = true;
64      AddVariable(new Variable("Max", new DoubleData(1.0)));
65    }
66
[1153]67    /// <summary>
68    /// Generates a new uniformly distributed random number and adds it to the value in the given
69    /// <paramref name="scope"/>.
70    /// </summary>
71    /// <param name="scope">The current scope where to add the generated random number.</param>
[1157]72    /// <returns><c>null</c>.</returns>
[2]73    public override IOperation Apply(IScope scope) {
74      IObjectData value = GetVariableValue<IObjectData>("Value", scope, false);
75      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
76      double factor = GetVariableValue<DoubleData>("ShakingFactor", scope, true).Data;
[719]77      double min = GetVariableValue<DoubleData>("Min", scope, true).Data;
78      double max = GetVariableValue<DoubleData>("Max", scope, true).Data;
[2]79
80      double ex = (max - min) / 2.0 + min;
81      double newRange = (max - min) * factor;
82      min = ex - newRange / 2;
83      max = ex + newRange / 2;
84
[763]85      AddUniform(value, mt, min, max);
[2]86      return null;
87    }
88
[763]89    private void AddUniform(IObjectData value, MersenneTwister mt, double min, double max) {
90      // dispatch manually on dynamic type
91      if (value is IntData)
92        AddUniform((IntData)value, mt, min, max);
93      else if (value is ConstrainedIntData)
94        AddUniform((ConstrainedIntData)value, mt, min, max);
95      else if (value is DoubleData)
96        AddUniform((DoubleData)value, mt, min, max);
97      else if (value is ConstrainedDoubleData)
98        AddUniform((ConstrainedDoubleData)value, mt, min, max);
99      else throw new InvalidOperationException("Can't handle type " + value.GetType().Name);
100    }
[2]101
[1153]102    /// <summary>
103    /// Adds a new double random variable being restricted to some constraints to the value of the given
104    /// <paramref name="data"/>.
105    /// </summary>
106    /// <exception cref="InvalidProgramException">Thrown when no valid value can be found.</exception>
107    /// <param name="data">The data where to add the new variable and where to assign the new value to.</param>
108    /// <param name="mt">The random number generator.</param>
109    /// <param name="min">The left border of the interval in which the next random number has to lie.</param>
110    /// <param name="max">The right border (exclusive) of the interval in which the next random number
111    /// has to lie.</param>
[763]112    public void AddUniform(ConstrainedDoubleData data, MersenneTwister mt, double min, double max) {
113      for (int tries = MAX_NUMBER_OF_TRIES; tries >= 0; tries--) {
114        double newValue = data.Data + mt.NextDouble() * (max - min) + min;
115        if (IsIntegerConstrained(data)) {
116          newValue = Math.Floor(newValue);
[2]117        }
[763]118        if (data.TrySetData(newValue)) {
119          return;
120        }
[2]121      }
[763]122      throw new InvalidProgramException("Couldn't find a valid value");
123    }
[2]124
[1153]125    /// <summary>
126    /// Adds a new int random variable being restricted to some constraints to the value of the given
127    /// <paramref name="data"/>.
128    /// </summary>
129    /// <exception cref="InvalidProgramException">Thrown when no valid value could be found.</exception>
130    /// <param name="data">The data where to add the random value and where to assign the new value to.</param>
131    /// <param name="mt">The random number generator.</param>
132    /// <param name="min">The left border of the interval in which the next random number has to lie.</param>
133    /// <param name="max">The right border (exclusive) of the interval in which the next random number
134    /// has to lie.</param>
[763]135    public void AddUniform(ConstrainedIntData data, MersenneTwister mt, double min, double max) {
136      for (int tries = MAX_NUMBER_OF_TRIES; tries >= 0; tries--) {
137        int newValue = (int)Math.Floor(data.Data + mt.NextDouble() * (max - min) + min);
138        if (data.TrySetData(newValue)) {
139          return;
[2]140        }
141      }
[763]142      throw new InvalidProgramException("Couldn't find a valid value");
143    }
[2]144
[1153]145    /// <summary>
146    /// Generates a new double random variable and adds it to the value of
147    /// the given <paramref name="data"/>.
148    /// </summary>
149    /// <param name="data">The double object where to add the random value.</param>
150    /// <param name="mt">The random number generator.</param>
151    /// <param name="min">The left border of the interval in which the next random number has to lie.</param>
152    /// <param name="max">The right border (exclusive) of the interval in which the next random number
153    /// has to lie.</param>
[763]154    public void AddUniform(DoubleData data, MersenneTwister mt, double min, double max) {
155      data.Data = data.Data + mt.NextDouble() * (max - min) + min;
156    }
[2]157
[1153]158    /// <summary>
159    /// Generates a new int random variable and adds it to the value of the given
160    /// <paramref name="data"/>.
161    /// </summary>
162    /// <param name="data">The int object where to add the random value.</param>
163    /// <param name="mt">The random number generator.</param>
164    /// <param name="min">The left border of the interval in which the next random number has to lie.</param>
165    /// <param name="max">The right border (exclusive) of the interval in which the next random number
166    /// has to lie.</param>
[763]167    public void AddUniform(IntData data, MersenneTwister mt, double min, double max) {
168      data.Data = (int)Math.Floor(data.Data + mt.NextDouble() * (max - min) + min);
169    }
170    private bool IsIntegerConstrained(ConstrainedDoubleData data) {
171      foreach (IConstraint constraint in data.Constraints) {
172        if (constraint is IsIntegerConstraint) {
173          return true;
[2]174        }
175      }
[763]176      return false;
[2]177    }
178  }
179}
Note: See TracBrowser for help on using the repository browser.