1  #region License Information


2  /* HeuristicLab


3  * Copyright (C) 20022014 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 


22  using System;


23  using System.Collections.Generic;


24  using System.Linq;


25  using HeuristicLab.Common;


26  using HeuristicLab.Random;


27 


28  namespace 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  /// <returns>A sequence of values from start to end (inclusive)</returns>


40  [Obsolete("It is recommended to use the decimal overload to achieve a higher numerical accuracy.")]


41  public static IEnumerable<double> GenerateSteps(double start, double end, double stepWidth) {


42  //mkommend: IEnumerable.Cast fails due to boxing and unboxing of the involved types


43  // http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs#27bb217a6d5457ec


44  // http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representationandidentity.aspx


45 


46  return GenerateSteps((decimal)start, (decimal)end, (decimal)stepWidth).Select(x => (double)x);


47  }


48 


49  /// <summary>


50  /// Generates a sequence of evenly spaced points by returning the start value and adding the stepwidth until the end is reached or surpassed.


51  /// </summary>


52  /// <param name="start">The smallest and first value of the sequence.</param>


53  /// <param name="end">The largest and last value of the sequence.</param>


54  /// <param name="stepWidth">The step size between subsequent values.</param>


55  /// <returns>A sequence of values from start to end</returns>


56  public static IEnumerable<decimal> GenerateSteps(decimal start, decimal end, decimal stepWidth) {


57  if (stepWidth == 0)


58  throw new ArgumentException("The step width cannot be zero.");


59  if (start < end && stepWidth < 0)


60  throw new ArgumentException("The step width must be larger than zero for increasing sequences (start < end).");


61  if (start > end && stepWidth > 0)


62  throw new ArgumentException("The step width must be smaller than zero for decreasing sequences (start > end).");


63 


64  decimal x = start;


65  while (x <= end) {


66  yield return x;


67  x += stepWidth;


68  }


69  }


70 


71  /// <summary>


72  /// Generates a sequence of points between start and end according to given transformation


73  /// </summary>


74  /// <param name="start">The smallest and first value of the sequence.</param>


75  /// <param name="end">The largest and last value of the sequence.</param>


76  /// <param name="stepWidth">The step size between subsequent values (before transform)</param>


77  /// <param name="transform">The transform function</param>


78  /// <returns></returns>


79  [Obsolete("It is recommended to use the decimal overload to achieve a higher numerical accuracy.")]


80  public static IEnumerable<double> GenerateSteps(double start, double end, double stepWidth, Func<double, double> transform) {


81  return GenerateSteps(start,end, stepWidth).Select(transform);


82  }


83 


84  /// <summary>


85  /// Generates a sequence of points between start and end according to given transformation


86  /// </summary>


87  /// <param name="start">The smallest and first value of the sequence.</param>


88  /// <param name="end">The largest and last value of the sequence.</param>


89  /// <param name="stepWidth">The step size between subsequent values (before transform)</param>


90  /// <param name="transform">The transform function</param>


91  /// <returns></returns>


92  public static IEnumerable<decimal> GenerateSteps(decimal start, decimal end, decimal stepWidth, Func<decimal, decimal> transform) {


93  return GenerateSteps(start, end, stepWidth).Select(transform);


94  }


95 


96  /// <summary>


97  /// Generates uniformly distributed values between start and end (inclusive!)


98  /// </summary>


99  /// <param name="n">Number of values to generate.</param>


100  /// <param name="start">The lower value (inclusive)</param>


101  /// <param name="end">The upper value (inclusive)</param>


102  /// <returns>An enumerable including n values in [start, end]</returns>


103  public static IEnumerable<double> GenerateUniformDistributedValues(int n, double start, double end) {


104  for (int i = 0; i < n; i++) {


105  // we need to return a random value including end.


106  // so we cannot use rand.NextDouble() as it returns a value strictly smaller than 1.


107  double r = rand.NextUInt() / (double)uint.MaxValue; // r \in [0,1]


108  yield return r * (end  start) + start;


109  }


110  }


111 


112  /// <summary>


113  /// Generates normally distributed values sampling from N(mu, sigma)


114  /// </summary>


115  /// <param name="n">Number of values to generate.</param>


116  /// <param name="mu">The mu parameter of the normal distribution</param>


117  /// <param name="sigma">The sigma parameter of the normal distribution</param>


118  /// <returns>An enumerable including n values ~ N(mu, sigma)</returns>


119  public static IEnumerable<double> GenerateNormalDistributedValues(int n, double mu, double sigma) {


120  for (int i = 0; i < n; i++)


121  yield return NormalDistributedRandom.NextDouble(rand, mu, sigma);


122  }


123 


124  // iterative approach


125  public static IEnumerable<IEnumerable<double>> GenerateAllCombinationsOfValuesInLists(List<List<double>> lists) {


126  List<List<double>> allCombinations = new List<List<double>>();


127  if (lists.Count < 1) {


128  return allCombinations;


129  }


130 


131  List<IEnumerator<double>> enumerators = new List<IEnumerator<double>>();


132  foreach (var list in lists) {


133  allCombinations.Add(new List<double>());


134  enumerators.Add(list.GetEnumerator());


135  }


136 


137  bool finished = !enumerators.All(x => x.MoveNext());


138 


139  while (!finished) {


140  GetCurrentCombination(enumerators, allCombinations);


141  finished = MoveNext(enumerators, lists);


142  }


143  return allCombinations;


144  }


145 


146  private static bool MoveNext(List<IEnumerator<double>> enumerators, List<List<double>> lists) {


147  int cur = enumerators.Count  1;


148  while (cur >= 0 && !enumerators[cur].MoveNext()) {


149  enumerators[cur] = lists[cur].GetEnumerator();


150  enumerators[cur].MoveNext();


151  cur;


152  }


153  return cur < 0;


154  }


155 


156  private static void GetCurrentCombination(List<IEnumerator<double>> enumerators, List<List<double>> allCombinations) {


157  for (int i = 0; i < enumerators.Count(); i++) {


158  allCombinations[i].Add(enumerators[i].Current);


159  }


160  }


161  }


162  }

