Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Random/3.2/NormalDistributedRandom.cs @ 2873

Last change on this file since 2873 was 2222, checked in by gkronber, 15 years ago

Merged changes from GP-refactoring branch back into the trunk #713.

File size: 16.7 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 System.Xml;
27using System.Globalization;
28
29namespace HeuristicLab.Random {
30
31  /// <summary>
32  /// Normally distributed random variable.
33  /// Uses the Ziggurat transform to efficiently generate normal distributed random numbers.
34  /// See "The Ziggurat Method for Generating Random Variables" (G. Marsaglia and W.W. Tsang 2000).
35  /// </summary>
36  public class NormalDistributedRandom : ItemBase, IRandom {
37
38    private double mu;
39
40    /// <summary>
41    /// Gets or sets the value for µ.
42    /// </summary>
43    public double Mu {
44      get { return mu; }
45      set { mu = value; }
46    }
47    private double sigma;
48
49    /// <summary>
50    /// Gets or sets the value for sigma.
51    /// </summary>
52    public double Sigma {
53      get { return sigma; }
54      set { sigma = value; }
55    }
56    private IRandom uniform;
57    private static readonly double[] w = new double[] {
58      1.7290404664e-09,
59      1.2680928529e-10,
60      1.6897518107e-10,
61      1.9862687883e-10,
62      2.2232431174e-10,
63      2.4244936614e-10,
64      2.6016130916e-10,
65      2.7611987696e-10,
66      2.9073962682e-10,
67      3.0429969655e-10,
68      3.1699795566e-10,
69      3.2898020419e-10,
70      3.4035738117e-10,
71      3.5121602848e-10,
72      3.6162509098e-10,
73      3.7164057942e-10,
74      3.8130856805e-10,
75      3.9066758162e-10,
76      3.9975012189e-10,
77      4.0858399997e-10,
78      4.1719308563e-10,
79      4.2559822333e-10,
80      4.3381759296e-10,
81      4.4186720949e-10,
82      4.4976131153e-10,
83      4.5751258337e-10,
84      4.6513240481e-10,
85      4.7263104541e-10,
86      4.8001774777e-10,
87      4.8730097735e-10,
88      4.9448850570e-10,
89      5.0158732723e-10,
90      5.0860404777e-10,
91      5.1554460700e-10,
92      5.2241466708e-10,
93      5.2921933502e-10,
94      5.3596349581e-10,
95      5.4265170135e-10,
96      5.4928817050e-10,
97      5.5587695558e-10,
98      5.6242188684e-10,
99      5.6892646150e-10,
100      5.7539412124e-10,
101      5.8182819673e-10,
102      5.8823168558e-10,
103      5.9460769641e-10,
104      6.0095900478e-10,
105      6.0728838625e-10,
106      6.1359850534e-10,
107      6.1989202660e-10,
108      6.2617133700e-10,
109      6.3243904558e-10,
110      6.3869737277e-10,
111      6.4494881657e-10,
112      6.5119559745e-10,
113      6.5744004685e-10,
114      6.6368432972e-10,
115      6.6993072201e-10,
116      6.7618144417e-10,
117      6.8243871665e-10,
118      6.8870464887e-10,
119      6.9498151678e-10,
120      7.0127148533e-10,
121      7.0757677495e-10,
122      7.1389966161e-10,
123      7.2024242126e-10,
124      7.2660727435e-10,
125      7.3299660786e-10,
126      7.3941280876e-10,
127      7.4585826404e-10,
128      7.5233547170e-10,
129      7.5884698525e-10,
130      7.6539541372e-10,
131      7.7198347714e-10,
132      7.7861395109e-10,
133      7.8528972214e-10,
134      7.9201378789e-10,
135      7.9878920145e-10,
136      8.0561923799e-10,
137      8.1250728368e-10,
138      8.1945689123e-10,
139      8.2647166888e-10,
140      8.3355555791e-10,
141      8.4071272166e-10,
142      8.4794732347e-10,
143      8.5526402627e-10,
144      8.6266754851e-10,
145      8.7016316375e-10,
146      8.7775620106e-10,
147      8.8545243360e-10,
148      8.9325818964e-10,
149      9.0117996399e-10,
150      9.0922497309e-10,
151      9.1740082198e-10,
152      9.2571583732e-10,
153      9.3417884539e-10,
154      9.4279972718e-10,
155      9.5158891877e-10,
156      9.6055785548e-10,
157      9.6971930486e-10,
158      9.7908692265e-10,
159      9.8867602993e-10,
160      9.9850361313e-10,
161      1.0085882129e-09,
162      1.0189509236e-09,
163      1.0296150599e-09,
164      1.0406069340e-09,
165      1.0519566329e-09,
166      1.0636980186e-09,
167      1.0758701707e-09,
168      1.0885182755e-09,
169      1.1016947354e-09,
170      1.1154610569e-09,
171      1.1298901814e-09,
172      1.1450695947e-09,
173      1.1611052120e-09,
174      1.1781275955e-09,
175      1.1962995039e-09,
176      1.2158286600e-09,
177      1.2369856250e-09,
178      1.2601323318e-09,
179      1.2857697129e-09,
180      1.3146201905e-09,
181      1.3477839955e-09,
182      1.3870635751e-09,
183      1.4357403044e-09,
184      1.5008658760e-09,
185      1.6030947680e-09
186    };
187    private static readonly long[] k = new long[] {
188      1991057938,
189      0,
190      1611602771,
191      1826899878,
192      1918584482,
193      1969227037,
194      2001281515,
195      2023368125,
196      2039498179,
197      2051788381,
198      2061460127,
199      2069267110,
200      2075699398,
201      2081089314,
202      2085670119,
203      2089610331,
204      2093034710,
205      2096037586,
206      2098691595,
207      2101053571,
208      2103168620,
209      2105072996,
210      2106796166,
211      2108362327,
212      2109791536,
213      2111100552,
214      2112303493,
215      2113412330,
216      2114437283,
217      2115387130,
218      2116269447,
219      2117090813,
220      2117856962,
221      2118572919,
222      2119243101,
223      2119871411,
224      2120461303,
225      2121015852,
226      2121537798,
227      2122029592,
228      2122493434,
229      2122931299,
230      2123344971,
231      2123736059,
232      2124106020,
233      2124456175,
234      2124787725,
235      2125101763,
236      2125399283,
237      2125681194,
238      2125948325,
239      2126201433,
240      2126441213,
241      2126668298,
242      2126883268,
243      2127086657,
244      2127278949,
245      2127460589,
246      2127631985,
247      2127793506,
248      2127945490,
249      2128088244,
250      2128222044,
251      2128347141,
252      2128463758,
253      2128572095,
254      2128672327,
255      2128764606,
256      2128849065,
257      2128925811,
258      2128994934,
259      2129056501,
260      2129110560,
261      2129157136,
262      2129196237,
263      2129227847,
264      2129251929,
265      2129268426,
266      2129277255,
267      2129278312,
268      2129271467,
269      2129256561,
270      2129233410,
271      2129201800,
272      2129161480,
273      2129112170,
274      2129053545,
275      2128985244,
276      2128906855,
277      2128817916,
278      2128717911,
279      2128606255,
280      2128482298,
281      2128345305,
282      2128194452,
283      2128028813,
284      2127847342,
285      2127648860,
286      2127432031,
287      2127195339,
288      2126937058,
289      2126655214,
290      2126347546,
291      2126011445,
292      2125643893,
293      2125241376,
294      2124799783,
295      2124314271,
296      2123779094,
297      2123187386,
298      2122530867,
299      2121799464,
300      2120980787,
301      2120059418,
302      2119015917,
303      2117825402,
304      2116455471,
305      2114863093,
306      2112989789,
307      2110753906,
308      2108037662,
309      2104664315,
310      2100355223,
311      2094642347,
312      2086670106,
313      2074676188,
314      2054300022,
315      2010539237
316   };
317    private static readonly double[] f = new double[] {
318      1.0000000000e+00,
319      9.6359968185e-01,
320      9.3628269434e-01,
321      9.1304361820e-01,
322      8.9228165150e-01,
323      8.7324303389e-01,
324      8.5550057888e-01,
325      8.3878362179e-01,
326      8.2290720940e-01,
327      8.0773830414e-01,
328      7.9317700863e-01,
329      7.7914607525e-01,
330      7.6558417082e-01,
331      7.5244158506e-01,
332      7.3967725039e-01,
333      7.2725689411e-01,
334      7.1515148878e-01,
335      7.0333611965e-01,
336      6.9178915024e-01,
337      6.8049186468e-01,
338      6.6942769289e-01,
339      6.5858197212e-01,
340      6.4794182777e-01,
341      6.3749545813e-01,
342      6.2723249197e-01,
343      6.1714339256e-01,
344      6.0721951723e-01,
345      5.9745317698e-01,
346      5.8783704042e-01,
347      5.7836467028e-01,
348      5.6902998686e-01,
349      5.5982738733e-01,
350      5.5075180531e-01,
351      5.4179835320e-01,
352      5.3296267986e-01,
353      5.2424055338e-01,
354      5.1562821865e-01,
355      5.0712203979e-01,
356      4.9871864915e-01,
357      4.9041482806e-01,
358      4.8220765591e-01,
359      4.7409430146e-01,
360      4.6607214212e-01,
361      4.5813870430e-01,
362      4.5029163361e-01,
363      4.4252872467e-01,
364      4.3484783173e-01,
365      4.2724698782e-01,
366      4.1972434521e-01,
367      4.1227802634e-01,
368      4.0490642190e-01,
369      3.9760786295e-01,
370      3.9038079977e-01,
371      3.8322380185e-01,
372      3.7613546848e-01,
373      3.6911445856e-01,
374      3.6215949059e-01,
375      3.5526937246e-01,
376      3.4844297171e-01,
377      3.4167915583e-01,
378      3.3497685194e-01,
379      3.2833510637e-01,
380      3.2175290585e-01,
381      3.1522938609e-01,
382      3.0876362324e-01,
383      3.0235484242e-01,
384      2.9600214958e-01,
385      2.8970485926e-01,
386      2.8346219659e-01,
387      2.7727350593e-01,
388      2.7113807201e-01,
389      2.6505529881e-01,
390      2.5902456045e-01,
391      2.5304529071e-01,
392      2.4711695313e-01,
393      2.4123899639e-01,
394      2.3541094363e-01,
395      2.2963231802e-01,
396      2.2390270233e-01,
397      2.1822164953e-01,
398      2.1258877218e-01,
399      2.0700371265e-01,
400      2.0146611333e-01,
401      1.9597564638e-01,
402      1.9053204358e-01,
403      1.8513499200e-01,
404      1.7978426814e-01,
405      1.7447963357e-01,
406      1.6922089458e-01,
407      1.6400785744e-01,
408      1.5884037316e-01,
409      1.5371830761e-01,
410      1.4864157140e-01,
411      1.4361007512e-01,
412      1.3862377405e-01,
413      1.3368265331e-01,
414      1.2878671288e-01,
415      1.2393598258e-01,
416      1.1913054436e-01,
417      1.1437050998e-01,
418      1.0965602100e-01,
419      1.0498725623e-01,
420      1.0036443919e-01,
421      9.5787845552e-02,
422      9.1257803142e-02,
423      8.6774669588e-02,
424      8.2338899374e-02,
425      7.7950984240e-02,
426      7.3611505330e-02,
427      6.9321118295e-02,
428      6.5080583096e-02,
429      6.0890771449e-02,
430      5.6752663106e-02,
431      5.2667401731e-02,
432      4.8636294901e-02,
433      4.4660862535e-02,
434      4.0742866695e-02,
435      3.6884389818e-02,
436      3.3087886870e-02,
437      2.9356317595e-02,
438      2.5693291798e-02,
439      2.2103304043e-02,
440      1.8592102453e-02,
441      1.5167297795e-02,
442      1.1839478277e-02,
443      8.6244847625e-03,
444      5.5489949882e-03,
445      2.6696291752e-03
446    };
447
448    /// <summary>
449    /// Initializes a new instance of <see cref="NormalDistributedRandom"/> with µ = 0 and sigma = 1
450    /// and a new random number generator.
451    /// </summary>
452    public NormalDistributedRandom() {
453      this.mu = 0.0;
454      this.sigma = 1.0;
455      this.uniform = new MersenneTwister();
456    }
457
458    /// <summary>
459    /// Initializes a new instance of <see cref="NormalDistributedRandom"/> with the given parameters.
460    /// <note type="caution"> No CopyConstructor! The random number generator is not copied!</note>
461    /// </summary>   
462    /// <param name="uniformRandom">The random number generator.</param>
463    /// <param name="mu">The value for µ.</param>
464    /// <param name="sigma">The value for sigma.</param>
465    public NormalDistributedRandom(IRandom uniformRandom, double mu, double sigma) {
466      this.mu = mu;
467      this.sigma = sigma;
468      this.uniform = uniformRandom;
469    }
470
471    #region IRandom Members
472
473    /// <inheritdoc cref="IRandom.Reset()"/>
474    public void Reset() {
475      uniform.Reset();
476    }
477
478    /// <inheritdoc cref="IRandom.Reset(int)"/>
479    public void Reset(int seed) {
480      uniform.Reset(seed);
481    }
482
483    /// <summary>
484    /// TODO: The method is not implemented.
485    /// </summary>
486    /// <returns>TODO</returns>
487    public int Next() {
488      throw new Exception("The method or operation is not implemented.");
489    }
490
491    /// <summary>
492    /// TODO: The method is not implemented.
493    /// </summary>
494    /// <param name="maxVal">TODO</param>
495    /// <returns>TODO</returns>
496    public int Next(int maxVal) {
497      throw new Exception("The method or operation is not implemented.");
498    }
499
500    /// <summary>
501    /// TODO: The method is not implemented.
502    /// </summary>
503    /// <param name="minVal">TODO</param>
504    /// <param name="maxVal">TODO</param>
505    /// <returns>TODO</returns>
506    public int Next(int minVal, int maxVal) {
507      throw new Exception("The method or operation is not implemented.");
508    }
509
510    /// <summary>
511    /// Generates a new double random number.
512    /// </summary>
513    /// <returns>A double random number.</returns>
514    public double NextDouble() {
515      double signFactor = uniform.Next()%2==0?1.0:-1.0;
516      return sigma* signFactor * NextPositiveDouble() + mu;
517    }
518
519    private double NextPositiveDouble() {
520      int j = uniform.Next();
521      int i = (j & 127);
522      if(Math.Abs(j) < k[i]) {
523        return j * w[i];
524      } else {
525        double r = 3.442620;
526        double x, y;
527        x = j * w[i];
528        if(i == 0) {
529          do {
530            x = -Math.Log(ScaledUniform()) * 0.2904764;
531            y = -Math.Log(ScaledUniform());
532          } while(y + y < x * x);
533          return (j > 0) ? r + x : -r - x;
534        }
535        if(f[i] + ScaledUniform() * (f[i - 1] - f[i]) < Math.Exp(-0.5 * x * x)) {
536          return x;
537        } else {
538          // recurse
539          return (NextPositiveDouble());
540        }
541      }
542    }
543
544    private double ScaledUniform() {
545      return 0.5 + uniform.Next() * 0.2328306e-9;
546    }
547
548
549    #endregion
550
551    #region persistence
552    /// <summary>
553    /// Saves the current instance as <see cref="XmlNode"/> in the specified <paramref name="document"/>.
554    /// </summary>
555    /// <remarks>The value of µ and sigma are saved as child nodes with tag names <c>Mu</c> and <c>Sigma</c>,
556    /// also the random number generator is saved as a child node with tag name <c>UniformRandom</c>.</remarks>
557    /// <param name="name">The (tag)name of the <see cref="XmlNode"/>.</param>
558    /// <param name="document">The <see cref="XmlDocument"/> where the data is saved.</param>
559    /// <param name="persistedObjects">A dictionary of all already persisted objects. (Needed to avoid cycles.)</param>
560    /// <returns>The saved <see cref="XmlNode"/>.</returns>
561    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
562      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
563
564      XmlNode muNode = document.CreateNode(XmlNodeType.Element, "Mu", null);
565      muNode.InnerText = mu.ToString("r", CultureInfo.InvariantCulture);
566      node.AppendChild(muNode);
567
568      XmlNode sigmaNode = document.CreateNode(XmlNodeType.Element, "Sigma", null);
569      sigmaNode.InnerText = sigma.ToString("r", CultureInfo.InvariantCulture);
570      node.AppendChild(sigmaNode);
571
572      node.AppendChild(PersistenceManager.Persist("UniformRandom", uniform, document, persistedObjects));
573
574      return node;
575    }
576
577    /// <summary>
578    /// Loads the persisted normally distributed random variable from the specified <paramref name="node"/>.
579    /// </summary>
580    /// <remarks>The elements of the current instance must be saved in a special way, see
581    /// <see cref="GetXmlNode"/>.</remarks>
582    /// <param name="node">The <see cref="XmlNode"/> where the instance is saved.</param>
583    /// <param name="restoredObjects">The dictionary of all already restored objects. (Needed to avoid cycles.)</param>
584    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
585      base.Populate(node, restoredObjects);
586
587      mu = double.Parse(node.SelectSingleNode("Mu").InnerText, CultureInfo.InvariantCulture);
588      sigma = double.Parse(node.SelectSingleNode("Sigma").InnerText, CultureInfo.InvariantCulture);
589      uniform = (IRandom)PersistenceManager.Restore(node.SelectSingleNode("UniformRandom"), restoredObjects);
590    }
591
592    /// <summary>
593    /// Clones the current instance (deep clone).
594    /// </summary>
595    /// <remarks>Deep clone through <see cref="Auxiliary.Clone"/> method of helper class
596    /// <see cref="Auxiliary"/>.</remarks>
597    /// <param name="clonedObjects">Dictionary of all already cloned objects. (Needed to avoid cycles.)</param>
598    /// <returns>The cloned object as <see cref="NormalDistributedRandom"/>.</returns>
599    public override object Clone(IDictionary<Guid, object> clonedObjects) {
600      NormalDistributedRandom clone = new NormalDistributedRandom((IRandom)Auxiliary.Clone(uniform, clonedObjects), mu, sigma);
601      clonedObjects.Add(Guid, clone);
602      return clone;
603    }
604
605    #endregion
606  }
607}
Note: See TracBrowser for help on using the repository browser.