Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs @ 10214

Last change on this file since 10214 was 9999, checked in by gkronber, 11 years ago

#2102 merged r9973:9975 and r9994 from trunk to stable

File size: 5.9 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) 2002-2013 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 originalValues = variableValuesGetter(problemData.Dataset);
85          var matchingValues = GetEqualValues(originalValues, variableValuesMapping);
86          variableValuesSetter(problemData.Dataset, matchingValues);
87        }
88      };
89
90      action.BeginInvoke(activeView, delegate(IAsyncResult result) {
91        action.EndInvoke(result);
92        mainForm.RemoveOperationProgressFromContent(activeView.Content);
93      }, null);
94    }
95
96    private static ValuesType GetEqualValues(ValuesType originalValues, Dictionary<ValuesType, ValuesType> variableValuesMapping) {
97      if (variableValuesMapping.ContainsKey(originalValues)) return variableValuesMapping[originalValues];
98
99      var matchingValues = variableValuesMapping.FirstOrDefault(kv => kv.Key == kv.Value && EqualVariableValues(originalValues, kv.Key)).Key ?? originalValues;
100      variableValuesMapping[originalValues] = matchingValues;
101      return matchingValues;
102    }
103
104    private static bool EqualVariableValues(ValuesType values1, ValuesType values2) {
105      //compare variable names for equality
106      if (!values1.Keys.SequenceEqual(values2.Keys)) return false;
107      foreach (var key in values1.Keys) {
108        var v1 = values1[key];
109        var v2 = values2[key];
110        if (v1.Count != v2.Count) return false;
111        for (int i = 0; i < v1.Count; i++) {
112          if (!v1[i].Equals(v2[i])) return false;
113        }
114      }
115      return true;
116    }
117
118    private static readonly Action<Dataset, Dictionary<string, IList>> variableValuesSetter;
119    private static readonly Func<Dataset, Dictionary<string, IList>> variableValuesGetter;
120    /// <summary>
121    /// The static initializer is used to create expressions for getting and setting the private variableValues field in the dataset.
122    /// This is done by expressions because the field is private and compiled expression calls are much faster compared to standad reflection calls.
123    /// </summary>
124    static ShrinkDataAnalysisRunsMenuItem() {
125      var dataset = Expression.Parameter(typeof(Dataset));
126      var variableValues = Expression.Parameter(typeof(ValuesType));
127      var valuesExpression = Expression.Field(dataset, "variableValues");
128      var assignExpression = Expression.Assign(valuesExpression, variableValues);
129
130      var variableValuesSetExpression = Expression.Lambda<Action<Dataset, ValuesType>>(assignExpression, dataset, variableValues);
131      variableValuesSetter = variableValuesSetExpression.Compile();
132
133      var variableValuesGetExpression = Expression.Lambda<Func<Dataset, ValuesType>>(valuesExpression, dataset);
134      variableValuesGetter = variableValuesGetExpression.Compile();
135    }
136  }
137}
Note: See TracBrowser for help on using the repository browser.