Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
07/08/14 19:46:45 (10 years ago)
Author:
mkommend
Message:

#1763: Merged r9930, r11086, r11111, r11112, r11115, r11123 into stable (all other changes were already merged to the stable branch.

Location:
stable
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • stable

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs

    r11146 r11150  
    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;
    107       if (visualNode.Content == null) { throw new Exception("Visual node content cannot be null."); }
     191      if (visualNode.Content == null) { throw new Exception("VisualNode content cannot be null."); }
    108192      var symbExprTreeNode = (SymbolicExpressionTreeNode)visualNode.Content;
    109       if (!foldedNodes.ContainsKey(symbExprTreeNode)) return; // constant nodes cannot be folded
     193      var tree = Content.Model.SymbolicExpressionTree;
    110194      var parent = symbExprTreeNode.Parent;
    111195      int indexOfSubtree = parent.IndexOfSubtree(symbExprTreeNode);
    112       SwitchNodeWithReplacementNode(parent, indexOfSubtree);
    113       UpdateModel(Content.Model.SymbolicExpressionTree);
     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)) {
     203        // undo node folding
     204        SwitchNodeWithReplacementNode(parent, indexOfSubtree);
     205      }
     206      UpdateModel(tree);
    114207    }
    115208
     
    130223      double max = impacts.Max();
    131224      double min = impacts.Min();
    132       foreach (var treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {
     225      foreach (ISymbolicExpressionTreeNode treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {
    133226        VisualTreeNode<ISymbolicExpressionTreeNode> visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
    134227
    135228        if (!(treeNode is ConstantTreeNode) && nodeImpacts.ContainsKey(treeNode)) {
    136           visualTree.ToolTip = visualTree.Content.ToString(); // to avoid duplicate tooltips
     229          visualTree.ToolTip = visualTree.Content.ToString();
    137230          double impact = nodeImpacts[treeNode];
    138231
     
    156249        }
    157250        if (visualTree != null)
    158           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)) {
    159254            visualTree.LineColor = Color.DarkOrange;
    160255          }
Note: See TracChangeset for help on using the changeset viewer.