Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Random/NormalRandomAdder.cs @ 1449

Last change on this file since 1449 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: 8.3 KB
Line 
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 {
30  /// <summary>
31  /// Normally distributed random number generator that adds the generated value to the existing value
32  /// in the specified scope.
33  /// </summary>
34  public class NormalRandomAdder : OperatorBase {
35    private static int MAX_NUMBER_OF_TRIES = 100;
36
37    /// <inheritdoc select="summary"/>
38    public override string Description {
39      get {
40        return @"Samples a normally distributed (mu, sigma * shakingFactor) random variable and adds the result to variable 'Value'.
41       
42If a constraint for the allowed range of 'Value' is defined and the result of the operation would be smaller then
43the smallest allowed value then 'Value' is set to the lower bound and vice versa for the upper bound.";
44      }
45    }
46
47    /// <summary>
48    /// Gets or sets the value for µ.
49    /// </summary>
50    /// <remarks>Gets or sets the variable with the name <c>Mu</c> through the method
51    /// <see cref="OperatorBase.GetVariable"/> of class <see cref="OperatorBase"/>.</remarks>
52    public double Mu {
53      get { return ((DoubleData)GetVariable("Mu").Value).Data; }
54      set { ((DoubleData)GetVariable("Mu").Value).Data = value; }
55    }
56    /// <summary>
57    /// Gets or sets the value for sigma.
58    /// </summary>
59    /// <remarks>Gets or sets the variable with the name <c>Sigma</c> through the method
60    /// <see cref="OperatorBase.GetVariable"/> of class <see cref="OperatorBase"/>.</remarks>
61    public double Sigma {
62      get { return ((DoubleData)GetVariable("Sigma").Value).Data; }
63      set { ((DoubleData)GetVariable("Sigma").Value).Data = value; }
64    }
65
66    /// <summary>
67    /// Initializes a new instance of <see cref="NormalRandomAdder"/> with five variable infos
68    /// (<c>Mu</c>, <c>Sigma</c>, <c>Value</c>, <c>ShakingFactor</c> and <c>Random</c>).
69    /// </summary>
70    public NormalRandomAdder() {
71      AddVariableInfo(new VariableInfo("Mu", "Parameter mu of the normal distribution", typeof(DoubleData), VariableKind.None));
72      GetVariableInfo("Mu").Local = true;
73      AddVariable(new Variable("Mu", new DoubleData(0.0)));
74
75      AddVariableInfo(new VariableInfo("Sigma", "Parameter sigma of the normal distribution", typeof(DoubleData), VariableKind.None));
76      GetVariableInfo("Sigma").Local = true;
77      AddVariable(new Variable("Sigma", new DoubleData(1.0)));
78
79      AddVariableInfo(new VariableInfo("Value", "The value to manipulate (actual type is one of: IntData, DoubleData, ConstrainedIntData, ConstrainedDoubleData)", typeof(IObjectData), VariableKind.In));
80      AddVariableInfo(new VariableInfo("ShakingFactor", "Determines the force of the shaking factor (effective sigma = sigma * shakingFactor)", typeof(DoubleData), VariableKind.In));
81      AddVariableInfo(new VariableInfo("Random", "The random generator to use", typeof(MersenneTwister), VariableKind.In));
82    }
83
84    /// <summary>
85    /// Generates a new normally distributed random number and adds it to the specified value in the
86    /// given <paramref name="scope"/>.
87    /// </summary>
88    /// <param name="scope">The scope where to add the generated random number.</param>
89    /// <returns><c>null</c>.</returns>
90    public override IOperation Apply(IScope scope) {
91      IObjectData value = GetVariableValue<IObjectData>("Value", scope, false);
92      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
93      double factor = GetVariableValue<DoubleData>("ShakingFactor", scope, true).Data;
94      double mu = GetVariableValue<DoubleData>("Mu", scope, true).Data;
95      double sigma = GetVariableValue<DoubleData>("Sigma", scope, true).Data;
96      NormalDistributedRandom normal = new NormalDistributedRandom(mt, mu, sigma * factor);
97
98      AddNormal(value, normal);
99      return null;
100    }
101
102    private void AddNormal(IObjectData value, NormalDistributedRandom normal) {
103      // dispatch manually based on dynamic type
104      if (value is IntData)
105        AddNormal((IntData)value, normal);
106      else if (value is ConstrainedIntData)
107        AddNormal((ConstrainedIntData)value, normal);
108      else if (value is ConstrainedDoubleData)
109        AddNormal((ConstrainedDoubleData)value, normal);
110      else if (value is DoubleData)
111        AddNormal((DoubleData)value, normal);
112      else throw new InvalidOperationException("Can't handle type " + value.GetType().Name);
113    }
114    /// <summary>
115    /// Generates a new double random number and adds it to the value of
116    /// the given <paramref name="data"/>.
117    /// </summary>
118    /// <param name="data">The double object where to add the random number.</param>
119    /// <param name="normal">The continuous, normally distributed random variable.</param>
120    public void AddNormal(DoubleData data, NormalDistributedRandom normal) {
121      data.Data += normal.NextDouble();
122    }
123
124    /// <summary>
125    /// Generates a new double random number and adds it to the value of the given <paramref name="data"/>
126    /// checking its constraints.
127    /// </summary>
128    /// <exception cref="InvalidProgramException">Thrown when with the current settings no valid value
129    /// could be found.</exception>
130    /// <param name="data">The double object where to add the random number and whose constraints
131    /// to fulfill.</param>
132    /// <param name="normal">The continuous, normally distributed random variable.</param>
133    public void AddNormal(ConstrainedDoubleData data, NormalDistributedRandom normal) {
134      for (int tries = MAX_NUMBER_OF_TRIES; tries >= 0; tries--) {
135        double newValue = data.Data + normal.NextDouble();
136        if (IsIntegerConstrained(data)) {
137          newValue = Math.Round(newValue);
138        }
139        if (data.TrySetData(newValue)) {
140          return;
141        }
142      }
143      throw new InvalidProgramException("Coudn't find a valid value");
144    }
145
146    /// <summary>
147    /// Generates a new int random number and adds it to value of the given <paramref name="data"/>.
148    /// </summary>
149    /// <param name="data">The int object where to add the random number.</param>
150    /// <param name="normal">The continuous, normally distributed random variable.</param>
151    public void AddNormal(IntData data, NormalDistributedRandom normal) {
152      data.Data = (int)Math.Round(data.Data + normal.NextDouble());
153    }
154
155    /// <summary>
156    /// Generates a new int random number and adds it to the value of the given <paramref name="data"/>
157    /// checking its constraints.
158    /// </summary>
159    /// <exception cref="InvalidProgramException">Thrown when with the current settings no valid value
160    /// could be found.</exception>
161    /// <param name="data">The int object where to add the generated value and whose contraints to check.</param>
162    /// <param name="normal">The continuous, normally distributed random variable.</param>
163    public void AddNormal(ConstrainedIntData data, NormalDistributedRandom normal) {
164      for (int tries = MAX_NUMBER_OF_TRIES; tries >= 0; tries--) {
165        if (data.TrySetData((int)Math.Round(data.Data + normal.NextDouble())))
166          return;
167      }
168      throw new InvalidProgramException("Couldn't find a valid value.");
169    }
170
171    private bool IsIntegerConstrained(ConstrainedDoubleData data) {
172      foreach (IConstraint constraint in data.Constraints) {
173        if (constraint is IsIntegerConstraint) {
174          return true;
175        }
176      }
177      return false;
178    }
179  }
180}
Note: See TracBrowser for help on using the repository browser.