Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs @ 13578

Last change on this file since 13578 was 12578, checked in by mkommend, 9 years ago

#2276: Corrected shrink menu item to only consider objects of type Dataset.

File size: 6.0 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#endregion
23
24using System;
25using System.Collections;
26using System.Collections.Generic;
27using System.Linq;
28using System.Linq.Expressions;
29using HeuristicLab.Common;
30using HeuristicLab.MainForm;
31using HeuristicLab.Optimization;
32using HeuristicLab.Optimizer;
33
34using MenuItem = HeuristicLab.MainForm.WindowsForms.MenuItem;
35using ValuesType = System.Collections.Generic.Dictionary<string, System.Collections.IList>;
36
37namespace HeuristicLab.Problems.DataAnalysis.Views {
38  internal sealed class ShrinkDataAnalysisRunsMenuItem : MenuItem, IOptimizerUserInterfaceItemProvider {
39    public override string Name {
40      get { return "Remove Duplicate Datasets"; }
41    }
42    public override IEnumerable<string> Structure {
43      get { return new string[] { "&Edit", "&Data Analysis" }; }
44    }
45    public override int Position {
46      get { return 5300; }
47    }
48    public override string ToolTipText {
49      get { return "This command shrinks the memory usage of data analysis optimizers by checking and unifying duplicate datasets."; }
50    }
51
52    protected override void OnToolStripItemSet(EventArgs e) {
53      ToolStripItem.Enabled = false;
54    }
55
56    protected override void OnActiveViewChanged(object sender, EventArgs e) {
57      IContentView activeView = MainFormManager.MainForm.ActiveView as IContentView;
58      if (activeView == null) {
59        ToolStripItem.Enabled = false;
60        return;
61      }
62
63      var content = activeView.Content;
64      RunCollection runCollection = content as RunCollection;
65      if (runCollection == null && content is IOptimizer)
66        runCollection = ((IOptimizer)content).Runs;
67
68      if (runCollection == null) {
69        ToolStripItem.Enabled = false;
70        return;
71      }
72
73      ToolStripItem.Enabled = runCollection.Any(run => run.Parameters.Any(p => p.Value is IDataAnalysisProblemData));
74    }
75
76    public override void Execute() {
77      IContentView activeView = (IContentView)MainFormManager.MainForm.ActiveView;
78      var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
79      mainForm.AddOperationProgressToContent(activeView.Content, "Removing duplicate datasets.");
80
81      Action<IContentView> action = (view) => {
82        var variableValuesMapping = new Dictionary<ValuesType, ValuesType>();
83        foreach (var problemData in view.Content.GetObjectGraphObjects(excludeStaticMembers: true).OfType<IDataAnalysisProblemData>()) {
84          var dataset = problemData.Dataset as Dataset;
85          if (dataset == null) continue;
86          var originalValues = variableValuesGetter(dataset);
87          var matchingValues = GetEqualValues(originalValues, variableValuesMapping);
88          variableValuesSetter(dataset, matchingValues);
89        }
90      };
91
92      action.BeginInvoke(activeView, delegate(IAsyncResult result) {
93        action.EndInvoke(result);
94        mainForm.RemoveOperationProgressFromContent(activeView.Content);
95      }, null);
96    }
97
98    private static ValuesType GetEqualValues(ValuesType originalValues, Dictionary<ValuesType, ValuesType> variableValuesMapping) {
99      if (variableValuesMapping.ContainsKey(originalValues)) return variableValuesMapping[originalValues];
100
101      var matchingValues = variableValuesMapping.FirstOrDefault(kv => kv.Key == kv.Value && EqualVariableValues(originalValues, kv.Key)).Key ?? originalValues;
102      variableValuesMapping[originalValues] = matchingValues;
103      return matchingValues;
104    }
105
106    private static bool EqualVariableValues(ValuesType values1, ValuesType values2) {
107      //compare variable names for equality
108      if (!values1.Keys.SequenceEqual(values2.Keys)) return false;
109      foreach (var key in values1.Keys) {
110        var v1 = values1[key];
111        var v2 = values2[key];
112        if (v1.Count != v2.Count) return false;
113        for (int i = 0; i < v1.Count; i++) {
114          if (!v1[i].Equals(v2[i])) return false;
115        }
116      }
117      return true;
118    }
119
120    private static readonly Action<Dataset, Dictionary<string, IList>> variableValuesSetter;
121    private static readonly Func<Dataset, Dictionary<string, IList>> variableValuesGetter;
122    /// <summary>
123    /// The static initializer is used to create expressions for getting and setting the private variableValues field in the dataset.
124    /// This is done by expressions because the field is private and compiled expression calls are much faster compared to standad reflection calls.
125    /// </summary>
126    static ShrinkDataAnalysisRunsMenuItem() {
127      var dataset = Expression.Parameter(typeof(Dataset));
128      var variableValues = Expression.Parameter(typeof(ValuesType));
129      var valuesExpression = Expression.Field(dataset, "variableValues");
130      var assignExpression = Expression.Assign(valuesExpression, variableValues);
131
132      var variableValuesSetExpression = Expression.Lambda<Action<Dataset, ValuesType>>(assignExpression, dataset, variableValues);
133      variableValuesSetter = variableValuesSetExpression.Compile();
134
135      var variableValuesGetExpression = Expression.Lambda<Func<Dataset, ValuesType>>(valuesExpression, dataset);
136      variableValuesGetter = variableValuesGetExpression.Compile();
137    }
138  }
139}
Note: See TracBrowser for help on using the repository browser.