Free cookie consent management tool by TermsFeed Policy Generator

source: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs @ 7470

Last change on this file since 7470 was 7470, checked in by abeham, 12 years ago

#1614

  • Removed incompatible problem linhp318.tsp (contains fixed edges)
  • Fixed AssemblyInfo for TSPLIB
  • Added unit tests
  • Worked on assignment / solution view
File size: 12.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.ComponentModel;
25using System.Drawing;
26using System.Linq;
27using System.Windows.Forms;
28using HeuristicLab.Core.Views;
29using HeuristicLab.Encodings.IntegerVectorEncoding;
30using HeuristicLab.MainForm;
31using HeuristicLab.MainForm.WindowsForms;
32
33namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views {
34  [View("GQAPAssignmentView")]
35  [Content(typeof(GQAPAssignment), IsDefaultView = true)]
36  public partial class GQAPAssignmentView : ItemView {
37    private static readonly double BrightnessLevel = 0.5;
38
39    public new GQAPAssignment Content {
40      get { return (GQAPAssignment)base.Content; }
41      set { base.Content = value; }
42    }
43
44    public GQAPAssignmentView() {
45      InitializeComponent();
46    }
47
48    #region Register Content Events
49    protected override void DeregisterContentEvents() {
50      Content.PropertyChanged -= new PropertyChangedEventHandler(Content_PropertyChanged);
51      base.DeregisterContentEvents();
52    }
53    protected override void RegisterContentEvents() {
54      base.RegisterContentEvents();
55      Content.PropertyChanged += new PropertyChangedEventHandler(Content_PropertyChanged);
56    }
57    #endregion
58
59    protected override void OnContentChanged() {
60      base.OnContentChanged();
61      UpdateQuality();
62      UpdateFlowDistanceQuality();
63      UpdateInstallationQuality();
64      UpdateOverbookedCapacity();
65      UpdateAssignment();
66    }
67
68    protected override void SetEnabledStateOfControls() {
69      base.SetEnabledStateOfControls();
70    }
71
72    #region Content Event Handlers
73    private void Content_PropertyChanged(object sender, PropertyChangedEventArgs e) {
74      switch (e.PropertyName) {
75        case "Quality": UpdateQuality(); break;
76        case "FlowDistanceQuality": UpdateFlowDistanceQuality(); break;
77        case "InstallationQuality": UpdateInstallationQuality(); break;
78        case "OverbookedCapacity": UpdateOverbookedCapacity(); break;
79        case "Assignment": UpdateAssignment(); break;
80        case "EquipmentNames": UpdateAssignment(); break;
81        case "LocationNames": UpdateAssignment(); break;
82        default: break;
83      }
84    }
85
86    private void Content_Assignment_ToStringChanged(object sender, EventArgs e) {
87      UpdateAssignment();
88    }
89    #endregion
90
91    #region Event Handlers
92    private void assignmentTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
93      if (Content != null) {
94        assignmentTreeView.BeginUpdate();
95        try {
96          if (assignmentTreeView.SelectedNode == null) {
97            ColorByInstallationCosts();
98          } else {
99            var equipmentNode = (assignmentTreeView.SelectedNode as EquipmentNode);
100            if (equipmentNode != null) {
101              ColorByWeight(equipmentNode);
102            }
103            var locationNode = (assignmentTreeView.SelectedNode as LocationNode);
104            if (locationNode != null) {
105              ColorByWeight(locationNode);
106            }
107          }
108        } finally { assignmentTreeView.EndUpdate(); }
109      }
110    }
111
112    private void assignmentTreeView_MouseUp(object sender, MouseEventArgs e) {
113      var hit = assignmentTreeView.HitTest(e.X, e.Y);
114      if (hit.Node == null || hit.Location == TreeViewHitTestLocations.None || hit.Location == TreeViewHitTestLocations.RightOfLabel) {
115        assignmentTreeView.SelectedNode = null;
116        ColorByInstallationCosts();
117      }
118    }
119    #endregion
120
121    #region Helpers
122    private void UpdateQuality() {
123      if (InvokeRequired) Invoke((Action)UpdateQuality);
124      else {
125        if (Content == null) {
126          qualityLabel.Text = "-";
127        } else {
128          qualityLabel.Text = Content.Quality.ToString();
129        }
130      }
131    }
132
133    private void UpdateFlowDistanceQuality() {
134      if (InvokeRequired) Invoke((Action)UpdateFlowDistanceQuality);
135      else {
136        if (Content == null || Content.FlowDistanceQuality == null) {
137          flowDistanceQualityLabel.Text = "-";
138        } else {
139          flowDistanceQualityLabel.Text = Content.FlowDistanceQuality.ToString();
140        }
141      }
142    }
143
144    private void UpdateInstallationQuality() {
145      if (InvokeRequired) Invoke((Action)UpdateInstallationQuality);
146      else {
147        if (Content == null || Content.InstallationQuality == null) {
148          installationQualityLabel.Text = "-";
149        } else {
150          installationQualityLabel.Text = Content.InstallationQuality.ToString();
151        }
152      }
153    }
154
155    private void UpdateOverbookedCapacity() {
156      if (InvokeRequired) Invoke((Action)UpdateOverbookedCapacity);
157      else {
158        if (Content == null || Content.OverbookedCapacity == null) {
159          overbookedCapacityLabel.Text = "-";
160        } else {
161          overbookedCapacityLabel.Text = Content.OverbookedCapacity.ToString();
162        }
163      }
164    }
165
166    private void UpdateAssignment() {
167      if (InvokeRequired) Invoke((Action)UpdateAssignment);
168      else {
169        assignmentTreeView.Nodes.Clear();
170        if (Content != null) {
171          IntegerVector assignment = Content.Assignment;
172          Dictionary<int, TreeNode> locationNodes = new Dictionary<int, TreeNode>();
173          for (int i = 0; i < assignment.Length; i++) {
174            if (!locationNodes.ContainsKey(assignment[i])) {
175              string locationName = assignment[i].ToString();
176              if (Content.LocationNames != null && Content.LocationNames.Length > assignment[i])
177                locationName = Content.LocationNames[assignment[i]];
178              locationNodes.Add(assignment[i], new LocationNode(assignment[i], locationName));
179            }
180            string equipmentName = i.ToString();
181            if (Content.EquipmentNames != null && Content.EquipmentNames.Length > i)
182              equipmentName = Content.EquipmentNames[i];
183            locationNodes[assignment[i]].Nodes.Add(new EquipmentNode(i, equipmentName));
184          }
185
186          assignmentTreeView.BeginUpdate();
187          try {
188            foreach (var node in locationNodes.OrderBy(x => x.Key).Select(x => x.Value)) {
189              assignmentTreeView.Nodes.Add(node);
190              node.Expand();
191            }
192            ColorByInstallationCosts();
193          } finally { assignmentTreeView.EndUpdate(); }
194        }
195      }
196    }
197
198    private void ColorByInstallationCosts() {
199      var installationCosts = new Dictionary<EquipmentNode, double>();
200      foreach (var node in GetAllSubNodes(assignmentTreeView.Nodes).OfType<EquipmentNode>()) {
201        int location = Content.Assignment[node.Equipment];
202        installationCosts[node] = Content.InstallationCosts[node.Equipment, location];
203      }
204      double max = installationCosts.Values.Max();
205      foreach (var kvp in installationCosts) {
206        if (max == 0) {
207          kvp.Key.BackColor = assignmentTreeView.BackColor;
208          kvp.Key.ForeColor = assignmentTreeView.ForeColor;
209        } else {
210          int colorComponent = (int)(255 * Math.Pow((max - kvp.Value) / max, 2));
211          kvp.Key.BackColor = Color.FromArgb(255, colorComponent, colorComponent);
212          if (kvp.Key.BackColor.GetBrightness() < BrightnessLevel) kvp.Key.ForeColor = Color.White;
213          else kvp.Key.ForeColor = Color.Black;
214        }
215      }
216    }
217
218    private void ColorByWeight(EquipmentNode selectedNode) {
219      int equipment = selectedNode.Equipment;
220      double rowSum = 0, colSum = 0;
221      for (int i = 0; i < Content.Weights.Columns; i++)
222        if (i != equipment) rowSum += Content.Weights[equipment, i];
223      for (int i = 0; i < Content.Weights.Rows; i++)
224        if (i != equipment) colSum += Content.Weights[i, equipment];
225
226      var otherEquipments = GetAllSubNodes(assignmentTreeView.Nodes)
227        .OfType<EquipmentNode>()
228        .Where(x => x != selectedNode);
229
230      selectedNode.BackColor = assignmentTreeView.BackColor;
231      selectedNode.ForeColor = assignmentTreeView.ForeColor;
232      foreach (var other in otherEquipments) {
233        if (rowSum == 0 && colSum == 0) {
234          other.BackColor = assignmentTreeView.BackColor;
235          other.ForeColor = assignmentTreeView.ForeColor;
236        } else {
237          double rowInvProportion = rowSum == 0 ? 1.0 : (rowSum - Content.Weights[equipment, other.Equipment]) / rowSum;
238          double colInvProportion = colSum == 0 ? 1.0 : (colSum - Content.Weights[other.Equipment, equipment]) / colSum;
239          int colorComponent = (int)(255 * Math.Pow(Math.Min(rowInvProportion, colInvProportion), 2));
240          other.BackColor = Color.FromArgb(colorComponent, 255, colorComponent);
241          if (other.BackColor.GetBrightness() < BrightnessLevel) other.ForeColor = Color.White;
242          else other.ForeColor = Color.Black;
243        }
244      }
245    }
246
247    private void ColorByWeight(LocationNode selectedNode) {
248      var equipments = new HashSet<int>(Content.Assignment.Select((v, i) => new { Index = i, Value = v })
249        .Where(x => x.Value == selectedNode.Location).Select(x => x.Index));
250      var rowSums = new Dictionary<int, double>(equipments.Count);
251      var colSums = new Dictionary<int, double>(equipments.Count);
252      foreach (var e in equipments) {
253        rowSums[e] = 0;
254        colSums[e] = 0;
255        for (int i = 0; i < Content.Weights.Columns; i++) {
256          if (!equipments.Contains(i)) rowSums[e] += Content.Weights[e, i];
257          if (!equipments.Contains(i)) colSums[e] += Content.Weights[i, e];
258        }
259      }
260      var equipmentNodes = GetAllSubNodes(assignmentTreeView.Nodes)
261        .OfType<EquipmentNode>();
262
263      var relevantEquipments = new HashSet<int>(equipments.Where(x => rowSums[x] > 0 || colSums[x] > 0));
264      foreach (var other in equipmentNodes) {
265        if (!relevantEquipments.Any() || equipments.Contains(other.Equipment)) {
266          other.BackColor = assignmentTreeView.BackColor;
267          other.ForeColor = assignmentTreeView.ForeColor;
268        } else {
269          double rowInvProportion = relevantEquipments.Min(x => rowSums[x] == 0 ? 1.0 : (rowSums[x] - Content.Weights[x, other.Equipment]) / rowSums[x]);
270          double colInvProportion = relevantEquipments.Min(x => colSums[x] == 0 ? 1.0 : (colSums[x] - Content.Weights[other.Equipment, x]) / colSums[x]);
271          int colorComponent = (int)(255 * Math.Pow(Math.Min(rowInvProportion, colInvProportion), 2));
272          other.BackColor = Color.FromArgb(colorComponent, 255, colorComponent);
273          if (other.BackColor.GetBrightness() < BrightnessLevel) other.ForeColor = Color.White;
274          else other.ForeColor = Color.Black;
275        }
276      }
277    }
278
279    private IEnumerable<TreeNode> GetAllSubNodes(TreeNodeCollection nodes) {
280      foreach (TreeNode node in nodes) {
281        yield return node;
282        foreach (TreeNode subNode in GetAllSubNodes(node.Nodes))
283          yield return subNode;
284      }
285    }
286    #endregion
287
288    #region Helper Classes
289    private class LocationNode : TreeNode {
290      public int Location { get; set; }
291
292      public LocationNode() : base() { }
293      public LocationNode(int location, string name)
294        : base(name) {
295        Location = location;
296      }
297    }
298
299    private class EquipmentNode : TreeNode {
300      public int Equipment { get; set; }
301
302      public EquipmentNode() : base() { }
303      public EquipmentNode(int equipment, string name)
304        : base(name) {
305        Equipment = equipment;
306      }
307    }
308    #endregion
309  }
310}
Note: See TracBrowser for help on using the repository browser.