Changeset 7422


Ignore:
Timestamp:
01/27/12 16:14:06 (9 years ago)
Author:
bburlacu
Message:

#1763: The simplifier view now uses a clone of the current model on which the actual simplification or tree pruning is applied. This fixes a crash when the user clicks on the Symbolic Regression Model while the background thread is pruning the tree (because it was trying to display the tree while it was being changed). Also took out the display part from the CalculateReplacementNodesAndNodeImpacts method and put it in a separate method.

Location:
branches/HeuristicLab.TreeSimplifierView
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.TreeSimplifierView/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.Views-3.4.csproj

    r7411 r7422  
    217217    </BootstrapperPackage>
    218218  </ItemGroup>
    219   <ItemGroup>
    220     <EmbeddedResource Include="InteractiveSymbolicDataAnalysisSolutionSimplifierView.resx">
    221       <DependentUpon>InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs</DependentUpon>
    222     </EmbeddedResource>
    223     <EmbeddedResource Include="SymbolicExpressionTreeNodeChangeValueDialog.resx">
    224       <DependentUpon>SymbolicExpressionTreeNodeChangeValueDialog.cs</DependentUpon>
    225     </EmbeddedResource>
    226   </ItemGroup>
    227219  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
    228220  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
  • branches/HeuristicLab.TreeSimplifierView/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs

    r7411 r7422  
    3737    private Dictionary<ISymbolicExpressionTreeNode, double> originalValues;
    3838    private bool updateInProgress = false;
    39     private VisualSymbolicExpressionTreeNode visualTreeNode; // need some kind of state for correctly handling events
     39    private VisualSymbolicExpressionTreeNode visualTreeNode; // for correctly handling events when changing node values
     40    private ISymbolicExpressionTree model;
    4041
    4142    public InteractiveSymbolicDataAnalysisSolutionSimplifierView() {
     
    7172
    7273    protected virtual void OnModelChanged() {
    73       this.CalculateReplacementNodesAndNodeImpacts();
     74      model = (model == null)
     75                ? (ISymbolicExpressionTree)Content.Model.SymbolicExpressionTree.Clone()
     76                : Content.Model.SymbolicExpressionTree;
     77      this.CalculateReplacementNodesAndNodeImpacts(model);
     78      this.PaintModel();
    7479    }
    7580
    7681    protected virtual void OnProblemDataChanged() {
    7782      this.CalculateReplacementNodesAndNodeImpacts();
     83      this.PaintModel();
    7884    }
    7985
    8086    protected override void OnContentChanged() {
     87      model = (model == null)
     88          ? (ISymbolicExpressionTree)Content.Model.SymbolicExpressionTree.Clone()
     89          : Content.Model.SymbolicExpressionTree;
    8190      base.OnContentChanged();
    82       this.CalculateReplacementNodesAndNodeImpacts();
     91      this.CalculateReplacementNodesAndNodeImpacts(model);
     92      this.PaintModel();
    8393      this.viewHost.Content = this.Content;
    8494    }
    8595
    8696    private void CalculateReplacementNodesAndNodeImpacts() {
    87       if (Content != null && Content.Model != null && Content.ProblemData != null) {
    88         var tree = Content.Model.SymbolicExpressionTree;
    89         var replacementValues = CalculateReplacementValues(tree);
    90         foreach (var pair in replacementValues) {
    91           if (!(pair.Key is ConstantTreeNode)) {
    92             replacementNodes[pair.Key] = MakeConstantTreeNode(pair.Value);
    93           }
    94         }
    95         nodeImpacts = CalculateImpactValues(Content.Model.SymbolicExpressionTree);
    96 
    97         if (!updateInProgress) {
    98           // automatically fold all branches with impact = 0
    99           List<ISymbolicExpressionTreeNode> nodeList = Content.Model.SymbolicExpressionTree.Root.GetSubtree(0).IterateNodesPrefix().ToList();
    100           foreach (var parent in nodeList) {
    101             for (int subTreeIndex = 0; subTreeIndex < parent.SubtreeCount; subTreeIndex++) {
    102               var child = parent.GetSubtree(subTreeIndex);
    103               if (!(child.Symbol is Constant) && nodeImpacts[child].IsAlmost(0.0)) {
    104                 SwitchNodeWithReplacementNode(parent, subTreeIndex);
    105               }
     97      if (Content == null || Content.Model == null || Content.ProblemData == null) return;
     98      //var tree = Content.Model.SymbolicExpressionTree;
     99      var tree = model;
     100      var replacementValues = CalculateReplacementValues(tree);
     101      foreach (var pair in replacementValues.Where(pair => !(pair.Key is ConstantTreeNode))) {
     102        replacementNodes[pair.Key] = MakeConstantTreeNode(pair.Value);
     103      }
     104      nodeImpacts = CalculateImpactValues(tree);
     105
     106      if (!updateInProgress) {
     107        // automatically fold all branches with impact = 0
     108        List<ISymbolicExpressionTreeNode> nodeList = tree.Root.GetSubtree(0).IterateNodesPrefix().ToList();
     109        foreach (var parent in nodeList) {
     110          for (int subTreeIndex = 0; subTreeIndex < parent.SubtreeCount; subTreeIndex++) {
     111            var child = parent.GetSubtree(subTreeIndex);
     112            if (!(child.Symbol is Constant) && nodeImpacts[child].IsAlmost(0.0)) {
     113              SwitchNodeWithReplacementNode(parent, subTreeIndex);
    106114            }
    107115          }
    108116        }
    109 
    110         // show only interesting part of solution
    111         if (tree.Root.SubtreeCount > 1)
    112           this.treeChart.Tree = new SymbolicExpressionTree(tree.Root); // RPB + ADFs
    113         else
    114           this.treeChart.Tree = new SymbolicExpressionTree(tree.Root.GetSubtree(0).GetSubtree(0)); // 1st child of RPB
    115         this.PaintNodeImpacts();
    116       }
     117      }
     118      PaintModel();
     119    }
     120
     121    private void CalculateReplacementNodesAndNodeImpacts(ISymbolicExpressionTree tree) {
     122      var replacementValues = CalculateReplacementValues(tree);
     123      foreach (var pair in replacementValues.Where(pair => !(pair.Key is ConstantTreeNode))) {
     124        replacementNodes[pair.Key] = MakeConstantTreeNode(pair.Value);
     125      }
     126      nodeImpacts = CalculateImpactValues(tree);
     127
     128      if (!updateInProgress) {
     129        // automatically fold all branches with impact = 0
     130        List<ISymbolicExpressionTreeNode> nodeList = tree.Root.GetSubtree(0).IterateNodesPrefix().ToList();
     131        foreach (var parent in nodeList) {
     132          for (int subTreeIndex = 0; subTreeIndex < parent.SubtreeCount; subTreeIndex++) {
     133            var child = parent.GetSubtree(subTreeIndex);
     134            if (!(child.Symbol is Constant) && nodeImpacts[child].IsAlmost(0.0)) {
     135              SwitchNodeWithReplacementNode(parent, subTreeIndex);
     136            }
     137          }
     138        }
     139      }
     140      PaintModel();
     141    }
     142
     143    private void PaintModel() {
     144      // show only interesting part of solution
     145      this.treeChart.Tree = model.Root.SubtreeCount > 1 ? new SymbolicExpressionTree(model.Root) : new SymbolicExpressionTree(model.Root.GetSubtree(0).GetSubtree(0));
     146      this.PaintNodeImpacts();
    117147    }
    118148
     
    132162    private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
    133163      visualTreeNode = (VisualSymbolicExpressionTreeNode)sender;
    134       var tree = Content.Model.SymbolicExpressionTree;
     164      var tree = model;
    135165      // check if the node value/weight has been altered
    136166      // if so, the first double click will return the node to its original value/weight
     
    219249      var value = double.Parse(textBox.Text);
    220250      var subTree = visualTreeNode.SymbolicExpressionTreeNode;
    221       var tree = Content.Model.SymbolicExpressionTree;
    222251
    223252      if (subTree.Symbol is Constant)
     
    226255        (subTree as VariableTreeNode).Weight = value;
    227256
    228       // show only interesting part of solution
    229       treeChart.Tree = tree.Root.SubtreeCount > 1 ? new SymbolicExpressionTree(tree.Root) : new SymbolicExpressionTree(tree.Root.GetSubtree(0).GetSubtree(0));
    230       updateInProgress = true;
    231       UpdateModel(tree);
    232       updateInProgress = false;
     257      PaintModel();
    233258    }
    234259
     
    249274      double max = impacts.Max();
    250275      double min = impacts.Min();
    251       foreach (ISymbolicExpressionTreeNode treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {
     276      foreach (ISymbolicExpressionTreeNode treeNode in model.IterateNodesPostfix()) {
    252277        VisualSymbolicExpressionTreeNode visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
    253278        bool flag1 = replacementNodes.ContainsKey(treeNode);
     
    287312
    288313    private void PaintCollapsedNodes() {
    289       foreach (ISymbolicExpressionTreeNode treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {
     314      foreach (ISymbolicExpressionTreeNode treeNode in model.IterateNodesPostfix()) {
    290315        bool flag1 = replacementNodes.ContainsKey(treeNode);
    291316        bool flag2 = originalValues.ContainsKey(treeNode);
     
    300325    private void btnSimplify_Click(object sender, EventArgs e) {
    301326      SymbolicDataAnalysisExpressionTreeSimplifier simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
    302       var simplifiedExpressionTree = simplifier.Simplify(Content.Model.SymbolicExpressionTree);
     327      var simplifiedExpressionTree = simplifier.Simplify(model);
    303328      UpdateModel(simplifiedExpressionTree);
    304329    }
    305330
     331    protected abstract void btnOptimizeConstants_Click(object sender, EventArgs e);
     332
    306333    private void btnPrune_Click(object sender, EventArgs e) {
     334      btnPrune.Enabled = false;
    307335      backgroundWorker1.RunWorkerAsync();
    308336    }
    309337
     338    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
     339      var worker = sender as BackgroundWorker;
     340      PruneTree(worker);
     341    }
     342
     343    private void PruneTree(BackgroundWorker worker) {
     344      var tree = model;
     345      // get all tree nodes
     346      foreach (var node in GetNodesAtDepth(tree.Root, new Data.IntRange(2, tree.Depth))) {
     347        if (worker.CancellationPending)
     348          break; // pruning cancelled
     349        if (!(node.Symbol is Constant) && nodeImpacts.ContainsKey(node) && nodeImpacts[node] < 0.001) {
     350          SwitchNodeWithReplacementNode(node.Parent, node.Parent.IndexOfSubtree(node));
     351          nodeImpacts = CalculateImpactValues(tree);
     352          // we do not refresh the replacementValues because they won't change when folding nodes with such low impacts (<0.001)
     353        }
     354      }
     355    }
     356
     357    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
     358      if (e.Cancelled) {
     359        // The user canceled the operation.
     360      } else if (e.Error != null) {
     361        // There was an error during the operation.
     362        // Error-handling
     363      } else {
     364        // The operation completed normally. We can update the model
     365        UpdateModel(model);
     366      }
     367      btnPrune.Enabled = true;
     368    }
     369
     370    #region helpers
    310371    private static IEnumerable<ISymbolicExpressionTreeNode> GetNodesAtDepth(ISymbolicExpressionTreeNode root, Data.IntRange range) {
    311372      var list = new List<Tuple<ISymbolicExpressionTreeNode, int>> { new Tuple<ISymbolicExpressionTreeNode, int>(root, 0) };
     
    328389      }
    329390    }
    330 
    331     protected abstract void btnOptimizeConstants_Click(object sender, EventArgs e);
    332 
    333     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
    334       BackgroundWorker worker = sender as BackgroundWorker;
    335       PruneTree(worker);
    336 
    337     }
    338 
    339     private void PruneTree(BackgroundWorker worker) {
    340       var tree = Content.Model.SymbolicExpressionTree;
    341       // get all tree nodes
    342       foreach (var node in GetNodesAtDepth(tree.Root, new Data.IntRange(2, tree.Depth))) {
    343         if (worker.CancellationPending)
    344           break; // pruning cancelled
    345         if (!(node.Symbol is Constant) && nodeImpacts.ContainsKey(node) && nodeImpacts[node] < 0.001) {
    346           SwitchNodeWithReplacementNode(node.Parent, node.Parent.IndexOfSubtree(node));
    347           CalculateReplacementNodesAndNodeImpacts();
    348         }
    349       }
    350     }
    351 
    352     private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
    353       if (e.Cancelled) {
    354         // The user canceled the operation.
    355       } else if (e.Error != null) {
    356         // There was an error during the operation.
    357         // Error-handling
    358       } else {
    359         // The operation completed normally. We can update the model
    360         UpdateModel(Content.Model.SymbolicExpressionTree);
    361       }
    362     }
     391    #endregion
    363392  }
    364393}
Note: See TracChangeset for help on using the changeset viewer.