Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Random/3.3/NormalRandomizer.cs @ 2297

Last change on this file since 2297 was 1853, checked in by epitzer, 15 years ago

Fix EmptyStorableClass attributes. (#603)

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