Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Random/UniformRandomizer.cs @ 805

Last change on this file since 805 was 763, checked in by gkronber, 16 years ago

removed visitor interfaces and methods in HeuristicLab.Data and fixed classes in HeuristicLab.Random to work without visitor methods. #343 (Rethink about usefulness of visitors for ObjectData and Constraints)

File size: 5.2 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  public class UniformRandomizer : OperatorBase {
31    private static int MAX_NUMBER_OF_TRIES = 100;
32    public override string Description {
33      get { return "Initializes the value of variable 'Value' to a random value uniformly distributed between 'Min' and 'Max' (exclusive)"; }
34    }
35
36    public double Max {
37      get { return ((DoubleData)GetVariable("Max").Value).Data; }
38      set { ((DoubleData)GetVariable("Max").Value).Data = value; }
39    }
40    public double Min {
41      get { return ((DoubleData)GetVariable("Min").Value).Data; }
42      set { ((DoubleData)GetVariable("Min").Value).Data = value; }
43    }
44
45    public UniformRandomizer() {
46      AddVariableInfo(new VariableInfo("Value", "The value to manipulate (type is one of: IntData, ConstrainedIntData, DoubleData, ConstrainedDoubleData)", typeof(IObjectData), VariableKind.In));
47      AddVariableInfo(new VariableInfo("Random", "The random generator to use", typeof(MersenneTwister), VariableKind.In));
48      AddVariableInfo(new VariableInfo("Min", "Lower bound of the uniform distribution (inclusive)", typeof(DoubleData), VariableKind.None));
49      GetVariableInfo("Min").Local = true;
50      AddVariable(new Variable("Min", new DoubleData(0.0)));
51
52      AddVariableInfo(new VariableInfo("Max", "Upper bound of the uniform distribution (exclusive)", typeof(DoubleData), VariableKind.None));
53      GetVariableInfo("Max").Local = true;
54      AddVariable(new Variable("Max", new DoubleData(1.0)));
55    }
56
57    public override IOperation Apply(IScope scope) {
58      IObjectData value = GetVariableValue<IObjectData>("Value", scope, false);
59      MersenneTwister mt = GetVariableValue<MersenneTwister>("Random", scope, true);
60      double min = GetVariableValue<DoubleData>("Min", scope, true).Data;
61      double max = GetVariableValue<DoubleData>("Max", scope, true).Data;
62
63      RandomizeUniform(value, mt, min, max);
64      return null;
65    }
66
67    private void RandomizeUniform(IObjectData value, MersenneTwister mt, double min, double max) {
68      // Dispatch manually based on dynamic type,
69      // a bit awkward but necessary until we create a better type hierarchy for numeric types (gkronber 15.11.2008).
70      if (value is DoubleData)
71        RandomizeUniform((DoubleData)value, mt, min, max);
72      else if (value is ConstrainedDoubleData)
73        RandomizeUniform((ConstrainedDoubleData)value, mt, min, max);
74      else if (value is IntData)
75        RandomizeUniform((IntData)value, mt, min, max);
76      else if (value is ConstrainedIntData)
77        RandomizeUniform((ConstrainedIntData)value, mt, min, max);
78      else throw new ArgumentException("Can't handle type " + value.GetType().Name);
79    }
80
81
82      public void RandomizeUniform(DoubleData data, MersenneTwister mt, double min, double max) {
83        data.Data = mt.NextDouble() * (max - min) + min;
84      }
85
86      public void RandomizeUniform(IntData data, MersenneTwister mt, double min, double max) {
87        data.Data = (int)Math.Floor(mt.NextDouble() * (max - min) + min);
88      }
89
90      public void RandomizeUniform(ConstrainedDoubleData data, MersenneTwister mt, double min, double max) {
91        for(int tries = MAX_NUMBER_OF_TRIES; tries >= 0; tries--) {
92          double r = mt.NextDouble() * (max - min) + min;
93          if(IsIntegerConstrained(data)) {
94            r = Math.Floor(r);
95          }
96          if(data.TrySetData(r)) {
97            return;
98          }
99        }
100        throw new InvalidOperationException("Couldn't find a valid value");
101      }
102
103      public void RandomizeUniform(ConstrainedIntData data, MersenneTwister mt, double min, double max) {
104        for(int tries = MAX_NUMBER_OF_TRIES; tries >= 0; tries--) {
105          int r = (int)Math.Floor(mt.NextDouble() * (max - min) + min);
106          if(data.TrySetData(r)) {
107            return;
108          }
109        }
110        throw new InvalidOperationException("Couldn't find a valid value");
111      }
112
113      private bool IsIntegerConstrained(ConstrainedDoubleData data) {
114        foreach(IConstraint constraint in data.Constraints) {
115          if(constraint is IsIntegerConstraint) {
116            return true;
117          }
118        }
119        return false;
120      }
121    }
122}
Note: See TracBrowser for help on using the repository browser.