Changeset 15555
- Timestamp:
- 12/20/17 23:35:23 (7 years ago)
- Location:
- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPPathRelinking.cs
r15553 r15555 32 32 33 33 namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment { 34 /// <summary> 35 /// This is an implementation of the algorithm described in Mateus, G.R., Resende, M.G.C. & Silva, R.M.A. J Heuristics (2011) 17: 527. https://doi.org/10.1007/s10732-010-9144-0 36 /// </summary> 34 37 [Item("GQAPPathRelinking", "Operator that performs path relinking between two solutions. It is described in Mateus, G., Resende, M., and Silva, R. 2011. GRASP with path-relinking for the generalized quadratic assignment problem. Journal of Heuristics 17, Springer Netherlands, pp. 527-565.")] 35 38 [StorableClass] … … 71 74 var cmp = new IntegerVectorEqualityComparer(); 72 75 76 var greedy = true; // greedy performed better according to the paper 73 77 var sFit = problemInstance.ToSingleObjective(sourceEval); 74 78 var tFit = problemInstance.ToSingleObjective(targetEval); … … 114 118 } 115 119 if (B.Count > 0) { // line 21 of Algorithm 4 116 var pi = B.SampleProportional(random, 1, B_fit.Select(x => 1.0 / x), false).First(); // line 22 of Algorithm 4 120 GQAPSolution pi; 121 // line 22 of Algorithm 4 122 if (greedy) { 123 pi = B.Select((val, idx) => new { Index = idx, Value = val }).MinItems(x => B_fit[x.Index]).Shuffle(random).First().Value; 124 } else { 125 pi = B.SampleProportional(random, 1, B_fit.Select(x => 1.0 / x), false).First(); 126 } 117 127 var diff = IntegerVectorEqualityComparer.GetDifferingIndices(pi.Assignment, target); // line 23 of Algorithm 4 118 128 var I = phi.Except(diff); // line 24 of Algorithm 4 … … 126 136 pi_star = pi; // line 30 of Algorithm 4 127 137 } 128 } else return pi_star ?? new GQAPSolution((IntegerVector)source.Clone(), (Evaluation)sourceEval.Clone());138 } else return pi_star; 129 139 phi = new HashSet<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target)); 130 140 } 131 141 132 return pi_star ?? new GQAPSolution((IntegerVector)source.Clone(), (Evaluation)sourceEval.Clone());142 return pi_star; 133 143 } 134 144 -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/ApproximateLocalSearch.cs
r15553 r15555 31 31 using HeuristicLab.Parameters; 32 32 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; 33 using HeuristicLab.Random; 33 34 34 35 namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment { 36 /// <summary> 37 /// This is an implementation of the algorithm described in Mateus, G.R., Resende, M.G.C. & Silva, R.M.A. J Heuristics (2011) 17: 527. https://doi.org/10.1007/s10732-010-9144-0 38 /// </summary> 35 39 [Item("ApproximateLocalSearch", "The approximate local search is described in Mateus, G., Resende, M., and Silva, R. 2011. GRASP with path-relinking for the generalized quadratic assignment problem. Journal of Heuristics 17, Springer Netherlands, pp. 527-565.")] 36 40 [StorableClass] … … 105 109 106 110 /// <summary> 107 /// The implementation differs slightly from Mateus et al. in that the maximumIterations parameter defines a cap108 /// on the number of steps that the local search can perform. While the maxSampleSize parameter corresponds to109 /// the maxItr parameter defined by Mateus et al.110 111 /// </summary> 111 112 /// <param name="random">The random number generator to use.</param> … … 127 128 var evaluations = 0.0; 128 129 var deltaEvaluationFactor = 1.0 / assignment.Length; 129 while (true) {130 int count = 0;131 var CLS = new List<Tuple<NMove, double, Evaluation>>();132 double sum = 0.0;130 var greedy = true; // greedy selection performed better in 5 of 8 instances according to the paper 131 while (true) { // line 1 of Algorithm 3 132 var count = 0; // line 2 of Algorithm 3 133 var CLS = new List<Tuple<NMove, double, Evaluation>>(); // line 3 of Algorithm 3 133 134 do { 134 NMove move; 135 if (random.NextDouble() < oneMoveProbability) 136 move = StochasticNMoveSingleMoveGenerator.GenerateOneMove(random, assignment, capacities); 137 else move = StochasticNMoveSingleMoveGenerator.GenerateTwoMove(random, assignment, capacities); 138 135 var move = Move(random, assignment, oneMoveProbability, capacities); // line 4 of Algorithm 3 136 139 137 var moveEval = GQAPNMoveEvaluator.Evaluate(move, assignment, evaluation, problemInstance); 140 138 evaluations += move.Indices.Count * deltaEvaluationFactor; 141 139 double moveQuality = problemInstance.ToSingleObjective(moveEval); 142 140 143 if (moveEval.ExcessDemand <= 0.0 && moveQuality < quality) { 144 CLS.Add(Tuple.Create(move, moveQuality, moveEval)); 145 sum += 1.0 / moveQuality; 141 if (moveEval.ExcessDemand <= 0.0 && moveQuality < quality) { // line 5 of Algorithm 3 142 CLS.Add(Tuple.Create(move, moveQuality, moveEval)); // line 6 of Algorithm 3 146 143 } 147 count++; 148 } while (CLS.Count < maxCLS && count < maximumIterations); 144 count++; // line 8 of Algorithm 3 145 } while (CLS.Count < maxCLS && count < maximumIterations); // line 9 of Algorithm 3 149 146 150 if (CLS.Count == 0) { 147 if (CLS.Count == 0) { // line 10 of Algorithm 3 151 148 evaluatedSolutions += (int)Math.Ceiling(evaluations); 152 149 return; // END 153 150 } else { 154 var ball = random.NextDouble() * sum; 155 var selected = CLS.Last(); 156 foreach (var candidate in CLS) { 157 ball -= 1.0 / candidate.Item2; 158 if (ball <= 0.0) { 159 selected = candidate; 160 break; 161 } 151 // line 11 of Algorithm 3 152 Tuple<NMove, double, Evaluation> selected; 153 if (greedy) { 154 selected = CLS.MinItems(x => x.Item2).Shuffle(random).First(); 155 } else { 156 selected = CLS.SampleProportional(random, 1, CLS.Select(x => 1.0 / x.Item2), false, false).Single(); 162 157 } 163 158 NMoveMaker.Apply(assignment, selected.Item1); … … 166 161 } 167 162 } 163 } 164 165 private static NMove Move(IRandom random, IntegerVector assignment, double oneMoveProbability, DoubleArray capacities) { 166 if (random.NextDouble() < oneMoveProbability) 167 return StochasticNMoveSingleMoveGenerator.GenerateOneMove(random, assignment, capacities); 168 return StochasticNMoveSingleMoveGenerator.GenerateTwoMove(random, assignment, capacities); 168 169 } 169 170 -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/GreedyRandomizedSolutionCreator.cs
r15553 r15555 33 33 34 34 namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment { 35 /// <summary> 36 /// This is an implementation of the algorithm described in Mateus, G.R., Resende, M.G.C. & Silva, R.M.A. J Heuristics (2011) 17: 527. https://doi.org/10.1007/s10732-010-9144-0 37 /// </summary> 35 38 [Item("GreedyRandomizedSolutionCreator", "Creates a solution according to the procedure described in Mateus, G., Resende, M., and Silva, R. 2011. GRASP with path-relinking for the generalized quadratic assignment problem. Journal of Heuristics 17, Springer Netherlands, pp. 527-565.")] 36 39 [StorableClass] … … 60 63 public static IntegerVector CreateSolution(IRandom random, GQAPInstance problemInstance, 61 64 int maximumTries, bool createMostFeasibleSolution, CancellationToken cancelToken) { 65 var weights = problemInstance.Weights; 66 var distances = problemInstance.Distances; 62 67 var demands = problemInstance.Demands; 63 68 var capacities = problemInstance.Capacities.ToArray(); 69 var transportCosts = problemInstance.TransportationCosts; 64 70 var equipments = demands.Length; 65 71 var locations = capacities.Length; … … 69 75 double minViolation = double.MaxValue; 70 76 int[] bestAssignment = null; 71 var CF = new bool[equipments]; // set of chosen facilities / equipments 72 var T = new List<int>(equipments); // set of facilities / equpiments that can be assigned to the set of chosen locations (CL) 77 var F = new List<int>(equipments); // set of (initially) all facilities / equipments 78 var CF = new List<int>(equipments); // set of chosen facilities / equipments 79 var L = new List<int>(locations); // set of (initially) all locations 73 80 var CL_list = new List<int>(locations); // list of chosen locations 74 81 var CL_selected = new bool[locations]; // bool decision if location is chosen 75 var F = new List<int>(equipments); // set of (initially) all facilities / equipments 76 var L = new List<int>(locations); // set of (initially) all locations 77 82 var T = new List<int>(equipments); // set of facilities / equpiments that can be assigned to the set of chosen locations (CL) 83 var H = new double[locations]; // proportions for choosing locations in stage 1 84 var W = new double[equipments]; // proportions for choosing facilities in stage 2 85 var Z = new double[locations]; // proportions for choosing locations in stage 2 86 78 87 while (maximumTries <= 0 || tries < maximumTries) { 79 88 cancelToken.ThrowIfCancellationRequested(); 80 89 81 Array.Copy(capacities, slack, locations); 82 Array.Clear(CF, 0, equipments); 83 Array.Clear(CL_selected, 0, locations); 84 CL_list.Clear(); 85 T.Clear(); 86 87 F.Clear(); F.AddRange(Enumerable.Range(0, equipments)); 88 L.Clear(); L.AddRange(Enumerable.Range(0, locations)); 89 90 double threshold = 1.0; 91 do { 92 if (L.Count > 0 && random.NextDouble() < threshold) { 93 int l = L.SampleRandom(random); 94 L.Remove(l); 95 CL_list.Add(l); 96 CL_selected[l] = true; 97 T = new List<int>(WhereDemandEqualOrLess(F, GetMaximumSlack(slack, CL_selected), demands)); 98 } 99 if (T.Count > 0) { 100 var fidx = Enumerable.Range(0, T.Count).SampleRandom(random); 101 var f = T[fidx]; 102 T.RemoveAt(fidx); 103 F.Remove(f); // TODO: slow 104 CF[f] = true; 105 int l = WhereSlackGreaterOrEqual(CL_list, demands[f], slack).SampleRandom(random); 106 assignment[f] = l + 1; 90 Array.Copy(capacities, slack, locations); // line 2 of Algorihm 2 91 CF.Clear(); // line 2 of Algorihm 2 92 Array.Clear(CL_selected, 0, locations); // line 2 of Algorihm 2 93 CL_list.Clear(); // line 2 of Algorihm 2 94 T.Clear(); // line 2 of Algorihm 2 95 96 F.Clear(); F.AddRange(Enumerable.Range(0, equipments)); // line 2 of Algorihm 2 97 L.Clear(); L.AddRange(Enumerable.Range(0, locations)); // line 2 of Algorihm 2 98 99 double threshold = 1.0; // line 3 of Algorithm 2 100 do { // line 4 of Algorithm 2 101 if (L.Count > 0 && random.NextDouble() < threshold) { // line 5 of Algorithm 2 102 // H is the proportion that a location is chosen 103 // The paper doesn't mention what happens if the candidate list CL 104 // does not contain an element in which case according to the formula 105 // all H_k elements would be 0 which would be equal to random selection 106 var HH = H.Select((v, i) => new { Index = i, Value = v }) 107 .Where(x => !CL_selected[x.Index]) 108 .Select(x => x.Value); 109 int l = L.SampleProportional(random, 1, HH, false, false).Single(); // line 6 of Algorithm 2 110 L.Remove(l); // line 7 of Algorithm 2 111 CL_list.Add(l); // line 7 of Algorithm 2 112 CL_selected[l] = true; // line 7 of Algorithm 2 113 for (var k = 0; k < locations; k++) 114 if (!CL_selected[k]) 115 H[k] += capacities[k] * capacities[l] / distances[k, l]; 116 T = new List<int>(WhereDemandEqualOrLess(F, GetMaximumSlack(slack, CL_selected), demands)); // line 8 of Algorithm 2 117 } 118 if (T.Count > 0) { // line 10 of Algorithm 2 119 // W is the proportion that an equipment is chosen 120 Array.Clear(W, 0, W.Length); 121 var wk = 0; 122 foreach (var k in T) { 123 for (var h = 0; h < equipments; h++) { 124 if (k == h) continue; 125 W[wk] += weights[k, h]; 126 } 127 W[wk] *= demands[k]; 128 wk++; 129 } 130 var f = T.SampleProportional(random, 1, W.Take(T.Count), false, false) // line 11 of Algorithm 2 131 .Single(); 132 T.Remove(f); // line 12 of Algorithm 2 133 F.Remove(f); // line 12 of Algorithm 2 134 CF.Add(f); // line 12 of Algorithm 2 135 var R = WhereSlackGreaterOrEqual(CL_list, demands[f], slack).ToList(); // line 13 of Algorithm 2 136 // Z is the proportion that a location is chosen in stage 2 137 Array.Clear(Z, 0, Z.Length); 138 var zk = 0; 139 foreach (var k in R) { 140 // d is an increase in fitness if f would be assigned to location k 141 var d = problemInstance.InstallationCosts[f, k]; 142 foreach (var i in CF) { 143 if (assignment[i] == 0) continue; // i is unassigned 144 var j = assignment[i] - 1; 145 d += transportCosts * weights[f, i] * distances[k, j]; 146 } 147 foreach (var h in CL_list) { 148 if (k == h) continue; 149 Z[zk] += slack[k] * capacities[h] / (d * distances[k, h]); 150 } 151 zk++; 152 } 153 int l = R.SampleProportional(random, 1, Z.Take(R.Count), false, false).Single(); // line 14 of Algorithm 2 154 assignment[f] = l + 1; // line 15 of Algorithm 2 107 155 slack[l] -= demands[f]; 108 T = new List<int>(WhereDemandEqualOrLess(F, GetMaximumSlack(slack, CL_selected), demands)); 109 threshold = 1.0 - (double)T.Count / Math.Max(F.Count, 1.0); 110 } 111 } while (T.Count > 0 || L.Count > 0); 156 T = new List<int>(WhereDemandEqualOrLess(F, GetMaximumSlack(slack, CL_selected), demands)); // line 16 of Algorithm 2 157 threshold = 1.0 - (double)T.Count / Math.Max(F.Count, 1.0); // line 17 of Algorithm 2 158 } 159 } while (T.Count > 0 || L.Count > 0); // line 19 of Algorithm 2 160 112 161 if (maximumTries > 0) tries++; 162 113 163 if (F.Count == 0) { 114 bestAssignment = assignment ;164 bestAssignment = assignment.Select(x => x - 1).ToArray(); 115 165 break; 116 166 } else if (createMostFeasibleSolution) { … … 130 180 double violation = slack.Select(x => x < 0 ? -x : 0).Sum(); 131 181 if (violation < minViolation) { 132 bestAssignment = assignment; 133 assignment = new int[equipments]; 182 bestAssignment = assignment.Select(x => x - 1).ToArray(); 134 183 minViolation = violation; 135 184 } 185 assignment = new int[equipments]; 136 186 } 137 187 } 138 188 139 if (bestAssignment == null || bestAssignment.Any(x => x == 0))189 if (bestAssignment == null) 140 190 throw new InvalidOperationException(String.Format("No solution could be found in {0} tries.", maximumTries)); 141 191 142 return new IntegerVector(bestAssignment .Select(x => x - 1).ToArray());192 return new IntegerVector(bestAssignment); 143 193 } 144 194 -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/RandomButFeasibleSolutionCreator.cs
r15504 r15555 65 65 int counter = 0; 66 66 double minViolation = double.MaxValue; 67 var slack = new DoubleArray(capacities.Length);68 var assignment = new IntegerVector(demands.Length);67 var slack = new double[capacities.Length]; 68 var assignment = new int[demands.Length]; 69 69 70 70 while (!isFeasible) { … … 86 86 isFeasible = violation == 0; 87 87 if (isFeasible || violation < minViolation) { 88 result = (IntegerVector)assignment.Clone();88 result = new IntegerVector(assignment); 89 89 minViolation = violation; 90 90 } … … 100 100 } 101 101 102 private static IEnumerable<int> GetFreeLocations(int equipment, DoubleArray demands, DoubleArrayfreeCapacities) {102 private static IEnumerable<int> GetFreeLocations(int equipment, DoubleArray demands, double[] freeCapacities) { 103 103 var freeLocations = freeCapacities 104 104 .Select((v, idx) => new KeyValuePair<int, double>(idx, v)) -
branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/SlackMinimizationSolutionCreator.cs
r15504 r15555 74 74 int counter = 0; 75 75 double minViolation = double.MaxValue; 76 var slack = new DoubleArray(capacities.Length);76 var slack = new double[capacities.Length]; 77 77 var assignment = new Dictionary<int, int>(demands.Length); 78 78 … … 150 150 } 151 151 152 private static void RandomFeasibleWalk(IRandom random, Dictionary<int, int> assignment, DoubleArray demands, DoubleArrayslack, int walkLength) {152 private static void RandomFeasibleWalk(IRandom random, Dictionary<int, int> assignment, DoubleArray demands, double[] slack, int walkLength) { 153 153 for (int i = 0; i < walkLength; i++) { 154 154 var equipments = Enumerable.Range(0, demands.Length).Shuffle(random);
Note: See TracChangeset
for help on using the changeset viewer.