#region License Information
/* HeuristicLab
* Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using HeuristicLab.Core.Views;
using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
using HeuristicLab.MainForm;
using HeuristicLab.Problems.DataAnalysis.Symbolic;
namespace HeuristicLab.EvolutionaryTracking.Views {
[View("SymbolicExpressionTreeGenealogyGraph")]
[Content(typeof(SymbolicExpressionTreeGenealogyGraph), IsDefaultView = true)]
public sealed partial class GenealogyGraphView : ItemView {
private VisualSymbolicExpressionTreeNode selectedVisualSymbExprTreeNode;
private SymbolicExpressionTreeNodeSimilarityComparer comparer;
private Dictionary clonedNodes;
public new SymbolicExpressionTreeGenealogyGraph Content {
get { return (SymbolicExpressionTreeGenealogyGraph)base.Content; }
set { base.Content = value; }
}
public GenealogyGraphView()
: base() {
InitializeComponent();
// set button icons here because if set in the designer file, they get overwritten
this.highlightAllButton.Image = Common.Resources.VSImageLibrary.Gradient;
this.simpleLineagesCheckBox.Image = Common.Resources.VSImageLibrary.ArrowDown;
this.lockGenealogyCheckBox.Image = Common.Resources.VSImageLibrary.ProtectForm;
comparer = new SymbolicExpressionTreeNodeSimilarityComparer {
MatchConstantValues = true,
MatchVariableWeights = true,
MatchVariableNames = true
};
}
protected override void DeregisterContentEvents() {
// TODO: Deregister your event handlers here
genealogyGraphChart.GenealogyGraphNodeClicked -= graphChart_GenealogyGraphNodeClicked;
symbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked -= treeChart_SymbolicExpressionTreeNodeClicked;
symbolicExpressionTreeChart.SymbolicExpressionTreeNodeDoubleClicked -= treeChart_SymbolicExpressionTreeNodeDoubleClicked;
Content.GraphUpdated -= genealogyGraphUpdated;
base.DeregisterContentEvents();
}
protected override void RegisterContentEvents() {
base.RegisterContentEvents();
// TODO: Register your event handlers here
genealogyGraphChart.GenealogyGraphNodeClicked += graphChart_GenealogyGraphNodeClicked;
symbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked += treeChart_SymbolicExpressionTreeNodeClicked;
symbolicExpressionTreeChart.SymbolicExpressionTreeNodeDoubleClicked += treeChart_SymbolicExpressionTreeNodeDoubleClicked;
Content.GraphUpdated += genealogyGraphUpdated;
}
#region Event Handlers (Content)
// TODO: Put event handlers of the content here
protected override void OnContentChanged() {
base.OnContentChanged();
if (Content == null)
genealogyGraphChart.Graph = null;
else {
genealogyGraphChart.Graph = Content;
// var best = Content.Nodes.OrderByDescending(x => x.Quality).First();
// symbolicExpressionTreeChart.Tree = best.SymbolicExpressionTree;
}
}
private void Content_GraphChanged(object sender, EventArgs e) {
}
protected override void SetEnabledStateOfControls() {
base.SetEnabledStateOfControls();
genealogyGraphChart.Enabled = Content != null;
}
#endregion
#region Event Handlers (child controls)
// TODO: Put event handlers of child controls here.
private void graphChart_GenealogyGraphNodeClicked(object sender, MouseEventArgs e) {
// the type hierarchy goes like this: VisualGenealogyGraphNode --> GenealogyGraphNode --> SymbolicExpressionTree
var visualGenealogyGraphNode = (VisualGenealogyGraphNode)sender;
var genealogyGraphNode = visualGenealogyGraphNode.Data;
symbolicExpressionTreeChart.Tree = genealogyGraphNode.SymbolicExpressionTree;
if (genealogyGraphNode.InEdges == null) return;
var arc = genealogyGraphNode.InEdges.Last(x => x.Source != x.Target);
if (arc == null || arc.Data == null) return;
var fragment = (IFragment)arc.Data;
if (fragment.Root == null) return;
foreach (var node in fragment.Root.IterateNodesBreadth()) {
var visualSymbExprTreeNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node);
visualSymbExprTreeNode.LineColor = Color.OrangeRed;
}
symbolicExpressionTreeChart.Repaint();
}
private void genealogyGraphUpdated(object sender, EventArgs args) {
genealogyGraphChart.Graph = Content;
}
private void treeChart_SymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) {
genealogyGraphChart.Chart.UpdateEnabled = false;
switch (e.Button) {
case MouseButtons.Left: {
selectedVisualSymbExprTreeNode = (VisualSymbolicExpressionTreeNode)sender;
if (selectedVisualSymbExprTreeNode == null) return;
ISymbolicExpressionTreeNode selectedSubtree = selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode;
var clonedSubtree = (ISymbolicExpressionTreeNode)selectedSubtree.Clone();
// map original nodes to cloned nodes
clonedNodes = selectedSubtree.IterateNodesPrefix()
.Zip(clonedSubtree.IterateNodesPrefix(), (original, clone) => new { original, clone })
.ToDictionary(p => p.original, p => p.clone);
foreach (var node in symbolicExpressionTreeChart.Tree.IterateNodesPrefix()) {
symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node).FillColor = Color.Transparent;
}
foreach (var node in selectedSubtree.IterateNodesPrefix()) {
symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node).FillColor = Color.LightBlue;
}
break;
}
case MouseButtons.Middle: {
var visualNode = (VisualSymbolicExpressionTreeNode)sender;
if (selectedVisualSymbExprTreeNode == null || selectedVisualSymbExprTreeNode == visualNode) return;
var selectedNode = visualNode.SymbolicExpressionTreeNode;
if (clonedNodes.ContainsKey(selectedNode)) {
var selectedClone = clonedNodes[selectedNode];
var parent = selectedClone.Parent;
if (parent == null) break;
int index = parent.IndexOfSubtree(selectedClone);
if (index == -1) break;
parent.RemoveSubtree(parent.IndexOfSubtree(selectedClone));
foreach (var node in selectedNode.IterateNodesPrefix()) {
symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node).FillColor = Color.Transparent;
}
}
break;
}
}
if (selectedVisualSymbExprTreeNode == null || clonedNodes == null) return;
// update visual graph nodes that contain matching trees
MatchNodesAndRepaint();
// refresh the tree chart
symbolicExpressionTreeChart.Repaint();
}
void MatchNodesAndRepaint() {
genealogyGraphChart.Chart.UpdateEnabled = false;
genealogyGraphChart.ClearAllNodes(); // clear node colors
var fragment = new Fragment { Root = clonedNodes[selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode] };
var fragmentLength = fragment.Length;
// highlight nodes
genealogyGraphChart.HighlightNodes(from node in genealogyGraphChart.Graph.Nodes
let tree = node.SymbolicExpressionTree
where tree.Length >= fragmentLength
where tree.Root.ContainsFragment(fragment, comparer)
select tree);
// highlight edges that contain a matching fragment
var fragmentSimilarityComparer = new SymbolicExpressionTreeFragmentSimilarityComparer {
SimilarityComparer = comparer
};
var matchingEdges = genealogyGraphChart.Graph.Nodes.Where(n => n.InEdges != null)
.SelectMany(n => n.InEdges).Where(edge => edge.Data != null && ((IFragment)edge.Data).Root != null)
.Where(edge => fragmentSimilarityComparer.Equals(fragment, (IFragment)edge.Data));
genealogyGraphChart.HighlightArcs(matchingEdges, Color.DodgerBlue);
genealogyGraphChart.Chart.UpdateEnabled = true;
genealogyGraphChart.Chart.EnforceUpdate();
}
private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
}
#endregion
private void matchConstantsCheckBox_CheckedChanged(object sender, EventArgs e) {
comparer.MatchConstantValues = matchConstantsCheckBox.Checked;
if (selectedVisualSymbExprTreeNode != null)
MatchNodesAndRepaint();
}
private void matchVariableWeightsCheckBox_CheckedChanged(object sender, EventArgs e) {
comparer.MatchVariableWeights = matchVariableWeightsCheckBox.Checked;
if (selectedVisualSymbExprTreeNode != null)
MatchNodesAndRepaint();
}
private void matchVariableNamesCheckBox_CheckedChanged(object sender, EventArgs e) {
comparer.MatchVariableNames = matchVariableNamesCheckBox.Checked;
if (selectedVisualSymbExprTreeNode != null)
MatchNodesAndRepaint();
}
private void simpleLineagesCheckBox_CheckedChanged(object sender, EventArgs e) {
genealogyGraphChart.SimpleLineages = simpleLineagesCheckBox.Checked;
}
private void highlightAllButton_Click(object sender, EventArgs e) {
symbolicExpressionTreeChart.Repaint();
genealogyGraphChart.HighlightAll();
}
private void lockGenealogyCheckBox_CheckedChanged(object sender, EventArgs e) {
genealogyGraphChart.LockGenealogy = lockGenealogyCheckBox.Checked;
}
private void highlightRootParentsButton_Click(object sender, EventArgs e) {
var nodes = genealogyGraphChart.Graph.Nodes.Where(n => n.InEdges != null && n.InEdges.Count == 2).Select(n => (SymbolicExpressionTreeGenealogyGraphNode)n.InEdges[0].Source).ToList();
genealogyGraphChart.HighlightNodes(nodes);
}
private void highlightSecondaryParentsButton_Click(object sender, EventArgs e) {
var nodes = genealogyGraphChart.Graph.Nodes.Where(n => n.InEdges != null && n.InEdges.Count == 2).Select(n => (SymbolicExpressionTreeGenealogyGraphNode)n.InEdges[1].Source).ToList();
genealogyGraphChart.HighlightNodes(nodes);
}
}
}