Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1614

  • Added Transpose() extension method for double[,] matrices
  • Added IProblemInstanceConsumer<T> interface
  • Implemented general ProblemView which auto-detects all instances a problem can consume
  • Added ability of IProblemInstanceProvider to directly feed a consumer
  • Implemented general view for problem instance providers
  • Fixed a few bugs
File size: 12.6 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      Content.Solution.PropertyChanged -= new PropertyChangedEventHandler(ContentSolution_PropertyChanged);
52      base.DeregisterContentEvents();
53    }
54    protected override void RegisterContentEvents() {
55      base.RegisterContentEvents();
56      Content.PropertyChanged += new PropertyChangedEventHandler(Content_PropertyChanged);
57      Content.Solution.PropertyChanged += new PropertyChangedEventHandler(ContentSolution_PropertyChanged);
58    }
59    #endregion
60
61    protected override void OnContentChanged() {
62      base.OnContentChanged();
63      UpdateQuality();
64      UpdateFlowDistanceQuality();
65      UpdateInstallationQuality();
66      UpdateOverbookedCapacity();
67      UpdateAssignment();
68    }
69
70    protected override void SetEnabledStateOfControls() {
71      base.SetEnabledStateOfControls();
72    }
73
74    #region Content Event Handlers
75    private void Content_PropertyChanged(object sender, PropertyChangedEventArgs e) {
76      switch (e.PropertyName) {
77        case "EquipmentNames": UpdateAssignment(); break;
78        case "LocationNames": UpdateAssignment(); break;
79        default: break;
80      }
81    }
82    private void ContentSolution_PropertyChanged(object sender, PropertyChangedEventArgs e) {
83      switch (e.PropertyName) {
84        case "Quality": UpdateQuality(); break;
85        case "FlowDistanceQuality": UpdateFlowDistanceQuality(); break;
86        case "InstallationQuality": UpdateInstallationQuality(); break;
87        case "OverbookedCapacity": UpdateOverbookedCapacity(); break;
88        case "Assignment": UpdateAssignment(); break;
89        default: break;
90      }
91    }
92    #endregion
93
94    #region Event Handlers
95    private void assignmentTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
96      if (Content != null) {
97        assignmentTreeView.BeginUpdate();
98        try {
99          if (assignmentTreeView.SelectedNode == null) {
100            ColorByInstallationCosts();
101          } else {
102            var equipmentNode = (assignmentTreeView.SelectedNode as EquipmentNode);
103            if (equipmentNode != null) {
104              ColorByWeight(equipmentNode);
105            }
106            var locationNode = (assignmentTreeView.SelectedNode as LocationNode);
107            if (locationNode != null) {
108              ColorByWeight(locationNode);
109            }
110          }
111        } finally { assignmentTreeView.EndUpdate(); }
112      }
113    }
114
115    private void assignmentTreeView_MouseUp(object sender, MouseEventArgs e) {
116      var hit = assignmentTreeView.HitTest(e.X, e.Y);
117      if (hit.Node == null || hit.Location == TreeViewHitTestLocations.None || hit.Location == TreeViewHitTestLocations.RightOfLabel) {
118        assignmentTreeView.SelectedNode = null;
119        ColorByInstallationCosts();
120      }
121    }
122    #endregion
123
124    #region Helpers
125    private void UpdateQuality() {
126      if (InvokeRequired) Invoke((Action)UpdateQuality);
127      else {
128        if (Content == null) {
129          qualityLabel.Text = "-";
130        } else {
131          qualityLabel.Text = Content.Solution.Quality.ToString();
132        }
133      }
134    }
135
136    private void UpdateFlowDistanceQuality() {
137      if (InvokeRequired) Invoke((Action)UpdateFlowDistanceQuality);
138      else {
139        if (Content == null || Content.Solution.FlowDistanceQuality == null) {
140          flowDistanceQualityLabel.Text = "-";
141        } else {
142          flowDistanceQualityLabel.Text = Content.Solution.FlowDistanceQuality.ToString();
143        }
144      }
145    }
146
147    private void UpdateInstallationQuality() {
148      if (InvokeRequired) Invoke((Action)UpdateInstallationQuality);
149      else {
150        if (Content == null || Content.Solution.InstallationQuality == null) {
151          installationQualityLabel.Text = "-";
152        } else {
153          installationQualityLabel.Text = Content.Solution.InstallationQuality.ToString();
154        }
155      }
156    }
157
158    private void UpdateOverbookedCapacity() {
159      if (InvokeRequired) Invoke((Action)UpdateOverbookedCapacity);
160      else {
161        if (Content == null || Content.Solution.OverbookedCapacity == null) {
162          overbookedCapacityLabel.Text = "-";
163        } else {
164          overbookedCapacityLabel.Text = Content.Solution.OverbookedCapacity.ToString();
165        }
166      }
167    }
168
169    private void UpdateAssignment() {
170      if (InvokeRequired) Invoke((Action)UpdateAssignment);
171      else {
172        assignmentTreeView.Nodes.Clear();
173        if (Content != null) {
174          IntegerVector assignment = Content.Solution.Assignment;
175          Dictionary<int, TreeNode> locationNodes = new Dictionary<int, TreeNode>();
176          for (int i = 0; i < assignment.Length; i++) {
177            if (!locationNodes.ContainsKey(assignment[i])) {
178              string locationName = assignment[i].ToString();
179              if (Content.LocationNames != null && Content.LocationNames.Length > assignment[i])
180                locationName = Content.LocationNames[assignment[i]];
181              locationNodes.Add(assignment[i], new LocationNode(assignment[i], locationName));
182            }
183            string equipmentName = i.ToString();
184            if (Content.EquipmentNames != null && Content.EquipmentNames.Length > i)
185              equipmentName = Content.EquipmentNames[i];
186            locationNodes[assignment[i]].Nodes.Add(new EquipmentNode(i, equipmentName));
187          }
188
189          assignmentTreeView.BeginUpdate();
190          try {
191            foreach (var node in locationNodes.OrderBy(x => x.Key).Select(x => x.Value)) {
192              assignmentTreeView.Nodes.Add(node);
193              node.Expand();
194            }
195            ColorByInstallationCosts();
196          } finally { assignmentTreeView.EndUpdate(); }
197        }
198      }
199    }
200
201    private void ColorByInstallationCosts() {
202      var installationCosts = new Dictionary<EquipmentNode, double>();
203      foreach (var node in GetAllSubNodes(assignmentTreeView.Nodes).OfType<EquipmentNode>()) {
204        int location = Content.Solution.Assignment[node.Equipment];
205        installationCosts[node] = Content.InstallationCosts[node.Equipment, location];
206      }
207      double max = installationCosts.Values.Max();
208      foreach (var kvp in installationCosts) {
209        if (max == 0) {
210          kvp.Key.BackColor = assignmentTreeView.BackColor;
211          kvp.Key.ForeColor = assignmentTreeView.ForeColor;
212        } else {
213          int colorComponent = (int)(255 * Math.Pow((max - kvp.Value) / max, 2));
214          kvp.Key.BackColor = Color.FromArgb(255, colorComponent, colorComponent);
215          if (kvp.Key.BackColor.GetBrightness() < BrightnessLevel) kvp.Key.ForeColor = Color.White;
216          else kvp.Key.ForeColor = Color.Black;
217        }
218      }
219    }
220
221    private void ColorByWeight(EquipmentNode selectedNode) {
222      int equipment = selectedNode.Equipment;
223      double rowSum = 0, colSum = 0;
224      for (int i = 0; i < Content.Weights.Columns; i++)
225        if (i != equipment) rowSum += Content.Weights[equipment, i];
226      for (int i = 0; i < Content.Weights.Rows; i++)
227        if (i != equipment) colSum += Content.Weights[i, equipment];
228
229      var otherEquipments = GetAllSubNodes(assignmentTreeView.Nodes)
230        .OfType<EquipmentNode>()
231        .Where(x => x != selectedNode);
232
233      selectedNode.BackColor = assignmentTreeView.BackColor;
234      selectedNode.ForeColor = assignmentTreeView.ForeColor;
235      foreach (var other in otherEquipments) {
236        if (rowSum == 0 && colSum == 0) {
237          other.BackColor = assignmentTreeView.BackColor;
238          other.ForeColor = assignmentTreeView.ForeColor;
239        } else {
240          double rowInvProportion = rowSum == 0 ? 1.0 : (rowSum - Content.Weights[equipment, other.Equipment]) / rowSum;
241          double colInvProportion = colSum == 0 ? 1.0 : (colSum - Content.Weights[other.Equipment, equipment]) / colSum;
242          int colorComponent = (int)(255 * Math.Pow(Math.Min(rowInvProportion, colInvProportion), 2));
243          other.BackColor = Color.FromArgb(colorComponent, 255, colorComponent);
244          if (other.BackColor.GetBrightness() < BrightnessLevel) other.ForeColor = Color.White;
245          else other.ForeColor = Color.Black;
246        }
247      }
248    }
249
250    private void ColorByWeight(LocationNode selectedNode) {
251      var equipments = new HashSet<int>(Content.Solution.Assignment.Select((v, i) => new { Index = i, Value = v })
252        .Where(x => x.Value == selectedNode.Location).Select(x => x.Index));
253      var rowSums = new Dictionary<int, double>(equipments.Count);
254      var colSums = new Dictionary<int, double>(equipments.Count);
255      foreach (var e in equipments) {
256        rowSums[e] = 0;
257        colSums[e] = 0;
258        for (int i = 0; i < Content.Weights.Columns; i++) {
259          if (!equipments.Contains(i)) rowSums[e] += Content.Weights[e, i];
260          if (!equipments.Contains(i)) colSums[e] += Content.Weights[i, e];
261        }
262      }
263      var equipmentNodes = GetAllSubNodes(assignmentTreeView.Nodes)
264        .OfType<EquipmentNode>();
265
266      var relevantEquipments = new HashSet<int>(equipments.Where(x => rowSums[x] > 0 || colSums[x] > 0));
267      foreach (var other in equipmentNodes) {
268        if (!relevantEquipments.Any() || equipments.Contains(other.Equipment)) {
269          other.BackColor = assignmentTreeView.BackColor;
270          other.ForeColor = assignmentTreeView.ForeColor;
271        } else {
272          double rowInvProportion = relevantEquipments.Min(x => rowSums[x] == 0 ? 1.0 : (rowSums[x] - Content.Weights[x, other.Equipment]) / rowSums[x]);
273          double colInvProportion = relevantEquipments.Min(x => colSums[x] == 0 ? 1.0 : (colSums[x] - Content.Weights[other.Equipment, x]) / colSums[x]);
274          int colorComponent = (int)(255 * Math.Pow(Math.Min(rowInvProportion, colInvProportion), 2));
275          other.BackColor = Color.FromArgb(colorComponent, 255, colorComponent);
276          if (other.BackColor.GetBrightness() < BrightnessLevel) other.ForeColor = Color.White;
277          else other.ForeColor = Color.Black;
278        }
279      }
280    }
281
282    private IEnumerable<TreeNode> GetAllSubNodes(TreeNodeCollection nodes) {
283      foreach (TreeNode node in nodes) {
284        yield return node;
285        foreach (TreeNode subNode in GetAllSubNodes(node.Nodes))
286          yield return subNode;
287      }
288    }
289    #endregion
290
291    #region Helper Classes
292    private class LocationNode : TreeNode {
293      public int Location { get; set; }
294
295      public LocationNode() : base() { }
296      public LocationNode(int location, string name)
297        : base(name) {
298        Location = location;
299      }
300    }
301
302    private class EquipmentNode : TreeNode {
303      public int Equipment { get; set; }
304
305      public EquipmentNode() : base() { }
306      public EquipmentNode(int equipment, string name)
307        : base(name) {
308        Equipment = equipment;
309      }
310    }
311    #endregion
312  }
313}
Note: See TracBrowser for help on using the repository browser.