Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2936_GQAPIntegration/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs @ 16654

Last change on this file since 16654 was 16077, checked in by abeham, 6 years ago

#2936: Added integration branch

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