Changeset 15701


Ignore:
Timestamp:
01/31/18 18:15:42 (3 years ago)
Author:
abeham
Message:

#1614:

  • Several improvements to the run collection RLD view and additional robustification
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/1614_GeneralizedQAP/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs

    r15699 r15701  
    8787    private readonly BindingList<ProblemInstance> problems;
    8888
    89     private bool suppressUpdates;
     89    private bool updateInProgress;
     90    private bool suppressContentEvents;
    9091    private readonly IndexedDataTable<double> byCostDataTable;
    9192    public IndexedDataTable<double> ByCostDataTable {
     
    9798      invisibleTargetSeries = new List<Series>();
    9899
    99       targetChart.CustomizeAllChartAreas();
    100       targetChart.ChartAreas[0].CursorX.Interval = 1;
    101       targetChart.SuppressExceptions = true;
    102       byCostDataTable = new IndexedDataTable<double>("ECDF by Cost", "A data table containing the ECDF of function values (relative to best-known).") {
    103         VisualProperties = {
    104           YAxisTitle = "Proportion of runs",
    105           YAxisMinimumFixedValue = 0,
    106           YAxisMinimumAuto = false,
    107           YAxisMaximumFixedValue = 1,
    108           YAxisMaximumAuto = false
    109         }
    110       };
    111       byCostViewHost.Content = byCostDataTable;
    112       suppressUpdates = true;
    113       relativeOrAbsoluteComboBox.SelectedItem = targetsAreRelative ? "relative" : "absolute";
    114       problems = new BindingList<ProblemInstance>();
    115       problemComboBox.DataSource = new BindingSource() { DataSource = problems };
    116       problemComboBox.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
    117       suppressUpdates = false;
     100      try {
     101        updateInProgress = true;
     102        targetChart.CustomizeAllChartAreas();
     103        targetChart.ChartAreas[0].CursorX.Interval = 1;
     104        targetChart.SuppressExceptions = true;
     105        byCostDataTable = new IndexedDataTable<double>("ECDF by Cost", "A data table containing the ECDF of function values (relative to best-known).") {
     106          VisualProperties = {
     107            YAxisTitle = "Proportion of runs",
     108            YAxisMinimumFixedValue = 0,
     109            YAxisMinimumAuto = false,
     110            YAxisMaximumFixedValue = 1,
     111            YAxisMaximumAuto = false
     112          }
     113        };
     114        byCostViewHost.Content = byCostDataTable;
     115
     116        relativeOrAbsoluteComboBox.SelectedItem = targetsAreRelative ? "relative" : "absolute";
     117        problems = new BindingList<ProblemInstance>();
     118        problemComboBox.DataSource = new BindingSource() { DataSource = problems };
     119        problemComboBox.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
     120      } finally { updateInProgress = false; }
    118121    }
    119122
     
    137140
    138141    private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
    139       if (suppressUpdates) return;
     142      foreach (var run in e.Items) RegisterRunEvents(run);
     143      if (suppressContentEvents) return;
    140144      if (InvokeRequired) {
    141145        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_ItemsAdded), sender, e);
    142146        return;
    143147      }
    144       UpdateGroupAndProblemComboBox();
    145       UpdateDataTableComboBox();
    146       GroupRuns();
    147       foreach (var run in e.Items)
    148         RegisterRunEvents(run);
     148      try {
     149        updateInProgress = true;
     150        UpdateGroupAndProblemComboBox();
     151        UpdateDataTableComboBox();
     152        GroupRuns();
     153      } finally { updateInProgress = false; }
    149154    }
    150155    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
    151       if (suppressUpdates) return;
     156      foreach (var run in e.Items) DeregisterRunEvents(run);
     157      if (suppressContentEvents) return;
    152158      if (InvokeRequired) {
    153159        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved), sender, e);
    154160        return;
    155161      }
    156       UpdateGroupAndProblemComboBox();
    157       UpdateDataTableComboBox();
    158       GroupRuns();
    159       foreach (var run in e.Items)
    160         DeregisterRunEvents(run);
     162      try {
     163        updateInProgress = true;
     164        UpdateGroupAndProblemComboBox();
     165        UpdateDataTableComboBox();
     166        GroupRuns();
     167      } finally { updateInProgress = false; }
    161168    }
    162169    private void Content_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
    163       if (suppressUpdates) return;
     170      foreach (var run in e.OldItems) DeregisterRunEvents(run);
     171      foreach (var run in e.Items) RegisterRunEvents(run);
     172      if (suppressContentEvents) return;
    164173      if (InvokeRequired) {
    165174        Invoke(new CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset), sender, e);
    166175        return;
    167176      }
    168       UpdateGroupAndProblemComboBox();
    169       UpdateDataTableComboBox();
    170       GroupRuns();
    171       foreach (var run in e.OldItems)
    172         DeregisterRunEvents(run);
     177      try {
     178        updateInProgress = true;
     179        UpdateGroupAndProblemComboBox();
     180        UpdateDataTableComboBox();
     181        GroupRuns();
     182      } finally { updateInProgress = false; }
    173183    }
    174184    private void Content_AlgorithmNameChanged(object sender, EventArgs e) {
     
    182192        return;
    183193      }
    184       suppressUpdates = Content.UpdateOfRunsInProgress;
    185       if (!suppressUpdates) {
    186         UpdateDataTableComboBox();
    187         UpdateGroupAndProblemComboBox();
    188         UpdateRuns();
     194      suppressContentEvents = Content.UpdateOfRunsInProgress;
     195      if (!suppressContentEvents) {
     196        try {
     197          updateInProgress = true;
     198          UpdateGroupAndProblemComboBox();
     199          UpdateDataTableComboBox();
     200          GroupRuns();
     201        } finally { updateInProgress = false; }
    189202      }
    190203    }
     
    197210    }
    198211    private void run_PropertyChanged(object sender, PropertyChangedEventArgs e) {
    199       if (suppressUpdates) return;
     212      if (suppressContentEvents) return;
    200213      if (InvokeRequired) {
    201214        Invoke((Action<object, PropertyChangedEventArgs>)run_PropertyChanged, sender, e);
    202215      } else {
    203         if (e.PropertyName == "Visible")
    204           UpdateRuns();
     216        if (e.PropertyName == "Visible") {
     217          try {
     218            updateInProgress = true;
     219            UpdateRuns();
     220          } finally { updateInProgress = false; }
     221        }
    205222      }
    206223    }
     
    219236      UpdateCaption();
    220237      if (Content != null) {
    221         UpdateGroupAndProblemComboBox();
    222         UpdateDataTableComboBox();
    223         GroupRuns();
     238        try {
     239          updateInProgress = true;
     240          UpdateGroupAndProblemComboBox();
     241          UpdateDataTableComboBox();
     242          UpdateRuns();
     243        } finally { updateInProgress = false; }
    224244      }
    225245    }
     
    239259      }
    240260
    241       var table = (string)dataTableComboBox.SelectedItem;
    242       var problemDict = CalculateBestTargetPerProblemInstance(table);
    243 
    244       var problemTypesDifferent = problemDict.Keys.Select(x => x.ProblemType).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
    245       var problemNamesDifferent = problemDict.Keys.Select(x => x.ProblemName).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
    246       var evaluatorDifferent = problemDict.Keys.Select(x => x.Evaluator).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
    247       var maximizationDifferent = problemDict.Keys.Select(x => x.Maximization).Distinct().Count() > 1;
    248       var allEqual = !problemTypesDifferent && !problemNamesDifferent && !evaluatorDifferent && !maximizationDifferent;
    249 
    250261      var selectedProblemItem = (ProblemInstance)problemComboBox.SelectedItem;
    251       problemComboBox.DataSource = null;
    252       problemComboBox.Items.Clear();
    253       problems.Clear();
    254       problems.Add(ProblemInstance.MatchAll);
    255       problemComboBox.DataSource = new BindingSource() { DataSource = problems };
    256       problemComboBox.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
    257       if (problems[0].Equals(selectedProblemItem)) problemComboBox.SelectedItem = problems[0];
    258       foreach (var p in problemDict.ToList()) {
    259         p.Key.BestKnownQuality = p.Value;
    260         p.Key.DisplayProblemType = problemTypesDifferent;
    261         p.Key.DisplayProblemName = problemNamesDifferent || allEqual;
    262         p.Key.DisplayEvaluator = evaluatorDifferent;
    263         p.Key.DisplayMaximization = maximizationDifferent;
    264         problems.Add(p.Key);
    265         if (p.Key.Equals(selectedProblemItem)) problemComboBox.SelectedItem = p.Key;
    266       }
     262     
     263      UpdateProblemInstances();
     264     
     265      foreach (var p in problems) {
     266        if (p.Equals(selectedProblemItem))
     267          problemComboBox.SelectedItem = p;
     268      }
     269
     270      if (selectedProblemItem == null && problems.Count > 1) problemComboBox.SelectedItem = problems[1];
    267271
    268272      SetEnabledStateOfControls();
     
    284288        dataTableComboBox.SelectedItem = dataTableComboBox.Items[0];
    285289      }
     290
     291      UpdateProblemInstances();
    286292    }
    287293
     
    326332        groups.Add(new AlgorithmInstance(alg.Key, trials));
    327333      }
     334    }
     335
     336    private void UpdateProblemInstances() {
     337      try {
     338        problems.Clear();
     339        var table = (string)dataTableComboBox.SelectedItem;
     340        if (string.IsNullOrEmpty(table)) return;
     341
     342        var problemDict = CalculateBestTargetPerProblemInstance(table);
     343
     344        var problemTypesDifferent = problemDict.Keys.Select(x => x.ProblemType).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
     345        var problemNamesDifferent = problemDict.Keys.Select(x => x.ProblemName).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
     346        var evaluatorDifferent = problemDict.Keys.Select(x => x.Evaluator).Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1;
     347        var maximizationDifferent = problemDict.Keys.Select(x => x.Maximization).Distinct().Count() > 1;
     348        var allEqual = !problemTypesDifferent && !problemNamesDifferent && !evaluatorDifferent && !maximizationDifferent;
     349
     350        problems.Add(ProblemInstance.MatchAll);
     351        foreach (var p in problemDict.ToList()) {
     352          p.Key.BestKnownQuality = p.Value;
     353          p.Key.DisplayProblemType = problemTypesDifferent;
     354          p.Key.DisplayProblemName = problemNamesDifferent || allEqual;
     355          p.Key.DisplayEvaluator = evaluatorDifferent;
     356          p.Key.DisplayMaximization = maximizationDifferent;
     357          problems.Add(p.Key);
     358        }
     359      } finally { ((BindingSource)problemComboBox.DataSource).ResetBindings(false); }
    328360    }
    329361
     
    570602    private IEnumerable<double> GetAbsoluteTargets(ProblemInstance pInstance) {
    571603      if (!targetsAreRelative) return targets;
     604
    572605      var maximization = pInstance.IsMaximization();
    573606      var bestKnown = pInstance.BestKnownQuality;
     
    586619
    587620    private double[] GetAbsoluteTargetsWorstToBest(ProblemInstance pInstance) {
    588       if (double.IsNaN(pInstance.BestKnownQuality)) throw new ArgumentException("Problem instance does not have a defined best-known quality.");
     621      if (targetsAreRelative && double.IsNaN(pInstance.BestKnownQuality)) throw new ArgumentException("Problem instance does not have a defined best-known quality.");
    589622      var absTargets = GetAbsoluteTargets(pInstance);
    590623      return (pInstance.IsMaximization()
     
    719752
    720753    private void GenerateDefaultBudgets(string table) {
    721       var runs = Content.Where(x => x.Results.ContainsKey(table) && x.Results[table] is IndexedDataTable<double>
    722                                     && ((IndexedDataTable<double>)x.Results[table]).Rows.Count > 0
    723                                     && ((IndexedDataTable<double>)x.Results[table]).Rows.First().Values
    724                                       .Any(y => !double.IsNaN(y.Item2)))
    725                         .Select(x => ((IndexedDataTable<double>)x.Results[table]).Rows.First())
     754      var runs = Content.Where(x => x.Results.ContainsKey(table) && x.Results[table] is IndexedDataTable<double>)
     755                        .Select(x => (IndexedDataTable<double>)x.Results[table])
     756                        .Where(x => x.Rows.Count > 0)
     757                        .Select(x => x.Rows.First())
    726758                        .ToList();
    727759      if (runs.Count == 0) {
     
    733765      }
    734766
    735       var min = runs.Select(x => x.Values.Where(y => !double.IsNaN(y.Item2)).Select(y => y.Item1).Min()).Min();
    736       var max = runs.Select(x => x.Values.Where(y => !double.IsNaN(y.Item2)).Select(y => y.Item1).Max()).Max();
     767      var min = runs.Select(x => x.Values.Select(y => y.Item1).Min()).Min();
     768      var max = runs.Select(x => x.Values.Select(y => y.Item1).Max()).Max();
    737769      var points = 3;
    738770      budgets = Enumerable.Range(1, points).Select(x => min + (x / (double)points) * (max - min)).ToArray();
     
    770802      if (InvokeRequired) Invoke((Action)SynchronizeTargetTextBox);
    771803      else {
    772         suppressTargetsEvents = true;
    773         try {
    774           if (targetsAreRelative)
    775             targetsTextBox.Text = string.Join("% ; ", targets.Select(x => x * 100)) + "%";
    776           else targetsTextBox.Text = string.Join(" ; ", targets);
    777         } finally { suppressTargetsEvents = false; }
     804        if (targetsAreRelative)
     805          targetsTextBox.Text = string.Join("% ; ", targets.Select(x => x * 100)) + "%";
     806        else targetsTextBox.Text = string.Join(" ; ", targets);
    778807      }
    779808    }
    780809
    781810    private void groupComboBox_SelectedIndexChanged(object sender, EventArgs e) {
    782       UpdateRuns();
    783       SetEnabledStateOfControls();
     811      if (updateInProgress) return;
     812      try {
     813        updateInProgress = true;
     814        UpdateRuns();
     815        SetEnabledStateOfControls();
     816      } finally { updateInProgress = false; }
    784817    }
    785818    private void problemComboBox_SelectedIndexChanged(object sender, EventArgs e) {
    786       UpdateRuns();
    787       SetEnabledStateOfControls();
     819      if (updateInProgress) return;
     820      try {
     821        updateInProgress = true;
     822        UpdateRuns();
     823        SetEnabledStateOfControls();
     824      } finally { updateInProgress = false; }
    788825    }
    789826    private void dataTableComboBox_SelectedIndexChanged(object sender, EventArgs e) {
    790       if (dataTableComboBox.SelectedIndex >= 0)
    791         GenerateDefaultBudgets((string)dataTableComboBox.SelectedItem);
    792       UpdateBestKnownQualities();
    793       UpdateRuns();
    794       SetEnabledStateOfControls();
     827      if (updateInProgress) return;
     828      try {
     829        updateInProgress = true;
     830        if (dataTableComboBox.SelectedIndex >= 0)
     831          GenerateDefaultBudgets((string)dataTableComboBox.SelectedItem);
     832        UpdateBestKnownQualities();
     833        UpdateRuns();
     834        SetEnabledStateOfControls();
     835      } finally { updateInProgress = false; }
    795836    }
    796837
     
    805846
    806847    #region Event handlers for target analysis
    807     private bool suppressTargetsEvents;
    808848    private void targetsTextBox_Validating(object sender, CancelEventArgs e) {
    809       if (suppressTargetsEvents) return;
    810       var targetStrings = targetsTextBox.Text.Split(new[] { '%', ';', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
    811       var targetList = new List<decimal>();
    812       foreach (var ts in targetStrings) {
    813         decimal t;
    814         if (!decimal.TryParse(ts, out t)) {
    815           errorProvider.SetError(targetsTextBox, "Not all targets can be parsed: " + ts);
     849      if (updateInProgress) return;
     850      try {
     851        updateInProgress = true;
     852        var targetStrings = targetsTextBox.Text.Split(new[] { '%', ';', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
     853        var targetList = new List<decimal>();
     854        foreach (var ts in targetStrings) {
     855          decimal t;
     856          if (!decimal.TryParse(ts, out t)) {
     857            errorProvider.SetError(targetsTextBox, "Not all targets can be parsed: " + ts);
     858            e.Cancel = true;
     859            return;
     860          }
     861          if (targetsAreRelative)
     862            targetList.Add(t / 100);
     863          else targetList.Add(t);
     864        }
     865        if (targetList.Count == 0) {
     866          errorProvider.SetError(targetsTextBox, "Give at least one target value!");
    816867          e.Cancel = true;
    817868          return;
    818869        }
    819         if (targetsAreRelative)
    820           targetList.Add(t / 100);
    821         else targetList.Add(t);
    822       }
    823       if (targetList.Count == 0) {
    824         errorProvider.SetError(targetsTextBox, "Give at least one target value!");
    825         e.Cancel = true;
    826         return;
    827       }
    828       e.Cancel = false;
    829       errorProvider.SetError(targetsTextBox, null);
    830       targets = targetsAreRelative ? targetList.Select(x => (double)x).OrderByDescending(x => x).ToArray() : targetList.Select(x => (double)x).ToArray();
    831 
    832       SynchronizeTargetTextBox();
    833       UpdateResultsByTarget();
    834       SetEnabledStateOfControls();
     870        e.Cancel = false;
     871        errorProvider.SetError(targetsTextBox, null);
     872        targets = targetsAreRelative ? targetList.Select(x => (double)x).OrderByDescending(x => x).ToArray() : targetList.Select(x => (double)x).ToArray();
     873
     874        SynchronizeTargetTextBox();
     875        UpdateResultsByTarget();
     876        SetEnabledStateOfControls();
     877
     878      } finally { updateInProgress = false; }
    835879    }
    836880
    837881    private void aggregateTargetsCheckBox_CheckedChanged(object sender, EventArgs e) {
    838       SuspendRepaint();
     882      if (updateInProgress) return;
    839883      try {
    840         UpdateResultsByTarget();
    841       } finally { ResumeRepaint(true); }
    842     }
    843 
    844     private void relativeOrAbsoluteComboBox_SelectedIndexChanged(object sender, EventArgs e) {
    845       if (suppressUpdates) return;
    846       var pd = (ProblemInstance)problemComboBox.SelectedItem;
    847       if (!double.IsNaN(pd.BestKnownQuality)) {
    848         var max = pd.IsMaximization();
    849         if (targetsAreRelative) targets = GetAbsoluteTargets(pd).ToArray();
    850         else {
    851           // Rounding to 5 digits since it's certainly appropriate for this application
    852           if (pd.BestKnownQuality > 0) {
    853             targets = targets.Select(x => Math.Round(max ? 1.0 - (x / pd.BestKnownQuality) : (x / pd.BestKnownQuality) - 1.0, 5)).ToArray();
    854           } else if (pd.BestKnownQuality < 0) {
    855             targets = targets.Select(x => Math.Round(!max ? 1.0 - (x / pd.BestKnownQuality) : (x / pd.BestKnownQuality) - 1.0, 5)).ToArray();
    856           }
    857         }
    858       }
    859       targetsAreRelative = (string)relativeOrAbsoluteComboBox.SelectedItem == "relative";
    860       SynchronizeTargetTextBox();
    861 
    862       try {
     884        updateInProgress = true;
    863885        SuspendRepaint();
    864886        UpdateResultsByTarget();
    865       } finally { ResumeRepaint(true); }
     887      } finally {
     888        updateInProgress = false;
     889        ResumeRepaint(true);
     890      }
     891    }
     892
     893    private void relativeOrAbsoluteComboBox_SelectedIndexChanged(object sender, EventArgs e) {
     894      if (updateInProgress) return;
     895      try {
     896        updateInProgress = true;
     897        var pd = (ProblemInstance)problemComboBox.SelectedItem;
     898        if (!double.IsNaN(pd.BestKnownQuality)) {
     899          var max = pd.IsMaximization();
     900          if (targetsAreRelative) targets = GetAbsoluteTargets(pd).ToArray();
     901          else {
     902            // Rounding to 5 digits since it's certainly appropriate for this application
     903            if (pd.BestKnownQuality > 0) {
     904              targets = targets.Select(x => Math.Round(max ? 1.0 - (x / pd.BestKnownQuality) : (x / pd.BestKnownQuality) - 1.0, 5)).ToArray();
     905            } else if (pd.BestKnownQuality < 0) {
     906              targets = targets.Select(x => Math.Round(!max ? 1.0 - (x / pd.BestKnownQuality) : (x / pd.BestKnownQuality) - 1.0, 5)).ToArray();
     907            }
     908          }
     909        }
     910        targetsAreRelative = (string)relativeOrAbsoluteComboBox.SelectedItem == "relative";
     911        SynchronizeTargetTextBox();
     912       
     913        SuspendRepaint();
     914        UpdateResultsByTarget();
     915      } finally {
     916        updateInProgress = false;
     917        ResumeRepaint(true);
     918      }
    866919    }
    867920
     
    883936              : dialog.Values.Select(x => (double)x).ToArray();
    884937
    885             SynchronizeTargetTextBox();
    886             UpdateResultsByTarget();
    887             SetEnabledStateOfControls();
     938            try {
     939              updateInProgress = true;
     940              SynchronizeTargetTextBox();
     941              UpdateResultsByTarget();
     942              SetEnabledStateOfControls();
     943            } finally { updateInProgress = false; }
    888944          }
    889945        }
     
    896952     
    897953      foreach (var run in Content) {
    898         if (!run.Results.ContainsKey(table)) continue;
     954        if (!run.Results.ContainsKey(table) || !(run.Results[table] is IndexedDataTable<double>)) continue;
    899955        var resultsTable = (IndexedDataTable<double>)run.Results[table];
    900956        var values = resultsTable.Rows.First().Values;
    901957        var pd = new ProblemInstance(run);
    902958        pd = problems.Single(x => x.Equals(pd));
    903         if (double.IsNaN(pd.BestKnownQuality)) continue;
     959        if (targetsAreRelative && double.IsNaN(pd.BestKnownQuality)) continue;
    904960
    905961        var max = pd.IsMaximization();
     
    923979
    924980    private void markerCheckBox_CheckedChanged(object sender, EventArgs e) {
    925       SuspendRepaint();
    926981      try {
     982        updateInProgress = true;
     983        SuspendRepaint();
    927984        UpdateResultsByTarget();
    928       } finally { ResumeRepaint(true); }
     985      } finally {
     986        updateInProgress = false;
     987        ResumeRepaint(true);
     988      }
    929989    }
    930990
    931991    private void showLabelsCheckBox_CheckedChanged(object sender, EventArgs e) {
    932992      showLabelsInTargetChart = showLabelsCheckBox.Checked;
    933       SuspendRepaint();
    934993      try {
     994        updateInProgress = true;
     995        SuspendRepaint();
    935996        UpdateResultsByTarget();
    936       } finally { ResumeRepaint(true); }
     997      } finally {
     998        updateInProgress = false;
     999        ResumeRepaint(true);
     1000      }
    9371001    }
    9381002    #endregion
     
    11861250    }
    11871251
     1252    #region Helper classes
    11881253    private class AlgorithmInstance : INotifyPropertyChanged {
    11891254      private string name;
     
    15261591      }
    15271592    }
     1593    #endregion
    15281594  }
    15291595}
Note: See TracChangeset for help on using the changeset viewer.