Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2288_HeuristicLab.VariableInteractionNetworks/HeuristicLab.VariableInteractionNetworks.Views/3.3/RunCollectionVariableInteractionNetworkView.cs @ 16966

Last change on this file since 16966 was 16498, checked in by jzenisek, 5 years ago

#2288: adapted online calculation of variable impacts within VIN-view according to new interface of RegressionSolutionVariableImpactsCalculator.CalculateImpacts(..)

File size: 22.4 KB
RevLine 
[12198]1#region License Information
2/* HeuristicLab
[13727]3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[12198]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;
[13821]26using System.Globalization;
[12198]27using System.Linq;
[13727]28using System.Text;
[12198]29using System.Windows.Forms;
30using HeuristicLab.Common;
[13727]31using HeuristicLab.Core;
32using HeuristicLab.Core.Views;
[12198]33using HeuristicLab.Data;
34using HeuristicLab.MainForm;
35using HeuristicLab.Optimization;
36using HeuristicLab.Problems.DataAnalysis;
[13727]37using HeuristicLab.Visualization;
[13773]38using Ellipse = HeuristicLab.Visualization.Ellipse;
[13727]39using Rectangle = HeuristicLab.Visualization.Rectangle;
[12198]40
[13727]41namespace HeuristicLab.VariableInteractionNetworks.Views {
42  [View("Variable Interaction Network")]
43  [Content(typeof(RunCollection), IsDefaultView = false)]
[12198]44
[13727]45  public sealed partial class RunCollectionVariableInteractionNetworkView : ItemView {
46    public RunCollectionVariableInteractionNetworkView() {
47      InitializeComponent();
48      ConfigureNodeShapes();
49    }
[12229]50
[13727]51    public new RunCollection Content {
52      get { return (RunCollection)base.Content; }
53      set {
54        if (value != null && value != Content) {
55          base.Content = value;
[12320]56        }
[13727]57      }
58    }
[12229]59
[13773]60    private VariableInteractionNetwork variableInteractionNetwork;
[12229]61
[13773]62    private static void AssertSameProblemData(RunCollection runs) {
63      IDataset dataset = null;
64      IRegressionProblemData problemData = null;
65      foreach (var run in runs) {
66        var solution = (IRegressionSolution)run.Results.Values.Single(x => x is IRegressionSolution);
67        var ds = solution.ProblemData.Dataset;
68
69        if (solution.ProblemData == problemData) continue;
70        if (ds == dataset) continue;
71        if (problemData == null) {
72          problemData = solution.ProblemData;
73          continue;
[12320]74        }
[13773]75        if (dataset == null) {
76          dataset = ds;
77          continue;
[13727]78        }
[12198]79
[13773]80        if (problemData.TrainingPartition.Start != solution.ProblemData.TrainingPartition.Start || problemData.TrainingPartition.End != solution.ProblemData.TrainingPartition.End)
81          throw new InvalidOperationException("The runs must share the same data.");
[12198]82
[13773]83        if (!ds.DoubleVariables.SequenceEqual(dataset.DoubleVariables))
84          throw new InvalidOperationException("The runs must share the same data.");
85
86        foreach (var v in ds.DoubleVariables) {
87          var values1 = (IList<double>)ds.GetReadOnlyDoubleValues(v);
88          var values2 = (IList<double>)dataset.GetReadOnlyDoubleValues(v);
89
90          if (values1.Count != values2.Count)
91            throw new InvalidOperationException("The runs must share the same data.");
92
93          if (!values1.SequenceEqual(values2))
94            throw new InvalidOperationException("The runs must share the same data.");
[12320]95        }
[13773]96      }
97    }
[12198]98
[14275]99    public static RegressionEnsembleSolution CreateEnsembleSolution(IEnumerable<IRun> runs) {
[13773]100      var solutions = runs.Select(x => x.Results.Values.Single(v => v is IRegressionSolution)).Cast<IRegressionSolution>();
101      return new RegressionEnsembleSolution(new RegressionEnsembleModel(solutions.Select(x => x.Model)), solutions.First().ProblemData);
102    }
103
104    public static Dictionary<string, Tuple<IEnumerable<IRun>, Dictionary<string, double>>> CalculateVariableImpactsOnline(RunCollection runs, bool useBest) {
105      AssertSameProblemData(runs);
106      var solution = (IRegressionSolution)runs.First().Results.Values.Single(x => x is IRegressionSolution);
107      var dataset = (Dataset)solution.ProblemData.Dataset;
108      var originalValues = dataset.DoubleVariables.ToDictionary(x => x, x => dataset.GetReadOnlyDoubleValues(x).ToList());
[15421]109      var medians = dataset.DoubleVariables.ToDictionary(x => x, x => Enumerable.Repeat(originalValues[x].Median(), originalValues[x].Count).ToList());
[13773]110
111      var targetImpacts = new Dictionary<string, Tuple<IEnumerable<IRun>, Dictionary<string, double>>>();
112
[16295]113      var groups = runs.GroupBy(run => {
114        var sol = (IRegressionSolution)run.Results.Values.Single(x => x is IRegressionSolution);
115        return Concatenate(sol.ProblemData.AllowedInputVariables) + sol.ProblemData.TargetVariable;
116      });
117
[13773]118      if (useBest) {
119        // build network using only the best run for each target
[16295]120        foreach (var group in groups) {
121          var solutions = group.Select(run => Tuple.Create(run, (IRegressionSolution)run.Results.Values.Single(sol => sol is IRegressionSolution)));
122          var best = solutions.OrderBy(x => x.Item2.TrainingRSquared).Last();
[16498]123          var impacts = RegressionSolutionVariableImpactsCalculator.CalculateImpacts(best.Item2,
124            RegressionSolutionVariableImpactsCalculator.ReplacementMethodEnum.Shuffle,
125            RegressionSolutionVariableImpactsCalculator.FactorReplacementMethodEnum.Best,
126            RegressionSolutionVariableImpactsCalculator.DataPartitionEnum.All).ToDictionary(x => x.Item1, x => x.Item2);
[16295]127
128          targetImpacts[best.Item2.ProblemData.TargetVariable] = Tuple.Create(new[] { best.Item1 }.AsEnumerable(), impacts);
129        }
[13773]130      } else {
131        foreach (var group in groups) {
132          // calculate average impacts
133          var averageImpacts = new Dictionary<string, double>();
134          solution = (IRegressionSolution)group.First().Results.Values.Single(x => x is IRegressionSolution);
135          foreach (var run in group) {
136            var sol = (IRegressionSolution)run.Results.Values.Single(v => v is IRegressionSolution);
137
138            DoubleLimit estimationLimits = null;
139            if (run.Parameters.ContainsKey("EstimationLimits")) {
140              estimationLimits = (DoubleLimit)run.Parameters["EstimationLimits"];
[12568]141            }
[15421]142            var md = dataset.ToModifiable();
[16295]143
[16498]144            var impacts = RegressionSolutionVariableImpactsCalculator.CalculateImpacts(sol,
145              RegressionSolutionVariableImpactsCalculator.ReplacementMethodEnum.Shuffle,
146              RegressionSolutionVariableImpactsCalculator.FactorReplacementMethodEnum.Best,
147              RegressionSolutionVariableImpactsCalculator.DataPartitionEnum.All);           
[16295]148            foreach (var t in impacts) {
149              if (averageImpacts.ContainsKey(t.Item1))
150                averageImpacts[t.Item1] += t.Item2;
[13773]151              else {
[16295]152                averageImpacts[t.Item1] = t.Item2;
[13773]153              }
[12568]154            }
[13727]155          }
[16295]156
[13773]157          var count = group.Count();
[16497]158          foreach (var v in averageImpacts.Keys.ToList()) {
[13773]159            averageImpacts[v] /= count;
160          }
161
[16295]162          targetImpacts[solution.ProblemData.TargetVariable] = Tuple.Create(group.AsEnumerable(), averageImpacts);
[12320]163        }
[13727]164      }
[13773]165      return targetImpacts;
166    }
[12320]167
[14275]168    public static Dictionary<string, Tuple<IEnumerable<IRun>, Dictionary<string, double>>> CalculateVariableImpactsFromRunResults(RunCollection runs,
[13773]169      string qualityResultName, bool maximization, string impactsResultName, bool useBestRunsPerTarget = false) {
[16295]170
171      Func<IRun, double> getQuality = run => ((DoubleValue)run.Results[qualityResultName]).Value;
172      var targetGroups = runs.GroupBy(x => ((IRegressionProblemData)x.Parameters["ProblemData"]).TargetVariable).ToList();
[13773]173      var targetImpacts = new Dictionary<string, Tuple<IEnumerable<IRun>, Dictionary<string, double>>>();
[15421]174
[13727]175      if (useBestRunsPerTarget) {
[16295]176        foreach (var group in targetGroups) {
177          var ordered = group.OrderBy(getQuality);
178          var best = maximization ? ordered.Last() : ordered.First();
179          var pd = (IRegressionProblemData)best.Parameters["ProblemData"];
180          var target = group.Key;
181          var impacts = (DoubleMatrix)best.Results[impactsResultName];
182          targetImpacts[target] = Tuple.Create((IEnumerable<IRun>)new[] { best }, impacts.RowNames.Select((x, i) => new { x, i }).ToDictionary(x => x.x, x => impacts[x.i, 0]));
[12320]183        }
[13727]184      } else {
[16295]185        foreach (var target in targetGroups) {
[13727]186          var averageImpacts = CalculateAverageImpacts(new RunCollection(target), impactsResultName);
[13773]187          targetImpacts[target.Key] = new Tuple<IEnumerable<IRun>, Dictionary<string, double>>(target, averageImpacts);
[12198]188        }
[13727]189      }
[13773]190      return targetImpacts;
191    }
[12198]192
[14275]193    public static VariableInteractionNetwork CreateNetwork(Dictionary<string, Tuple<IEnumerable<IRun>, Dictionary<string, double>>> targetImpacts) {
[13773]194      var nodes = new Dictionary<string, IVertex>();
195      var vn = new VariableInteractionNetwork();
[13727]196      foreach (var ti in targetImpacts) {
197        var target = ti.Key;
[13773]198        var variableImpacts = ti.Value.Item2;
199        var targetRuns = ti.Value.Item1;
[13727]200        IVertex targetNode;
[12198]201
[13773]202        var variables = variableImpacts.Keys.ToList();
[13727]203        if (variables.Count == 0) continue;
[12198]204
[13727]205        if (!nodes.TryGetValue(target, out targetNode)) {
206          targetNode = new VariableNetworkNode { Label = target };
207          vn.AddVertex(targetNode);
208          nodes[target] = targetNode;
[12320]209        }
[12229]210
[13727]211        IVertex variableNode;
212        if (variables.Count > 1) {
213          var variableList = new List<string>(variables) { target };
214          var junctionLabel = Concatenate(variableList);
215          IVertex junctionNode;
[13874]216          var sb = new StringBuilder();
[13727]217          if (!nodes.TryGetValue(junctionLabel, out junctionNode)) {
[13789]218            var solutionsEnsemble = CreateEnsembleSolution(targetRuns);
[13874]219            junctionNode = new JunctionNetworkNode { Label = solutionsEnsemble.TrainingRSquared.ToString("N3", CultureInfo.CurrentCulture), Data = solutionsEnsemble };
[13727]220            vn.AddVertex(junctionNode);
221            nodes[junctionLabel] = junctionNode;
[13874]222            sb.AppendLine(junctionNode.Label);
[13727]223          }
224          IArc arc;
225          foreach (var v in variables) {
226            var impact = variableImpacts[v];
227            if (!nodes.TryGetValue(v, out variableNode)) {
228              variableNode = new VariableNetworkNode { Label = v };
229              vn.AddVertex(variableNode);
230              nodes[v] = variableNode;
[12320]231            }
[13821]232            arc = new Arc(variableNode, junctionNode) { Weight = impact, Label = impact.ToString("N3", CultureInfo.CurrentCulture) };
[13874]233            sb.AppendLine(v + ": " + arc.Label);
[13727]234            vn.AddArc(arc);
235          }
[13874]236          var jcnNode = (JunctionNetworkNode)junctionNode;
237          var trainingR2 = ((IRegressionSolution)jcnNode.Data).TrainingRSquared;
[13821]238          arc = new Arc(junctionNode, targetNode) { Weight = junctionNode.InArcs.Sum(x => x.Weight), Label = trainingR2.ToString("N3", CultureInfo.CurrentCulture) };
[13727]239          vn.AddArc(arc);
240        } else {
241          foreach (var v in variables) {
242            var impact = variableImpacts[v];
243            if (!nodes.TryGetValue(v, out variableNode)) {
244              variableNode = new VariableNetworkNode { Label = v };
245              vn.AddVertex(variableNode);
246              nodes[v] = variableNode;
[12320]247            }
[13821]248            var arc = new Arc(variableNode, targetNode) {
[15421]249              Weight = impact,
250              Label = impact.ToString("N3", CultureInfo.CurrentCulture)
[13821]251            };
[13727]252            vn.AddArc(arc);
253          }
[12320]254        }
[13727]255      }
256      return vn;
257    }
[12320]258
[14275]259    public static VariableInteractionNetwork ApplyThreshold(VariableInteractionNetwork originalNetwork, double threshold) {
[13806]260      var arcs = originalNetwork.Arcs.Where(x => x.Weight >= threshold).ToList();
261      if (!arcs.Any()) return originalNetwork;
262      var filteredNetwork = new VariableInteractionNetwork();
263      var cloner = new Cloner();
264      var vertices = arcs.SelectMany(x => new[] { x.Source, x.Target }).Select(cloner.Clone).Distinct(); // arcs are not cloned
265      filteredNetwork.AddVertices(vertices);
266      filteredNetwork.AddArcs(arcs.Select(x => (IArc)x.Clone(cloner)));
267
268      var unusedJunctions = filteredNetwork.Vertices.Where(x => x.InDegree == 0 && x is JunctionNetworkNode).ToList();
269      filteredNetwork.RemoveVertices(unusedJunctions);
270      var orphanedNodes = filteredNetwork.Vertices.Where(x => x.Degree == 0).ToList();
271      filteredNetwork.RemoveVertices(orphanedNodes);
272      return filteredNetwork.Vertices.Any() ? filteredNetwork : originalNetwork;
273    }
274
[13727]275    private static double CalculateAverageQuality(RunCollection runs) {
276      var pd = (IRegressionProblemData)runs.First().Parameters["ProblemData"];
277      var target = pd.TargetVariable;
278      var inputs = pd.AllowedInputVariables;
[12198]279
[13727]280      if (!runs.All(x => {
281        var problemData = (IRegressionProblemData)x.Parameters["ProblemData"];
282        return target == problemData.TargetVariable && inputs.SequenceEqual(problemData.AllowedInputVariables);
283      })) {
284        throw new ArgumentException("All runs must have the same target and inputs.");
285      }
286      return runs.Average(x => ((DoubleValue)x.Results["Best training solution quality"]).Value);
287    }
[12320]288
[14275]289    public static Dictionary<string, double> CalculateAverageImpacts(RunCollection runs, string resultName) {
[13727]290      var pd = (IRegressionProblemData)runs.First().Parameters["ProblemData"];
291      var target = pd.TargetVariable;
292      var inputs = pd.AllowedInputVariables.ToList();
[12320]293
[13727]294      var impacts = inputs.ToDictionary(x => x, x => 0d);
[12320]295
[13727]296      // check if all the runs have the same target and same inputs
297      if (!runs.All(x => {
298        var problemData = (IRegressionProblemData)x.Parameters["ProblemData"];
299        return target == problemData.TargetVariable && inputs.SequenceEqual(problemData.AllowedInputVariables);
300      })) {
301        throw new ArgumentException("All runs must have the same target and inputs.");
302      }
[12320]303
[13727]304      foreach (var run in runs) {
305        var impactsMatrix = (DoubleMatrix)run.Results[resultName];
306        int i = 0;
307        foreach (var v in impactsMatrix.RowNames) {
308          impacts[v] += impactsMatrix[i, 0];
309          ++i;
[12320]310        }
[13727]311      }
[12320]312
[13727]313      foreach (var v in inputs) {
314        impacts[v] /= runs.Count;
315      }
[12320]316
[13727]317      return impacts;
318    }
[12263]319
[13727]320    private static string Concatenate(IEnumerable<string> strings) {
321      var sb = new StringBuilder();
322      foreach (var s in strings) {
323        sb.Append(s);
324      }
325      return sb.ToString();
326    }
[12320]327
[13727]328    private void ConfigureNodeShapes() {
329      graphChart.ClearShapes();
330      var font = new Font(FontFamily.GenericSansSerif, 12);
331      graphChart.AddShape(typeof(VariableNetworkNode), new LabeledPrimitive(new Ellipse(graphChart.Chart, new PointD(0, 0), new PointD(30, 30), Pens.Black, Brushes.White), "", font));
332      graphChart.AddShape(typeof(JunctionNetworkNode), new LabeledPrimitive(new Rectangle(graphChart.Chart, new PointD(0, 0), new PointD(15, 15), Pens.Black, Brushes.DarkGray), "", font));
333    }
[12320]334
[16497]335    public void UpdateNetwork(VariableInteractionNetwork network) {
336      if (InvokeRequired) {
337        Invoke((Action<VariableInteractionNetwork>)UpdateNetwork, network);
338      } else {
339        graphChart.Graph = network;
340      }     
341    }
342
[13727]343    #region events
344    protected override void OnContentChanged() {
345      base.OnContentChanged();
346      var run = Content.First();
347      var pd = (IRegressionProblemData)run.Parameters["ProblemData"];
348      var variables = new HashSet<string>(new List<string>(pd.Dataset.DoubleVariables));
349      impactResultNameComboBox.Items.Clear();
350      foreach (var result in run.Results.Where(x => x.Value is DoubleMatrix)) {
351        var m = (DoubleMatrix)result.Value;
352        if (m.RowNames.All(x => variables.Contains(x)))
353          impactResultNameComboBox.Items.Add(result.Key);
354      }
355      qualityResultNameComboBox.Items.Clear();
356      foreach (var result in run.Results.Where(x => x.Value is DoubleValue)) {
357        qualityResultNameComboBox.Items.Add(result.Key);
358      }
359      if (impactResultNameComboBox.Items.Count > 0) {
360        impactResultNameComboBox.Text = (string)impactResultNameComboBox.Items[0];
361      }
362      if (qualityResultNameComboBox.Items.Count > 0) {
363        qualityResultNameComboBox.Text = (string)qualityResultNameComboBox.Items[0];
364      }
365      if (impactResultNameComboBox.Items.Count > 0 && qualityResultNameComboBox.Items.Count > 0)
366        NetworkConfigurationChanged(this, EventArgs.Empty);
367    }
[12320]368
[13727]369    private void TextBoxValidating(object sender, CancelEventArgs e) {
370      double v;
371      string errorMsg = "Could not parse the entered value. Please input a real number.";
372      var tb = (TextBox)sender;
373      if (!double.TryParse(tb.Text, out v)) {
374        e.Cancel = true;
375        tb.Select(0, tb.Text.Length);
[12320]376
[13727]377        // Set the ErrorProvider error with the text to display.
378        this.errorProvider.SetError(tb, errorMsg);
379        errorProvider.BlinkStyle = ErrorBlinkStyle.NeverBlink;
380        errorProvider.SetIconPadding(tb, -20);
381      }
382    }
[12320]383
[13773]384    private void ImpactThresholdTextBoxValidated(object sender, EventArgs e) {
[13727]385      var tb = (TextBox)sender;
386      errorProvider.SetError(tb, string.Empty);
[13806]387      double impact;
[13874]388      if (!double.TryParse(tb.Text, out impact)) {
[13821]389        impact = 0.2;
[13874]390      }
[13806]391      var network = ApplyThreshold(variableInteractionNetwork, impact);
[13773]392      graphChart.Graph = network;
[13727]393    }
[12320]394
[13727]395    private void LayoutConfigurationBoxValidated(object sender, EventArgs e) {
396      var tb = (TextBox)sender;
397      errorProvider.SetError(tb, string.Empty);
398      LayoutConfigurationChanged(sender, e);
399    }
[12320]400
[13727]401    private void NetworkConfigurationChanged(object sender, EventArgs e) {
402      var useBest = impactAggregationComboBox.SelectedIndex <= 0;
[13893]403      var threshold = impactThresholdTrackBar.Value / 100.0;
[13727]404      var qualityResultName = qualityResultNameComboBox.Text;
405      var impactsResultName = impactResultNameComboBox.Text;
406      if (string.IsNullOrEmpty(qualityResultName) || string.IsNullOrEmpty(impactsResultName))
407        return;
408      var maximization = maximizationCheckBox.Checked;
[13773]409      var impacts = CalculateVariableImpactsFromRunResults(Content, qualityResultName, maximization, impactsResultName, useBest);
410      variableInteractionNetwork = CreateNetwork(impacts);
411      var network = ApplyThreshold(variableInteractionNetwork, threshold);
412      graphChart.Graph = network;
[12263]413    }
[13727]414
415    private void LayoutConfigurationChanged(object sender, EventArgs e) {
416      ConstrainedForceDirectedLayout.EdgeRouting routingMode;
417      switch (edgeRoutingComboBox.SelectedIndex) {
418        case 0:
419          routingMode = ConstrainedForceDirectedLayout.EdgeRouting.None;
420          break;
421        case 1:
422          routingMode = ConstrainedForceDirectedLayout.EdgeRouting.Polyline;
423          break;
424        case 2:
425          routingMode = ConstrainedForceDirectedLayout.EdgeRouting.Orthogonal;
426          break;
427        default:
428          throw new ArgumentException("Invalid edge routing mode.");
429      }
430      var idealEdgeLength = double.Parse(idealEdgeLengthTextBox.Text);
[14275]431      if (routingMode == graphChart.RoutingMode && idealEdgeLength.IsAlmost(graphChart.DefaultEdgeLength)) return;
[13727]432      graphChart.RoutingMode = routingMode;
433      graphChart.PerformEdgeRouting = routingMode != ConstrainedForceDirectedLayout.EdgeRouting.None;
[14275]434      graphChart.DefaultEdgeLength = idealEdgeLength;
[13727]435      graphChart.Draw();
436    }
[13773]437
[13874]438    private void ControlsEnable(bool enabled) {
439      qualityResultNameComboBox.Enabled
440        = impactResultNameComboBox.Enabled
441        = impactAggregationComboBox.Enabled
[13893]442        = impactThresholdTrackBar.Enabled
[13874]443        = onlineImpactCalculationButton.Enabled
444        = edgeRoutingComboBox.Enabled
[13893]445        = idealEdgeLengthTextBox.Enabled
446        = maximizationCheckBox.Enabled = enabled;
[13874]447    }
448
[13773]449    private void onlineImpactCalculationButton_Click(object sender, EventArgs args) {
450      var worker = new BackgroundWorker();
451      worker.DoWork += (o, e) => {
[13874]452        ControlsEnable(false);
[16295]453        var impacts = CalculateVariableImpactsOnline(Content, impactAggregationComboBox.SelectedIndex == 0);
[13789]454        variableInteractionNetwork = CreateNetwork(impacts);
[13893]455        var threshold = impactThresholdTrackBar.Minimum + (double)impactThresholdTrackBar.Value / impactThresholdTrackBar.Maximum;
[13789]456        graphChart.Graph = ApplyThreshold(variableInteractionNetwork, threshold);
[13773]457      };
[13874]458      worker.RunWorkerCompleted += (o, e) => ControlsEnable(true);
[13773]459      worker.RunWorkerAsync();
460    }
[13893]461
462    private void relayoutGraphButton_Click(object sender, EventArgs e) {
463      graphChart.Draw();
464    }
[13727]465    #endregion
[13893]466
467    private void exportImpactsMatrixButton_Click(object sender, EventArgs e) {
468      var graph = graphChart.Graph;
469      var labels = graph.Vertices.OfType<VariableNetworkNode>().Select(x => x.Label).ToList();
470      labels.Sort(); // sort variables alphabetically
471      var matrix = new DoubleMatrix(labels.Count, labels.Count) { RowNames = labels, ColumnNames = labels };
472      var indexes = labels.Select((x, i) => new { Label = x, Index = i }).ToDictionary(x => x.Label, x => x.Index);
473      var junctions = graph.Vertices.OfType<JunctionNetworkNode>().ToList();
474      foreach (var jn in junctions) {
475        var target = jn.OutArcs.First().Target.Label;
476        var targetIndex = indexes[target];
477        foreach (var input in jn.InArcs) {
478          var inputIndex = indexes[input.Source.Label];
479          var inputImpact = input.Weight;
480          matrix[targetIndex, inputIndex] = inputImpact;
481        }
482      }
483      for (int i = 0; i < labels.Count; ++i) matrix[i, i] = 1;
484      MainFormManager.MainForm.ShowContent(matrix);
485    }
486
487    private void impactThresholdTrackBar_ValueChanged(object sender, EventArgs e) {
488      var impact = impactThresholdTrackBar.Minimum + (double)impactThresholdTrackBar.Value / impactThresholdTrackBar.Maximum;
489      impactThresholdLabel.Text = impact.ToString("N3", CultureInfo.CurrentCulture);
490      var network = ApplyThreshold(variableInteractionNetwork, impact);
491      graphChart.Graph = network;
492    }
493
494
[13727]495  }
496}
Note: See TracBrowser for help on using the repository browser.