using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; using HeuristicLab.Common; 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("LineageExplorerView")] [Content(typeof(LineageExplorer), IsDefaultView = false)] public sealed partial class LineageExplorerView : ItemView { private Dictionary treeMap; private List lineage; private Dictionary> fragmentFrequencies; public new LineageExplorer Content { get { return (LineageExplorer)base.Content; } set { base.Content = value; } } public LineageExplorerView() { InitializeComponent(); treeMap = new Dictionary(); } protected override void DeregisterContentEvents() { // TODO: Deregister your event handlers here base.DeregisterContentEvents(); } protected override void RegisterContentEvents() { base.RegisterContentEvents(); // TODO: Register your event handlers here } #region Event Handlers (Content) // TODO: Put event handlers of the content here #endregion protected override void OnContentChanged() { base.OnContentChanged(); if (Content == null) { } else { var tuples = Content.Trees.OrderByDescending(x => x.Item2).ToList(); scopeListTreeView.Nodes.AddRange(tuples.Select(x => new TreeNode(x.Item2.ToString())).ToArray()); for (int i = 0; i != tuples.Count; ++i) { treeMap.Add(scopeListTreeView.Nodes[i], tuples[i].Item1); double quality = tuples[i].Item2; int colorIndex = (int)Math.Floor(quality * ColorGradient.Colors.Count); var color = ColorGradient.Colors[colorIndex]; scopeListTreeView.Nodes[i].ForeColor = color; } } } protected override void SetEnabledStateOfControls() { base.SetEnabledStateOfControls(); // TODO: Enable or disable controls based on whether the content is null or the view is set readonly } private void scopeListTreeView_AfterSelect(object sender, TreeViewEventArgs e) { var treeNode = scopeListTreeView.SelectedNode; var symbExprTree = treeMap[treeNode]; fragmentFrequencies = fragmentFrequencies ?? new Dictionary>(); if (fragmentFrequencies.ContainsKey(symbExprTree) && false) { // colorize tree nodes according to fragment frequencies symbolicExpressionTreeChart.SuspendRepaint = true; var frequencies = fragmentFrequencies[symbExprTree]; foreach (var node in symbExprTree.IterateNodesBreadth()) { double freq = frequencies[node]; int index = (int)Math.Floor(freq * ColorGradient.Colors.Count / scopeListTreeView.GetNodeCount(false)); if (index == ColorGradient.Colors.Count) index--; var color = ColorGradient.Colors[index]; var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node); visualNode.FillColor = Color.FromArgb(200, color); } symbolicExpressionTreeChart.SuspendRepaint = false; symbolicExpressionTreeChart.Repaint(); } // highlight crossover fragment HighlightFragment(symbExprTree); var graphNode = Content.GenealogyGraph.GetGraphNodes(symbExprTree).Last(); lineage = lineage ?? new List(); lineage.Clear(); lineage.Add(graphNode); var gn = graphNode; while (gn.InEdges != null && gn.InEdges.Count != 0) { gn = (SymbolicExpressionTreeGenealogyGraphNode)gn.InEdges[0].Source; lineage.Add(gn); } lineage.Reverse(); // increasing order by generation // update the righthand side tree view qualityImprovementTreeView.Nodes.Clear(); for (int i = 0; i != lineage.Count; ++i) { var node = new TreeNode(string.Format("Generation {0}", lineage[i].Rank)); qualityImprovementTreeView.Nodes.Add(node); var quality = lineage[i].Quality; int colorIndex = (int)Math.Floor(quality * ColorGradient.Colors.Count); var color = ColorGradient.Colors[colorIndex]; node.ForeColor = color; } } /// /// Given a symbolic expression tree, find the corresponding vertex in the genealogy graph, and highlight the fragment /// that is saved as a data member in the incoming arc from the parent in the previous generation /// /// private void HighlightFragment(ISymbolicExpressionTree symbExprTree) { // update the symbolic expression tree chart with the new selected tree: symbolicExpressionTreeChart.SuspendRepaint = true; symbolicExpressionTreeChart.Tree = symbExprTree; var matchingNodes = Content.GenealogyGraph.GetGraphNodes(symbExprTree); SymbolicExpressionTreeGenealogyGraphNode graphNode = matchingNodes.First(); if (graphNode.InEdges == null) { symbolicExpressionTreeChart.SuspendRepaint = false; symbolicExpressionTreeChart.Repaint(); return; } var fragment = graphNode.InEdges.Count == 1 ? (IFragment)graphNode.InEdges[0].Data : (IFragment)graphNode.InEdges[1].Data; if (fragment.Root == null) { symbolicExpressionTreeChart.SuspendRepaint = false; symbolicExpressionTreeChart.Repaint(); return; } foreach (var node in fragment.Root.IterateNodesBreadth()) { var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node); visualNode.LineColor = Color.DodgerBlue; } symbolicExpressionTreeChart.SuspendRepaint = false; symbolicExpressionTreeChart.Repaint(); } private void qualityImprovementTreeView_AfterSelect(object sender, TreeViewEventArgs e) { var tree = lineage[qualityImprovementTreeView.SelectedNode.Index].SymbolicExpressionTree; HighlightFragment(tree); } private void calculateFragmentFrequencyButton_Click(object sender, EventArgs e) { // the individual can occur multiple times in the graph if it is(was) elite. we take the first occurence. var graphNode = Content.GenealogyGraph.GetGraphNodes(symbolicExpressionTreeChart.Tree).First(); var trees = Content.GenealogyGraph.Nodes.Where(x => x.Rank.IsAlmost(graphNode.Rank)).Select(x => x.SymbolicExpressionTree).ToList(); var fragments = graphNode.SymbolicExpressionTree.IterateNodesBreadth().Select(n => new Fragment { Root = n }); var similarityComparer = new SymbolicExpressionTreeNodeSimilarityComparer { MatchConstantValues = false, MatchVariableNames = true, MatchVariableWeights = false }; var canonicalSorter = new SymbolicExpressionTreeCanonicalSorter(); fragmentFrequencies = fragmentFrequencies ?? new Dictionary>(); if (!fragmentFrequencies.ContainsKey(graphNode.SymbolicExpressionTree)) { fragmentFrequencies[graphNode.SymbolicExpressionTree] = new Dictionary(); } fragmentFrequencies[graphNode.SymbolicExpressionTree].Clear(); symbolicExpressionTreeChart.SuspendRepaint = true; foreach (var f in fragments) { double freq = 0; foreach (var t in trees) { if (t.Root.ContainsFragment(f, similarityComparer)) ++freq; } fragmentFrequencies[graphNode.SymbolicExpressionTree].Add(f.Root, freq); // colorize tree nodes according to fragment frequencies int index = (int)Math.Floor(freq * ColorGradient.Colors.Count / trees.Count); if (index == ColorGradient.Colors.Count) index--; var color = ColorGradient.Colors[index]; foreach (var node in f.Root.IterateNodesBreadth()) { var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node); visualNode.FillColor = Color.FromArgb(200, color); } } symbolicExpressionTreeChart.SuspendRepaint = false; symbolicExpressionTreeChart.Repaint(); } private void symbolicExpressionTreeChart_SymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) { } private void showGenealogyButton_Click(object sender, EventArgs e) { var tree = symbolicExpressionTreeChart.Tree; if (tree == null) return; var graphNode = Content.GenealogyGraph.GetGraphNodes(tree).First(); var graph = new SymbolicExpressionTreeGenealogyGraph(); var ancestors = graphNode.Ancestors(); foreach (var ancestorNode in ancestors) { graph.AddNode(ancestorNode); } using (var dialog = new GenealogyGraphDialog { Graph = graph }) { dialog.ShowDialog(this); } } private void button1_Click(object sender, EventArgs e) { using (var dialog = new FrequentFragmentsDialog()) { var panel = new Panel { Dock = DockStyle.Left, Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Bottom }; panel.Controls.Add(new SymbolicExpressionTreeChart() { Tree = treeMap.Values.First() }); panel.Controls.Add(new Label { Text = "Fragment frequency." }); dialog.fragmentsPanel.Controls.Add(panel); dialog.ShowDialog(this); } } private void showFrequentFragmentsButton_Click(object sender, EventArgs e) { int bestN; bool success = int.TryParse(bestNTextBox.Text, out bestN); if (!success) bestN = 10; var tuples = Content.Trees.Select(t => new { Tree = t.Item1, Quality = t.Item2 }).OrderByDescending(x => x.Quality).ToList(); var bestTrees = tuples.Take(bestN).Select(x => x.Tree).ToList(); var similarityComparer = new SymbolicExpressionTreeNodeSimilarityComparer { MatchConstantValues = false, MatchVariableNames = true, MatchVariableWeights = false }; var fragments = bestTrees.SelectMany(t => t.IterateNodesBreadth()).Where(n => n.GetLength() >= 3).Distinct(similarityComparer).Select(n => new Fragment { Root = n }); double bestNQuality = tuples.Take(bestN).Sum(x => x.Quality); // average quality of best N individuals in the population using (var dialog = new FrequentFragmentsDialog()) { foreach (var fragment in fragments.Take(20)) { double avgQuality = bestNQuality; double frequency = bestN; foreach (var t in tuples.Skip(bestN)) { var tree = t.Tree; if (tree.Root.ContainsFragment(fragment, similarityComparer)) { avgQuality += t.Quality; frequency++; } } if (frequency > 0.2) { var panel = new Panel { Dock = DockStyle.Left, Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Bottom }; panel.Controls.Add(new SymbolicExpressionTreeChart() { Tree = treeMap.Values.First() }); panel.Controls.Add(new Label { Text = "Fragment frequency." }); dialog.fragmentsPanel.Controls.Add(panel); } } dialog.ShowDialog(this); } } #region Event Handlers (child controls) // TODO: Put event handlers of child controls here. #endregion } }