Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
05/03/16 21:20:55 (9 years ago)
Author:
bburlacu
Message:

#2597: Speed up response calculation in the GradientChart by using an internal dataset to store variable values.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/GradientChart.cs

    r13825 r13829  
    3232namespace HeuristicLab.Problems.DataAnalysis.Views {
    3333  public partial class GradientChart : EnhancedChart {
    34     private ModifiableDataset dataset;
     34    private ModifiableDataset sharedDataset; // used for syncronising variable values between charts
     35    private ModifiableDataset internalDataset; // used to cache values and speed up calculations
    3536
    3637    public bool ShowLegend { get; set; }
     
    191192      this.problemData = pd;
    192193      this.variable = variable;
    193       this.dataset = dataset;
     194      this.sharedDataset = dataset;
    194195      this.min = min;
    195196      this.max = max;
    196197      this.points = points;
     198
     199      // add an event such that whenever a value is changed in the shared dataset,
     200      // this change is reflected in the internal dataset (where the value becomes a whole column)
     201      var variables = sharedDataset.DoubleVariables.ToList();
     202      sharedDataset.ItemChanged += (o, e) => {
     203        var rowIndex = e.Value;
     204        var columnIndex = e.Value2;
     205        var ds = (ModifiableDataset)o;
     206        var variableName = variables[columnIndex];
     207        if (variableName == Variable) return;
     208        var v = ds.GetDoubleValue(variableName, rowIndex);
     209        var values = new List<double>(Enumerable.Repeat(v, Points));
     210        internalDataset.ReplaceVariable(variableName, values);
     211      };
     212
     213      // configure internal dataset. we also expand the range in order to get nice tick intervals on the x axis
     214      const int tics = 5;
     215      double xmin, xmax, xinterval;
     216      ChartUtil.CalculateAxisInterval(min, max, tics, out xmin, out xmax, out xinterval);
     217      var step = (xmax - xmin) / points;
     218      var xvalues = new List<double>();
     219      for (int i = 0; i < points; ++i) { xvalues.Add(xmin + i * step); }
     220      internalDataset = new ModifiableDataset(variables, variables.Select(x => x == Variable ? xvalues : new List<double>(Enumerable.Repeat(sharedDataset.GetDoubleValue(x, 0), xvalues.Count))));
    197221    }
    198222
    199223    public void UpdateChart() {
    200224      // throw exceptions?
    201       if (dataset == null || solutionList == null || !solutionList.Any())
     225      if (sharedDataset == null || solutionList == null || !solutionList.Any())
    202226        return;
    203227      if (min.IsAlmost(max) || min > max || points == 0)
    204228        return;
    205229      Series.Clear();
    206 
    207       var defaultValue = dataset.GetDoubleValue(variable, 0);
    208230      var vla = VerticalLineAnnotation;
     231      Annotations.Clear();
     232      var defaultValue = sharedDataset.GetDoubleValue(variable, 0);
     233      vla.Visible = ShowCursor;
     234      Annotations.Add(vla);
    209235      vla.X = defaultValue;
    210       vla.Visible = ShowCursor;
    211       Annotations.Clear();
    212       Annotations.Add(vla);
    213236
    214237      double axisMin, axisMax, axisInterval;
     
    262285        }
    263286      }
    264       dataset = new ModifiableDataset(variables, variableValues);
    265     }
    266 
    267     private double GetEstimatedValue(IRegressionSolution solution, double x) {
    268       var v = dataset.GetDoubleValue(Variable, 0);
    269       dataset.SetVariableValue(x, Variable, 0);
    270       var y = solution.Model.GetEstimatedValues(dataset, new[] { 0 }).Single();
    271       dataset.SetVariableValue(v, Variable, 0);
    272       return y;
     287      sharedDataset = new ModifiableDataset(variables, variableValues);
    273288    }
    274289
    275290    private Series PlotSeries(IRegressionSolution solution) {
    276       var v = dataset.GetDoubleValue(variable, 0);
     291      var v = sharedDataset.GetDoubleValue(variable, 0);
    277292      var series = new Series { ChartType = SeriesChartType.Point };
    278 
    279       var step = (max - min) / points;
    280       var axisX = ChartAreas[0].AxisX;
    281       if (ShowXAxisLabel) {
    282         axisX.Title = Variable + " : " + v.ToString("N3", CultureInfo.CurrentCulture);
    283       }
    284       var axisY = ChartAreas[0].AxisY;
    285       if (ShowYAxisLabel) { axisY.Title = Target; }
    286       double y;
    287       // lefthand section outside of the training range
    288       for (double x = axisX.Minimum; x < min; x += step) {
    289         y = GetEstimatedValue(solution, x);
    290         series.Points.Add(new DataPoint(x, y) { MarkerSize = 2, MarkerColor = Color.Orange });
    291       }
    292       // points in the trainig range
    293       for (double x = min; x < max; x += step) {
    294         y = GetEstimatedValue(solution, x);
    295         series.Points.Add(new DataPoint(x, y) { MarkerSize = 2 });
    296       }
    297       // righthand section outside of the training range
    298       for (double x = max; x < axisX.Maximum; x += step) {
    299         y = GetEstimatedValue(solution, x);
    300         series.Points.Add(new DataPoint(x, y) { MarkerSize = 2, MarkerColor = Color.Orange });
    301       }
    302 
     293      // get values from series
     294      var xvalues = internalDataset.GetReadOnlyDoubleValues(Variable);
     295      var yvalues = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows));
     296      int i = 0;
     297      foreach (var y in yvalues) {
     298        var x = xvalues[i++];
     299        series.Points.Add(new DataPoint(x, y) { MarkerSize = 2, MarkerColor = Color.DodgerBlue });
     300      }
    303301      if (ShowCursor) {
    304         y = GetEstimatedValue(solution, v);
     302        var y = solution.Model.GetEstimatedValues(sharedDataset, new[] { 0 }).Single();
    305303        series.Points.Add(new DataPoint(v, y) { MarkerSize = 5, MarkerColor = Color.Red });
    306304      }
     
    308306        series.IsVisibleInLegend = true;
    309307      }
    310 
    311308      return series;
    312309    }
     
    355352      var annotation = VerticalLineAnnotation;
    356353      var x = annotation.X;
    357       dataset.SetVariableValue(x, Variable, 0);
     354      sharedDataset.SetVariableValue(x, Variable, 0);
    358355      for (int i = 0; i < solutionList.Count; ++i) {
    359         var y = GetEstimatedValue(solutionList[i], x);
     356        var y = solutionList[i].Model.GetEstimatedValues(sharedDataset, new[] { 0 }).Single();
    360357        var s = Series[i];
    361358        var n = s.Points.Count;
Note: See TracChangeset for help on using the changeset viewer.