Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs @ 7870

Last change on this file since 7870 was 7768, checked in by abeham, 13 years ago

#1722

  • Added a check before parameterizing operators if there are any in the collection
File size: 20.8 KB
RevLine 
[5558]1#region License Information
2/* HeuristicLab
[7259]3 * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[5558]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;
[7626]23using System.Collections.Generic;
[5558]24using System.Drawing;
25using System.Linq;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Data;
29using HeuristicLab.Encodings.PermutationEncoding;
30using HeuristicLab.Optimization;
31using HeuristicLab.Parameters;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
[5562]33using HeuristicLab.PluginInfrastructure;
[7558]34using HeuristicLab.Problems.Instances;
[5558]35
36namespace HeuristicLab.Problems.QuadraticAssignment {
[5838]37  [Item("Quadratic Assignment Problem", "The Quadratic Assignment Problem (QAP) can be described as the problem of assigning N facilities to N fixed locations such that there is exactly one facility in each location and that the sum of the distances multiplied by the connection strength between the facilities becomes minimal.")]
[5558]38  [Creatable("Problems")]
39  [StorableClass]
[7558]40  public sealed class QuadraticAssignmentProblem : SingleObjectiveHeuristicOptimizationProblem<IQAPEvaluator, IPermutationCreator>, IStorableContent,
41    IProblemInstanceConsumer<QAPData>,
42    IProblemInstanceConsumer<TSPData> {
[5953]43    public string Filename { get; set; }
44
[7201]45    public static new Image StaticItemImage {
[5558]46      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
47    }
48
49    #region Parameter Properties
[6525]50    public IValueParameter<ItemSet<Permutation>> BestKnownSolutionsParameter {
51      get { return (IValueParameter<ItemSet<Permutation>>)Parameters["BestKnownSolutions"]; }
[6342]52    }
[5641]53    public IValueParameter<Permutation> BestKnownSolutionParameter {
54      get { return (IValueParameter<Permutation>)Parameters["BestKnownSolution"]; }
[5558]55    }
[5641]56    public IValueParameter<DoubleMatrix> WeightsParameter {
57      get { return (IValueParameter<DoubleMatrix>)Parameters["Weights"]; }
[5558]58    }
[5838]59    public IValueParameter<DoubleMatrix> DistancesParameter {
60      get { return (IValueParameter<DoubleMatrix>)Parameters["Distances"]; }
[5558]61    }
62    #endregion
63
64    #region Properties
[6525]65    public ItemSet<Permutation> BestKnownSolutions {
[6342]66      get { return BestKnownSolutionsParameter.Value; }
67      set { BestKnownSolutionsParameter.Value = value; }
68    }
[5558]69    public Permutation BestKnownSolution {
70      get { return BestKnownSolutionParameter.Value; }
71      set { BestKnownSolutionParameter.Value = value; }
72    }
73    public DoubleMatrix Weights {
74      get { return WeightsParameter.Value; }
75      set { WeightsParameter.Value = value; }
76    }
[5838]77    public DoubleMatrix Distances {
78      get { return DistancesParameter.Value; }
79      set { DistancesParameter.Value = value; }
[5558]80    }
[5563]81
[5583]82    private BestQAPSolutionAnalyzer BestQAPSolutionAnalyzer {
83      get { return Operators.OfType<BestQAPSolutionAnalyzer>().FirstOrDefault(); }
84    }
[6342]85
86    private QAPAlleleFrequencyAnalyzer QAPAlleleFrequencyAnalyzer {
87      get { return Operators.OfType<QAPAlleleFrequencyAnalyzer>().FirstOrDefault(); }
88    }
89
90    private QAPPopulationDiversityAnalyzer QAPPopulationDiversityAnalyzer {
91      get { return Operators.OfType<QAPPopulationDiversityAnalyzer>().FirstOrDefault(); }
92    }
[5558]93    #endregion
94
95    [StorableConstructor]
96    private QuadraticAssignmentProblem(bool deserializing) : base(deserializing) { }
[5562]97    private QuadraticAssignmentProblem(QuadraticAssignmentProblem original, Cloner cloner)
[5558]98      : base(original, cloner) {
[7351]99      RegisterEventHandlers();
[5558]100    }
101    public QuadraticAssignmentProblem()
[5931]102      : base(new QAPEvaluator(), new RandomPermutationCreator()) {
[6525]103      Parameters.Add(new OptionalValueParameter<ItemSet<Permutation>>("BestKnownSolutions", "The list of best known solutions which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", null));
[5648]104      Parameters.Add(new OptionalValueParameter<Permutation>("BestKnownSolution", "The best known solution which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", null));
[5558]105      Parameters.Add(new ValueParameter<DoubleMatrix>("Weights", "The strength of the connection between the facilities.", new DoubleMatrix(5, 5)));
[5838]106      Parameters.Add(new ValueParameter<DoubleMatrix>("Distances", "The distance matrix which can either be specified directly without the coordinates, or can be calculated automatically from the coordinates.", new DoubleMatrix(5, 5)));
[5558]107
[6939]108      Maximization.Value = false;
109      MaximizationParameter.Hidden = true;
[5563]110
[5558]111      Weights = new DoubleMatrix(new double[,] {
112        { 0, 1, 0, 0, 1 },
113        { 1, 0, 1, 0, 0 },
114        { 0, 1, 0, 1, 0 },
115        { 0, 0, 1, 0, 1 },
116        { 1, 0, 0, 1, 0 }
117      });
118
[5838]119      Distances = new DoubleMatrix(new double[,] {
[5558]120        {   0, 360, 582, 582, 360 },
121        { 360,   0, 360, 582, 582 },
122        { 582, 360,   0, 360, 582 },
123        { 582, 582, 360,   0, 360 },
124        { 360, 582, 582, 360,   0 }
125      });
126
[5931]127      SolutionCreator.PermutationParameter.ActualName = "Assignment";
128      ParameterizeSolutionCreator();
129      ParameterizeEvaluator();
[5558]130
131      InitializeOperators();
[7351]132      RegisterEventHandlers();
[5558]133    }
134
135    public override IDeepCloneable Clone(Cloner cloner) {
136      return new QuadraticAssignmentProblem(this, cloner);
137    }
138
[6342]139    [StorableHook(HookType.AfterDeserialization)]
140    private void AfterDeserialization() {
141      // BackwardsCompatibility3.3
142      #region Backwards compatible code, remove with 3.4
143      if (!Parameters.ContainsKey("BestKnownSolutions")) {
[6525]144        Parameters.Add(new OptionalValueParameter<ItemSet<Permutation>>("BestKnownSolutions", "The list of best known solutions which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", null));
145      } else if (Parameters["BestKnownSolutions"].GetType().Equals(typeof(OptionalValueParameter<ItemList<Permutation>>))) {
146        ItemList<Permutation> list = ((OptionalValueParameter<ItemList<Permutation>>)Parameters["BestKnownSolutions"]).Value;
[6540]147        Parameters.Remove("BestKnownSolutions");
[6571]148        Parameters.Add(new OptionalValueParameter<ItemSet<Permutation>>("BestKnownSolutions", "The list of best known solutions which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", (list != null ? new ItemSet<Permutation>(list) : null)));
[6342]149      }
150      if (Parameters.ContainsKey("DistanceMatrix")) {
[6525]151        DoubleMatrix d = ((ValueParameter<DoubleMatrix>)Parameters["DistanceMatrix"]).Value;
[6342]152        Parameters.Remove("DistanceMatrix");
[6525]153        Parameters.Add(new ValueParameter<DoubleMatrix>("Distances", "The distance matrix which can either be specified directly without the coordinates, or can be calculated automatically from the coordinates.", d));
[6342]154      }
[7351]155      RegisterEventHandlers();
[6342]156      #endregion
157    }
158
[5558]159    #region Events
[5562]160    protected override void OnSolutionCreatorChanged() {
161      SolutionCreator.PermutationParameter.ActualNameChanged += new EventHandler(SolutionCreator_PermutationParameter_ActualNameChanged);
162      ParameterizeSolutionCreator();
163      ParameterizeEvaluator();
[5583]164      ParameterizeAnalyzers();
[5562]165      ParameterizeOperators();
166      base.OnSolutionCreatorChanged();
[5558]167    }
[5562]168    protected override void OnEvaluatorChanged() {
[5583]169      Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
[5562]170      ParameterizeEvaluator();
[5583]171      ParameterizeAnalyzers();
[5562]172      ParameterizeOperators();
173      base.OnEvaluatorChanged();
[5558]174    }
[5562]175
176    private void SolutionCreator_PermutationParameter_ActualNameChanged(object sender, EventArgs e) {
177      ParameterizeEvaluator();
[5583]178      ParameterizeAnalyzers();
[5562]179      ParameterizeOperators();
[5558]180    }
[5583]181    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
182      ParameterizeAnalyzers();
183      ParameterizeOperators();
184    }
[5562]185    private void WeightsParameter_ValueChanged(object sender, EventArgs e) {
186      Weights.RowsChanged += new EventHandler(Weights_RowsChanged);
[5855]187      Weights.ColumnsChanged += new EventHandler(Weights_ColumnsChanged);
[5562]188      ParameterizeSolutionCreator();
189      ParameterizeEvaluator();
190      ParameterizeOperators();
[5855]191      AdjustDistanceMatrix();
[5558]192    }
[5562]193    private void Weights_RowsChanged(object sender, EventArgs e) {
[5855]194      if (Weights.Rows != Weights.Columns)
195        ((IStringConvertibleMatrix)Weights).Columns = Weights.Rows;
196      else {
197        ParameterizeSolutionCreator();
198        ParameterizeEvaluator();
199        ParameterizeOperators();
200        AdjustDistanceMatrix();
201      }
202    }
203    private void Weights_ColumnsChanged(object sender, EventArgs e) {
204      if (Weights.Rows != Weights.Columns)
205        ((IStringConvertibleMatrix)Weights).Rows = Weights.Columns;
206      else {
207        ParameterizeSolutionCreator();
208        ParameterizeEvaluator();
209        ParameterizeOperators();
210        AdjustDistanceMatrix();
211      }
212    }
213    private void DistancesParameter_ValueChanged(object sender, EventArgs e) {
214      Distances.RowsChanged += new EventHandler(Distances_RowsChanged);
215      Distances.ColumnsChanged += new EventHandler(Distances_ColumnsChanged);
[5562]216      ParameterizeSolutionCreator();
217      ParameterizeEvaluator();
218      ParameterizeOperators();
[5855]219      AdjustWeightsMatrix();
[5562]220    }
[5855]221    private void Distances_RowsChanged(object sender, EventArgs e) {
222      if (Distances.Rows != Distances.Columns)
223        ((IStringConvertibleMatrix)Distances).Columns = Distances.Rows;
224      else {
225        ParameterizeSolutionCreator();
226        ParameterizeEvaluator();
227        ParameterizeOperators();
228        AdjustWeightsMatrix();
229      }
230    }
231    private void Distances_ColumnsChanged(object sender, EventArgs e) {
232      if (Distances.Rows != Distances.Columns)
233        ((IStringConvertibleMatrix)Distances).Rows = Distances.Columns;
234      else {
235        ParameterizeSolutionCreator();
236        ParameterizeEvaluator();
237        ParameterizeOperators();
238        AdjustWeightsMatrix();
239      }
240    }
[5558]241    #endregion
242
243    #region Helpers
[7351]244    private void RegisterEventHandlers() {
[5598]245      SolutionCreator.PermutationParameter.ActualNameChanged += new EventHandler(SolutionCreator_PermutationParameter_ActualNameChanged);
246      Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
[5562]247      WeightsParameter.ValueChanged += new EventHandler(WeightsParameter_ValueChanged);
248      Weights.RowsChanged += new EventHandler(Weights_RowsChanged);
[5855]249      Weights.ColumnsChanged += new EventHandler(Weights_ColumnsChanged);
250      DistancesParameter.ValueChanged += new EventHandler(DistancesParameter_ValueChanged);
251      Distances.RowsChanged += new EventHandler(Distances_RowsChanged);
252      Distances.ColumnsChanged += new EventHandler(Distances_ColumnsChanged);
[5558]253    }
254
255    private void InitializeOperators() {
[7626]256      var defaultOperators = new HashSet<IPermutationOperator>(new IPermutationOperator[] {
257        new PartiallyMatchedCrossover(),
258        new Swap2Manipulator(),
259        new ExhaustiveSwap2MoveGenerator()
260      });
261      Operators.AddRange(defaultOperators);
262      Operators.AddRange(ApplicationManager.Manager.GetInstances<IPermutationOperator>().Except(defaultOperators, new TypeEqualityComparer<IPermutationOperator>()));
[6088]263      Operators.RemoveAll(x => x is ISingleObjectiveMoveEvaluator);
264      Operators.AddRange(ApplicationManager.Manager.GetInstances<IQAPMoveEvaluator>());
[5583]265      Operators.Add(new BestQAPSolutionAnalyzer());
[6342]266      Operators.Add(new QAPAlleleFrequencyAnalyzer());
267      Operators.Add(new QAPPopulationDiversityAnalyzer());
268      Operators.Add(new QAPExhaustiveSwap2LocalImprovement());
[5583]269      ParameterizeAnalyzers();
[5563]270      ParameterizeOperators();
[5558]271    }
272    private void ParameterizeSolutionCreator() {
[5563]273      if (SolutionCreator != null) {
274        SolutionCreator.PermutationTypeParameter.Value = new PermutationType(PermutationTypes.Absolute);
275        SolutionCreator.LengthParameter.Value = new IntValue(Weights.Rows);
276      }
[5558]277    }
278    private void ParameterizeEvaluator() {
[5563]279      if (Evaluator != null) {
280        Evaluator.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
[5838]281        Evaluator.DistancesParameter.ActualName = DistancesParameter.Name;
[5563]282        Evaluator.WeightsParameter.ActualName = WeightsParameter.Name;
283      }
[5558]284    }
[5583]285    private void ParameterizeAnalyzers() {
286      if (BestQAPSolutionAnalyzer != null) {
287        BestQAPSolutionAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
[5838]288        BestQAPSolutionAnalyzer.DistancesParameter.ActualName = DistancesParameter.Name;
[5583]289        BestQAPSolutionAnalyzer.WeightsParameter.ActualName = WeightsParameter.Name;
290        BestQAPSolutionAnalyzer.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
291        BestQAPSolutionAnalyzer.ResultsParameter.ActualName = "Results";
292        BestQAPSolutionAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
[6342]293        BestQAPSolutionAnalyzer.BestKnownSolutionsParameter.ActualName = BestKnownSolutionsParameter.Name;
[5583]294        BestQAPSolutionAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
295      }
[6342]296      if (QAPAlleleFrequencyAnalyzer != null) {
297        QAPAlleleFrequencyAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
298        QAPAlleleFrequencyAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
299        QAPAlleleFrequencyAnalyzer.DistancesParameter.ActualName = DistancesParameter.Name;
300        QAPAlleleFrequencyAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
301        QAPAlleleFrequencyAnalyzer.ResultsParameter.ActualName = "Results";
302        QAPAlleleFrequencyAnalyzer.SolutionParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
303        QAPAlleleFrequencyAnalyzer.WeightsParameter.ActualName = WeightsParameter.Name;
304      }
305      if (QAPPopulationDiversityAnalyzer != null) {
306        QAPPopulationDiversityAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
307        QAPPopulationDiversityAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
308        QAPPopulationDiversityAnalyzer.ResultsParameter.ActualName = "Results";
309        QAPPopulationDiversityAnalyzer.SolutionParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
310      }
[5583]311    }
[5562]312    private void ParameterizeOperators() {
313      foreach (IPermutationCrossover op in Operators.OfType<IPermutationCrossover>()) {
314        op.ParentsParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
315        op.ChildParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
316      }
317      foreach (IPermutationManipulator op in Operators.OfType<IPermutationManipulator>()) {
318        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
319      }
320      foreach (IPermutationMoveOperator op in Operators.OfType<IPermutationMoveOperator>()) {
321        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
322      }
[5563]323      if (Operators.OfType<IMoveGenerator>().Any()) {
[7768]324        if (Operators.OfType<IMoveGenerator>().OfType<IPermutationInversionMoveOperator>().Any()) {
325          string inversionMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationInversionMoveOperator>().First().InversionMoveParameter.ActualName;
326          foreach (IPermutationInversionMoveOperator op in Operators.OfType<IPermutationInversionMoveOperator>())
327            op.InversionMoveParameter.ActualName = inversionMove;
[5785]328        }
[7768]329        if (Operators.OfType<IMoveGenerator>().OfType<IPermutationTranslocationMoveOperator>().Any()) {
330          string translocationMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationTranslocationMoveOperator>().First().TranslocationMoveParameter.ActualName;
331          foreach (IPermutationTranslocationMoveOperator op in Operators.OfType<IPermutationTranslocationMoveOperator>())
332            op.TranslocationMoveParameter.ActualName = translocationMove;
333        }
334        if (Operators.OfType<IMoveGenerator>().OfType<IPermutationSwap2MoveOperator>().Any()) {
335          string swapMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationSwap2MoveOperator>().First().Swap2MoveParameter.ActualName;
336          foreach (IPermutationSwap2MoveOperator op in Operators.OfType<IPermutationSwap2MoveOperator>()) {
337            op.Swap2MoveParameter.ActualName = swapMove;
338          }
339        }
[5563]340      }
[6042]341      foreach (var op in Operators.OfType<IPermutationMultiNeighborhoodShakingOperator>())
342        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
[6342]343
344      QAPExhaustiveSwap2LocalImprovement localOpt = Operators.OfType<QAPExhaustiveSwap2LocalImprovement>().SingleOrDefault();
345      if (localOpt != null) {
346        localOpt.AssignmentParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
347        localOpt.DistancesParameter.ActualName = DistancesParameter.Name;
348        localOpt.MaximizationParameter.ActualName = MaximizationParameter.Name;
349        localOpt.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
350        localOpt.WeightsParameter.ActualName = WeightsParameter.Name;
351      }
[5562]352    }
[5598]353
[5855]354    private void AdjustDistanceMatrix() {
355      if (Distances.Rows != Weights.Rows || Distances.Columns != Weights.Columns) {
356        ((IStringConvertibleMatrix)Distances).Rows = Weights.Rows;
357      }
358    }
359
360    private void AdjustWeightsMatrix() {
361      if (Weights.Rows != Distances.Rows || Weights.Columns != Distances.Columns) {
362        ((IStringConvertibleMatrix)Weights).Rows = Distances.Rows;
363      }
364    }
[5558]365    #endregion
[5562]366
[7558]367    public void Load(QAPData data) {
368      var weights = new DoubleMatrix(data.Weights);
369      var distances = new DoubleMatrix(data.Distances);
[7641]370      Name = data.Name;
371      Description = data.Description;
[7558]372      Load(weights, distances);
373      EvaluateAndLoadAssignment(data.BestKnownAssignment);
[5562]374      OnReset();
375    }
[5563]376
[7558]377    public void Load(TSPData data) {
378      if (data.Dimension > 1000)
379        throw new System.IO.InvalidDataException("Instances with more than 1000 customers are not supported by the QAP.");
380      var weights = new DoubleMatrix(data.Dimension, data.Dimension);
381      for (int i = 0; i < data.Dimension; i++)
382        weights[i, (i + 1) % data.Dimension] = 1;
383      var distances = new DoubleMatrix(data.GetDistanceMatrix());
[7641]384      Name = data.Name;
385      Description = data.Description;
[7558]386      Load(weights, distances);
387      EvaluateAndLoadAssignment(data.BestKnownTour);
[6891]388      OnReset();
[5563]389    }
[6952]390
[7558]391    public void Load(DoubleMatrix weights, DoubleMatrix distances) {
392      if (weights == null || weights.Rows == 0)
393        throw new System.IO.InvalidDataException("The given instance does not contain weights!");
394      if (weights.Rows != weights.Columns)
395        throw new System.IO.InvalidDataException("The weights matrix is not a square matrix!");
396      if (distances == null || distances.Rows == 0)
397        throw new System.IO.InvalidDataException("The given instance does not contain distances!");
398      if (distances.Rows != distances.Columns)
399        throw new System.IO.InvalidDataException("The distances matrix is not a square matrix!");
400      if (weights.Rows != distances.Columns)
401        throw new System.IO.InvalidDataException("The weights matrix and the distance matrix are not of equal size!");
[6952]402
[7558]403      Weights = weights;
404      Distances = distances;
[6952]405
[7558]406      BestKnownQuality = null;
407      BestKnownSolution = null;
408      BestKnownSolutions = null;
409    }
[6952]410
[7558]411    public void EvaluateAndLoadAssignment(int[] assignment) {
412      if (assignment == null || assignment.Length == 0) return;
413      var vector = new Permutation(PermutationTypes.Absolute, assignment);
414      var result = QAPEvaluator.Apply(vector, Weights, Distances);
415      BestKnownQuality = new DoubleValue(result);
416      BestKnownSolution = vector;
417      BestKnownSolutions = new ItemSet<Permutation>();
418      BestKnownSolutions.Add((Permutation)vector.Clone());
[6952]419    }
[5558]420  }
421}
Note: See TracBrowser for help on using the repository browser.