Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Problems.LinearAssignment/3.3/LinearAssignmentProblem.cs @ 17745

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

#2971: Added first draft of results implementation and problem adaptation.

File size: 10.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 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.Drawing;
24using System.Linq;
25using System.Threading;
26using HEAL.Attic;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.PermutationEncoding;
31using HeuristicLab.Optimization;
32using HeuristicLab.Parameters;
33
34namespace HeuristicLab.Problems.LinearAssignment {
35  [Item("Linear Assignment Problem (LAP)", "In the linear assignment problem (LAP) an assignment of workers to jobs has to be found such that each worker is assigned to exactly one job, each job is assigned to exactly one worker and the sum of the resulting costs is minimal (or maximal).")]
36  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 130)]
37  [StorableType("7766E004-A93D-4CA6-8012-AE5E8F4C4D85")]
38  public sealed class LinearAssignmentProblem : PermutationProblem {
39    public static readonly string CostsDescription = "The cost matrix that describes the assignment of rows to columns.";
40    public static readonly string RowNamesDescription = "The elements represented by the rows of the costs matrix.";
41    public static readonly string ColumnNamesDescription = "The elements represented by the columns of the costs matrix.";
42
43    public override Image ItemImage {
44      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
45    }
46
47    #region Parameter Properties
48    public IValueParameter<DoubleMatrix> CostsParameter {
49      get { return (IValueParameter<DoubleMatrix>)Parameters["Costs"]; }
50    }
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<StringArray> RowNamesParameter {
58      get { return (IValueParameter<StringArray>)Parameters["RowNames"]; }
59    }
60    public IValueParameter<StringArray> ColumnNamesParameter {
61      get { return (IValueParameter<StringArray>)Parameters["ColumnNames"]; }
62    }
63    private IResultParameter<LAPAssignment> BestLAPSolutionParameter {
64      get { return (IResultParameter<LAPAssignment>)Parameters["Best LAP Solution"]; }
65    }
66    #endregion
67
68    #region Properties
69    public DoubleMatrix Costs {
70      get { return CostsParameter.Value; }
71      set { CostsParameter.Value = value; }
72    }
73    public StringArray RowNames {
74      get { return RowNamesParameter.Value; }
75      set { RowNamesParameter.Value = value; }
76    }
77    public StringArray ColumnNames {
78      get { return ColumnNamesParameter.Value; }
79      set { ColumnNamesParameter.Value = value; }
80    }
81    public ItemSet<Permutation> BestKnownSolutions {
82      get { return BestKnownSolutionsParameter.Value; }
83      set { BestKnownSolutionsParameter.Value = value; }
84    }
85    public Permutation BestKnownSolution {
86      get { return BestKnownSolutionParameter.Value; }
87      set { BestKnownSolutionParameter.Value = value; }
88    }
89    #endregion
90
91    [StorableConstructor]
92    private LinearAssignmentProblem(StorableConstructorFlag _) : base(_) { }
93    private LinearAssignmentProblem(LinearAssignmentProblem original, Cloner cloner)
94      : base(original, cloner) {
95      AttachEventHandlers();
96    }
97    public LinearAssignmentProblem()
98      : base(new PermutationEncoding("Assignment")) {
99      Encoding.LengthParameter.ReadOnly = DimensionRefParameter.ReadOnly = true;
100
101      Parameters.Add(new ValueParameter<DoubleMatrix>("Costs", CostsDescription, new DoubleMatrix(3, 3)));
102      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));
103      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));
104      Parameters.Add(new OptionalValueParameter<StringArray>("RowNames", RowNamesDescription));
105      Parameters.Add(new OptionalValueParameter<StringArray>("ColumnNames", ColumnNamesDescription));
106      Parameters.Add(new ResultParameter<LAPAssignment>("Best LAP Solution", "The best so far LAP solution found."));
107
108      ((ValueParameter<DoubleMatrix>)CostsParameter).ReactOnValueToStringChangedAndValueItemImageChanged = false;
109      ((OptionalValueParameter<StringArray>)RowNamesParameter).ReactOnValueToStringChangedAndValueItemImageChanged = false;
110      ((OptionalValueParameter<StringArray>)ColumnNamesParameter).ReactOnValueToStringChangedAndValueItemImageChanged = false;
111
112      RowNames = new StringArray(new string[] { "Eric", "Robert", "Allison" });
113      ColumnNames = new StringArray(new string[] { "MRI", "Blood test", "Angiogram" });
114      Costs[0, 0] = 4; Costs[0, 1] = 5; Costs[0, 2] = 3;
115      Costs[1, 0] = 6; Costs[1, 1] = 6; Costs[1, 2] = 4;
116      Costs[2, 0] = 5; Costs[2, 1] = 5; Costs[2, 2] = 1;
117
118      Operators.RemoveAll(x => x is IMoveOperator);
119      AttachEventHandlers();
120    }
121
122    public override IDeepCloneable Clone(Cloner cloner) {
123      return new LinearAssignmentProblem(this, cloner);
124    }
125
126    public override ISingleObjectiveEvaluationResult Evaluate(Permutation assignment, IRandom random, CancellationToken cancellationToken) {
127      var costs = Costs;
128
129      int len = assignment.Length;
130      double quality = 0;
131      for (int i = 0; i < len; i++) {
132        quality += costs[i, assignment[i]];
133      }
134
135      return new SingleObjectiveEvaluationResult(quality);
136    }
137
138    public override void Analyze(ISingleObjectiveSolutionContext<Permutation>[] solutionContexts, IRandom random) {
139      base.Analyze(solutionContexts, random);
140
141      //TODO reimplement code below using results directly
142      //var costs = Costs;
143      //var rowNames = RowNames;
144      //var columnNames = ColumnNames;
145      //bool max = Maximization;
146
147      //var sorted = qualities.Select((x, index) => new { Index = index, Quality = x }).OrderBy(x => x.Quality).ToArray();
148      //if (max) Array.Reverse(sorted);
149      //int i = sorted[0].Index;
150      //var best = Tuple.Create(permutations[i], qualities[i]);
151
152      //if (double.IsNaN(BestKnownQuality) || IsBetter(best.Item2, BestKnownQuality)) {
153      //  // if there isn't a best-known quality or we improved the best-known quality we'll add the current solution as best-known
154      //  BestKnownQuality = best.Item2;
155      //  BestKnownSolution = (Permutation)best.Item1.Clone();
156      //  BestKnownSolutions = new ItemSet<Permutation>(new PermutationEqualityComparer());
157      //  BestKnownSolutions.Add((Permutation)best.Item1.Clone());
158      //} else if (BestKnownQuality == best.Item2) {
159      //  // if we matched the best-known quality we'll try to set the best-known solution if it isn't null
160      //  // and try to add it to the pool of best solutions if it is different
161      //  if (BestKnownSolution == null) BestKnownSolution = (Permutation)best.Item1.Clone();
162      //  if (BestKnownSolutions == null) BestKnownSolutions = new ItemSet<Permutation>(new PermutationEqualityComparer());
163
164      //  foreach (var k in sorted) { // for each solution that we found check if it is in the pool of best-knowns
165      //    if (IsBetter(best.Item2, k.Quality)) break; // stop when we reached a solution worse than the best-known quality
166      //    var p = permutations[k.Index];
167      //    if (!BestKnownSolutions.Contains(p))
168      //      BestKnownSolutions.Add((Permutation)permutations[k.Index].Clone());
169      //  }
170      //}
171
172      //LAPAssignment solution = BestLAPSolutionParameter.ActualValue;
173      //if (solution == null) {
174      //  solution = new LAPAssignment(costs, rowNames, columnNames, (Permutation)best.Item1.Clone(), new DoubleValue(best.Item2));
175      //  BestLAPSolutionParameter.ActualValue = solution;
176      //} else {
177      //  if (IsBetter(best.Item2, solution.Quality.Value)) {
178      //    solution.Costs = costs;
179      //    solution.Assignment = (Permutation)best.Item1.Clone();
180      //    solution.Quality.Value = best.Item2;
181      //    if (rowNames != null)
182      //      solution.RowNames = rowNames;
183      //    else solution.RowNames = null;
184      //    if (columnNames != null)
185      //      solution.ColumnNames = columnNames;
186      //    else solution.ColumnNames = null;
187      //  }
188      //}
189
190    }
191
192    #region Events
193    private void Costs_RowsChanged(object sender, EventArgs e) {
194      if (Costs.Rows != Costs.Columns) {
195        ((IStringConvertibleMatrix)Costs).Columns = Costs.Rows;
196        Dimension = Costs.Rows;
197      }
198    }
199    private void Costs_ColumnsChanged(object sender, EventArgs e) {
200      if (Costs.Rows != Costs.Columns) {
201        ((IStringConvertibleMatrix)Costs).Rows = Costs.Columns;
202        Dimension = Costs.Rows;
203      }
204    }
205    private void Costs_Reset(object sender, EventArgs e) {
206      Dimension = Costs.Rows;
207    }
208    #endregion
209
210    #region Helpers
211    [StorableHook(HookType.AfterDeserialization)]
212    private void AfterDeserialization() {
213      AttachEventHandlers();
214    }
215
216    private void AttachEventHandlers() {
217      Costs.RowsChanged += new EventHandler(Costs_RowsChanged);
218      Costs.ColumnsChanged += new EventHandler(Costs_ColumnsChanged);
219      Costs.Reset += new EventHandler(Costs_Reset);
220    }
221    #endregion
222  }
223}
Note: See TracBrowser for help on using the repository browser.