Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2738_QAPGenerators/HeuristicLab.Problems.Instances.QAPGenerator/3.3/PRNG/BetaDistributedRandom.cs @ 17912

Last change on this file since 17912 was 14704, checked in by abeham, 8 years ago

#2738: added branch

File size: 4.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 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 HeuristicLab.Common;
24using HeuristicLab.Core;
25using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
26using HeuristicLab.Random;
27
28namespace HeuristicLab.Problems.Instances.QAPGenerator {
29  [Item("Beta-distributed random number generator", "Creates random numbers that are distributed according to the beta distribution.")]
30  [StorableClass]
31  public sealed class BetaDistributedRandom : Item, IRandom {
32    private double alpha, beta, minimum, maximum;
33
34    [Storable]
35    public double Alpha {
36      get { return alpha; }
37      set { alpha = value; }
38    }
39
40    [Storable]
41    public double Beta {
42      get { return beta; }
43      set { beta = value; }
44    }
45
46    [Storable]
47    public double Minimum {
48      get { return minimum; }
49      set { minimum = value; }
50    }
51
52    [Storable]
53    public double Maximum {
54      get { return maximum; }
55      set { maximum = value; }
56    }
57
58    [Storable]
59    private IRandom uniform;
60
61    [Storable]
62    private IRandom normal;
63
64    [StorableConstructor]
65    private BetaDistributedRandom(bool deserializing) : base(deserializing) { }
66    private BetaDistributedRandom(BetaDistributedRandom original, Cloner cloner)
67      : base(original, cloner) {
68      this.alpha = original.alpha;
69      this.beta = original.beta;
70      this.uniform = cloner.Clone(uniform);
71    }
72    public BetaDistributedRandom() : this(new MersenneTwister(), 5, 5) { }
73    public BetaDistributedRandom(IRandom uniform, double alpha, double beta) : this(uniform, alpha, beta, 0, 1) { }
74    public BetaDistributedRandom(IRandom uniform, double alpha, double beta, double minimum, double maximum) {
75      if (alpha.IsAlmost(0) || beta.IsAlmost(0)) throw new ArgumentException("Alpha or Beta must be greater than 0.");
76      this.uniform = uniform;
77      this.normal = new NormalDistributedRandom(uniform, 0, 1);
78      this.alpha = alpha;
79      this.beta = beta;
80      this.minimum = minimum;
81      this.maximum = maximum;
82    }
83
84    public override IDeepCloneable Clone(Cloner cloner) {
85      return new BetaDistributedRandom(this, cloner);
86    }
87
88    public void Reset() {
89      uniform.Reset();
90    }
91
92    public void Reset(int seed) {
93      uniform.Reset(seed);
94    }
95
96    public int Next() {
97      throw new NotImplementedException();
98    }
99
100    public int Next(int maxVal) {
101      throw new NotImplementedException();
102    }
103
104    public int Next(int minVal, int maxVal) {
105      throw new NotImplementedException();
106    }
107
108    public double NextDouble() {
109      if ((alpha <= 1.0) && (beta <= 1.0)) {
110        // Use Jonk's algorithm
111        while (true) {
112          var x = Math.Pow(uniform.NextDouble(), 1.0 / alpha);
113          var y = Math.Pow(uniform.NextDouble(), 1.0 / beta);
114          if ((x + y) <= 1.0) return minimum + (maximum - minimum) * (x / (x + y));
115        }
116      }
117      var Ga = NextDoubleGammaDistributed(alpha);
118      var Gb = NextDoubleGammaDistributed(beta);
119      return minimum + (maximum - minimum) * (Ga / (Ga + Gb));
120    }
121
122    private double NextDoubleGammaDistributed(double shape) {
123      double u, v, x;
124
125      if (shape.IsAlmost(1.0))
126        return -Math.Log(1.0 - uniform.NextDouble());
127
128      if (shape < 1.0) {
129        while (true) {
130          u = uniform.NextDouble();
131          v = -Math.Log(1.0 - uniform.NextDouble());
132          if (u <= 1.0 - shape) {
133            x = Math.Pow(u, 1.0 / shape);
134            if (x <= v) return x;
135          } else {
136            var y = -Math.Log((1 - u) / shape);
137            x = Math.Pow(1.0 - shape + shape * y, 1.0 / shape);
138            if (x <= (v + y)) return x;
139          }
140        }
141      }
142      // shape > 1.0
143      var b = shape - 1.0 / 3.0;
144      var c = 1.0 / Math.Sqrt(9 * b);
145      for (; ; ) {
146        do {
147          x = normal.NextDouble();
148          v = 1.0 + c * x;
149        } while (v <= 0.0);
150
151        v = v * v * v;
152        u = uniform.NextDouble();
153        if (u < 1.0 - 0.0331 * (x * x) * (x * x)) return (b * v);
154        if (Math.Log(u) < 0.5 * x * x + b * (1.0 - v + Math.Log(v))) return (b * v);
155      }
156    }
157  }
158}
Note: See TracBrowser for help on using the repository browser.