Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2904_CalculateImpacts/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.cs @ 16034

Last change on this file since 16034 was 16034, checked in by fholzing, 6 years ago

#2904: Removed callback, adapted both view and calculator.

File size: 9.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Threading;
26using System.Threading.Tasks;
27using HeuristicLab.Common;
28using HeuristicLab.Data;
29using HeuristicLab.MainForm;
30
31namespace HeuristicLab.Problems.DataAnalysis.Views {
32  [View("Variable Impacts")]
33  [Content(typeof(IRegressionSolution))]
34  public partial class RegressionSolutionVariableImpactsView : DataAnalysisSolutionEvaluationView {
35    private enum SortingCriteria {
36      ImpactValue,
37      Occurrence,
38      VariableName
39    }
40    private CancellationTokenSource cancellationToken = new CancellationTokenSource();
41    private List<Tuple<string, double>> rawVariableImpacts = new List<Tuple<string, double>>();
42
43    public new IRegressionSolution Content {
44      get { return (IRegressionSolution)base.Content; }
45      set {
46        base.Content = value;
47      }
48    }
49
50    public RegressionSolutionVariableImpactsView()
51      : base() {
52      InitializeComponent();
53
54      //Set the default values
55      this.dataPartitionComboBox.SelectedIndex = 0;
56      this.replacementComboBox.SelectedIndex = 3;
57      this.factorVarReplComboBox.SelectedIndex = 0;
58      this.sortByComboBox.SelectedItem = SortingCriteria.ImpactValue;
59    }
60
61    protected override void RegisterContentEvents() {
62      base.RegisterContentEvents();
63      Content.ModelChanged += new EventHandler(Content_ModelChanged);
64      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
65    }
66    protected override void DeregisterContentEvents() {
67      base.DeregisterContentEvents();
68      Content.ModelChanged -= new EventHandler(Content_ModelChanged);
69      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
70    }
71
72    protected virtual void Content_ProblemDataChanged(object sender, EventArgs e) {
73      OnContentChanged();
74    }
75    protected virtual void Content_ModelChanged(object sender, EventArgs e) {
76      OnContentChanged();
77    }
78    protected override void OnContentChanged() {
79      base.OnContentChanged();
80      if (Content == null) {
81        variableImactsArrayView.Content = null;
82      } else {
83        UpdateVariableImpact();
84      }
85    }
86    private void RegressionSolutionVariableImpactsView_VisibleChanged(object sender, EventArgs e) {
87      cancellationToken.Cancel();
88    }
89
90    private void dataPartitionComboBox_SelectedIndexChanged(object sender, EventArgs e) {
91      UpdateVariableImpact();
92    }
93    private void replacementComboBox_SelectedIndexChanged(object sender, EventArgs e) {
94      UpdateVariableImpact();
95    }
96    private void sortByComboBox_SelectedIndexChanged(object sender, EventArgs e) {
97      //Update the default ordering (asc,desc), but remove the eventHandler beforehand (otherwise the data would be ordered twice)
98      ascendingCheckBox.CheckedChanged -= ascendingCheckBox_CheckedChanged;
99      ascendingCheckBox.Checked = (SortingCriteria)sortByComboBox.SelectedItem != SortingCriteria.ImpactValue;
100      ascendingCheckBox.CheckedChanged += ascendingCheckBox_CheckedChanged;
101
102      UpdateOrdering();
103    }
104    private void ascendingCheckBox_CheckedChanged(object sender, EventArgs e) {
105      UpdateOrdering();
106    }
107
108    private async void UpdateVariableImpact() {
109      IProgress progress;
110
111      //Check if the selection is valid
112      if (Content == null) { return; }
113      if (replacementComboBox.SelectedIndex < 0) { return; }
114      if (dataPartitionComboBox.SelectedIndex < 0) { return; }
115      if (factorVarReplComboBox.SelectedIndex < 0) { return; }
116
117      //Prepare arguments
118      var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
119      var replMethod = (RegressionSolutionVariableImpactsCalculator.ReplacementMethodEnum)replacementComboBox.Items[replacementComboBox.SelectedIndex];
120      var factorReplMethod = (RegressionSolutionVariableImpactsCalculator.FactorReplacementMethodEnum)factorVarReplComboBox.Items[factorVarReplComboBox.SelectedIndex];
121      var dataPartition = (RegressionSolutionVariableImpactsCalculator.DataPartitionEnum)dataPartitionComboBox.SelectedItem;
122
123      variableImactsArrayView.Caption = Content.Name + " Variable Impacts";
124      progress = mainForm.AddOperationProgressToView(this, "Calculating variable impacts for " + Content.Name);
125      progress.ProgressValue = 0;
126
127      cancellationToken = new CancellationTokenSource();
128
129      try {
130        var problemData = Content.ProblemData;
131        var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(Content.Model.VariablesUsedForPrediction));
132        //Remember the original ordering of the variables
133        var originalVariableOrdering = problemData.Dataset.VariableNames
134          .Where(v => inputvariables.Contains(v))
135          .Where(v => problemData.Dataset.VariableHasType<double>(v) || problemData.Dataset.VariableHasType<string>(v))
136          .ToList();
137
138        List<Tuple<string, double>> impacts = null;
139        await Task.Run(() => { impacts = CalculateVariableImpacts(originalVariableOrdering, Content.Model, problemData, Content.EstimatedValues, dataPartition, replMethod, factorReplMethod, cancellationToken.Token, progress); });
140        if (impacts == null) { return; }
141
142        rawVariableImpacts.Clear();
143        originalVariableOrdering.ForEach(v => rawVariableImpacts.Add(new Tuple<string, double>(v, impacts.First(vv => vv.Item1 == v).Item2)));
144        UpdateOrdering();
145      }
146      finally {
147        ((MainForm.WindowsForms.MainForm)MainFormManager.MainForm).RemoveOperationProgressFromView(this);
148      }
149    }
150    private List<Tuple<string, double>> CalculateVariableImpacts(List<string> originalVariableOrdering,
151      IRegressionModel model,
152      IRegressionProblemData problemData,
153      IEnumerable<double> estimatedValues,
154      RegressionSolutionVariableImpactsCalculator.DataPartitionEnum dataPartition,
155      RegressionSolutionVariableImpactsCalculator.ReplacementMethodEnum replMethod,
156      RegressionSolutionVariableImpactsCalculator.FactorReplacementMethodEnum factorReplMethod,
157      CancellationToken token,
158      IProgress progress) {
159      List<Tuple<string, double>> impacts = new List<Tuple<string, double>>();
160      int count = originalVariableOrdering.Count;
161      int i = 0;
162
163      foreach (var variable in originalVariableOrdering) {
164        if (cancellationToken.Token.IsCancellationRequested) { return null; }
165        progress.ProgressValue = (double)++i / count;
166        progress.Status = string.Format("Calculating impact for variable {0} ({1} of {2})", variable, i, count);
167
168        double impact = RegressionSolutionVariableImpactsCalculator.CalculateImpact(variable, model, problemData, Content.EstimatedValues, dataPartition, replMethod, factorReplMethod);
169        impacts.Add(new Tuple<string, double>(variable, impact));
170      }
171
172      return impacts;
173    }
174
175    /// <summary>
176    /// Updates the <see cref="variableImactsArrayView"/> according to the selected ordering <see cref="ascendingCheckBox"/> of the selected Column <see cref="sortByComboBox"/>
177    /// The default is "Descending" by "VariableImpact" (as in previous versions)
178    /// </summary>
179    private void UpdateOrdering() {
180      //Check if valid sortingCriteria is selected and data exists
181      if (sortByComboBox.SelectedIndex == -1) { return; }
182      if (rawVariableImpacts == null) { return; }
183      if (!rawVariableImpacts.Any()) { return; }
184
185      var selectedItem = (SortingCriteria)sortByComboBox.SelectedItem;
186      bool ascending = ascendingCheckBox.Checked;
187
188      IEnumerable<Tuple<string, double>> orderedEntries = null;
189
190      //Sort accordingly
191      switch (selectedItem) {
192        case SortingCriteria.ImpactValue:
193          orderedEntries = rawVariableImpacts.OrderBy(v => v.Item2);
194          break;
195        case SortingCriteria.Occurrence:
196          orderedEntries = rawVariableImpacts;
197          break;
198        case SortingCriteria.VariableName:
199          orderedEntries = rawVariableImpacts.OrderBy(v => v.Item1, new NaturalStringComparer());
200          break;
201        default:
202          throw new NotImplementedException("Ordering for selected SortingCriteria not implemented");
203      }
204
205      if (!ascending) { orderedEntries = orderedEntries.Reverse(); }
206
207      //Write the data back
208      var impactArray = new DoubleArray(orderedEntries.Select(i => i.Item2).ToArray()) {
209        ElementNames = orderedEntries.Select(i => i.Item1)
210      };
211
212      //Could be, if the View was closed
213      if (!variableImactsArrayView.IsDisposed) {
214        variableImactsArrayView.Content = (DoubleArray)impactArray.AsReadOnly();
215      }
216    }
217  }
218}
Note: See TracBrowser for help on using the repository browser.