Changeset 7432 for branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common/3.3
- Timestamp:
- 01/31/12 15:17:16 (12 years ago)
- Location:
- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common/3.3
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common/3.3/ExtensionMethods.cs
r7415 r7432 28 28 public static class ExtensionMethods { 29 29 30 /// <summary> 31 /// Selects an element from an enumerable randomly with equal probability for each element. If the sequence is empty, selected will be false and default(T) will be returned. 32 /// </summary> 33 /// <typeparam name="T">The type of the items that are to be selected.</typeparam> 34 /// <param name="source">The enumerable that contains the items.</param> 35 /// <param name="random">The random number generator, its NextDouble() method must return a value in the range [0;1).</param> 36 /// <param name="selected">True if an element was selected, false otherwise (only because of an empty sequence).</param> 37 /// <returns>The selected item.</returns> 38 public static T ChooseRandomOrDefault<T>(this IEnumerable<T> source, IRandom random, out bool selected) { 39 if (source == null) throw new ArgumentNullException("SelectRandomOrDefault: source is null"); 40 uint counter = 1; 41 selected = false; 42 T selectedItem = default(T); 43 foreach (T item in source) { 44 if (counter * random.NextDouble() < 1.0) { // use multiplication instead of division 45 selectedItem = item; 46 selected = true; 47 } 48 counter++; 49 } 50 return selectedItem; 51 } 52 53 /// <summary> 54 /// Selects an element from an enumerable randomly with equal probability for each element. 55 /// </summary> 56 /// <typeparam name="T">The type of the items that are to be selected.</typeparam> 57 /// <param name="source">The enumerable that contains the items.</param> 58 /// <param name="random">The random number generator, its NextDouble() method must return a value in the range [0;1).</param> 59 /// <returns>The selected item.</returns> 60 public static T ChooseRandom<T>(this IEnumerable<T> source, IRandom random) { 61 if (source == null) throw new ArgumentNullException("SelectRandom: source is null"); 62 if (!source.Any()) throw new ArgumentException("SelectRandom: sequence is empty."); 63 uint counter = 1; 64 T selectedItem = default(T); 65 foreach (T item in source) { 66 if (counter * random.NextDouble() < 1.0) // use multiplication instead of division 67 selectedItem = item; 68 counter++; 69 } 70 return selectedItem; 71 } 72 73 /// <summary> 74 /// Shuffles an enumerable and returns an new enumerable according to the Fisher-Yates shuffle. 75 /// </summary> 76 /// <remarks> 77 /// Source code taken from http://stackoverflow.com/questions/1287567/c-is-using-random-and-orderby-a-good-shuffle-algorithm. 78 /// Note that this is an online shuffle, but the source enumerable is transformed into an array. 79 /// </remarks> 80 /// <typeparam name="T">The type of the items that are to be shuffled.</typeparam> 81 /// <param name="source">The enumerable that contains the items.</param> 82 /// <param name="random">The random number generator, its Next(int) method must deliver uniformly distributed random numbers.</param> 83 /// <returns>An enumerable with the elements shuffled.</returns> 84 public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, IRandom random) { 85 T[] elements = source.ToArray(); 86 // Note i > 0 to avoid final pointless iteration 87 for (int i = elements.Length - 1; i > 0; i--) { 88 // Swap element "i" with a random earlier element it (or itself) 89 int swapIndex = random.Next(i + 1); 90 yield return elements[swapIndex]; 91 elements[swapIndex] = elements[i]; 92 // we don't actually perform the swap, we can forget about the 93 // swapped element because we already returned it. 94 } 95 96 // there is one item remaining that was not returned - we return it now 97 yield return elements[0]; 98 } 30 #region Choosing from a sequence 31 /// <summary> 32 /// Chooses one elements from a sequence under equal chances for each element. 33 /// </summary> 34 /// <remarks> 35 /// Runtime complexity is O(1) for sequences that are <see cref="IList{T}"/> and 36 /// O(N) for all other. 37 /// </remarks> 38 /// <typeparam name="T">The type of the items to be selected.</typeparam> 39 /// <param name="source">The sequence of elements.</param> 40 /// <param name="random">The random number generator to use, its NextDouble() method must produce values in the range [0;1)</param> 41 /// <param name="count">The number of items to be selected.</param> 42 /// <returns>A sequence of elements that have been chosen randomly.</returns> 43 public static T ChooseUniformRandom<T>(this IEnumerable<T> source, IRandom random) { 44 return source.ChooseUniformRandom(random, 1).First(); 45 } 46 /// <summary> 47 /// Chooses <paramref name="count"/> elements from a sequence with repetition under equal chances for each element. 48 /// </summary> 49 /// <remarks> 50 /// Runtime complexity is O(count) for sequences that are <see cref="IList{T}"/> and 51 /// O(N * count) for all other. 52 /// 53 /// The method is online. 54 /// </remarks> 55 /// <typeparam name="T">The type of the items to be selected.</typeparam> 56 /// <param name="source">The sequence of elements.</param> 57 /// <param name="random">The random number generator to use, its NextDouble() method must produce values in the range [0;1)</param> 58 /// <param name="count">The number of items to be selected.</param> 59 /// <returns>A sequence of elements that have been chosen randomly.</returns> 60 public static IEnumerable<T> ChooseUniformRandom<T>(this IEnumerable<T> source, IRandom random, int count) { 61 if (source == null) throw new ArgumentNullException("source", "sequence is null"); 62 if (!source.Any()) throw new ArgumentException("sequence is empty.", "source"); 63 64 var listSource = source as IList<T>; 65 if (listSource != null) 66 while (count > 0) { 67 yield return listSource[random.Next(listSource.Count)]; 68 count--; 69 } 70 71 while (count > 0) { 72 var enumerator = source.GetEnumerator(); 73 enumerator.MoveNext(); 74 T selectedItem = enumerator.Current; 75 int counter = 1; 76 while (enumerator.MoveNext()) { 77 counter++; 78 if (counter * random.NextDouble() < 1.0) 79 selectedItem = enumerator.Current; 80 } 81 yield return selectedItem; 82 count--; 83 } 84 } 85 /// <summary> 86 /// Chooses <paramref name="count"/> elements from a sequence without repetition under equal chances for each element. 87 /// </summary> 88 /// <remarks> 89 /// Runtime complexity is O(count) for sequences that are <see cref="IList{T}"/> and 90 /// O(N * count) for all other. 91 /// 92 /// The method is online, but the source enumerable is transformed into an array. 93 /// </remarks> 94 /// <typeparam name="T">The type of the items to be selected.</typeparam> 95 /// <param name="source">The sequence of elements.</param> 96 /// <param name="random">The random number generator to use, its NextDouble() method must produce values in the range [0;1)</param> 97 /// <param name="count">The number of items to be selected.</param> 98 /// <returns>A sequence of elements that have been chosen randomly.</returns> 99 public static IEnumerable<T> ChooseUniformRandomWithoutRepetition<T>(this IEnumerable<T> source, IRandom random, int count) { 100 return source.Shuffle(random).Take(count); 101 } 102 103 /// <summary> 104 /// Chooses items out of a sequence with repetition. The chance that an item is selected is proportional or inverse-proportional 105 /// to the value obtained from <paramref name="valueSelector"/>. 106 /// </summary> 107 /// <remarks> 108 /// In case both <paramref name="maximization"/> and <paramref name="windowing"/> are false values must be > 0, 109 /// otherwise an InvalidOperationException is thrown. 110 /// 111 /// The method is online, but internally holds two arrays: One that is the sequence itself and another one for the values. The <paramref name="valueSelector"/> 112 /// is only applied once for each item. 113 /// </remarks> 114 /// <typeparam name="T">The type of the items to be selected.</typeparam> 115 /// <param name="source">The sequence of elements.</param> 116 /// <param name="random">The random number generator to use, its NextDouble() method must produce values in the range [0;1)</param> 117 /// <param name="count">The number of items to be selected.</param> 118 /// <param name="valueSelector">The function that calculates a proportional value for each item.</param> 119 /// <param name="windowing">Whether to scale the proportional values or not.</param> 120 /// <param name="maximization">Determines whether to choose proportionally (true) or inverse-proportionally (false).</param> 121 /// <returns>A sequence of selected items. The sequence might contain the same item more than once.</returns> 122 public static IEnumerable<T> ChooseProportionalRandom<T>(this IEnumerable<T> source, IRandom random, int count, Func<T, double> valueSelector, bool windowing, bool maximization) { 123 return source.ChooseProportionalRandom(random, valueSelector, windowing, maximization).Take(count); 124 } 125 /// <summary> 126 /// Same as <seealso cref="ChooseProportionalRandom<T>"/>, but selects each item exactly once. 127 /// </summary> 128 /// <remarks> 129 /// In case both <paramref name="maximization"/> and <paramref name="windowing"/> are false values must be > 0, 130 /// otherwise an InvalidOperationException is thrown. 131 /// 132 /// The method is online, but internally holds two arrays: One that is the sequence itself and another one for the values. The <paramref name="valueSelector"/> 133 /// is only applied once for each item. 134 /// </remarks> 135 /// <typeparam name="T">The type of the items to be selected.</typeparam> 136 /// <param name="source">The sequence of elements.</param> 137 /// <param name="random">The random number generator to use, its NextDouble() method must produce values in the range [0;1)</param> 138 /// <param name="count">The number of items to be selected.</param> 139 /// <param name="valueSelector">The function that calculates a proportional value for each item.</param> 140 /// <param name="windowing">Whether to scale the proportional values or not.</param> 141 /// <param name="maximization">Determines whether to choose proportionally (true) or inverse-proportionally (false).</param> 142 /// <returns>A sequence of selected items.</returns> 143 public static IEnumerable<T> ChooseProportionalRandomWithoutRepetition<T>(this IEnumerable<T> source, IRandom random, int count, Func<T, double> valueSelector, bool windowing, bool maximization) { 144 return source.ChooseProportionalRandomWithoutRepetition(random, valueSelector, windowing, maximization).Take(count); 145 } 146 #region Proportional Helpers 147 private static IEnumerable<T> ChooseProportionalRandom<T>(this IEnumerable<T> source, IRandom random, Func<T, double> valueSelector, bool windowing, bool maximization) { 148 if (source == null) throw new ArgumentNullException("source", "sequence is null"); 149 if (!source.Any()) throw new ArgumentException("sequence is empty.", "source"); 150 151 var sourceArray = source.ToArray(); 152 var valueArray = PrepareProportional<T>(sourceArray, valueSelector, windowing, maximization); 153 double total = valueArray.Sum(); 154 155 while (true) { 156 int index = 0; 157 double ball = valueArray[index], sum = random.NextDouble() * total; 158 while (ball < sum) 159 ball += valueArray[++index]; 160 yield return sourceArray[index]; 161 } 162 } 163 private static IEnumerable<T> ChooseProportionalRandomWithoutRepetition<T>(this IEnumerable<T> source, IRandom random, Func<T, double> valueSelector, bool windowing, bool maximization) { 164 if (source == null) throw new ArgumentNullException("source", "sequence is null"); 165 if (!source.Any()) throw new ArgumentException("sequence is empty.", "source"); 166 167 var sourceArray = source.ToArray(); 168 var valueArray = PrepareProportional<T>(sourceArray, valueSelector, windowing, maximization); 169 double total = valueArray.Sum(); 170 171 HashSet<int> chosenIndices = new HashSet<int>(); 172 while (chosenIndices.Count < sourceArray.Length) { 173 int index = 0; 174 double ball = valueArray[index], sum = random.NextDouble() * total; 175 while (ball < sum) { 176 index++; 177 if (!chosenIndices.Contains(index)) 178 ball += valueArray[++index]; 179 } 180 yield return sourceArray[index]; 181 chosenIndices.Add(index); 182 total -= valueArray[index]; 183 } 184 } 185 private static double[] PrepareProportional<T>(IList<T> sourceArray, Func<T, double> valueSelector, bool windowing, bool maximization) { 186 double maxValue = double.MinValue, minValue = double.MaxValue; 187 double[] valueArray = new double[sourceArray.Count]; 188 189 for (int i = 0; i < sourceArray.Count; i++) { 190 valueArray[i] = valueSelector(sourceArray[i]); 191 if (valueArray[i] > maxValue) maxValue = valueArray[i]; 192 if (valueArray[i] < minValue) minValue = valueArray[i]; 193 } 194 if (minValue == maxValue) { // all values are equal 195 for (int i = 0; i < sourceArray.Count; i++) { 196 valueArray[i] = 1.0; 197 } 198 } else { 199 if (windowing) { 200 if (maximization) ProportionalScale(valueArray, minValue); 201 else InverseProportionalScale(valueArray, maxValue); 202 } else { 203 if (minValue < 0.0) throw new InvalidOperationException("Proportional selection without windowing does not work with values < 0."); 204 if (!maximization) InverseProportionalScale(valueArray, 2 * maxValue); 205 } 206 } 207 return valueArray; 208 } 209 private static void ProportionalScale(double[] values, double minValue) { 210 for (int i = 0; i < values.Length; i++) { 211 values[i] = values[i] - minValue; 212 } 213 } 214 private static void InverseProportionalScale(double[] values, double maxValue) { 215 for (int i = 0; i < values.Length; i++) { 216 values[i] = maxValue - values[i]; 217 } 218 } 219 #endregion 99 220 100 221 /// <summary> … … 109 230 /// <param name="keySelector">The function that selects the key.</param> 110 231 /// <returns>The element in the enumeration where the selected key is the maximum.</returns> 111 public static T SelectMax<T, TComparable>(this IEnumerable<T> source, Func<T, TComparable> keySelector) where TComparable : IComparable { 232 public static T ChooseMax<T, TComparable>(this IEnumerable<T> source, Func<T, TComparable> keySelector) where TComparable : IComparable { 233 if (source == null) throw new ArgumentNullException("source", "sequence is null"); 112 234 IEnumerator<T> enumerator = source.GetEnumerator(); 113 if (!enumerator.MoveNext()) throw new InvalidOperationException("Sequence is empty!");235 if (!enumerator.MoveNext()) throw new ArgumentException("sequence is empty", "source"); 114 236 T result = enumerator.Current; 115 237 TComparable max = keySelector(result); … … 136 258 /// <param name="keySelector">The function that selects the key.</param> 137 259 /// <returns>The element in the enumeration where the selected key is the minimum.</returns> 138 public static T SelectMin<T, TComparable>(this IEnumerable<T> source, Func<T, TComparable> keySelector) where TComparable : IComparable { 260 public static T ChooseMin<T, TComparable>(this IEnumerable<T> source, Func<T, TComparable> keySelector) where TComparable : IComparable { 261 if (source == null) throw new ArgumentNullException("source", "sequence is null"); 139 262 IEnumerator<T> enumerator = source.GetEnumerator(); 140 if (!enumerator.MoveNext()) throw new InvalidOperationException("Sequence is empty!");263 if (!enumerator.MoveNext()) throw new ArgumentException("sequence is empty", "source"); 141 264 T result = enumerator.Current; 142 265 TComparable min = keySelector(result); … … 151 274 return result; 152 275 } 153 276 #endregion 277 278 #region Shuffling 279 /// <summary> 280 /// Shuffles an enumerable and returns a new enumerable according to the Fisher-Yates shuffle. 281 /// </summary> 282 /// <remarks> 283 /// Note that this is an online shuffle, but the source enumerable is transformed into an array. 284 /// 285 /// The implementation is described in http://stackoverflow.com/questions/1287567/c-is-using-random-and-orderby-a-good-shuffle-algorithm. 286 /// </remarks> 287 /// <typeparam name="T">The type of the items that are to be shuffled.</typeparam> 288 /// <param name="source">The enumerable that contains the items.</param> 289 /// <param name="random">The random number generator, its Next(n) method must deliver uniformly distributed random numbers in the range [0;n).</param> 290 /// <returns>An enumerable with the elements shuffled.</returns> 291 public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, IRandom random) { 292 T[] elements = source.ToArray(); 293 for (int i = elements.Length - 1; i > 0; i--) { 294 // Swap element "i" with a random earlier element it (or itself) 295 int swapIndex = random.Next(i + 1); 296 yield return elements[swapIndex]; 297 elements[swapIndex] = elements[i]; 298 // we don't actually perform the swap, we can forget about the 299 // swapped element because we already returned it. 300 } 301 yield return elements[0]; 302 } 303 #endregion 304 305 #region Graph walk 154 306 /// <summary> 155 307 /// Walks an operator graph in that it jumps from one operator to all its operator parameters and yields each operator it touches. … … 178 330 } 179 331 } 180 332 #endregion 181 333 } 182 334 } -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common/3.3/IntegerVectorEqualityComparer.cs
r7412 r7432 38 38 return obj.GetHashCode(); 39 39 } 40 41 public static double GetSimilarity(IntegerVector a, IntegerVector b) { 42 int similar = 0; 43 for (int i = 0; i < a.Length; i++) { 44 if (a[i] == b[i]) similar++; 45 } 46 return similar / (double)a.Length; 47 } 48 49 public static double GetDistance(IntegerVector a, IntegerVector b) { 50 return 1.0 - GetSimilarity(a, b); 51 } 52 53 public static IEnumerable<int> GetDifferingIndices(IntegerVector a, IntegerVector b) { 54 for (int i = 0; i < a.Length; i++) 55 if (a[i] != b[i]) yield return i; 56 } 40 57 } 41 58 }
Note: See TracChangeset
for help on using the changeset viewer.