Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1614: restructured architecture to allow for different evaluator with different penalty strategies

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