source: branches/ProblemRefactoring/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs @ 13377

Last change on this file since 13377 was 13377, checked in by mkommend, 4 years ago

#2521: Added missing interfaces to problems.

File size: 25.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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.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;
33using HeuristicLab.PluginInfrastructure;
34using HeuristicLab.Problems.Instances;
35
36namespace HeuristicLab.Problems.QuadraticAssignment {
37  [Item("Quadratic Assignment Problem (QAP)", "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.")]
38  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 140)]
39  [StorableClass]
40  public sealed class QuadraticAssignmentProblem : SingleObjectiveHeuristicOptimizationProblem<IQAPEvaluator, IPermutationCreator>,
41    ISingleObjectiveProblem<PermutationEncoding, Permutation>, IStorableContent,
42    IProblemInstanceConsumer<QAPData>,
43    IProblemInstanceConsumer<TSPData> {
44    public string Filename { get; set; }
45
46    public static new Image StaticItemImage {
47      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
48    }
49
50    #region Parameter Properties
51    public IValueParameter<ItemSet<Permutation>> BestKnownSolutionsParameter {
52      get { return (IValueParameter<ItemSet<Permutation>>)Parameters["BestKnownSolutions"]; }
53    }
54    public IValueParameter<Permutation> BestKnownSolutionParameter {
55      get { return (IValueParameter<Permutation>)Parameters["BestKnownSolution"]; }
56    }
57    public IValueParameter<DoubleMatrix> WeightsParameter {
58      get { return (IValueParameter<DoubleMatrix>)Parameters["Weights"]; }
59    }
60    public IValueParameter<DoubleMatrix> DistancesParameter {
61      get { return (IValueParameter<DoubleMatrix>)Parameters["Distances"]; }
62    }
63    public IValueParameter<DoubleValue> LowerBoundParameter {
64      get { return (IValueParameter<DoubleValue>)Parameters["LowerBound"]; }
65    }
66    public IValueParameter<DoubleValue> AverageQualityParameter {
67      get { return (IValueParameter<DoubleValue>)Parameters["AverageQuality"]; }
68    }
69    #endregion
70
71    #region Properties
72    public ItemSet<Permutation> BestKnownSolutions {
73      get { return BestKnownSolutionsParameter.Value; }
74      set { BestKnownSolutionsParameter.Value = value; }
75    }
76    public Permutation BestKnownSolution {
77      get { return BestKnownSolutionParameter.Value; }
78      set { BestKnownSolutionParameter.Value = value; }
79    }
80    public DoubleMatrix Weights {
81      get { return WeightsParameter.Value; }
82      set { WeightsParameter.Value = value; }
83    }
84    public DoubleMatrix Distances {
85      get { return DistancesParameter.Value; }
86      set { DistancesParameter.Value = value; }
87    }
88    public DoubleValue LowerBound {
89      get { return LowerBoundParameter.Value; }
90      set { LowerBoundParameter.Value = value; }
91    }
92    public DoubleValue AverageQuality {
93      get { return AverageQualityParameter.Value; }
94      set { AverageQualityParameter.Value = value; }
95    }
96
97    private BestQAPSolutionAnalyzer BestQAPSolutionAnalyzer {
98      get { return Operators.OfType<BestQAPSolutionAnalyzer>().FirstOrDefault(); }
99    }
100
101    private QAPAlleleFrequencyAnalyzer QAPAlleleFrequencyAnalyzer {
102      get { return Operators.OfType<QAPAlleleFrequencyAnalyzer>().FirstOrDefault(); }
103    }
104
105    private QAPPopulationDiversityAnalyzer QAPPopulationDiversityAnalyzer {
106      get { return Operators.OfType<QAPPopulationDiversityAnalyzer>().FirstOrDefault(); }
107    }
108    #endregion
109
110    [StorableConstructor]
111    private QuadraticAssignmentProblem(bool deserializing) : base(deserializing) { }
112    private QuadraticAssignmentProblem(QuadraticAssignmentProblem original, Cloner cloner)
113      : base(original, cloner) {
114      RegisterEventHandlers();
115    }
116    public QuadraticAssignmentProblem()
117      : base(new QAPEvaluator(), new RandomPermutationCreator()) {
118      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));
119      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));
120      Parameters.Add(new ValueParameter<DoubleMatrix>("Weights", "The strength of the connection between the facilities.", new DoubleMatrix(5, 5)));
121      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)));
122      Parameters.Add(new OptionalValueParameter<DoubleValue>("LowerBound", "The Gilmore-Lawler lower bound to the solution quality."));
123      Parameters.Add(new OptionalValueParameter<DoubleValue>("AverageQuality", "The expected quality of a random solution."));
124
125      Maximization.Value = false;
126      MaximizationParameter.Hidden = true;
127
128      WeightsParameter.GetsCollected = false;
129      Weights = new DoubleMatrix(new double[,] {
130        { 0, 1, 0, 0, 1 },
131        { 1, 0, 1, 0, 0 },
132        { 0, 1, 0, 1, 0 },
133        { 0, 0, 1, 0, 1 },
134        { 1, 0, 0, 1, 0 }
135      });
136
137      DistancesParameter.GetsCollected = false;
138      Distances = new DoubleMatrix(new double[,] {
139        {   0, 360, 582, 582, 360 },
140        { 360,   0, 360, 582, 582 },
141        { 582, 360,   0, 360, 582 },
142        { 582, 582, 360,   0, 360 },
143        { 360, 582, 582, 360,   0 }
144      });
145
146      SolutionCreator.PermutationParameter.ActualName = "Assignment";
147      ParameterizeSolutionCreator();
148      ParameterizeEvaluator();
149
150      InitializeOperators();
151      RegisterEventHandlers();
152    }
153
154    public override IDeepCloneable Clone(Cloner cloner) {
155      return new QuadraticAssignmentProblem(this, cloner);
156    }
157
158    [StorableHook(HookType.AfterDeserialization)]
159    private void AfterDeserialization() {
160      // BackwardsCompatibility3.3
161      #region Backwards compatible code, remove with 3.4
162      if (!Parameters.ContainsKey("BestKnownSolutions")) {
163        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));
164      } else if (Parameters["BestKnownSolutions"].GetType().Equals(typeof(OptionalValueParameter<ItemList<Permutation>>))) {
165        ItemList<Permutation> list = ((OptionalValueParameter<ItemList<Permutation>>)Parameters["BestKnownSolutions"]).Value;
166        Parameters.Remove("BestKnownSolutions");
167        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)));
168      }
169      if (Parameters.ContainsKey("DistanceMatrix")) {
170        DoubleMatrix d = ((ValueParameter<DoubleMatrix>)Parameters["DistanceMatrix"]).Value;
171        Parameters.Remove("DistanceMatrix");
172        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));
173      }
174      if (!Parameters.ContainsKey("LowerBound")) {
175        Parameters.Add(new OptionalValueParameter<DoubleValue>("LowerBound", "The Gilmore-Lawler lower bound to the solution quality."));
176        LowerBound = new DoubleValue(GilmoreLawlerBoundCalculator.CalculateLowerBound(Weights, Distances));
177      }
178      if (!Parameters.ContainsKey("AverageQuality")) {
179        Parameters.Add(new OptionalValueParameter<DoubleValue>("AverageQuality", "The expected quality of a random solution."));
180        AverageQuality = new DoubleValue(ComputeAverageQuality());
181      }
182      #endregion
183      RegisterEventHandlers();
184    }
185
186    #region Events
187    protected override void OnSolutionCreatorChanged() {
188      SolutionCreator.PermutationParameter.ActualNameChanged += new EventHandler(SolutionCreator_PermutationParameter_ActualNameChanged);
189      ParameterizeSolutionCreator();
190      ParameterizeEvaluator();
191      ParameterizeAnalyzers();
192      ParameterizeOperators();
193      base.OnSolutionCreatorChanged();
194    }
195    protected override void OnEvaluatorChanged() {
196      Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
197      ParameterizeEvaluator();
198      ParameterizeAnalyzers();
199      ParameterizeOperators();
200      base.OnEvaluatorChanged();
201    }
202
203    private void SolutionCreator_PermutationParameter_ActualNameChanged(object sender, EventArgs e) {
204      ParameterizeEvaluator();
205      ParameterizeAnalyzers();
206      ParameterizeOperators();
207    }
208    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
209      ParameterizeAnalyzers();
210      ParameterizeOperators();
211    }
212    private void WeightsParameter_ValueChanged(object sender, EventArgs e) {
213      Weights.RowsChanged += new EventHandler(Weights_RowsChanged);
214      Weights.ColumnsChanged += new EventHandler(Weights_ColumnsChanged);
215      Weights.ToStringChanged += new EventHandler(Weights_ToStringChanged);
216      ParameterizeSolutionCreator();
217      ParameterizeEvaluator();
218      ParameterizeOperators();
219      AdjustDistanceMatrix();
220    }
221    private void Weights_RowsChanged(object sender, EventArgs e) {
222      if (Weights.Rows != Weights.Columns)
223        ((IStringConvertibleMatrix)Weights).Columns = Weights.Rows;
224      else {
225        ParameterizeSolutionCreator();
226        ParameterizeEvaluator();
227        ParameterizeOperators();
228        AdjustDistanceMatrix();
229      }
230    }
231    private void Weights_ColumnsChanged(object sender, EventArgs e) {
232      if (Weights.Rows != Weights.Columns)
233        ((IStringConvertibleMatrix)Weights).Rows = Weights.Columns;
234      else {
235        ParameterizeSolutionCreator();
236        ParameterizeEvaluator();
237        ParameterizeOperators();
238        AdjustDistanceMatrix();
239      }
240    }
241    private void Weights_ToStringChanged(object sender, EventArgs e) {
242      UpdateParameterValues();
243    }
244    private void DistancesParameter_ValueChanged(object sender, EventArgs e) {
245      Distances.RowsChanged += new EventHandler(Distances_RowsChanged);
246      Distances.ColumnsChanged += new EventHandler(Distances_ColumnsChanged);
247      Distances.ToStringChanged += new EventHandler(Distances_ToStringChanged);
248      ParameterizeSolutionCreator();
249      ParameterizeEvaluator();
250      ParameterizeOperators();
251      AdjustWeightsMatrix();
252    }
253    private void Distances_RowsChanged(object sender, EventArgs e) {
254      if (Distances.Rows != Distances.Columns)
255        ((IStringConvertibleMatrix)Distances).Columns = Distances.Rows;
256      else {
257        ParameterizeSolutionCreator();
258        ParameterizeEvaluator();
259        ParameterizeOperators();
260        AdjustWeightsMatrix();
261      }
262    }
263    private void Distances_ColumnsChanged(object sender, EventArgs e) {
264      if (Distances.Rows != Distances.Columns)
265        ((IStringConvertibleMatrix)Distances).Rows = Distances.Columns;
266      else {
267        ParameterizeSolutionCreator();
268        ParameterizeEvaluator();
269        ParameterizeOperators();
270        AdjustWeightsMatrix();
271      }
272    }
273    private void Distances_ToStringChanged(object sender, EventArgs e) {
274      UpdateParameterValues();
275    }
276    #endregion
277
278    private void RegisterEventHandlers() {
279      SolutionCreator.PermutationParameter.ActualNameChanged += new EventHandler(SolutionCreator_PermutationParameter_ActualNameChanged);
280      Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
281      WeightsParameter.ValueChanged += new EventHandler(WeightsParameter_ValueChanged);
282      Weights.RowsChanged += new EventHandler(Weights_RowsChanged);
283      Weights.ColumnsChanged += new EventHandler(Weights_ColumnsChanged);
284      Weights.ToStringChanged += new EventHandler(Weights_ToStringChanged);
285      DistancesParameter.ValueChanged += new EventHandler(DistancesParameter_ValueChanged);
286      Distances.RowsChanged += new EventHandler(Distances_RowsChanged);
287      Distances.ColumnsChanged += new EventHandler(Distances_ColumnsChanged);
288      Distances.ToStringChanged += new EventHandler(Distances_ToStringChanged);
289    }
290
291    #region Helpers
292    private void InitializeOperators() {
293      var defaultOperators = new HashSet<IPermutationOperator>(new IPermutationOperator[] {
294        new PartiallyMatchedCrossover(),
295        new Swap2Manipulator(),
296        new ExhaustiveSwap2MoveGenerator()
297      });
298      Operators.AddRange(defaultOperators);
299      Operators.AddRange(ApplicationManager.Manager.GetInstances<IPermutationOperator>().Except(defaultOperators, new TypeEqualityComparer<IPermutationOperator>()));
300      Operators.RemoveAll(x => x is ISingleObjectiveMoveEvaluator);
301      Operators.AddRange(ApplicationManager.Manager.GetInstances<IQAPMoveEvaluator>());
302      Operators.Add(new BestQAPSolutionAnalyzer());
303      Operators.Add(new QAPAlleleFrequencyAnalyzer());
304      Operators.Add(new QAPPopulationDiversityAnalyzer());
305
306      Operators.Add(new QAPExhaustiveInsertionLocalImprovement());
307      Operators.Add(new QAPExhaustiveInversionLocalImprovement());
308      Operators.Add(new QAPStochasticScrambleLocalImprovement());
309      Operators.Add(new QAPExhaustiveSwap2LocalImprovement());
310
311      Operators.Add(new QAPSimilarityCalculator());
312      ParameterizeAnalyzers();
313      ParameterizeOperators();
314    }
315    private void ParameterizeSolutionCreator() {
316      if (SolutionCreator != null) {
317        SolutionCreator.PermutationTypeParameter.Value = new PermutationType(PermutationTypes.Absolute);
318        SolutionCreator.LengthParameter.Value = new IntValue(Weights.Rows);
319      }
320    }
321    private void ParameterizeEvaluator() {
322      if (Evaluator != null) {
323        Evaluator.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
324        Evaluator.DistancesParameter.ActualName = DistancesParameter.Name;
325        Evaluator.WeightsParameter.ActualName = WeightsParameter.Name;
326      }
327    }
328    private void ParameterizeAnalyzers() {
329      if (BestQAPSolutionAnalyzer != null) {
330        BestQAPSolutionAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
331        BestQAPSolutionAnalyzer.DistancesParameter.ActualName = DistancesParameter.Name;
332        BestQAPSolutionAnalyzer.WeightsParameter.ActualName = WeightsParameter.Name;
333        BestQAPSolutionAnalyzer.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
334        BestQAPSolutionAnalyzer.ResultsParameter.ActualName = "Results";
335        BestQAPSolutionAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
336        BestQAPSolutionAnalyzer.BestKnownSolutionsParameter.ActualName = BestKnownSolutionsParameter.Name;
337        BestQAPSolutionAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
338      }
339      if (QAPAlleleFrequencyAnalyzer != null) {
340        QAPAlleleFrequencyAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
341        QAPAlleleFrequencyAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
342        QAPAlleleFrequencyAnalyzer.DistancesParameter.ActualName = DistancesParameter.Name;
343        QAPAlleleFrequencyAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
344        QAPAlleleFrequencyAnalyzer.ResultsParameter.ActualName = "Results";
345        QAPAlleleFrequencyAnalyzer.SolutionParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
346        QAPAlleleFrequencyAnalyzer.WeightsParameter.ActualName = WeightsParameter.Name;
347      }
348      if (QAPPopulationDiversityAnalyzer != null) {
349        QAPPopulationDiversityAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
350        QAPPopulationDiversityAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
351        QAPPopulationDiversityAnalyzer.ResultsParameter.ActualName = "Results";
352        QAPPopulationDiversityAnalyzer.SolutionParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
353      }
354    }
355    private void ParameterizeOperators() {
356      foreach (IPermutationCrossover op in Operators.OfType<IPermutationCrossover>()) {
357        op.ParentsParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
358        op.ChildParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
359      }
360      foreach (IPermutationManipulator op in Operators.OfType<IPermutationManipulator>()) {
361        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
362      }
363      foreach (IPermutationMoveOperator op in Operators.OfType<IPermutationMoveOperator>()) {
364        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
365      }
366      if (Operators.OfType<IMoveGenerator>().Any()) {
367        if (Operators.OfType<IMoveGenerator>().OfType<IPermutationInversionMoveOperator>().Any()) {
368          string inversionMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationInversionMoveOperator>().First().InversionMoveParameter.ActualName;
369          foreach (IPermutationInversionMoveOperator op in Operators.OfType<IPermutationInversionMoveOperator>())
370            op.InversionMoveParameter.ActualName = inversionMove;
371        }
372        if (Operators.OfType<IMoveGenerator>().OfType<IPermutationTranslocationMoveOperator>().Any()) {
373          string translocationMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationTranslocationMoveOperator>().First().TranslocationMoveParameter.ActualName;
374          foreach (IPermutationTranslocationMoveOperator op in Operators.OfType<IPermutationTranslocationMoveOperator>())
375            op.TranslocationMoveParameter.ActualName = translocationMove;
376        }
377        if (Operators.OfType<IMoveGenerator>().OfType<IPermutationSwap2MoveOperator>().Any()) {
378          string swapMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationSwap2MoveOperator>().First().Swap2MoveParameter.ActualName;
379          foreach (IPermutationSwap2MoveOperator op in Operators.OfType<IPermutationSwap2MoveOperator>()) {
380            op.Swap2MoveParameter.ActualName = swapMove;
381          }
382        }
383      }
384      foreach (var op in Operators.OfType<IPermutationMultiNeighborhoodShakingOperator>())
385        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
386
387      QAPExhaustiveSwap2LocalImprovement localOpt = Operators.OfType<QAPExhaustiveSwap2LocalImprovement>().SingleOrDefault();
388      if (localOpt != null) {
389        localOpt.AssignmentParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
390        localOpt.DistancesParameter.ActualName = DistancesParameter.Name;
391        localOpt.MaximizationParameter.ActualName = MaximizationParameter.Name;
392        localOpt.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
393        localOpt.WeightsParameter.ActualName = WeightsParameter.Name;
394      }
395
396      QAPSimilarityCalculator similarityCalculator = Operators.OfType<QAPSimilarityCalculator>().SingleOrDefault();
397      if (similarityCalculator != null) {
398        similarityCalculator.SolutionVariableName = SolutionCreator.PermutationParameter.ActualName;
399        similarityCalculator.QualityVariableName = Evaluator.QualityParameter.ActualName;
400      }
401    }
402
403    private void AdjustDistanceMatrix() {
404      if (Distances.Rows != Weights.Rows || Distances.Columns != Weights.Columns) {
405        ((IStringConvertibleMatrix)Distances).Rows = Weights.Rows;
406      }
407    }
408
409    private void AdjustWeightsMatrix() {
410      if (Weights.Rows != Distances.Rows || Weights.Columns != Distances.Columns) {
411        ((IStringConvertibleMatrix)Weights).Rows = Distances.Rows;
412      }
413    }
414
415    private void UpdateParameterValues() {
416      Permutation lbSolution;
417      // calculate the optimum of a LAP relaxation and use it as lower bound of our QAP
418      LowerBound = new DoubleValue(GilmoreLawlerBoundCalculator.CalculateLowerBound(Weights, Distances, out lbSolution));
419      // evalute the LAP optimal solution as if it was a QAP solution
420      var lbSolutionQuality = QAPEvaluator.Apply(lbSolution, Weights, Distances);
421      // in case both qualities are the same it means that the LAP optimum is also a QAP optimum
422      if (LowerBound.Value.IsAlmost(lbSolutionQuality)) {
423        BestKnownSolution = lbSolution;
424        BestKnownQuality = new DoubleValue(LowerBound.Value);
425      }
426      AverageQuality = new DoubleValue(ComputeAverageQuality());
427    }
428
429    private double ComputeAverageQuality() {
430      double rt = 0, rd = 0, wt = 0, wd = 0;
431      int n = Weights.Rows;
432      for (int i = 0; i < n; i++)
433        for (int j = 0; j < n; j++) {
434          if (i == j) {
435            rd += Distances[i, i];
436            wd += Weights[i, i];
437          } else {
438            rt += Distances[i, j];
439            wt += Weights[i, j];
440          }
441        }
442
443      return rt * wt / (n * (n - 1)) + rd * wd / n;
444    }
445    #endregion
446
447    public void Load(QAPData data) {
448      var weights = new DoubleMatrix(data.Weights);
449      var distances = new DoubleMatrix(data.Distances);
450      Name = data.Name;
451      Description = data.Description;
452      Load(weights, distances);
453      if (data.BestKnownQuality.HasValue) BestKnownQuality = new DoubleValue(data.BestKnownQuality.Value);
454      EvaluateAndLoadAssignment(data.BestKnownAssignment);
455      OnReset();
456    }
457
458    public void Load(TSPData data) {
459      if (data.Dimension > 1000)
460        throw new System.IO.InvalidDataException("Instances with more than 1000 customers are not supported by the QAP.");
461      var weights = new DoubleMatrix(data.Dimension, data.Dimension);
462      for (int i = 0; i < data.Dimension; i++)
463        weights[i, (i + 1) % data.Dimension] = 1;
464      var distances = new DoubleMatrix(data.GetDistanceMatrix());
465      Name = data.Name;
466      Description = data.Description;
467      Load(weights, distances);
468      if (data.BestKnownQuality.HasValue) BestKnownQuality = new DoubleValue(data.BestKnownQuality.Value);
469      EvaluateAndLoadAssignment(data.BestKnownTour);
470      OnReset();
471    }
472
473    public void Load(DoubleMatrix weights, DoubleMatrix distances) {
474      if (weights == null || weights.Rows == 0)
475        throw new System.IO.InvalidDataException("The given instance does not contain weights!");
476      if (weights.Rows != weights.Columns)
477        throw new System.IO.InvalidDataException("The weights matrix is not a square matrix!");
478      if (distances == null || distances.Rows == 0)
479        throw new System.IO.InvalidDataException("The given instance does not contain distances!");
480      if (distances.Rows != distances.Columns)
481        throw new System.IO.InvalidDataException("The distances matrix is not a square matrix!");
482      if (weights.Rows != distances.Columns)
483        throw new System.IO.InvalidDataException("The weights matrix and the distance matrix are not of equal size!");
484
485      Weights = weights;
486      Distances = distances;
487
488      BestKnownQuality = null;
489      BestKnownSolution = null;
490      BestKnownSolutions = null;
491      UpdateParameterValues();
492    }
493
494    public void EvaluateAndLoadAssignment(int[] assignment) {
495      if (assignment == null || assignment.Length == 0) return;
496      var vector = new Permutation(PermutationTypes.Absolute, assignment);
497      var result = QAPEvaluator.Apply(vector, Weights, Distances);
498      BestKnownQuality = new DoubleValue(result);
499      BestKnownSolution = vector;
500      BestKnownSolutions = new ItemSet<Permutation>();
501      BestKnownSolutions.Add((Permutation)vector.Clone());
502    }
503  }
504}
Note: See TracBrowser for help on using the repository browser.