Changeset 7432 for branches/GeneralizedQAP
- Timestamp:
- 01/31/12 15:17:16 (13 years ago)
- Location:
- branches/GeneralizedQAP
- Files:
-
- 2 deleted
- 12 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 } -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Analyzers/BestGQAPSolutionAnalyzer.cs
r7423 r7432 155 155 int bestIndex; 156 156 var tmp = qualities.Select((x, index) => new { Index = index, Value = x.Value }); 157 if (maximization) bestIndex = tmp. SelectMax(x => x.Value).Index;158 else bestIndex = tmp. SelectMin(x => x.Value).Index;157 if (maximization) bestIndex = tmp.ChooseMax(x => x.Value).Index; 158 else bestIndex = tmp.ChooseMin(x => x.Value).Index; 159 159 160 160 if (bestKnownQuality == null || HasSolutionImproved(bestKnownQuality.Value, qualities[bestIndex].Value, maximization)) { -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignment.cs
r7418 r7432 28 28 29 29 namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment { 30 [Item("Generalized QAP Assignment", "Represents a solution to the generalized QAP.")]30 [Item("Generalized QAP Assignment", "Represents the solution as well as the problem parameters of a GQAP instance.")] 31 31 [StorableClass] 32 32 public sealed class GQAPAssignment : Item, INotifyPropertyChanged { -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GQAPAssignmentArchive.cs
r7418 r7432 145 145 private GQAPAssignmentArchive(GQAPAssignmentArchive original, Cloner cloner) 146 146 : base(original, cloner) { 147 solutions = cloner.Clone(original.solutions); 147 148 equipmentNames = cloner.Clone(original.equipmentNames); 148 149 locationNames = cloner.Clone(original.locationNames); -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/GeneralizedQuadraticAssignmentProblem.cs
r7423 r7432 142 142 private GeneralizedQuadraticAssignmentProblem(GeneralizedQuadraticAssignmentProblem original, Cloner cloner) 143 143 : base(original, cloner) { 144 AttachEventHandlers();144 RegisterEventHandlers(); 145 145 } 146 146 public GeneralizedQuadraticAssignmentProblem() … … 186 186 187 187 InitializeOperators(); 188 AttachEventHandlers();188 RegisterEventHandlers(); 189 189 } 190 190 … … 220 220 [StorableHook(HookType.AfterDeserialization)] 221 221 private void AfterDeserialization() { 222 AttachEventHandlers();223 } 224 225 private void AttachEventHandlers() {222 RegisterEventHandlers(); 223 } 224 225 private void RegisterEventHandlers() { 226 226 Evaluator.QualityParameter.ActualNameChanged += new System.EventHandler(Evaluator_QualityParameter_ActualNameChanged); 227 227 SolutionCreator.AssignmentParameter.ActualNameChanged += new EventHandler(SolutionCreator_IntegerVectorParameter_ActualNameChanged); -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/HeuristicLab.Problems.GeneralizedQuadraticAssignment-3.3.csproj
r7419 r7432 97 97 <Compile Include="GeneralizedQuadraticAssignmentProblem.cs" /> 98 98 <Compile Include="GQAPAssignmentArchive.cs" /> 99 <Compile Include="GQAPIntegerVectorProximityCalculator.cs" />100 99 <Compile Include="GQAPSolution.cs" /> 101 100 <Compile Include="Interfaces\IQualitiesAwareGQAPOperator.cs" /> -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/DemandEquivalentSwapEquipmentManipluator.cs
r7419 r7432 79 79 assignment[equipment2] = location1; 80 80 groupedLocations[location2].Remove(equipment2); 81 bool selected; 82 equipment2 = groupedLocations[location2].ChooseRandomOrDefault(random, out selected); 83 if (!selected) break; 81 if (!groupedLocations[location2].Any()) break; 82 equipment2 = groupedLocations[location2].ChooseUniformRandom(random); 84 83 } 85 84 } -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GQAPPathRelinking.cs
r7425 r7432 73 73 public IValueLookupParameter<DoubleValue> OverbookedCapacityPenaltyParameter { 74 74 get { return (IValueLookupParameter<DoubleValue>)Parameters["OverbookedCapacityPenalty"]; } 75 } 76 77 public IValueParameter<PercentValue> CandidateSizeFactorParameter { 78 get { return (IValueParameter<PercentValue>)Parameters["CandidateSizeFactor"]; } 75 79 } 76 80 … … 92 96 Parameters.Add(new ValueLookupParameter<DoubleValue>("TransportationCosts", GeneralizedQuadraticAssignmentProblem.TransportationCostsDescription)); 93 97 Parameters.Add(new ValueLookupParameter<DoubleValue>("OverbookedCapacityPenalty", GeneralizedQuadraticAssignmentProblem.OverbookedCapacityPenaltyDescription)); 98 Parameters.Add(new ValueParameter<PercentValue>("CandidateSizeFactor", "(η) Determines the size of the set of feasible moves in each path-relinking step relative to the maximum size. A value of 50% means that only half of all possible moves are considered each step.", new PercentValue(0.5))); 94 99 } 95 100 … … 98 103 } 99 104 100 public static IntegerVector Apply(IRandom random, ItemArray<IntegerVector> parents, ItemArray<DoubleValue> qualities, DoubleArray demands, 101 DoubleArray capacities, DoubleMatrix weights, DoubleMatrix distances, DoubleMatrix installationCosts, DoubleValue transportationCosts, 102 DoubleValue overbookedCapacityPenalty) { 105 public static IntegerVector Apply(IRandom random, ItemArray<IntegerVector> parents, BoolValue maximization, ItemArray<DoubleValue> qualities, 106 ItemArray<DoubleValue> flowDistanceQualities, ItemArray<DoubleValue> installationQualities, ItemArray<DoubleValue> overbookedCapacities, 107 DoubleArray demands, DoubleArray capacities, DoubleMatrix weights, DoubleMatrix distances, DoubleMatrix installationCosts, 108 DoubleValue transportationCosts, DoubleValue overbookedCapacityPenalty, DoubleValue candidateSizeFactor) { 103 109 if (random == null) throw new ArgumentNullException("random", "No IRandom provider is given."); 104 110 if (parents == null || !parents.Any()) throw new ArgumentException("No parents given for path relinking.", "parents"); … … 110 116 var source = parents[0]; 111 117 var target = parents[1]; 112 113 var nu = 1.0; 118 IntegerVector result; 119 double resultQuality, resultFDQ, resultIQ, resultOC; 120 121 int betterParent = 1; 122 if ((maximization.Value && qualities[0].Value >= qualities[1].Value) 123 || (!maximization.Value && qualities[0].Value <= qualities[1].Value)) 124 betterParent = 0; 125 126 result = (IntegerVector)parents[betterParent].Clone(); 127 resultQuality = qualities[betterParent].Value; 128 resultFDQ = flowDistanceQualities[betterParent].Value; 129 resultIQ = installationQualities[betterParent].Value; 130 resultOC = overbookedCapacities[betterParent].Value; 131 114 132 var pi_prime = (IntegerVector)source.Clone(); 115 133 var fix = new HashSet<int>(); 116 134 var nonFix = new HashSet<int>(Enumerable.Range(0, demands.Length)); 117 var phi = new HashSet<int>( GQAPIntegerVectorProximityCalculator.GetDifference(pi_prime, target));135 var phi = new HashSet<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target)); 118 136 119 137 while (phi.Any()) { 120 var B = new HashSet<GQAPSolution>(new GQAPSolutionStructuralEqualityComparer());138 var B = new List<GQAPSolution>(); 121 139 foreach (var v in phi) { 140 int oldLocation = pi_prime[v]; 122 141 pi_prime[v] = target[v]; 123 var pi2 = makeFeasible(pi_prime, v); 124 125 double flowDistanceQuality, installationQuality, overbookedCapacity; 142 var pi2 = makeFeasible(random, pi_prime, v, nonFix, demands, capacities); 143 pi_prime[v] = oldLocation; 144 145 double currentFDQ, currentIQ, currentOC; 126 146 GQAPEvaluator.Evaluate(pi2, weights, distances, installationCosts, demands, capacities, 127 out flowDistanceQuality, out installationQuality, out overbookedCapacity);128 129 if ( overbookedCapacity<= 0.0) {130 var quality = GQAPEvaluator.GetCombinedQuality( flowDistanceQuality, installationQuality, overbookedCapacity,147 out currentFDQ, out currentIQ, out currentOC); 148 149 if (currentOC <= 0.0) { 150 var quality = GQAPEvaluator.GetCombinedQuality(currentFDQ, currentIQ, currentOC, 131 151 transportationCosts.Value, overbookedCapacityPenalty.Value); 132 var solution = new GQAPSolution(pi2, new DoubleValue(quality), new DoubleValue(flowDistanceQuality), new DoubleValue(installationQuality), new DoubleValue(overbookedCapacity)); 133 if (B.Count >= nu * phi.Count) { 134 if (!B.Contains(solution) && quality <= B.Select(x => x.Quality.Value).Max()) { 135 // TODO: replace most similar element in B with worse cost 152 var solution = new GQAPSolution(pi2, new DoubleValue(quality), new DoubleValue(currentFDQ), 153 new DoubleValue(currentIQ), new DoubleValue(currentOC)); 154 if (B.Count >= candidateSizeFactor.Value * phi.Count) { 155 int mostSimilarIndex = -1; 156 double mostSimilarValue = 1.0; 157 for (int i = 0; i < B.Count; i++) { 158 if (IsBetter(maximization.Value, solution.Quality.Value, B[i].Quality.Value)) { 159 var similarity = IntegerVectorEqualityComparer.GetSimilarity(solution.Assignment, B[i].Assignment); 160 if (similarity == 1.0) { 161 mostSimilarIndex = -1; 162 break; 163 } else if (similarity < mostSimilarValue) { 164 mostSimilarValue = similarity; 165 mostSimilarIndex = i; 166 } 167 } 136 168 } 137 } else if (!B.Contains(solution)) { 138 B.Add(solution); 169 if (mostSimilarIndex >= 0) 170 B[mostSimilarIndex] = solution; 171 } else { 172 bool contains = false; 173 foreach (var b in B) { 174 if (!IntegerVectorEqualityComparer.GetDifferingIndices(solution.Assignment, b.Assignment).Any()) { 175 contains = true; 176 break; 177 } 178 } 179 if (!contains) B.Add(solution); 139 180 } 140 181 } 141 182 } 142 183 if (B.Any()) { 143 var pi = B.ChooseRandom(random); 144 var diff = GQAPIntegerVectorProximityCalculator.GetDifference(pi.Assignment, target); 145 var I = phi.Except(phi.Intersect(diff)); 146 var i = I.ChooseRandom(random); 184 GQAPSolution pi; 185 if (maximization.Value) pi = B.ChooseProportionalRandom(random, 1, x => x.Quality.Value, false, true).First(); 186 else pi = B.ChooseProportionalRandom(random, 1, x => 1.0 / x.Quality.Value, false, true).First(); 187 var diff = IntegerVectorEqualityComparer.GetDifferingIndices(pi.Assignment, target); 188 var I = phi.Except(diff); 189 var i = I.ChooseUniformRandom(random); 147 190 fix.Add(i); 148 191 nonFix.Remove(i); 149 192 pi_prime = pi.Assignment; 150 // TODO 151 } 193 if (IsBetter(maximization.Value, pi.Quality.Value, resultQuality)) { 194 result = pi.Assignment; 195 resultQuality = pi.Quality.Value; 196 resultFDQ = pi.FlowDistanceQuality.Value; 197 resultIQ = pi.InstallationQuality.Value; 198 resultOC = pi.OverbookedCapacity.Value; 199 } 200 } else return result; 201 phi = new HashSet<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target)); 152 202 } 153 203 154 return pi_prime;204 return result; 155 205 } 156 206 157 207 protected override IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents) { 158 return Apply(random, parents, QualityParameter.ActualValue, DemandsParameter.ActualValue, 208 return Apply(random, parents, MaximizationParameter.ActualValue, QualityParameter.ActualValue, FlowDistanceQualityParameter.ActualValue, 209 InstallationQualityParameter.ActualValue, OverbookedCapacityParameter.ActualValue, DemandsParameter.ActualValue, 159 210 CapacitiesParameter.ActualValue, WeightsParameter.ActualValue, DistancesParameter.ActualValue, 160 211 InstallationCostsParameter.ActualValue, TransportationCostsParameter.ActualValue, 161 OverbookedCapacityPenaltyParameter.ActualValue); 162 } 163 164 private static IntegerVector makeFeasible(IntegerVector assignment, int equipment) { 165 // TODO: implement 166 return assignment; 212 OverbookedCapacityPenaltyParameter.ActualValue, CandidateSizeFactorParameter.Value); 213 } 214 215 private static IntegerVector makeFeasible(IRandom random, IntegerVector assignment, int equipment, HashSet<int> nonFix, DoubleArray demands, DoubleArray capacities, int maximumTries = 1000) { 216 int l = assignment[equipment]; 217 var slack = ComputeSlack(assignment, demands, capacities); 218 if (slack[l] >= 0) return (IntegerVector)assignment.Clone(); 219 220 IntegerVector result = null; 221 int k = 0; 222 while (k < maximumTries && slack[l] < 0) { 223 result = (IntegerVector)assignment.Clone(); 224 do { 225 var maxSlack = slack.Max(); 226 var T = nonFix.Where(x => x != equipment && assignment[x] == l && demands[x] <= maxSlack); 227 if (T.Any()) { 228 int i = T.ChooseProportionalRandom(random, 1, x => demands[x], false, true).First(); 229 var j = Enumerable.Range(0, capacities.Length).Where(x => slack[x] >= demands[i]).ChooseUniformRandom(random); 230 result[i] = j; 231 slack[j] -= demands[i]; 232 slack[l] += demands[i]; 233 } else break; 234 } while (slack[l] < 0); 235 k++; 236 } 237 return result; 238 } 239 240 private static DoubleArray ComputeSlack(IntegerVector assignment, DoubleArray demands, DoubleArray capacities) { 241 var slack = (DoubleArray)capacities.Clone(); 242 for (int i = 0; i < assignment.Length; i++) { 243 slack[assignment[i]] -= demands[i]; 244 } 245 return slack; 246 } 247 248 private static bool IsBetter(bool maximization, double quality, double otherQuality) { 249 return maximization && quality > otherQuality || !maximization && quality < otherQuality; 167 250 } 168 251 } -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/GreedyRandomizedSolutionCreator.cs
r7415 r7432 70 70 do { 71 71 if (L.Any() && random.NextDouble() < threshold) { 72 int l = L.Choose Random(random);72 int l = L.ChooseUniformRandom(random); 73 73 L.Remove(l); 74 74 CL.Add(l); … … 76 76 } 77 77 if (T.Any()) { 78 int f = T.Choose Random(random);78 int f = T.ChooseUniformRandom(random); 79 79 T.Remove(f); 80 80 F.Remove(f); 81 81 CF.Add(f); 82 int l = WithSlackGreaterOrEqual(CL, demands[f], slack).Choose Random(random);82 int l = WithSlackGreaterOrEqual(CL, demands[f], slack).ChooseUniformRandom(random); 83 83 assignment.Add(f, l); 84 84 slack[l] -= demands[f]; -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/QualitySimilarityMerger.cs
r7419 r7432 94 94 95 95 foreach (var candidate in candidates) { 96 double[] similarities = population.Select(x => GQAPIntegerVectorProximityCalculator.CalculateGenotypeSimilarity(x.Solution, candidate.Solution)).ToArray();96 double[] similarities = population.Select(x => IntegerVectorEqualityComparer.GetSimilarity(x.Solution, candidate.Solution)).ToArray(); 97 97 if (!similarities.Any()) { 98 98 population.Add(candidate); -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/RelocateEquipmentManipluator.cs
r7419 r7432 72 72 } 73 73 74 bool selected; 75 var overstuffedLocation = usedCapacities.Where(x => capacities[x.Key] < x.Value).ChooseRandomOrDefault(random, out selected); 76 if (selected) { 77 int equipment = groupedLocations[overstuffedLocation.Key].ChooseRandomOrDefault(random, out selected); 78 var freeLocations = usedCapacities.Where(x => capacities[x.Key] > x.Value).ToList(); 79 var location = freeLocations.Where(x => capacities[x.Key] > x.Value + demands[equipment]).ChooseRandomOrDefault(random, out selected); 80 if (selected) { 81 assignment[equipment] = location.Key; 82 } else { 83 location = freeLocations.ChooseRandomOrDefault(random, out selected); 84 if (selected) assignment[equipment] = location.Key; 85 else assignment[equipment] = random.Next(locations); 86 } 87 } else { 74 var overbookedLocations = usedCapacities.Where(x => capacities[x.Key] < x.Value); 75 var freeLocations = usedCapacities.Where(x => capacities[x.Key] > x.Value); 76 if (!overbookedLocations.Any() || !freeLocations.Any()) { // perform a random relocation 88 77 assignment[random.Next(assignment.Length)] = random.Next(locations); 78 return; 79 } 80 81 var sourceLocation = overbookedLocations.ChooseUniformRandom(random); 82 int equipmentToRelocate = groupedLocations[sourceLocation.Key].ChooseUniformRandom(random); 83 var bestFreeLocations = freeLocations.Where(x => capacities[x.Key] > x.Value + demands[equipmentToRelocate]); 84 85 if (bestFreeLocations.Any()) { // a feasible solution will still be feasible, an infeasible solution might become feasible 86 var selected = bestFreeLocations.ChooseUniformRandom(random); 87 assignment[equipmentToRelocate] = sourceLocation.Key; 88 } else { // the solution will become infeasible 89 sourceLocation = freeLocations.ChooseUniformRandom(random); 90 assignment[equipmentToRelocate] = sourceLocation.Key; 89 91 } 90 92 }
Note: See TracChangeset
for help on using the changeset viewer.