Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks.Views/3.3/VariableInteractionNetworkView.cs @ 12568

Last change on this file since 12568 was 12568, checked in by arapeanu, 9 years ago

#2288: Fixed bug in SymbolicDataAnalysisVariableImpactsAnalyzer (simplification before optimization) and in VariableInteractionNetworkView for computing the adjacency matrix and sorting the variable impacts matrix

File size: 21.3 KB
RevLine 
[12198]1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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.ComponentModel;
25using System.Drawing;
26using System.Linq;
27using System.Windows.Forms;
28using HeuristicLab.Common;
29using HeuristicLab.Data;
30using HeuristicLab.MainForm;
31using HeuristicLab.MainForm.WindowsForms;
32using HeuristicLab.Optimization;
33using HeuristicLab.Problems.DataAnalysis;
34using HeuristicLab.Problems.DataAnalysis.Symbolic;
35using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
[12229]36using System.Collections;
[12198]37
[12320]38namespace HeuristicLab.VariableInteractionNetworks.Views
39{
40    [View("Variable Interaction Network")]
41    [Content(typeof(RunCollection), IsDefaultView = false)]
[12198]42
[12320]43    public sealed partial class VariableInteractionNetworkView : AsynchronousContentView
44    {
45        private const string variableImpactResultName = "Variable impacts";
46        private const string TrainingBestSolutionParameterName = "Best training solution";
[12229]47
[12320]48        public new RunCollection Content
49        {
50            get { return (RunCollection)base.Content; }
51            set { base.Content = value; }
52        }
[12229]53
[12320]54        public VariableInteractionNetworkView()
55        {
56            InitializeComponent();
57        }
[12229]58
[12320]59        internal class NoFocusTrackBar : System.Windows.Forms.TrackBar
60        {
61            [System.Runtime.InteropServices.DllImport("user32.dll")]
62            public extern static int SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[12229]63
[12320]64            private static int MakeParam(int loWord, int hiWord)
65            {
66                return (hiWord << 16) | (loWord & 0xffff);
67            }
[12229]68
[12320]69            protected override void OnGotFocus(EventArgs e)
70            {
71                base.OnGotFocus(e);
72                SendMessage(this.Handle, 0x0128, MakeParam(1, 0x1), 0);
73            }
74        }
[12198]75
[12320]76        #region events
[12198]77
[12320]78        //  #region Event Handlers (Content)
79        protected override void OnContentChanged()
80        {
81            base.OnContentChanged();
82            if (Content == null)
83            {
84                // TODO: Add code when content has been changed and is null
85            }
86            else
87            {
88                // TODO: Add code when content has been changed and is not null
[12568]89                viewHost2.Content = CalculateNodeImportance(CalculateAdjacencyMatrix());
[12320]90                var adjMatrix = CalculateAdjacencyMatrix();
91                viewHost1.Content = adjMatrix;
92                viewHost3.Content = (DoubleMatrix)adjMatrix.Clone();
93                trackBar1.Minimum = (int)(1000 * GetMinNonNullElement(adjMatrix));
94                trackBar1.Maximum = (int)(1000 * (adjMatrix.Max()));
95            }
96        }
97        #endregion
[12198]98
[12320]99        protected override void SetEnabledStateOfControls()
[12198]100        {
[12320]101            base.SetEnabledStateOfControls();
102            // TODO: Enable or disable controls based on whether the content is null or the view is set readonly
103        }
104
105        #region Event Handlers (child controls)
106        // TODO: Put event handlers of child controls here.
107        #endregion
108
109        private DoubleMatrix CalculateAdjacencyMatrix()
110        {
111            var runCollection = Content;
[12568]112            var inputVariables = ((IRegressionProblemData)runCollection.First().Parameters["ProblemData"]).InputVariables.Select(x => x.Value).ToList();
113            var groupRunCollection = Content.GroupBy(x => ((IRegressionProblemData)x.Parameters["ProblemData"]).TargetVariable).OrderBy(x => inputVariables.IndexOf(x.Key)).ToList();
[12320]114
115            var allVariableImpacts = runCollection.Select(run => (DoubleMatrix)run.Results[variableImpactResultName]);
116            var variableNames = (from variableImpact in allVariableImpacts
117                                 from variableName in variableImpact.RowNames
118                                 select variableName).Distinct().ToArray();
[12568]119           
120            var vars = new List<Tuple<int, string>>();
121           
122            var allowedInputs = ((IRegressionProblemData)groupRunCollection[0].First().Parameters["ProblemData"]).AllowedInputVariables.ToList();
123
[12320]124            var adjMatrix = new DoubleMatrix(variableNames.Length, variableNames.Length);
125
[12568]126            for (int i = 0; i < adjMatrix.Rows; ++i)
127            {
128                int inputIndex = allowedInputs.FindIndex(x => x == variableNames[i]);
129                vars.Add(new Tuple<int, string>(inputIndex, variableNames[i]));
130            }
131
132            vars.Sort((a, b) => a.Item1.CompareTo(b.Item1));
133
134            for (int i = 0; i < adjMatrix.Rows; ++i)
135            {
136                variableNames[i] = vars[i].Item2;
137            }
138            adjMatrix.RowNames = variableNames;
[12320]139            adjMatrix.ColumnNames = adjMatrix.RowNames;
[12568]140
[12320]141            for (int j = 0; j < groupRunCollection.Count; ++j)
[12198]142            {
[12320]143                var g = groupRunCollection[j];
[12568]144               
[12320]145                var matrix = CalculateAdjacencyRows(g);
[12568]146                var variables = new List<double>();
[12320]147
148                for (int i = 0; i < matrix.Columns; ++i)
149                {
[12568]150                    variables.Add(matrix[0, i]);
[12320]151                }
[12568]152               
[12320]153                for (int i = 0; i < variables.Count; ++i)
154                {
[12568]155                    if (i == j)
156                    {
157                        adjMatrix[i, i] = 0;
158                        variables.Insert(i, 0);
159                    }
160                    else
161                        adjMatrix[j, i] = variables[i];
[12320]162                }
[12198]163            }
[12320]164            return adjMatrix;
165        }
166
167        private DoubleMatrix CalculateAdjacencyRows(IEnumerable<IRun> runs)
168        {
169            var runNames = runs.Select(x => x.Name).ToArray();
170            var runsArray = runs.ToArray();
171            DoubleMatrix varImpactMatrix = CalculateVariableImpactMatrix(runsArray, runNames);
[12568]172         
173            var targetMatrix = new DoubleMatrix(1, varImpactMatrix.Rows);
[12320]174
175            for (int i = 0; i < varImpactMatrix.Rows; ++i)
[12198]176            {
[12320]177                targetMatrix[0, i] = varImpactMatrix[i, runNames.Length];
[12198]178            }
[12320]179
[12568]180            targetMatrix.RowNames = new[] { "Impacts" };
181            targetMatrix.ColumnNames = varImpactMatrix.RowNames;
[12320]182            return targetMatrix;
[12198]183        }
184
[12320]185        private DoubleMatrix UpdateAdjacencyMatrixByThresholdAndTargetVariable(double threshold, string targetVariable, DoubleMatrix adjMatrix)
186        {
187            var originalMatrix = (DoubleMatrix)viewHost1.Content;
188            var groupRunCollection = Content.GroupBy(x => ((IRegressionProblemData)x.Parameters["ProblemData"]).TargetVariable).ToList();
189            string[] targets = adjMatrix.RowNames.ToArray();
190            var targetIndex = Array.IndexOf(targets, targetVariable);
[12229]191
[12320]192            for (int j = 0; j < groupRunCollection.Count; ++j)
193            {
194                double originalValue = originalMatrix[targetIndex, j];
195                adjMatrix[targetIndex, j] = (originalValue <= Math.Max(threshold, Double.Parse(genThreshold.Text))) ? 0 : originalValue;
196            }
197            return adjMatrix;
198        }
199
200        private DoubleMatrix UpdateAdjacencyMatrixByThreshold(double threshold, DoubleMatrix adjMatrix)
[12198]201        {
[12320]202            var originalMatrix = (DoubleMatrix)viewHost1.Content;
203            var groupRunCollection = Content.GroupBy(x => ((IRegressionProblemData)x.Parameters["ProblemData"]).TargetVariable).ToList();
204
205            for (int i = 0; i < adjMatrix.Rows; ++i)
206            {
207                for (int j = 0; j < adjMatrix.Columns; ++j)
208                {
209                    double originalValue = originalMatrix[i, j];
210                    adjMatrix[i, j] = originalValue <= threshold ? 0 : originalValue;
211                }
212            }
213            return adjMatrix;
[12198]214        }
215
[12320]216        private double GetMinNonNullElement(DoubleMatrix adjMatrix)
217        {
218            double min = adjMatrix.Max();
219            for (int i = 0; i < adjMatrix.Rows; i++)
220            {
221                for (int j = 0; j < adjMatrix.Columns; j++)
222                {                 
223                    min = (min > adjMatrix[i, j] && adjMatrix[i, j] != 0) ? adjMatrix[i, j] : min;
224                }
225            }
226            return min;
227        }
[12198]228
[12320]229        private double GetMaxFromRow(int rowIndex, DoubleMatrix adjMatrix)
[12198]230        {
[12320]231            double max = adjMatrix.Min();
232            for (int j = 0; j < adjMatrix.Columns; ++j)
[12198]233            {
[12320]234                max = (max < adjMatrix[rowIndex, j] && adjMatrix[rowIndex, j] != 0) ? adjMatrix[rowIndex, j] : max;
235            }
236            return max;
[12198]237        }
238
[12320]239        private DoubleMatrix CalculateNodeImportance(DoubleMatrix adjMatrix)
240        {
241            DoubleMatrix nodeImportance = new DoubleMatrix(adjMatrix.Rows, 1);
242            var variables = new List<Tuple<string, double>>();
243            var rowNames = adjMatrix.RowNames.ToList();
244            var groupRunCollection = Content.GroupBy(x => ((IRegressionProblemData)x.Parameters["ProblemData"]).TargetVariable).ToList();
245            double[] meanQuality = new double[groupRunCollection.Count];
[12263]246
[12320]247            for (int j = 0; j < groupRunCollection.Count; ++j)
248            {
249                var g = groupRunCollection[j];
250                meanQuality[j] = g.Average(x => ((IRegressionSolution)x.Results[TrainingBestSolutionParameterName]).TrainingRSquared);
251            }
[12263]252
[12320]253            for (int i = 0; i < adjMatrix.Columns; ++i)
254            {
255                for (int j = 0; j < adjMatrix.Rows; ++j)
256                {
257                    nodeImportance[i, 0] += adjMatrix[j, i] * meanQuality[j];
258                }
259                nodeImportance[i, 0] /= (adjMatrix.Rows - 1);
260                variables.Add(new Tuple<string, double>(rowNames[i], nodeImportance[i, 0]));
261            }
[12263]262
[12320]263            variables.Sort((b, a) => a.Item2.CompareTo(b.Item2));
[12263]264
[12320]265            for (int i = 0; i < nodeImportance.Rows; ++i)
266            {
267                nodeImportance[i, 0] = variables[i].Item2;
268                rowNames[i] = variables[i].Item1;
269            }
[12263]270
[12320]271            nodeImportance.RowNames = rowNames;
272            nodeImportance.ColumnNames = new[] { "Node Importance" };
273            return nodeImportance;
274        }
[12229]275
[12568]276        //modified from RunCollectionVariableImpactView
[12320]277        private DoubleMatrix CalculateVariableImpactMatrix(IRun[] runs, string[] runNames)
278        {
279            IEnumerable<DoubleMatrix> allVariableImpacts = (from run in runs
280                                                            select run.Results[variableImpactResultName]).Cast<DoubleMatrix>();
281            IEnumerable<string> variableNames = (from variableImpact in allVariableImpacts
282                                                 from variableName in variableImpact.RowNames
283                                                 select variableName).Distinct();
[12229]284
[12320]285            // filter variableNames: only include names that have at least one non-zero value in a run
286            List<string> variableNamesList = (from variableName in variableNames
287                                              where GetVariableImpacts(variableName, allVariableImpacts).Any(x => !x.IsAlmost(0.0))
288                                              select variableName).ToList();
[12229]289
[12320]290            List<string> columnNames = new List<string>(runNames);
291            columnNames.Add("Mean");
[12229]292
[12320]293            int numberOfRuns = runs.Length;
[12229]294
[12320]295            DoubleMatrix matrix = new DoubleMatrix(variableNamesList.Count, numberOfRuns + 1);
296            matrix.SortableView = true;
297            matrix.ColumnNames = columnNames;
298
299            List<List<double>> variableImpactsOverRuns = (from variableName in variableNamesList
300                                                          select GetVariableImpacts(variableName, allVariableImpacts).ToList()).ToList();
301
302            for (int row = 0; row < variableImpactsOverRuns.Count; row++)
303            {
304                matrix[row, numberOfRuns] = Math.Round(variableImpactsOverRuns[row].Average(), 3);
305            }
306
307            // fill matrix with impacts from runs
308            for (int i = 0; i < runs.Length; i++)
309            {
310                IRun run = runs[i];
311                DoubleMatrix runVariableImpacts = (DoubleMatrix)run.Results[variableImpactResultName];
312                for (int j = 0; j < runVariableImpacts.Rows; j++)
313                {
314                    int rowIndex = variableNamesList.FindIndex(s => s == runVariableImpacts.RowNames.ElementAt(j));
315                    if (rowIndex > -1)
316                    {
317                        matrix[rowIndex, i] = Math.Round(runVariableImpacts[j, 0], 3);
318                    }
319                }
320            }
[12568]321
322            // sort by median
323            var sortedMatrix = (DoubleMatrix)matrix.Clone();
324            var sortedIndexes = from i in Enumerable.Range(0, sortedMatrix.Rows)
325                                orderby matrix[i, numberOfRuns]
326                                select i;
327
328            int targetIndex = 0;
329            foreach (var sourceIndex in sortedIndexes)
330            {
331                for (int c = 0; c < matrix.Columns; c++)
332                    sortedMatrix[targetIndex, c] = matrix[sourceIndex, c];
333                targetIndex++;
334            }
335            sortedMatrix.RowNames = sortedIndexes.Select(i => variableNamesList[i]);
336
337            var vars = new List<Tuple<int, string, double>>();
338            var rowNames = sortedMatrix.RowNames.ToList();
339
340            var groupRunCollection = Content.GroupBy(x => ((IRegressionProblemData)x.Parameters["ProblemData"]).TargetVariable).ToList();
341            var inputs = ((IRegressionProblemData)groupRunCollection[0].First().Parameters["ProblemData"]).InputVariables.ToList();
342            List<string> inp = (from input in inputs
343                                select (input.ToString())).ToList();
344
345            for (int i = 0; i < sortedMatrix.Rows; ++i)
346            {
347                int inputIndex = inp.FindIndex(x => x == rowNames[i]);
348                vars.Add(new Tuple<int, string, double>(inputIndex, rowNames[i], sortedMatrix[i, runNames.Length]));
349            }
350
351                vars.Sort((a, b) => a.Item1.CompareTo(b.Item1));
352               
353            for (int i = 0; i < sortedMatrix.Rows; ++i)
354            {
355                sortedMatrix[i, runNames.Length] = vars[i].Item3;
356                rowNames[i] = vars[i].Item2;
357            }
358            sortedMatrix.RowNames = rowNames;
359
360            return sortedMatrix;
[12320]361        }
362
363        //taken from RunCollectionVariableImpactView
364        private IEnumerable<double> GetVariableImpacts(string variableName, IEnumerable<DoubleMatrix> allVariableImpacts)
[12198]365        {
[12320]366            foreach (DoubleMatrix runVariableImpacts in allVariableImpacts)
367            {
368                int row = 0;
369                foreach (string rowName in runVariableImpacts.RowNames)
370                {
371                    if (rowName == variableName)
372                        yield return runVariableImpacts[row, 0];
373                    row++;
374                }
375            }
[12229]376        }
[12198]377
[12320]378        private void trackBar1_ValueChanged(object sender, EventArgs e)
[12229]379        {
[12320]380            genThreshold.Text = (0.001 * trackBar1.Value).ToString();
381            textBox1.Text = (0.001 * trackBar1.Minimum).ToString();
382            textBox2.Text = (0.001 * trackBar1.Maximum).ToString();
383            viewHost3.Content = UpdateAdjacencyMatrixByThreshold(0.001 * trackBar1.Value, (DoubleMatrix)viewHost3.Content);
384        }
385
386        private void mouseDownEvent(TrackBar tb, MouseEventArgs e)
387        {
388                double percentage = (double)e.X / (double)(tb.Width - 6);
389                double clickPos = percentage * (tb.Maximum - tb.Minimum);
390                try
391                {
392                    tb.Value = (int)clickPos + tb.Minimum;
393                }
394                catch
395                {
396                    MessageBox.Show("Value outside range!");
397                    return;
398                }
399        }
400
401        private void trackBar1_MouseDown(object sender, MouseEventArgs e)
402        {
403            mouseDownEvent(trackBar1, e);
404        }
405
406        private void trackBar2_MouseDown(object sender, MouseEventArgs e)
407        {
408            if (targetVariablesCombo.SelectedIndex < 0)
[12229]409            {
[12320]410                return;
411            }
412            else
413            {
414                mouseDownEvent(trackBar2, e);
415            }
416        }
417
418        private void trackBar2_ValueChanged(object sender, EventArgs e)
419        {
420            targetThreshold.Text = (0.001 * trackBar2.Value).ToString();
421
422            if (targetVariablesCombo.SelectedIndex < 0)
423            {
424                MessageBox.Show("Please select target variable!");
425                return;
426            }
427            else
428            {
429                string selectedItem = (string)targetVariablesCombo.Items[targetVariablesCombo.SelectedIndex];
430                viewHost3.Content = UpdateAdjacencyMatrixByThresholdAndTargetVariable(0.001 * trackBar2.Value, selectedItem, (DoubleMatrix)viewHost3.Content);
431            }
432        }
433
434        private void genThresholdEvent()
435        {
436            this.errorProvider.SetError(genThreshold, "");
437
438            if (genThreshold.Text != "")
439            {
440                if (Double.Parse(genThreshold.Text) >= GetMinNonNullElement((DoubleMatrix)viewHost1.Content) && Double.Parse(genThreshold.Text) <= ((DoubleMatrix)viewHost1.Content).Max())
[12229]441                {
[12320]442                    genThreshold.Select(genThreshold.Text.Length, 0);
443                    trackBar1.Value = (int)(1000 * Double.Parse(genThreshold.Text));
444                    viewHost3.Content = UpdateAdjacencyMatrixByThreshold(Double.Parse(genThreshold.Text), (DoubleMatrix)viewHost3.Content);
[12229]445                }
[12320]446                else
447                {
448                    this.errorProvider.SetError(genThreshold, "Value out of range!");
449                }
[12229]450            }
[12320]451            else
452            {
453                MessageBox.Show("Please select a threshold!");
454                this.errorProvider.SetError(genThreshold, "");
455                return;
456            }
[12198]457        }
[12263]458
[12320]459        private void genThreshold_TextChanged(object sender, EventArgs e)
[12263]460        {
[12320]461            genThresholdEvent();
462        }
463
464        private void genThreshold_KeyDown(object sender, KeyEventArgs e)
465        {
466            if (e.KeyCode == Keys.Enter)
467                genThresholdEvent();       
468        }
469
470        private void targetThresholdEvent()
471        {
472            this.errorProvider2.SetError(targetThreshold, "");
473
474            if (targetVariablesCombo.SelectedIndex < 0)
[12263]475            {
[12320]476                return;
[12263]477            }
[12320]478            else
479            {
480                string selectedItem = (string)targetVariablesCombo.Items[targetVariablesCombo.SelectedIndex];
481                if (Double.Parse(targetThreshold.Text) >= Double.Parse(textBox3.Text) && Double.Parse(targetThreshold.Text) <= Double.Parse(textBox4.Text))
482                {
483                    trackBar2.Value = (int)(1000 * Double.Parse(targetThreshold.Text));
484                }
485                else
486                {
487                    this.errorProvider2.SetError(targetThreshold, "Value out of range!");
488                    return;
489                }
490            }
[12263]491        }
[12320]492
493        private void targetThreshold_TextChanged(object sender, EventArgs e)
494        {
495            targetThresholdEvent();
496        }
497
498        private void targetThreshold_KeyDown(object sender, KeyEventArgs e)
499        {
500            if (e.KeyCode == Keys.Enter)
501            {
502                targetThresholdEvent();
503            }
504        }
505
506        private void targetVariablesCombo_Dropdown(object sender, System.EventArgs e)
507        {
508            targetVariablesCombo.Items.Clear();
509            string[] targetVariables = ((DoubleMatrix)viewHost3.Content).RowNames.ToArray();
510            targetVariablesCombo.Items.AddRange(targetVariables);
511        }
512
513        private void targetVariablesCombo_SelectedIndexChanged(object sender, System.EventArgs e)
514        {
515            var targetIndex = targetVariablesCombo.SelectedIndex;
516            string selectedItem = (string)targetVariablesCombo.Items[targetIndex];
517            trackBar2.Minimum = 0;
518            trackBar2.Maximum = (int)(1000 * GetMaxFromRow(targetIndex, (DoubleMatrix)viewHost1.Content));
519            textBox3.Text = trackBar2.Minimum.ToString();
520            textBox4.Text = (0.001 * trackBar2.Maximum).ToString();
521            UpdateAdjacencyMatrixByThresholdAndTargetVariable(0.001 * trackBar2.Value, selectedItem, (DoubleMatrix)viewHost3.Content);
522        }
[12263]523    }
[12198]524}
Note: See TracBrowser for help on using the repository browser.