Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 15504 was 15504, checked in by abeham, 5 years ago

#1614: refactored code

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