Free cookie consent management tool by TermsFeed Policy Generator

source: branches/QAP/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs @ 5563

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

#1330

  • Added working version of QAP
File size: 11.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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.IO;
26using System.Linq;
27using System.Reflection;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Encodings.PermutationEncoding;
32using HeuristicLab.Optimization;
33using HeuristicLab.Parameters;
34using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
35using HeuristicLab.PluginInfrastructure;
36
37namespace HeuristicLab.Problems.QuadraticAssignment {
38  [Item("Quadratic Assignment Problem", "The Quadratic Assignment Problem (QAP) is the problem of assigning N facilities to N fixed locations such that there is exactly one facility in each location and that the distances multiplied by the connection strength between the facilities becomes minimal.")]
39  [Creatable("Problems")]
40  [StorableClass]
41  public sealed class QuadraticAssignmentProblem : SingleObjectiveProblem<IQAPEvaluator, IPermutationCreator> {
42    private static string InstancePrefix = "HeuristicLab.Problems.QuadraticAssignment.Data.";
43
44    public override Image ItemImage {
45      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
46    }
47
48    #region Parameter Properties
49    public ValueParameter<Permutation> BestKnownSolutionParameter {
50      get { return (ValueParameter<Permutation>)Parameters["BestKnownSolution"]; }
51    }
52    public ValueParameter<DoubleMatrix> CoordinatesParameter {
53      get { return (ValueParameter<DoubleMatrix>)Parameters["Coordinates"]; }
54    }
55    public ValueParameter<DoubleMatrix> WeightsParameter {
56      get { return (ValueParameter<DoubleMatrix>)Parameters["Weights"]; }
57    }
58    public ValueParameter<DoubleMatrix> DistanceMatrixParameter {
59      get { return (ValueParameter<DoubleMatrix>)Parameters["DistanceMatrix"]; }
60    }
61    public ValueParameter<BoolValue> UseDistanceMatrixParameter {
62      get { return (ValueParameter<BoolValue>)Parameters["UseDistanceMatrix"]; }
63    }
64
65    #endregion
66
67    #region Properties
68    public Permutation BestKnownSolution {
69      get { return BestKnownSolutionParameter.Value; }
70      set { BestKnownSolutionParameter.Value = value; }
71    }
72    public DoubleMatrix Coordinates {
73      get { return CoordinatesParameter.Value; }
74      set { CoordinatesParameter.Value = value; }
75    }
76    public DoubleMatrix Weights {
77      get { return WeightsParameter.Value; }
78      set { WeightsParameter.Value = value; }
79    }
80    public DoubleMatrix DistanceMatrix {
81      get { return DistanceMatrixParameter.Value; }
82      set { DistanceMatrixParameter.Value = value; }
83    }
84    public BoolValue UseDistanceMatrix {
85      get { return UseDistanceMatrixParameter.Value; }
86      set { UseDistanceMatrixParameter.Value = value; }
87    }
88
89    public IEnumerable<string> EmbeddedInstances {
90      get {
91        return Assembly.GetExecutingAssembly()
92          .GetManifestResourceNames()
93          .Where(x => x.EndsWith(".dat"))
94          .OrderBy(x => x)
95          .Select(x => x.Replace(".dat", String.Empty))
96          .Select(x => x.Replace(InstancePrefix, String.Empty));
97      }
98    }
99    #endregion
100
101    [StorableConstructor]
102    private QuadraticAssignmentProblem(bool deserializing) : base(deserializing) { }
103    private QuadraticAssignmentProblem(QuadraticAssignmentProblem original, Cloner cloner)
104      : base(original, cloner) {
105      AttachEventHandlers();
106    }
107    public QuadraticAssignmentProblem()
108      : base() {
109      Parameters.Add(new ValueParameter<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));
110      Parameters.Add(new ValueParameter<DoubleMatrix>("Coordinates", "The coordinates of the locations."));
111      Parameters.Add(new ValueParameter<DoubleMatrix>("Weights", "The strength of the connection between the facilities.", new DoubleMatrix(5, 5)));
112      Parameters.Add(new ValueParameter<DoubleMatrix>("DistanceMatrix", "The distance matrix which can either be specified directly without the coordinates, or can be calculated automatically from the coordinates.", new DoubleMatrix(5, 5)));
113      Parameters.Add(new ValueParameter<BoolValue>("UseDistanceMatrix", "Defaults to true, set to false only when the number of facilities is very high and a distance matrix would become too large (>1000 facilities).", new BoolValue(true)));
114
115      Maximization = new BoolValue(false);
116
117      Coordinates = new DoubleMatrix(new double[,] {
118        { 294.000,   3.000 },
119        { 585.246, 214.603 },
120        { 474.000, 556.983 },
121        { 114.000, 556.983 },
122        {   2.754, 214.603 }
123      });
124
125      Weights = new DoubleMatrix(new double[,] {
126        { 0, 1, 0, 0, 1 },
127        { 1, 0, 1, 0, 0 },
128        { 0, 1, 0, 1, 0 },
129        { 0, 0, 1, 0, 1 },
130        { 1, 0, 0, 1, 0 }
131      });
132
133      DistanceMatrix = new DoubleMatrix(new double[,] {
134        {   0, 360, 582, 582, 360 },
135        { 360,   0, 360, 582, 582 },
136        { 582, 360,   0, 360, 582 },
137        { 582, 582, 360,   0, 360 },
138        { 360, 582, 582, 360,   0 }
139      });
140
141      RandomPermutationCreator solutionCreator = new RandomPermutationCreator();
142      solutionCreator.LengthParameter.Value = new IntValue(5);
143      solutionCreator.PermutationParameter.ActualName = "Assignment";
144      QAPEvaluator evaluator = new QAPEvaluator();
145
146      SolutionCreatorParameter.Value = solutionCreator;
147      EvaluatorParameter.Value = evaluator;
148
149      InitializeOperators();
150      AttachEventHandlers();
151    }
152
153    public override IDeepCloneable Clone(Cloner cloner) {
154      return new QuadraticAssignmentProblem(this, cloner);
155    }
156
157    #region Events
158    protected override void OnSolutionCreatorChanged() {
159      SolutionCreator.PermutationParameter.ActualNameChanged += new EventHandler(SolutionCreator_PermutationParameter_ActualNameChanged);
160      ParameterizeSolutionCreator();
161      ParameterizeEvaluator();
162      ParameterizeOperators();
163      base.OnSolutionCreatorChanged();
164    }
165    protected override void OnEvaluatorChanged() {
166      ParameterizeEvaluator();
167      ParameterizeOperators();
168      base.OnEvaluatorChanged();
169    }
170
171    private void SolutionCreator_PermutationParameter_ActualNameChanged(object sender, EventArgs e) {
172      ParameterizeEvaluator();
173      ParameterizeOperators();
174    }
175    private void WeightsParameter_ValueChanged(object sender, EventArgs e) {
176      Weights.RowsChanged += new EventHandler(Weights_RowsChanged);
177      ParameterizeSolutionCreator();
178      ParameterizeEvaluator();
179      ParameterizeOperators();
180    }
181    private void Weights_RowsChanged(object sender, EventArgs e) {
182      ParameterizeSolutionCreator();
183      ParameterizeEvaluator();
184      ParameterizeOperators();
185    }
186    #endregion
187
188    #region Helpers
189    [StorableHook(HookType.AfterDeserialization)]
190    private void AfterDeserializationHook() {
191      AttachEventHandlers();
192    }
193
194    private void AttachEventHandlers() {
195      WeightsParameter.ValueChanged += new EventHandler(WeightsParameter_ValueChanged);
196      Weights.RowsChanged += new EventHandler(Weights_RowsChanged);
197      SolutionCreator.PermutationParameter.ActualNameChanged += new EventHandler(SolutionCreator_PermutationParameter_ActualNameChanged);
198    }
199
200    private void InitializeOperators() {
201      Operators.AddRange(ApplicationManager.Manager.GetInstances<IPermutationOperator>());
202      ParameterizeOperators();
203    }
204    private void ParameterizeSolutionCreator() {
205      if (SolutionCreator != null) {
206        SolutionCreator.PermutationTypeParameter.Value = new PermutationType(PermutationTypes.Absolute);
207        SolutionCreator.LengthParameter.Value = new IntValue(Weights.Rows);
208      }
209    }
210    private void ParameterizeEvaluator() {
211      if (Evaluator != null) {
212        Evaluator.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
213        Evaluator.UseDistanceMatrixParameter.ActualName = UseDistanceMatrixParameter.Name;
214        Evaluator.DistanceMatrixParameter.ActualName = DistanceMatrixParameter.Name;
215        Evaluator.CoordinatesParameter.ActualName = CoordinatesParameter.Name;
216        Evaluator.WeightsParameter.ActualName = WeightsParameter.Name;
217      }
218    }
219    private void ParameterizeOperators() {
220      foreach (IPermutationCrossover op in Operators.OfType<IPermutationCrossover>()) {
221        op.ParentsParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
222        op.ChildParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
223      }
224      foreach (IPermutationManipulator op in Operators.OfType<IPermutationManipulator>()) {
225        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
226      }
227      foreach (IPermutationMoveOperator op in Operators.OfType<IPermutationMoveOperator>()) {
228        op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
229      }
230      if (Operators.OfType<IMoveGenerator>().Any()) {
231        string inversionMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationInversionMoveOperator>().First().InversionMoveParameter.ActualName;
232        foreach (IPermutationInversionMoveOperator op in Operators.OfType<IPermutationInversionMoveOperator>())
233          op.InversionMoveParameter.ActualName = inversionMove;
234        string translocationMove = Operators.OfType<IMoveGenerator>().OfType<IPermutationTranslocationMoveOperator>().First().TranslocationMoveParameter.ActualName;
235        foreach (IPermutationTranslocationMoveOperator op in Operators.OfType<IPermutationTranslocationMoveOperator>())
236          op.TranslocationMoveParameter.ActualName = translocationMove;
237      }
238    }
239    #endregion
240
241    public void ImportFileInstance(string filename) {
242      QAPLIBParser parser = new QAPLIBParser();
243      parser.Parse(filename);
244      Coordinates = new DoubleMatrix();
245      DistanceMatrix = new DoubleMatrix(parser.Distances);
246      Weights = new DoubleMatrix(parser.Weights);
247      UseDistanceMatrix.Value = true;
248      Name = "Quadratic Assignment Problem (imported from " + Path.GetFileNameWithoutExtension(filename) + ")";
249      Description = "Imported problem data using QAPLIBParser " + Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyFileVersionAttribute), true).Cast<AssemblyFileVersionAttribute>().FirstOrDefault().Version + ".";
250      OnReset();
251    }
252
253    public void LoadEmbeddedInstance(string instance) {
254      using (Stream stream = Assembly.GetExecutingAssembly()
255        .GetManifestResourceStream(InstancePrefix + instance + ".dat")) {
256        QAPLIBParser parser = new QAPLIBParser();
257        parser.Parse(stream);
258        Coordinates = new DoubleMatrix();
259        DistanceMatrix = new DoubleMatrix(parser.Distances);
260        Weights = new DoubleMatrix(parser.Weights);
261        UseDistanceMatrix.Value = true;
262        Name = "Quadratic Assignment Problem (loaded instance " + instance + ")";
263        Description = "Loaded embedded problem data of instance " + instance + ".";
264        OnReset();
265      }
266    }
267  }
268}
Note: See TracBrowser for help on using the repository browser.