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 between start and end (inclusive!).


34  /// </summary>


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


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


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


38  /// <returns>An sequence of values from start to end (inclusive)</returns>


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


40  if (stepWidth.IsAlmost(0))


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


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


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


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


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


46  double x = start;


47  // x<=end could skip the last value because of numerical problems


48  while (x < end  x.IsAlmost(end)) {


49  yield return x;


50  x += stepWidth;


51  }


52  }


53 


54  /// <summary>


55  /// Generate a logarithmic sequence between start and end by applying a powerof10 function to an underlying evenly spaced sequence


56  /// </summary>


57  /// <param name="start">The start of the sequence</param>


58  /// <param name="end">The end of the sequence</param>


59  /// <param name="stepWidth">The stepwidth for the original sequence before the points are transformed</param>


60  /// <returns>A logarithmic sequence from start to end (inclusive)</returns>


61  public static IEnumerable<double> GenerateLogarithmicSteps(double start, double end, double stepWidth) {


62  return GenerateSteps(start, end, stepWidth, x => Math.Pow(10, x));


63  }


64 


65  /// <summary>


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


67  /// </summary>


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


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


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


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


72  /// <returns></returns>


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


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


75  }


76 


77  /// <summary>


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


79  /// </summary>


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


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


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


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


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


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


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


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


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


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


90  }


91  }


92 


93  /// <summary>


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


95  /// </summary>


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


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


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


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


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


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


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


103  }


104 


105  // iterative approach


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


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


108  if (lists.Count < 1) {


109  return allCombinations;


110  }


111 


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


113  foreach (var list in lists) {


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


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


116  }


117 


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


119 


120  while (!finished) {


121  GetCurrentCombination(enumerators, allCombinations);


122  finished = MoveNext(enumerators, lists);


123  }


124  return allCombinations;


125  }


126 


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


128  int cur = enumerators.Count  1;


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


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


131  enumerators[cur].MoveNext();


132  cur;


133  }


134  return cur < 0;


135  }


136 


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


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


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


140  }


141  }


142  }


143  }

