Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Random/NormalRandomizer.cs @ 1172

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