Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
12/22/17 01:32:13 (6 years ago)
Author:
abeham
Message:

#1614: fixed bugs

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/GQAPPathRelinking.cs

    r15555 r15558  
    4545      get { return (IScopeTreeLookupParameter<Evaluation>)Parameters["Evaluation"]; }
    4646    }
    47 
    4847    public IValueParameter<PercentValue> CandidateSizeFactorParameter {
    4948      get { return (IValueParameter<PercentValue>)Parameters["CandidateSizeFactor"]; }
     49    }
     50    public IValueLookupParameter<BoolValue> GreedyParameter {
     51      get { return (IValueLookupParameter<BoolValue>)Parameters["Greedy"]; }
    5052    }
    5153
     
    5860      Parameters.Add(new ScopeTreeLookupParameter<Evaluation>("Evaluation", GQAP.EvaluationDescription));
    5961      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)));
     62      Parameters.Add(new ValueLookupParameter<BoolValue>("Greedy", "Whether to use a greedy selection strategy or a probabilistic one.", new BoolValue(true)));
    6063    }
    6164
     
    6871      IntegerVector target, Evaluation targetEval,
    6972      GQAPInstance problemInstance, double candidateSizeFactor,
    70       out int evaluatedSolutions) {
     73      out int evaluatedSolutions, bool greedy = true) {
    7174      evaluatedSolutions = 0;
    7275      var demands = problemInstance.Demands;
    7376      var capacities = problemInstance.Capacities;
    7477      var cmp = new IntegerVectorEqualityComparer();
    75 
    76       var greedy = true; // greedy performed better according to the paper
     78     
    7779      var sFit = problemInstance.ToSingleObjective(sourceEval);
    7880      var tFit = problemInstance.ToSingleObjective(targetEval);
     
    8385      //var fix = new bool[demands.Length]; // line 3 of Algorithm 4, note that according to the description it is not necessary to track the fixed equipments
    8486      var nonFix = Enumerable.Range(0, demands.Length).ToList(); // line 3 of Algorithm 4
    85       var phi = new HashSet<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target)); // line 4 of Algorithm 4
    86 
     87      var phi = new List<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target)); // line 4 of Algorithm 4
     88
     89      var B = new List<GQAPSolution>((int)Math.Ceiling(phi.Count * candidateSizeFactor));
     90      var B_fit = new List<double>(B.Capacity);
    8791      while (phi.Count > 0) { // line 5 of Algorithm 4
    88         var B = new List<GQAPSolution>((int)Math.Ceiling(phi.Count * candidateSizeFactor)); // line 6 of Algorithm 4
    89         var B_fit = new List<double>(B.Capacity); // line 6 of Algorithm 4 (B is split into two synchronized lists)
     92        B.Clear(); // line 6 of Algorithm 4
     93        B_fit.Clear(); // line 6 of Algorithm 4 (B is split into two synchronized lists)
    9094        foreach (var v in phi) { // line 7 of Algorithm 4
    9195          int oldLocation = pi_prime[v];
     
    9397          var pi_dash = MakeFeasible(random, pi_prime, v, nonFix, demands, capacities); // line 9 of Algorithm 4
    9498          pi_prime[v] = oldLocation; // not mentioned in Algorithm 4, but seems reasonable
    95           var pi_dash_eval = problemInstance.Evaluate(pi_dash);
    96           evaluatedSolutions++;
    97           var pi_dash_fit = problemInstance.ToSingleObjective(pi_dash_eval);
    9899
    99100          if (problemInstance.IsFeasible(pi_dash)) { // line 10 of Algorithm 4
     101            var pi_dash_eval = problemInstance.Evaluate(pi_dash);
     102            evaluatedSolutions++;
     103            var pi_dash_fit = problemInstance.ToSingleObjective(pi_dash_eval);
     104
    100105            if (B.Any(x => cmp.Equals(x.Assignment, pi_dash))) continue; // cond. 2 of line 12 and cond. 1 of line 16 in Algorithm 4
    101106
     
    103108              var replacement = B_fit.Select((val, idx) => new { Index = idx, Fitness = val })
    104109                                            .Where(x => x.Fitness >= pi_dash_fit) // cond. 1 in line 12 of Algorithm 4
    105                                             .Select(x => new { Index = x.Index, Fitness = x.Fitness, Similarity = HammingSimilarityCalculator.CalculateSimilarity(B[x.Index].Assignment, pi_dash) })
     110                                            .Select(x => new { x.Index, x.Fitness, Similarity = HammingSimilarityCalculator.CalculateSimilarity(B[x.Index].Assignment, pi_dash) })
    106111                                            .ToArray();
    107112              if (replacement.Length > 0) {
    108                 var mostSimilar = replacement.MaxItems(x => x.Similarity).First().Index;
     113                var mostSimilar = replacement.MaxItems(x => x.Similarity).SampleRandom(random).Index;
    109114                B[mostSimilar].Assignment = pi_dash; // line 13 of Algorithm 4
    110115                B[mostSimilar].Evaluation = pi_dash_eval; // line 13 of Algorithm 4
     
    121126          // line 22 of Algorithm 4
    122127          if (greedy) {
    123             pi = B.Select((val, idx) => new { Index = idx, Value = val }).MinItems(x => B_fit[x.Index]).Shuffle(random).First().Value;
     128            pi = B.Select((val, idx) => new { Index = idx, Value = val }).MinItems(x => B_fit[x.Index]).SampleRandom(random).Value;
    124129          } else {
    125130            pi = B.SampleProportional(random, 1, B_fit.Select(x => 1.0 / x), false).First();
     
    137142          }
    138143        } else return pi_star;
    139         phi = new HashSet<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target));
     144        phi = new List<int>(IntegerVectorEqualityComparer.GetDifferingIndices(pi_prime, target));
    140145      }
    141146
     
    156161      return Apply(random, source, evaluations[betterParent],
    157162        target, evaluations[worseParent], problemInstance,
    158         CandidateSizeFactorParameter.Value.Value, out evaluatedSolution).Assignment;
    159     }
    160 
     163        CandidateSizeFactorParameter.Value.Value, out evaluatedSolution,
     164        GreedyParameter.ActualValue.Value).Assignment;
     165    }
     166
     167    /// <summary>
     168    /// Relocates equipments in the same location as <paramref name="equipment"/> to other locations in case the location
     169    /// is overutilized.
     170    /// </summary>
     171    /// <remarks>
     172    /// This method is performance critical, called very often and should run as fast as possible.
     173    /// </remarks>
     174    /// <param name="random">The random number generator.</param>
     175    /// <param name="pi">The current solution.</param>
     176    /// <param name="equipment">The equipment that was just assigned to a new location.</param>
     177    /// <param name="nonFix">The equipments that have not yet been fixed.</param>
     178    /// <param name="demands">The demands for all equipments.</param>
     179    /// <param name="capacities">The capacities of all locations.</param>
     180    /// <param name="maximumTries">The number of tries that should be done in relocating the equipments.</param>
     181    /// <returns>A feasible or infeasible solution</returns>
    161182    private static IntegerVector MakeFeasible(IRandom random, IntegerVector pi, int equipment, List<int> nonFix, DoubleArray demands, DoubleArray capacities, int maximumTries = 1000) {
    162183      int l = pi[equipment];
    163184      var slack = ComputeSlack(pi, demands, capacities);
    164185      if (slack[l] >= 0) // line 1 of Algorithm 5
    165         return new IntegerVector(pi); // line 2 of Algorithm 5
     186        return (IntegerVector)pi.Clone(); // line 2 of Algorithm 5
    166187
    167188      IntegerVector pi_prime = null;
    168189      int k = 0; // line 4 of Algorithm 5
    169       while (k < maximumTries && slack[l] < 0) {  // line 5 of Algorithm 5
    170         pi_prime = new IntegerVector(pi); // line 6 of Algorithm 5
     190      var maxSlack = slack.Max(); // line 8-9 of Algorithm 5
     191      var slack_prime = (double[])slack.Clone();
     192      var maxSlack_prime = maxSlack;
     193      // note that FTL can be computed only once for all tries as all tries restart with the same solution
     194      var FTL = nonFix.Where(x => x != equipment && pi[x] == l && demands[x] <= maxSlack).ToList(); // line 8-9 of Algorithm 5
     195      var FTLweight = FTL.Select(x => demands[x]).ToList();
     196      while (k < maximumTries && slack_prime[l] < 0) {  // line 5 of Algorithm 5
     197        pi_prime = (IntegerVector)pi.Clone(); // line 6 of Algorithm 5
     198        // set T can only shrink and not grow, thus it is created outside the loop and only updated inside
     199        var T = new List<int>(FTL); // line 8-9 of Algorithm 5
     200        var weightT = new List<double>(FTLweight);
    171201        do {  // line 7 of Algorithm 5
    172           var maxSlack = slack.Max(); // line 8-9 of Algorithm 5
    173           var T = nonFix.Where(x => pi[x] == l && demands[x] <= maxSlack).ToList(); // line 8-9 of Algorithm 5
    174202          if (T.Count > 0) { // line 10 of Algorithm 5
    175             int i = T.SampleProportional(random, 1, T.Select(x => demands[x]), false).First(); // line 11 of Algorithm 5
     203            var idx = Enumerable.Range(0, T.Count).SampleProportional(random, 1, weightT, false, false).First(); // line 11 of Algorithm 5
     204            int i = T[idx]; // line 11 of Algorithm 5
    176205            var j = Enumerable.Range(0, capacities.Length)
    177               .Where(x => slack[x] >= demands[i]) // line 12 of Algorithm 5
     206              .Where(x => slack_prime[x] >= demands[i]) // line 12 of Algorithm 5
    178207              .SampleRandom(random);  // line 13 of Algorithm 5
    179208            pi_prime[i] = j; // line 14 of Algorithm 5
    180             slack[j] -= demands[i]; // line 14 of Algorithm 5
    181             slack[l] += demands[i]; // line 14 of Algorithm 5
     209            T.RemoveAt(idx);
     210            weightT.RemoveAt(idx);
     211            var recomputeMaxSlack = slack_prime[j] == maxSlack_prime; // efficiency improvement: recompute max slack only if we assign to a location whose slack equals maxSlack
     212            slack_prime[j] -= demands[i]; // line 14 of Algorithm 5
     213            slack_prime[l] += demands[i]; // line 14 of Algorithm 5
     214            if (recomputeMaxSlack) {
     215              maxSlack_prime = slack_prime.Max();
     216              // T needs to be removed of equipments whose demand is higher than maxSlack only if maxSlack changes
     217              for (var h = 0; h < T.Count; h++) {
     218                var f = T[h];
     219                if (demands[f] > maxSlack_prime) {
     220                  T.RemoveAt(h);
     221                  weightT.RemoveAt(h);
     222                  h--;
     223                }
     224              }
     225            }
    182226          } else break; // cond. 1 in line 16 of Algorithm 5
    183         } while (slack[l] < 0); // cond. 2 in line 16 of Algorithm 5
     227        } while (slack_prime[l] < 0); // cond. 2 in line 16 of Algorithm 5
    184228        k++; // line 17 of Algorithm 5
     229        if (slack_prime[l] < 0) {
     230          // reset
     231          Array.Copy(slack, slack_prime, slack.Length);
     232          maxSlack_prime = maxSlack;
     233        }
    185234      }
    186235      return pi_prime; // line 19-23 of Algorithm 5
     
    188237
    189238    private static double[] ComputeSlack(IntegerVector assignment, DoubleArray demands, DoubleArray capacities) {
    190       var slack = new double[capacities.Length];
     239      var slack = capacities.ToArray();
    191240      for (int i = 0; i < assignment.Length; i++) {
    192241        slack[assignment[i]] -= demands[i];
Note: See TracChangeset for help on using the changeset viewer.