Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Scheduling/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/RunCollectionVariableImpactView.cs @ 6514

Last change on this file since 6514 was 5975, checked in by mkommend, 14 years ago

#1313: Updated view names to use spaces instead of !camelCasing.

File size: 10.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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.Windows.Forms;
26using HeuristicLab.Common;
27using HeuristicLab.Data;
28using HeuristicLab.MainForm;
29using HeuristicLab.MainForm.WindowsForms;
30using HeuristicLab.Optimization;
31
32namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
33  [Content(typeof(RunCollection), false)]
34  [View("Variable Impacts")]
35  public sealed partial class RunCollectionVariableImpactView : AsynchronousContentView {
36    private const string variableImpactResultName = "Variable impacts";
37    public RunCollectionVariableImpactView() {
38      InitializeComponent();
39    }
40
41    public new RunCollection Content {
42      get { return (RunCollection)base.Content; }
43      set { base.Content = value; }
44    }
45
46    #region events
47    protected override void RegisterContentEvents() {
48      base.RegisterContentEvents();
49      Content.UpdateOfRunsInProgressChanged += new EventHandler(Content_UpdateOfRunsInProgressChanged);
50      Content.ItemsAdded += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_ItemsAdded);
51      Content.ItemsRemoved += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved);
52      Content.CollectionReset += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset);
53      RegisterRunEvents(Content);
54    }
55    protected override void DeregisterContentEvents() {
56      base.RegisterContentEvents();
57      Content.UpdateOfRunsInProgressChanged -= new EventHandler(Content_UpdateOfRunsInProgressChanged);
58      Content.ItemsAdded -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_ItemsAdded);
59      Content.ItemsRemoved -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved);
60      Content.CollectionReset -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset);
61      DeregisterRunEvents(Content);
62    }
63    private void RegisterRunEvents(IEnumerable<IRun> runs) {
64      foreach (IRun run in runs)
65        run.Changed += new EventHandler(Run_Changed);
66    }
67    private void DeregisterRunEvents(IEnumerable<IRun> runs) {
68      foreach (IRun run in runs)
69        run.Changed -= new EventHandler(Run_Changed);
70    }
71    private void Content_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IRun> e) {
72      RegisterRunEvents(e.Items);
73      UpdateData();
74    }
75    private void Content_ItemsRemoved(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IRun> e) {
76      DeregisterRunEvents(e.Items);
77      UpdateData();
78    }
79    private void Content_CollectionReset(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IRun> e) {
80      DeregisterRunEvents(e.OldItems);
81      RegisterRunEvents(e.Items);
82      UpdateData();
83    }
84    private void Content_UpdateOfRunsInProgressChanged(object sender, EventArgs e) {
85      if (!Content.UpdateOfRunsInProgress) UpdateData();
86    }
87    private void Run_Changed(object sender, EventArgs e) {
88      if (!Content.UpdateOfRunsInProgress) UpdateData();
89    }
90    #endregion
91
92    protected override void OnContentChanged() {
93      base.OnContentChanged();
94      this.UpdateData();
95    }
96
97    private void UpdateData() {
98      matrixView.Content = CalculateVariableImpactMatrix();
99    }
100
101    private DoubleMatrix CalculateVariableImpactMatrix() {
102      DoubleMatrix matrix = null;
103      if (Content != null) {
104        List<IRun> runsWithVariables = Content.Where(r => r.Visible && r.Results.ContainsKey(variableImpactResultName)).ToList();
105        IEnumerable<DoubleMatrix> allVariableImpacts = (from run in runsWithVariables
106                                                        select run.Results[variableImpactResultName]).Cast<DoubleMatrix>();
107        IEnumerable<string> variableNames = (from variableImpact in allVariableImpacts
108                                             from variableName in variableImpact.RowNames
109                                             select variableName)
110                                            .Distinct();
111        // filter variableNames: only include names that have at least one non-zero value in a run
112        List<string> variableNamesList = (from variableName in variableNames
113                                          where GetVariableImpacts(variableName, allVariableImpacts).Any(x => !x.IsAlmost(0.0))
114                                          select variableName)
115                                         .ToList();
116
117        List<string> statictics = new List<string> { "Median Rank", "Mean", "StdDev", "pValue" };
118        List<string> columnNames = runsWithVariables.Select(r => r.Name).ToList();
119        columnNames.AddRange(statictics);
120        int runs = runsWithVariables.Count();
121
122        matrix = new DoubleMatrix(variableNamesList.Count, runs + statictics.Count);
123        matrix.SortableView = true;
124        matrix.RowNames = variableNamesList;
125        matrix.ColumnNames = columnNames;
126
127        for (int i = 0; i < runsWithVariables.Count; i++) {
128          IRun run = runsWithVariables[i];
129          DoubleMatrix runVariableImpacts = (DoubleMatrix)run.Results[variableImpactResultName];
130          for (int j = 0; j < runVariableImpacts.Rows; j++) {
131            int rowIndex = variableNamesList.FindIndex(s => s == runVariableImpacts.RowNames.ElementAt(j));
132            if (rowIndex > -1) {
133              matrix[rowIndex, i] = runVariableImpacts[j, 0];
134            }
135          }
136        }
137
138        List<List<double>> variableImpactsOverRuns = (from variableName in variableNamesList
139                                                      select GetVariableImpacts(variableName, allVariableImpacts).ToList())
140                                                     .ToList();
141        List<List<double>> variableRanks = (from variableName in variableNamesList
142                                            select GetVariableImpactRanks(variableName, allVariableImpacts).ToList())
143                                        .ToList();
144        if (variableImpactsOverRuns.Count() > 0) {
145          // the variable with the worst median impact value is chosen as the reference variable
146          // this is problematic if all variables are relevant, however works often in practice
147          List<double> referenceImpacts = (from impacts in variableImpactsOverRuns
148                                           let avg = impacts.Median()
149                                           orderby avg
150                                           select impacts)
151                                           .First();
152          // for all variables
153          for (int row = 0; row < variableImpactsOverRuns.Count; row++) {
154            // median rank
155            matrix[row, runs] = variableRanks[row].Median();
156            // also show mean and std.dev. of relative variable impacts to indicate the relative difference in impacts of variables
157            matrix[row, runs + 1] = variableImpactsOverRuns[row].Average();
158            matrix[row, runs + 2] = variableImpactsOverRuns[row].StandardDeviation();
159
160            double leftTail = 0; double rightTail = 0; double bothTails = 0;
161            // calc differences of impacts for current variable and reference variable
162            double[] z = new double[referenceImpacts.Count];
163            for (int i = 0; i < z.Length; i++) {
164              z[i] = variableImpactsOverRuns[row][i] - referenceImpacts[i];
165            }
166            // wilcoxon signed rank test is used because the impact values of two variables in a single run are not independent
167            alglib.wsr.wilcoxonsignedranktest(z, z.Length, 0, ref bothTails, ref leftTail, ref rightTail);
168            matrix[row, runs + 3] = bothTails;
169          }
170        }
171      }
172      return matrix;
173    }
174
175    private IEnumerable<double> GetVariableImpactRanks(string variableName, IEnumerable<DoubleMatrix> allVariableImpacts) {
176      foreach (DoubleMatrix runVariableImpacts in allVariableImpacts) {
177        // certainly not yet very efficient because ranks are computed multiple times for the same run
178        string[] variableNames = runVariableImpacts.RowNames.ToArray();
179        double[] values = (from row in Enumerable.Range(0, runVariableImpacts.Rows)
180                           select runVariableImpacts[row, 0] * -1)
181                          .ToArray();
182        Array.Sort(values, variableNames);
183        // calculate ranks
184        double[] ranks = new double[values.Length];
185        // check for tied ranks
186        int i = 0;
187        while (i < values.Length) {
188          ranks[i] = i + 1;
189          int j = i + 1;
190          while (j < values.Length && values[i].IsAlmost(values[j])) {
191            ranks[j] = ranks[i];
192            j++;
193          }
194          i = j;
195        }
196        int rankIndex = 0;
197        foreach (string rowVariableName in variableNames) {
198          if (rowVariableName == variableName)
199            yield return ranks[rankIndex];
200          rankIndex++;
201        }
202      }
203    }
204
205    private IEnumerable<double> GetVariableImpacts(string variableName, IEnumerable<DoubleMatrix> allVariableImpacts) {
206      foreach (DoubleMatrix runVariableImpacts in allVariableImpacts) {
207        int row = 0;
208        foreach (string rowName in runVariableImpacts.RowNames) {
209          if (rowName == variableName)
210            yield return runVariableImpacts[row, 0];
211          row++;
212        }
213      }
214    }
215  }
216}
Note: See TracBrowser for help on using the repository browser.