#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 => (SymbolicExpressionGenealogyGraphNode)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 => (SymbolicExpressionGenealogyGraphNode)n.InEdges[1].Source).ToList(); genealogyGraphChart.HighlightNodes(nodes); } } }