Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
07/18/14 16:39:50 (10 years ago)
Author:
bburlacu
Message:

#1772: Merged trunk changes.

Location:
branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic.Views
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic.Views

  • branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs

    r10650 r11208  
    11#region License Information
    22/* HeuristicLab
    3  * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44 *
    55 * This file is part of HeuristicLab.
     
    3333  public abstract partial class InteractiveSymbolicDataAnalysisSolutionSimplifierView : AsynchronousContentView {
    3434    private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> foldedNodes;
     35    private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> changedNodes;
    3536    private Dictionary<ISymbolicExpressionTreeNode, double> nodeImpacts;
     37
    3638    private enum TreeState { Valid, Invalid }
    37 
    38     public InteractiveSymbolicDataAnalysisSolutionSimplifierView() {
     39    private TreeState treeState;
     40
     41    protected InteractiveSymbolicDataAnalysisSolutionSimplifierView() {
    3942      InitializeComponent();
    4043      foldedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
     44      changedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
    4145      nodeImpacts = new Dictionary<ISymbolicExpressionTreeNode, double>();
    4246      this.Caption = "Interactive Solution Simplifier";
     47
     48      // initialize the tree modifier that will be used to perform edit operations over the tree
     49      treeChart.ModifyTree = Modify;
     50    }
     51
     52    /// <summary>
     53    /// Remove, Replace or Insert subtrees
     54    /// </summary>
     55    /// <param name="tree">The symbolic expression tree</param>
     56    /// <param name="parent">The insertion point (ie, the parent node who will receive a new child)</param>
     57    /// <param name="oldChild">The subtree to be replaced</param>
     58    /// <param name="newChild">The replacement subtree</param>
     59    /// <param name="removeSubtree">Flag used to indicate if whole subtrees should be removed (default behavior), or just the subtree root</param>
     60    private void Modify(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode parent,
     61      ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild, bool removeSubtree = true) {
     62      if (oldChild == null && newChild == null)
     63        throw new ArgumentNullException("Cannot deduce operation type from the arguments. Please provide non null operands.");
     64      if (oldChild == null) {
     65        // insertion operation
     66        parent.AddSubtree(newChild);
     67        newChild.Parent = parent;
     68      } else if (newChild == null) {
     69        // removal operation
     70        parent.RemoveSubtree(parent.IndexOfSubtree(oldChild));
     71        if (!removeSubtree) {
     72          for (int i = oldChild.SubtreeCount - 1; i >= 0; --i) {
     73            var subtree = oldChild.GetSubtree(i);
     74            oldChild.RemoveSubtree(i);
     75            parent.AddSubtree(subtree);
     76          }
     77        }
     78      } else {
     79        // replacement operation
     80        var replacementIndex = parent.IndexOfSubtree(oldChild);
     81        parent.RemoveSubtree(replacementIndex);
     82        parent.InsertSubtree(replacementIndex, newChild);
     83        newChild.Parent = parent;
     84        if (changedNodes.ContainsKey(oldChild)) {
     85          changedNodes.Add(newChild, changedNodes[oldChild]); // so that on double click the original node is restored
     86          changedNodes.Remove(oldChild);
     87        } else {
     88          changedNodes.Add(newChild, oldChild);
     89        }
     90      }
     91      treeState = IsValid(tree) ? TreeState.Valid : TreeState.Invalid;
     92      switch (treeState) {
     93        case TreeState.Valid:
     94          this.grpViewHost.Enabled = true;
     95          UpdateModel(Content.Model.SymbolicExpressionTree);
     96          break;
     97        case TreeState.Invalid:
     98          this.grpViewHost.Enabled = false;
     99          break;
     100      }
     101    }
     102
     103    // the optimizer always assumes 2 children for multiplication and addition nodes
     104    // thus, we enforce that the tree stays valid so that the constant optimization won't throw an exception
     105    // by returning 2 as the minimum allowed arity for addition and multiplication symbols
     106    private readonly Func<ISymbol, int> GetMinArity = symbol => {
     107      var min = symbol.MinimumArity;
     108      if (symbol is Multiplication || symbol is Division) return Math.Max(2, min);
     109      return min;
     110    };
     111    private bool IsValid(ISymbolicExpressionTree tree) {
     112      treeChart.Tree = tree;
     113      treeChart.Repaint();
     114      bool valid = !tree.IterateNodesPostfix().Any(node => node.SubtreeCount < GetMinArity(node.Symbol) || node.SubtreeCount > node.Symbol.MaximumArity);
     115      if (valid) {
     116        btnOptimizeConstants.Enabled = true;
     117        btnSimplify.Enabled = true;
     118        treeStatusValue.Visible = false;
     119      } else {
     120        btnOptimizeConstants.Enabled = false;
     121        btnSimplify.Enabled = false;
     122        treeStatusValue.Visible = true;
     123      }
     124      this.Refresh();
     125      return valid;
    43126    }
    44127
     
    83166
    84167      var impactAndReplacementValues = CalculateImpactAndReplacementValues(tree);
    85       nodeImpacts = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item1);
    86168      var replacementValues = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item2);
    87169      foreach (var pair in replacementValues.Where(pair => !(pair.Key is ConstantTreeNode))) {
    88170        foldedNodes[pair.Key] = MakeConstantTreeNode(pair.Value);
    89171      }
     172      nodeImpacts = impactAndReplacementValues.ToDictionary(x => x.Key, x => x.Value.Item1);
    90173      PaintNodeImpacts();
    91174    }
     
    104187
    105188    private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
     189      if (treeState == TreeState.Invalid) return;
    106190      var visualNode = (VisualTreeNode<ISymbolicExpressionTreeNode>)sender;
     191      if (visualNode.Content == null) { throw new Exception("VisualNode content cannot be null."); }
    107192      var symbExprTreeNode = (SymbolicExpressionTreeNode)visualNode.Content;
    108       if (symbExprTreeNode == null) return;
    109193      var tree = Content.Model.SymbolicExpressionTree;
    110194      var parent = symbExprTreeNode.Parent;
    111195      int indexOfSubtree = parent.IndexOfSubtree(symbExprTreeNode);
    112       if (foldedNodes.ContainsKey(symbExprTreeNode)) {
     196      if (changedNodes.ContainsKey(symbExprTreeNode)) {
     197        // undo node change
     198        parent.RemoveSubtree(indexOfSubtree);
     199        var originalNode = changedNodes[symbExprTreeNode];
     200        parent.InsertSubtree(indexOfSubtree, originalNode);
     201        changedNodes.Remove(symbExprTreeNode);
     202      } else if (foldedNodes.ContainsKey(symbExprTreeNode)) {
    113203        // undo node folding
    114204        SwitchNodeWithReplacementNode(parent, indexOfSubtree);
     
    119209    private void SwitchNodeWithReplacementNode(ISymbolicExpressionTreeNode parent, int subTreeIndex) {
    120210      ISymbolicExpressionTreeNode subTree = parent.GetSubtree(subTreeIndex);
    121       parent.RemoveSubtree(subTreeIndex);
    122211      if (foldedNodes.ContainsKey(subTree)) {
     212        parent.RemoveSubtree(subTreeIndex);
    123213        var replacementNode = foldedNodes[subTree];
    124214        parent.InsertSubtree(subTreeIndex, replacementNode);
     
    133223      double max = impacts.Max();
    134224      double min = impacts.Min();
    135       foreach (var treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {
     225      foreach (ISymbolicExpressionTreeNode treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {
    136226        VisualTreeNode<ISymbolicExpressionTreeNode> visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
    137227
    138228        if (!(treeNode is ConstantTreeNode) && nodeImpacts.ContainsKey(treeNode)) {
     229          visualTree.ToolTip = visualTree.Content.ToString();
    139230          double impact = nodeImpacts[treeNode];
    140231
     
    158249        }
    159250        if (visualTree != null)
    160           if (treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) {
     251          if (changedNodes.ContainsKey(treeNode)) {
     252            visualTree.LineColor = Color.DodgerBlue;
     253          } else if (treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) {
    161254            visualTree.LineColor = Color.DarkOrange;
    162255          }
Note: See TracChangeset for help on using the changeset viewer.