source: trunk/sources/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/ValueGenerator.cs @ 11435

Last change on this file since 11435 was 11435, checked in by mkommend, 8 years ago

#2259: Added includeEnd paramter to ValueGenerator.GenerateSteps and removed overloads that take a Func for value transformation.

File size: 6.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 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.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Random;
27
28namespace HeuristicLab.Problems.Instances.DataAnalysis {
29  public static class ValueGenerator {
30    private static FastRandom rand = new FastRandom();
31
32    /// <summary>
33    /// Generates a sequence of evenly spaced points by returning the start value and adding the stepwidth until the end is reached or surpassed.
34    ///
35    /// </summary>
36    /// <param name="start">The smallest and first value of the sequence.</param>
37    /// <param name="end">The largest and last value of the sequence.</param>
38    /// <param name="stepWidth">The step size between subsequent values.</param>
39    /// <param name="includeEnd">Determines if the end should be included in the sequence regardless if the end is divisible by the stepwidth.</param>
40    /// <returns>A sequence of values from start to end (inclusive)</returns>
41    [Obsolete("It is recommended to use the decimal overload to achieve a higher numerical accuracy.")]
42    public static IEnumerable<double> GenerateSteps(double start, double end, double stepWidth, bool includeEnd = false) {
43      //mkommend: IEnumerable.Cast fails due to boxing and unboxing of the involved types
44      // http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs#27bb217a6d5457ec
45      // http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx     
46
47      return GenerateSteps((decimal)start, (decimal)end, (decimal)stepWidth, includeEnd).Select(x => (double)x);
48    }
49
50    /// <summary>
51    /// Generates a sequence of evenly spaced points by returning the start value and adding the stepwidth until the end is reached or surpassed.
52    /// </summary>
53    /// <param name="start">The smallest and first value of the sequence.</param>
54    /// <param name="end">The largest and last value of the sequence.</param>
55    /// <param name="stepWidth">The step size between subsequent values.</param>
56    /// /// <param name="includeEnd">Determines if the end should be included in the sequence regardless if the end is divisible by the stepwidth.</param>
57    /// <returns>A sequence of values from start to end</returns>
58    public static IEnumerable<decimal> GenerateSteps(decimal start, decimal end, decimal stepWidth, bool includeEnd = false) {
59      if (stepWidth == 0)
60        throw new ArgumentException("The step width cannot be zero.");
61      if (start < end && stepWidth < 0)
62        throw new ArgumentException("The step width must be larger than zero for increasing sequences (start < end).");
63      if (start > end && stepWidth > 0)
64        throw new ArgumentException("The step width must be smaller than zero for decreasing sequences (start > end).");
65
66      decimal x = start;
67      while (x <= end) {
68        yield return x;
69        x += stepWidth;
70      }
71      if (x - stepWidth < end && includeEnd) yield return end;
72    }
73
74    /// <summary>
75    /// Generates uniformly distributed values between start and end (inclusive!)
76    /// </summary>
77    /// <param name="n">Number of values to generate.</param>
78    /// <param name="start">The lower value (inclusive)</param>
79    /// <param name="end">The upper value (inclusive)</param>
80    /// <returns>An enumerable including n values in [start, end]</returns>
81    public static IEnumerable<double> GenerateUniformDistributedValues(int n, double start, double end) {
82      for (int i = 0; i < n; i++) {
83        // we need to return a random value including end.
84        // so we cannot use rand.NextDouble() as it returns a value strictly smaller than 1.
85        double r = rand.NextUInt() / (double)uint.MaxValue;    // r \in [0,1]
86        yield return r * (end - start) + start;
87      }
88    }
89
90    /// <summary>
91    /// Generates normally distributed values sampling from N(mu, sigma)
92    /// </summary>
93    /// <param name="n">Number of values to generate.</param>
94    /// <param name="mu">The mu parameter of the normal distribution</param>
95    /// <param name="sigma">The sigma parameter of the normal distribution</param>
96    /// <returns>An enumerable including n values ~ N(mu, sigma)</returns>
97    public static IEnumerable<double> GenerateNormalDistributedValues(int n, double mu, double sigma) {
98      for (int i = 0; i < n; i++)
99        yield return NormalDistributedRandom.NextDouble(rand, mu, sigma);
100    }
101
102    // iterative approach
103    public static IEnumerable<IEnumerable<double>> GenerateAllCombinationsOfValuesInLists(List<List<double>> lists) {
104      List<List<double>> allCombinations = new List<List<double>>();
105      if (lists.Count < 1) {
106        return allCombinations;
107      }
108
109      List<IEnumerator<double>> enumerators = new List<IEnumerator<double>>();
110      foreach (var list in lists) {
111        allCombinations.Add(new List<double>());
112        enumerators.Add(list.GetEnumerator());
113      }
114
115      bool finished = !enumerators.All(x => x.MoveNext());
116
117      while (!finished) {
118        GetCurrentCombination(enumerators, allCombinations);
119        finished = MoveNext(enumerators, lists);
120      }
121      return allCombinations;
122    }
123
124    private static bool MoveNext(List<IEnumerator<double>> enumerators, List<List<double>> lists) {
125      int cur = enumerators.Count - 1;
126      while (cur >= 0 && !enumerators[cur].MoveNext()) {
127        enumerators[cur] = lists[cur].GetEnumerator();
128        enumerators[cur].MoveNext();
129        cur--;
130      }
131      return cur < 0;
132    }
133
134    private static void GetCurrentCombination(List<IEnumerator<double>> enumerators, List<List<double>> allCombinations) {
135      for (int i = 0; i < enumerators.Count(); i++) {
136        allCombinations[i].Add(enumerators[i].Current);
137      }
138    }
139  }
140}
Note: See TracBrowser for help on using the repository browser.