Index: branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs
===================================================================
--- branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs	(revision 7418)
+++ branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment.Views/3.3/GQAPAssignmentView.cs	(revision 7438)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Drawing;
 using System.Linq;
 using System.Windows.Forms;
@@ -34,4 +35,6 @@
   [Content(typeof(GQAPAssignment), IsDefaultView = true)]
   public partial class GQAPAssignmentView : ItemView {
+    private static readonly double BrightnessLevel = 0.5;
+
     public new GQAPAssignment Content {
       get { return (GQAPAssignment)base.Content; }
@@ -69,5 +72,5 @@
     }
 
-    #region Event Handlers
+    #region Content Event Handlers
     private void Content_PropertyChanged(object sender, PropertyChangedEventArgs e) {
       switch (e.PropertyName) {
@@ -89,4 +92,35 @@
     #endregion
 
+    #region Event Handlers
+    private void assignmentTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
+      if (Content != null) {
+        assignmentTreeView.BeginUpdate();
+        try {
+          if (assignmentTreeView.SelectedNode == null) {
+            ColorByInstallationCosts();
+          } else {
+            var equipmentNode = (assignmentTreeView.SelectedNode as EquipmentNode);
+            if (equipmentNode != null) {
+              ColorByWeight(equipmentNode);
+            }
+            var locationNode = (assignmentTreeView.SelectedNode as LocationNode);
+            if (locationNode != null) {
+              ColorByWeight(locationNode);
+            }
+          }
+        } finally { assignmentTreeView.EndUpdate(); }
+      }
+    }
+
+    private void assignmentTreeView_MouseUp(object sender, MouseEventArgs e) {
+      var hit = assignmentTreeView.HitTest(e.X, e.Y);
+      if (hit.Node == null || hit.Location == TreeViewHitTestLocations.None || hit.Location == TreeViewHitTestLocations.RightOfLabel) {
+        assignmentTreeView.SelectedNode = null;
+        ColorByInstallationCosts();
+      }
+    }
+    #endregion
+
+    #region Helpers
     private void UpdateQuality() {
       if (InvokeRequired) Invoke((Action)UpdateQuality);
@@ -145,10 +179,10 @@
               if (Content.LocationNames != null && Content.LocationNames.Length > assignment[i])
                 locationName = Content.LocationNames[assignment[i]];
-              locationNodes.Add(assignment[i], new TreeNode(locationName));
+              locationNodes.Add(assignment[i], new LocationNode(assignment[i], locationName));
             }
             string equipmentName = i.ToString();
             if (Content.EquipmentNames != null && Content.EquipmentNames.Length > i)
               equipmentName = Content.EquipmentNames[i];
-            locationNodes[assignment[i]].Nodes.Add(equipmentName);
+            locationNodes[assignment[i]].Nodes.Add(new EquipmentNode(i, equipmentName));
           }
 
@@ -159,8 +193,120 @@
               node.Expand();
             }
+            ColorByInstallationCosts();
           } finally { assignmentTreeView.EndUpdate(); }
         }
       }
     }
+
+    private void ColorByInstallationCosts() {
+      var installationCosts = new Dictionary<EquipmentNode, double>();
+      foreach (var node in GetAllSubNodes(assignmentTreeView.Nodes).OfType<EquipmentNode>()) {
+        int location = Content.Solution.Assignment[node.Equipment];
+        installationCosts[node] = Content.InstallationCosts[node.Equipment, location];
+      }
+      double max = installationCosts.Values.Max();
+      foreach (var kvp in installationCosts) {
+        if (max == 0) {
+          kvp.Key.BackColor = assignmentTreeView.BackColor;
+          kvp.Key.ForeColor = assignmentTreeView.ForeColor;
+        }
+        int colorComponent = (int)(255 * Math.Pow((max - kvp.Value) / max, 2));
+        kvp.Key.BackColor = Color.FromArgb(255, colorComponent, colorComponent);
+        if (kvp.Key.BackColor.GetBrightness() < BrightnessLevel) kvp.Key.ForeColor = Color.White;
+        else kvp.Key.ForeColor = Color.Black;
+      }
+    }
+
+    private void ColorByWeight(EquipmentNode selectedNode) {
+      int equipment = selectedNode.Equipment;
+      double rowSum = 0, colSum = 0;
+      for (int i = 0; i < Content.Weights.Columns; i++)
+        if (i != equipment) rowSum += Content.Weights[equipment, i];
+      for (int i = 0; i < Content.Weights.Rows; i++)
+        if (i != equipment) colSum += Content.Weights[i, equipment];
+
+      var otherEquipments = GetAllSubNodes(assignmentTreeView.Nodes)
+        .OfType<EquipmentNode>()
+        .Where(x => x != selectedNode);
+
+      selectedNode.BackColor = assignmentTreeView.BackColor;
+      selectedNode.ForeColor = assignmentTreeView.ForeColor;
+      foreach (var other in otherEquipments) {
+        if (rowSum == 0 && colSum == 0) {
+          other.BackColor = assignmentTreeView.BackColor;
+          other.ForeColor = assignmentTreeView.ForeColor;
+        } else {
+          double rowInvProportion = rowSum == 0 ? 1.0 : (rowSum - Content.Weights[equipment, other.Equipment]) / rowSum;
+          double colInvProportion = colSum == 0 ? 1.0 : (colSum - Content.Weights[other.Equipment, equipment]) / colSum;
+          int colorComponent = (int)(255 * Math.Pow(Math.Min(rowInvProportion, colInvProportion), 2));
+          other.BackColor = Color.FromArgb(colorComponent, 255, colorComponent);
+          if (other.BackColor.GetBrightness() < BrightnessLevel) other.ForeColor = Color.White;
+          else other.ForeColor = Color.Black;
+        }
+      }
+    }
+
+    private void ColorByWeight(LocationNode selectedNode) {
+      var equipments = new HashSet<int>(Content.Solution.Assignment.Select((v, i) => new { Index = i, Value = v })
+        .Where(x => x.Value == selectedNode.Location).Select(x => x.Index));
+      var rowSums = new Dictionary<int, double>(equipments.Count);
+      var colSums = new Dictionary<int, double>(equipments.Count);
+      foreach (var e in equipments) {
+        rowSums[e] = 0;
+        colSums[e] = 0;
+        for (int i = 0; i < Content.Weights.Columns; i++) {
+          if (!equipments.Contains(i)) rowSums[e] += Content.Weights[e, i];
+          if (!equipments.Contains(i)) colSums[e] += Content.Weights[i, e];
+        }
+      }
+      var equipmentNodes = GetAllSubNodes(assignmentTreeView.Nodes)
+        .OfType<EquipmentNode>();
+
+      var relevantEquipments = new HashSet<int>(equipments.Where(x => rowSums[x] > 0 || colSums[x] > 0));
+      foreach (var other in equipmentNodes) {
+        if (!relevantEquipments.Any() || equipments.Contains(other.Equipment)) {
+          other.BackColor = assignmentTreeView.BackColor;
+          other.ForeColor = assignmentTreeView.ForeColor;
+        } else {
+          double rowInvProportion = relevantEquipments.Min(x => rowSums[x] == 0 ? 1.0 : (rowSums[x] - Content.Weights[x, other.Equipment]) / rowSums[x]);
+          double colInvProportion = relevantEquipments.Min(x => colSums[x] == 0 ? 1.0 : (colSums[x] - Content.Weights[other.Equipment, x]) / colSums[x]);
+          int colorComponent = (int)(255 * Math.Pow(Math.Min(rowInvProportion, colInvProportion), 2));
+          other.BackColor = Color.FromArgb(colorComponent, 255, colorComponent);
+          if (other.BackColor.GetBrightness() < BrightnessLevel) other.ForeColor = Color.White;
+          else other.ForeColor = Color.Black;
+        }
+      }
+    }
+
+    private IEnumerable<TreeNode> GetAllSubNodes(TreeNodeCollection nodes) {
+      foreach (TreeNode node in nodes) {
+        yield return node;
+        foreach (TreeNode subNode in GetAllSubNodes(node.Nodes))
+          yield return subNode;
+      }
+    }
+    #endregion
+
+    #region Helper Classes
+    private class LocationNode : TreeNode {
+      public int Location { get; set; }
+
+      public LocationNode() : base() { }
+      public LocationNode(int location, string name)
+        : base(name) {
+        Location = location;
+      }
+    }
+
+    private class EquipmentNode : TreeNode {
+      public int Equipment { get; set; }
+
+      public EquipmentNode() : base() { }
+      public EquipmentNode(int equipment, string name)
+        : base(name) {
+        Equipment = equipment;
+      }
+    }
+    #endregion
   }
 }
