#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; using HeuristicLab.Visualization; namespace HeuristicLab.EvolutionaryTracking.Views { [View("SymbolicExpressionTreeGenealogyGraph")] [Content(typeof(SymbolicExpressionTreeGenealogyGraph), IsDefaultView = true)] public sealed partial class GenealogyGraphView : ItemView { private VisualSymbolicExpressionTreeNode selectedVisualSymbExprTreeNode; public new SymbolicExpressionTreeGenealogyGraph Content { get { return (SymbolicExpressionTreeGenealogyGraph)base.Content; } set { base.Content = value; } } private Dictionary clonedNodeMap; public GenealogyGraphView() : base() { InitializeComponent(); // set button icons here because if set in the designer file, they get overwritten this.moveModeButton.Image = Common.Resources.VSImageLibrary.Pointer; this.zoomModeButton.Image = Common.Resources.VSImageLibrary.Zoom; this.selectModeButton.Image = Common.Resources.VSImageLibrary.Object; similarityModeSelector.SelectedIndex = 0; // set default similarity mode to "exact" } protected override void DeregisterContentEvents() { // TODO: Deregister your event handlers here genealogyGraphChart.GenealogyGraphNodeClicked -= graphChart_GenealogyGraphNodeClicked; symbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked -= treeChart_SymbolicExpressionTreeNodeClicked; 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; } #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 = (SymbolicExpressionGenealogyGraphNode)visualGenealogyGraphNode.Data; symbolicExpressionTreeChart.Tree = genealogyGraphNode.SymbolicExpressionTree; // highlight the relevant fragment in the symbolic expression tree selectedVisualSymbExprTreeNode = null; bool repaint = false; // paint highlighted nodes in symbolic expression tree if (selectedVisualSymbExprTreeNode != null) { // clear selected subtree from the tree chart var nodes = symbolicExpressionTreeChart.Tree.IterateNodesBreadth() as List; var fragments = selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode.IterateNodesBreadth() as List; var similarityLevel = Enum.GetNames(typeof(SimilarityLevel))[similarityModeSelector.SelectedIndex]; int index = SymbolicExpressionTreeMatching.FindMatch(nodes, fragments, (SimilarityLevel)Enum.Parse(typeof(SimilarityLevel), similarityLevel)); if (index != -1) { selectedVisualSymbExprTreeNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(nodes[index]); var subtree = selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode; foreach (var node in subtree.IterateNodesBreadth()) { var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node); visualNode.LineColor = Color.Blue; } repaint = true; } } // paint graph nodes var tree = symbolicExpressionTreeChart.Tree; var graphNodes = Content.Nodes.Where(n => n.SymbolicExpressionTree == tree).ToList(); if (graphNodes.Count > 0) { foreach (var graphNode in graphNodes) if (graphNode != null && graphNode.InEdges != null) { var arc = graphNode.InEdges.Find(a => a.Data != null); if (arc != null) { var fragment = arc.Data as ISymbolicExpressionTreeNode; foreach (var node in fragment.IterateNodesBreadth()) { var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node); if (visualNode == null) continue; visualNode.LineColor = Color.Orange; } } repaint = true; } } if (repaint) symbolicExpressionTreeChart.Repaint(); } private void moveModeButton_CheckedChanged(object sender, EventArgs e) { var btn = (RadioButton)sender; if (btn.Checked) { genealogyGraphChart.Chart.Mode = ChartMode.Move; } } private void zoomModeButton_CheckedChanged(object sender, EventArgs e) { var btn = (RadioButton)sender; if (btn.Checked) { genealogyGraphChart.Chart.Mode = ChartMode.Zoom; } } private void selectModeButton_CheckedChanged(object sender, EventArgs e) { var btn = (RadioButton)sender; if (btn.Checked) { genealogyGraphChart.Chart.Mode = ChartMode.Select; } } private void treeChart_SymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) { ISymbolicExpressionTreeNode selectedSubtree = null; genealogyGraphChart.Chart.UpdateEnabled = false; switch (e.Button) { case MouseButtons.Left: { selectedVisualSymbExprTreeNode = (VisualSymbolicExpressionTreeNode)sender; if (selectedVisualSymbExprTreeNode == null) return; // find out which individuals in the genealogy graph contain this specific subtree selectedSubtree = selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode; // clone every node in the selected subtree so that edit operations are possible without altering the original subtree // save the originalNode-->clone mapping to make it easier to work with subtrees if (clonedNodeMap == null) clonedNodeMap = new Dictionary(); clonedNodeMap.Clear(); var selectedSubtreeClone = selectedSubtree.Clone() as SymbolicExpressionTreeNode; var subtreeNodes = selectedSubtree.IterateNodesPostfix().ToList(); var cloneNodes = selectedSubtreeClone.IterateNodesPostfix().ToList(); for (int i = 0; i != subtreeNodes.Count; ++i) clonedNodeMap.Add(subtreeNodes[i], cloneNodes[i]); // highlight subtree nodes in the tree chart foreach (var node in symbolicExpressionTreeChart.Tree.IterateNodesPostfix()) { var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node); visualNode.FillColor = Color.Transparent; } selectedSubtree.ForEachNodePostfix(node => { symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node).FillColor = Color.LightBlue; }); } break; case MouseButtons.Middle: { var visualNode = (VisualSymbolicExpressionTreeNode)sender; if (selectedVisualSymbExprTreeNode == null || selectedVisualSymbExprTreeNode == visualNode) return; selectedSubtree = clonedNodeMap[selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode]; var selectedNode = visualNode.SymbolicExpressionTreeNode; if (clonedNodeMap.ContainsKey(selectedNode)) { var selected = clonedNodeMap[selectedNode]; var parent = selected.Parent; parent.RemoveSubtree(parent.IndexOfSubtree(selected)); selectedNode.ForEachNodePostfix(node => { symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node).FillColor = Color.Transparent; clonedNodeMap.Remove(node); }); } } break; } // update visual graph nodes that contain matching trees Color[] colors = { Color.LightSkyBlue, Color.PaleGreen, Color.Tan }; genealogyGraphChart.ClearAllNodes(); // clear node colors // color each graph node according to the degree to which it matches the selected tree fragment var similarityValues = Enum.GetValues(typeof(SimilarityLevel)).Cast().ToList(); foreach (var graphNode in genealogyGraphChart.Graph.Nodes) { var tree = graphNode.SymbolicExpressionTree; for (int i = 0; i != similarityValues.Count; ++i) { if (tree.ContainsFragment(selectedSubtree, similarityValues[i])) { genealogyGraphChart.HighlightNode(graphNode, colors[i]); break; } } } genealogyGraphChart.Chart.UpdateEnabled = true; genealogyGraphChart.Chart.EnforceUpdate(); // refresh the tree chart symbolicExpressionTreeChart.Repaint(); } private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) { } private void similarityModeSelector_SelectedIndexChanged(object sender, EventArgs e) { if (selectedVisualSymbExprTreeNode == null) return; var treeNode = selectedVisualSymbExprTreeNode.SymbolicExpressionTreeNode; var similarityLevel = Enum.GetNames(typeof(SimilarityLevel))[similarityModeSelector.SelectedIndex]; var owners = genealogyGraphChart.Graph.TraceFragment(treeNode, (SimilarityLevel)Enum.Parse(typeof(SimilarityLevel), similarityLevel)).ToList(); if (owners.Any()) { genealogyGraphChart.Chart.UpdateEnabled = false; genealogyGraphChart.ClearAllNodes(); // clear the fill color of all nodes genealogyGraphChart.HighlightNodes(owners, Color.LightSkyBlue); // highlight matching individuals from the genealogy genealogyGraphChart.Chart.UpdateEnabled = true; } genealogyGraphChart.Chart.EnforceUpdate(); // highlight subtree nodes in the tree chart foreach (var node in symbolicExpressionTreeChart.Tree.IterateNodesPostfix()) { var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node); visualNode.FillColor = Color.Transparent; } foreach (var node in treeNode.IterateNodesPostfix()) { var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node); visualNode.FillColor = Color.LightBlue; } } #endregion private void inDegreeButton_Click(object sender, EventArgs e) { genealogyGraphChart.HighlightInDegree(); } private void outDegreeButton_Click(object sender, EventArgs e) { genealogyGraphChart.HighlightOutDegree(); } } }