source: branches/2936_GQAPIntegration/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/LocalImprovers/ApproximateLocalSearch.cs @ 16712

Last change on this file since 16712 was 16712, checked in by gkronber, 3 months ago

#2936: adapted branch to new persistence (works with HL trunk r16711)

File size: 10.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.IntegerVectorEncoding;
29using HeuristicLab.Operators;
30using HeuristicLab.Optimization;
31using HeuristicLab.Parameters;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33using HeuristicLab.Random;
34using HEAL.Attic;
35
36namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
37  /// <summary>
38  /// 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
39  /// </summary>
40  [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.")]
41  [StorableType("58C75FBC-C586-4048-A60B-DCF967CB2E33")]
42  public class ApproximateLocalSearch : SingleSuccessorOperator, IProblemInstanceAwareGQAPOperator,
43    IQualityAwareGQAPOperator, IGQAPLocalImprovementOperator, IAssignmentAwareGQAPOperator, IStochasticOperator {
44    public IProblem Problem { get; set; }
45    public Type ProblemType {
46      get { return typeof(GQAP); }
47    }
48
49    public ILookupParameter<GQAPInstance> ProblemInstanceParameter {
50      get { return (ILookupParameter<GQAPInstance>)Parameters["ProblemInstance"]; }
51    }
52    public ILookupParameter<IntegerVector> AssignmentParameter {
53      get { return (ILookupParameter<IntegerVector>)Parameters["Assignment"]; }
54    }
55    public ILookupParameter<DoubleValue> QualityParameter {
56      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
57    }
58    public ILookupParameter<Evaluation> EvaluationParameter {
59      get { return (ILookupParameter<Evaluation>)Parameters["Evaluation"]; }
60    }
61    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
62      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
63    }
64    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
65      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
66    }
67    public ILookupParameter<IRandom> RandomParameter {
68      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
69    }
70    public IValueLookupParameter<IntValue> MaximumCandidateListSizeParameter {
71      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumCandidateListSize"]; }
72    }
73    public IValueLookupParameter<PercentValue> OneMoveProbabilityParameter {
74      get { return (IValueLookupParameter<PercentValue>)Parameters["OneMoveProbability"]; }
75    }
76    public ILookupParameter<ResultCollection> ResultsParameter {
77      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
78    }
79    public IValueLookupParameter<BoolValue> GreedyParameter {
80      get { return (IValueLookupParameter<BoolValue>)Parameters["Greedy"]; }
81    }
82
83    [StorableConstructor]
84    protected ApproximateLocalSearch(StorableConstructorFlag _) : base(_) { }
85    protected ApproximateLocalSearch(ApproximateLocalSearch original, Cloner cloner) : base(original, cloner) { }
86    public ApproximateLocalSearch()
87      : base() {
88      Parameters.Add(new LookupParameter<GQAPInstance>("ProblemInstance", GQAP.ProblemInstanceDescription));
89      Parameters.Add(new LookupParameter<IntegerVector>("Assignment", GQAPSolutionCreator.AssignmentDescription));
90      Parameters.Add(new LookupParameter<DoubleValue>("Quality", ""));
91      Parameters.Add(new LookupParameter<Evaluation>("Evaluation", GQAP.EvaluationDescription));
92      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The maximum number of iterations that should be performed."));
93      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The number of evaluated solution equivalents."));
94      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator to use."));
95      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumCandidateListSize", "The maximum number of candidates that should be found in each step.", new IntValue(10)));
96      Parameters.Add(new ValueLookupParameter<PercentValue>("OneMoveProbability", "The probability for performing a 1-move, which is the opposite of performing a 2-move.", new PercentValue(.5)));
97      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The result collection that stores the results."));
98      Parameters.Add(new ValueLookupParameter<BoolValue>("Greedy", "Whether to use a greedy selection strategy or a probabilistic one.", new BoolValue(true)));
99    }
100
101    public override IDeepCloneable Clone(Cloner cloner) {
102      return new ApproximateLocalSearch(this, cloner);
103    }
104
105    public static void Apply(IRandom random, GQAPSolution sol, int maxCLS,
106      double oneMoveProbability, int maximumIterations,
107      GQAPInstance problemInstance, out int evaluatedSolutions, bool greedy = true) {
108      var fit = problemInstance.ToSingleObjective(sol.Evaluation);
109      var eval = sol.Evaluation;
110      Apply(random, sol.Assignment, ref fit, ref eval, maxCLS, oneMoveProbability, maximumIterations, problemInstance,
111        out evaluatedSolutions, greedy);
112      sol.Evaluation = eval;
113    }
114
115    /// <summary>
116    /// </summary>
117    /// <param name="random">The random number generator to use.</param>
118    /// <param name="assignment">The equipment-location assignment vector.</param>
119    /// <param name="quality">The solution quality.</param>
120    /// <param name="evaluation">The evaluation result of the solution.</param>
121    /// <param name="maxCLS">The maximum number of candidates that should be found in each step.</param>
122    /// <param name="oneMoveProbability">The probability for performing a 1-move, which is the opposite of performing a 2-move.</param>
123    /// <param name="maximumIterations">The maximum number of iterations that should be performed each time the candidate list is generated.</param>
124    /// <param name="problemInstance">The problem instance that contains the data.</param>
125    /// <param name="evaluatedSolutions">The number of evaluated solutions.</param>
126    /// <param name="greedy">Greedy selection performed better in 5 of 8 instances according to the paper</param>
127    public static void Apply(IRandom random, IntegerVector assignment,
128      ref double quality, ref Evaluation evaluation, int maxCLS,
129      double oneMoveProbability, int maximumIterations,
130      GQAPInstance problemInstance, out int evaluatedSolutions, bool greedy = true) {
131      evaluatedSolutions = 0;
132      var capacities = problemInstance.Capacities;
133      var demands = problemInstance.Demands;
134      var evaluations = 0.0;
135      var deltaEvaluationFactor = 1.0 / assignment.Length;
136      while (true) { // line 1 of Algorithm 3
137        var count = 0; // line 2 of Algorithm 3
138        var CLS = new List<Tuple<NMove, double, Evaluation>>(); // line 3 of Algorithm 3
139        do {
140          var move = Move(random, assignment, oneMoveProbability, capacities); // line 4 of Algorithm 3
141
142          var moveEval = GQAPNMoveEvaluator.Evaluate(move, assignment, evaluation, problemInstance);
143          evaluations += move.Indices.Count * deltaEvaluationFactor;
144          double moveQuality = problemInstance.ToSingleObjective(moveEval);
145
146          if (moveEval.ExcessDemand <= 0.0 && moveQuality < quality) { // line 5 of Algorithm 3
147            CLS.Add(Tuple.Create(move, moveQuality, moveEval)); // line 6 of Algorithm 3
148          }
149          count++; // line 8 of Algorithm 3
150        } while (CLS.Count < maxCLS && count < maximumIterations); // line 9 of Algorithm 3
151
152        if (CLS.Count == 0) { // line 10 of Algorithm 3
153          evaluatedSolutions += (int)Math.Ceiling(evaluations);
154          return; // END
155        } else {
156          // line 11 of Algorithm 3
157          Tuple<NMove, double, Evaluation> selected;
158          if (greedy) {
159            selected = CLS.MinItems(x => x.Item2).Shuffle(random).First();
160          } else {
161            selected = CLS.SampleProportional(random, 1, CLS.Select(x => 1.0 / x.Item2), false, false).Single();
162          }
163          NMoveMaker.Apply(assignment, selected.Item1);
164          quality = selected.Item2;
165          evaluation = selected.Item3;
166        }
167      }
168    }
169
170    private static NMove Move(IRandom random, IntegerVector assignment, double oneMoveProbability, DoubleArray capacities) {
171      if (random.NextDouble() < oneMoveProbability)
172        return StochasticNMoveSingleMoveGenerator.GenerateOneMove(random, assignment, capacities);
173      return StochasticNMoveSingleMoveGenerator.GenerateTwoMove(random, assignment, capacities);
174    }
175
176    public override IOperation Apply() {
177      var evaluation = EvaluationParameter.ActualValue;
178      var quality = QualityParameter.ActualValue;
179      var fit = quality.Value;
180      var evaluatedSolutions = 0;
181
182      Apply(RandomParameter.ActualValue,
183        AssignmentParameter.ActualValue,
184        ref fit,
185        ref evaluation,
186        MaximumCandidateListSizeParameter.ActualValue.Value,
187        OneMoveProbabilityParameter.ActualValue.Value,
188        MaximumIterationsParameter.ActualValue.Value,
189        ProblemInstanceParameter.ActualValue,
190        out evaluatedSolutions,
191        GreedyParameter.ActualValue.Value);
192
193      EvaluationParameter.ActualValue = evaluation;
194      quality.Value = fit;
195      EvaluatedSolutionsParameter.ActualValue.Value += evaluatedSolutions;
196      return base.Apply();
197    }
198  }
199}
Note: See TracBrowser for help on using the repository browser.