Free cookie consent management tool by TermsFeed Policy Generator

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

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

Fix EmptyStorableClass attributes. (#603)

File size: 8.1 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;
[1853]28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
[2]29
30namespace HeuristicLab.Random {
[1153]31  /// <summary>
32  /// Normally distributed random number generator.
33  /// </summary>
[1853]34  [EmptyStorableClass]
[2]35  public class NormalRandomizer : OperatorBase {
36    private static int MAX_NUMBER_OF_TRIES = 100;
37
[1153]38    /// <inheritdoc select="summary"/>
[2]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
[1153]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>
[426]48    public double Mu {
49      get { return ((DoubleData)GetVariable("Mu").Value).Data; }
50      set { ((DoubleData)GetVariable("Mu").Value).Data = value; }
51    }
[1153]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>
[426]57    public double Sigma {
58      get { return ((DoubleData)GetVariable("Sigma").Value).Data; }
59      set { ((DoubleData)GetVariable("Sigma").Value).Data = value; }
60    }
61
[1153]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>
[2]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;
[183]73      AddVariable(new Variable("Sigma", new DoubleData(1.0)));
[2]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
[1153]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>
[1157]84    /// <returns><c>null</c>.</returns>
[2]85    public override IOperation Apply(IScope scope) {
86      IObjectData value = GetVariableValue<IObjectData>("Value", scope, false);
87      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
[719]88      double mu = GetVariableValue<DoubleData>("Mu", scope, true).Data;
89      double sigma = GetVariableValue<DoubleData>("Sigma", scope, true).Data;
[2]90
[763]91      NormalDistributedRandom n = new NormalDistributedRandom(mt, mu, sigma);
92      RandomizeNormal(value, n);
[2]93      return null;
94    }
95
[763]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    }
[2]108
[1153]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>
[763]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);
[2]124        }
[763]125        if (data.TrySetData(r)) {
126          return;
[2]127        }
128      }
[763]129      throw new InvalidOperationException("Couldn't find a valid value in 100 tries with mu=" + normal.Mu + " sigma=" + normal.Sigma);
130    }
[2]131
[1153]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>
[763]141    public void RandomizeNormal(ConstrainedIntData data, NormalDistributedRandom normal) {
142      for (int tries = MAX_NUMBER_OF_TRIES; tries >= 0; tries--) {
143        double r = normal.NextDouble();
[1153]144        if (data.TrySetData((int)Math.Round(r))) // since r is a continuous, normally distributed random variable rounding should be OK
[763]145          return;
[2]146      }
[763]147      throw new InvalidOperationException("Couldn't find a valid value");
148    }
[2]149
[1153]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>
[763]156    public void RandomizeNormal(DoubleData data, NormalDistributedRandom normal) {
157      data.Data = normal.NextDouble();
158    }
[2]159
[1153]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>
[763]166    public void RandomizeNormal(IntData data, NormalDistributedRandom normal) {
167      data.Data = (int)Math.Round(normal.NextDouble());
168    }
[2]169
[763]170
171    private bool IsIntegerConstrained(ConstrainedDoubleData data) {
172      foreach (IConstraint constraint in data.Constraints) {
173        if (constraint is IsIntegerConstraint) {
174          return true;
[2]175        }
176      }
[763]177      return false;
[2]178    }
179  }
180}
Note: See TracBrowser for help on using the repository browser.