Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PersistenceReintegration/HeuristicLab.Optimizer/3.3/CreateExperimentDialog.cs @ 15722

Last change on this file since 15722 was 14929, checked in by gkronber, 7 years ago

#2520 fixed unit tests for new persistence: loading & storing all samples

File size: 40.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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.Globalization;
26using System.Linq;
27using System.Text;
28using System.Windows.Forms;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.MainForm.WindowsForms;
32using HeuristicLab.Optimization;
33using HeuristicLab.Parameters;
34using HeuristicLab.Problems.Instances;
35using HeuristicLab.Persistence;
36
37namespace HeuristicLab.Optimizer {
38  public partial class CreateExperimentDialog : Form {
39    [StorableType("b2f9efcf-e0c2-4d67-a159-12688451965a")]
40    private enum DialogMode { Normal = 1, DiscoveringInstances = 2, CreatingExperiment = 3, PreparingExperiment = 4 };
41
42    private IOptimizer optimizer;
43    public IOptimizer Optimizer {
44      get { return optimizer; }
45      set {
46        optimizer = value;
47        Experiment = null;
48        okButton.Enabled = optimizer != null;
49        SetTabControlVisibility();
50        FillInstanceTreeViewAsync();
51        FillParametersListView();
52      }
53    }
54
55    public Experiment Experiment { get; private set; }
56
57    private bool createBatchRun;
58    private int repetitions;
59    private readonly Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>> instances;
60    private readonly Dictionary<IValueParameter, IntArray> intParameters;
61    private readonly Dictionary<IValueParameter, DoubleArray> doubleParameters;
62    private readonly HashSet<IValueParameter> boolParameters;
63    private readonly Dictionary<IValueParameter, HashSet<IItem>> multipleChoiceParameters;
64    private readonly IItem optionalNullChoice = new BoolValue(); // any item will do
65
66    private StringBuilder failedInstances;
67    private bool suppressTreeViewEventHandling, suppressCheckAllNoneEventHandling;
68
69    public CreateExperimentDialog() : this(null) { }
70    public CreateExperimentDialog(IOptimizer optimizer) {
71      InitializeComponent();
72      instanceDiscoveryProgressLabel.BackColor = instancesTabPage.BackColor;
73      createBatchRun = createBatchRunCheckBox.Checked;
74      repetitions = (int)repetitionsNumericUpDown.Value;
75      // do not set the Optimizer property here, because we want to delay instance discovery to the time when the form loads
76      this.optimizer = optimizer;
77      Experiment = null;
78      okButton.Enabled = optimizer != null;
79
80      instances = new Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>>();
81      intParameters = new Dictionary<IValueParameter, IntArray>();
82      doubleParameters = new Dictionary<IValueParameter, DoubleArray>();
83      boolParameters = new HashSet<IValueParameter>();
84      multipleChoiceParameters = new Dictionary<IValueParameter, HashSet<IItem>>();
85    }
86
87    #region Event handlers
88    private void CreateExperimentDialog_Load(object sender, EventArgs e) {
89      SetTabControlVisibility();
90      FillInstanceTreeViewAsync();
91      FillParametersListView();
92    }
93
94    private void CreateExperimentDialog_FormClosing(object sender, FormClosingEventArgs e) {
95      if (experimentCreationBackgroundWorker.IsBusy) {
96        if (DialogResult != System.Windows.Forms.DialogResult.OK) {
97          if (experimentCreationBackgroundWorker.IsBusy) experimentCreationBackgroundWorker.CancelAsync();
98          if (instanceDiscoveryBackgroundWorker.IsBusy) instanceDiscoveryBackgroundWorker.CancelAsync();
99        }
100        e.Cancel = true;
101      }
102    }
103
104    private void okButton_Click(object sender, EventArgs e) {
105      SetMode(DialogMode.CreatingExperiment);
106      experimentCreationBackgroundWorker.RunWorkerAsync();
107    }
108
109    #region Parameters variation
110    private void parametersListView_ItemChecked(object sender, ItemCheckedEventArgs e) {
111      var parameter = (IValueParameter)e.Item.Tag;
112      var isConstrainedValueParameter = typeof(OptionalConstrainedValueParameter<>).Equals(parameter.GetType().GetGenericTypeDefinition())
113        || typeof(ConstrainedValueParameter<>).Equals(parameter.GetType().GetGenericTypeDefinition());
114
115      if (!isConstrainedValueParameter && parameter.Value == null) {
116        if (e.Item.Checked) e.Item.Checked = false;
117        return;
118      }
119
120      if (isConstrainedValueParameter) {
121        if (e.Item.Checked) multipleChoiceParameters.Add(parameter, new HashSet<IItem>());
122        else multipleChoiceParameters.Remove(parameter);
123      } else {
124
125        var intValue = parameter.Value as ValueTypeValue<int>;
126        if (intValue != null) {
127          if (e.Item.Checked) {
128            IntArray initialValues;
129            if (intValue.Value == int.MinValue)
130              initialValues = new IntArray(new int[] { -100, -50, 5 });
131            else if (intValue.Value == int.MaxValue)
132              initialValues = new IntArray(new int[] { 5, 50, 100 });
133            else if (intValue.Value == 0)
134              initialValues = new IntArray(new int[] { 0, 1, 2 });
135            else if (Math.Abs(intValue.Value) < 10)
136              initialValues = new IntArray(new int[] { intValue.Value - 1, intValue.Value, intValue.Value + 1 });
137            else initialValues = new IntArray(new int[] { intValue.Value / 2, intValue.Value, intValue.Value * 2 });
138            intParameters.Add(parameter, initialValues);
139            intParameters[parameter].Reset += new EventHandler(ValuesArray_Reset);
140          } else intParameters.Remove(parameter);
141        }
142
143        var doubleValue = parameter.Value as ValueTypeValue<double>;
144        if (doubleValue != null) {
145          if (e.Item.Checked) {
146            DoubleArray initialValues;
147            if (doubleValue.Value == double.MinValue)
148              initialValues = new DoubleArray(new double[] { -1, -0.5, 0 });
149            else if (doubleValue.Value == double.MaxValue)
150              initialValues = new DoubleArray(new double[] { 0, 0.5, 1 });
151            else if (doubleValue.Value == 0.0)
152              initialValues = new DoubleArray(new double[] { 0, 0.1, 0.2 });
153            else if (Math.Abs(doubleValue.Value) <= 1.0) {
154              if (doubleValue.Value > 0.9 || (doubleValue.Value < 0.0 && doubleValue.Value > -0.1))
155                initialValues = new DoubleArray(new double[] { doubleValue.Value - 0.2, doubleValue.Value - 0.1, doubleValue.Value });
156              else if (doubleValue.Value < -0.9 || (doubleValue.Value > 0 && doubleValue.Value < 0.1))
157                initialValues = new DoubleArray(new double[] { doubleValue.Value, doubleValue.Value + 0.1, doubleValue.Value + 0.2 });
158              else initialValues = new DoubleArray(new double[] { doubleValue.Value - 0.1, doubleValue.Value, doubleValue.Value + 0.1 });
159            } else initialValues = new DoubleArray(new double[] { doubleValue.Value / 2.0, doubleValue.Value, doubleValue.Value * 2.0 });
160            doubleParameters.Add(parameter, initialValues);
161            doubleParameters[parameter].Reset += new EventHandler(ValuesArray_Reset);
162          } else doubleParameters.Remove(parameter);
163        }
164
165        var boolValue = parameter.Value as ValueTypeValue<bool>;
166        if (boolValue != null) {
167          if (e.Item.Checked) boolParameters.Add(parameter);
168          else boolParameters.Remove(parameter);
169        }
170
171        bool isEnumValue = parameter.Value != null && parameter.Value.GetType().IsGenericType
172                           && typeof(EnumValue<>).IsAssignableFrom(parameter.Value.GetType().GetGenericTypeDefinition());
173        if (isEnumValue) {
174          if (e.Item.Checked) multipleChoiceParameters.Add(parameter, new HashSet<IItem>(new EnumValueEqualityComparer()));
175          else multipleChoiceParameters.Remove(parameter);
176        }
177      }
178
179      UpdateVariationsLabel();
180      if (e.Item.Selected) UpdateDetailsView(parameter);
181      else e.Item.Selected = true;
182    }
183
184    private void parametersListView_SelectedIndexChanged(object sender, EventArgs e) {
185      if (parametersListView.SelectedItems.Count == 0) {
186        ClearDetailsView();
187      } else {
188        var parameter = parametersListView.SelectedItems[0].Tag as IValueParameter;
189        UpdateDetailsView(parameter);
190      }
191    }
192
193    private void UpdateDetailsView(IValueParameter parameter) {
194      ClearDetailsView();
195
196      var isOptionalConstrainedValueParameter = typeof(OptionalConstrainedValueParameter<>).IsAssignableFrom(parameter.GetType().GetGenericTypeDefinition());
197      var isConstrainedValueParameter =
198        isOptionalConstrainedValueParameter
199        || typeof(ConstrainedValueParameter<>).Equals(parameter.GetType().GetGenericTypeDefinition());
200      bool isEnumValue = parameter.Value != null && parameter.Value.GetType().IsGenericType
201                         && typeof(EnumValue<>).IsAssignableFrom(parameter.Value.GetType().GetGenericTypeDefinition());
202
203      if (isConstrainedValueParameter || isEnumValue) {
204        detailsTypeLabel.Text = "Choices:";
205        choicesListView.Tag = parameter;
206
207        if (isConstrainedValueParameter) {
208          if (isOptionalConstrainedValueParameter) {
209            choicesListView.Items.Add(new ListViewItem("-") {
210              Tag = optionalNullChoice,
211              Checked = multipleChoiceParameters.ContainsKey(parameter)
212                        && multipleChoiceParameters[parameter].Contains(optionalNullChoice)
213            });
214          }
215          dynamic constrainedValuedParameter = parameter;
216          dynamic validValues = constrainedValuedParameter.ValidValues;
217          foreach (var choice in validValues) {
218            choicesListView.Items.Add(new ListViewItem(choice.ToString()) {
219              Tag = choice,
220              Checked = multipleChoiceParameters.ContainsKey(parameter)
221                        && multipleChoiceParameters[parameter].Contains(choice)
222            });
223          }
224        }
225        if (isEnumValue) {
226          var enumType = parameter.Value.GetType().GetGenericArguments()[0];
227          var enumValueType = typeof(EnumValue<>).MakeGenericType(enumType);
228          foreach (var enumChoice in Enum.GetValues(enumType)) {
229            choicesListView.Items.Add(new ListViewItem(enumChoice.ToString()) {
230              Tag = Activator.CreateInstance(enumValueType, enumChoice),
231              Checked = multipleChoiceParameters.ContainsKey(parameter)
232                        && multipleChoiceParameters[parameter].Any((dynamic item) => item.Value.Equals(enumChoice))
233            });
234          }
235        }
236        choicesListView.Enabled = multipleChoiceParameters.ContainsKey(parameter);
237        detailsTypeLabel.Visible = true;
238        choicesListView.Visible = true;
239        return;
240      }
241
242      if (parameter.Value is ValueTypeValue<bool>) {
243        detailsTypeLabel.Text = "Boolean parameter: True / False";
244        detailsTypeLabel.Visible = true;
245      }
246
247      var intValue = parameter.Value as ValueTypeValue<int>;
248      if (intValue != null) {
249        if (intParameters.ContainsKey(parameter))
250          stringConvertibleArrayView.Content = intParameters[parameter];
251        stringConvertibleArrayView.Visible = true;
252        stringConvertibleArrayView.ReadOnly = !intParameters.ContainsKey(parameter);
253        generateButton.Tag = parameter;
254        generateButton.Enabled = intParameters.ContainsKey(parameter);
255        generateButton.Visible = true;
256        return;
257      }
258
259      var doubleValue = parameter.Value as ValueTypeValue<double>;
260      if (doubleValue != null) {
261        if (doubleParameters.ContainsKey(parameter))
262          stringConvertibleArrayView.Content = doubleParameters[parameter];
263        stringConvertibleArrayView.Visible = true;
264        stringConvertibleArrayView.ReadOnly = !doubleParameters.ContainsKey(parameter);
265        generateButton.Tag = parameter;
266        generateButton.Enabled = doubleParameters.ContainsKey(parameter);
267        generateButton.Visible = true;
268        return;
269      }
270    }
271
272    #region Detail controls
273    private void choiceListView_ItemChecked(object sender, ItemCheckedEventArgs e) {
274      var parameter = (IValueParameter)choicesListView.Tag;
275      if (multipleChoiceParameters.ContainsKey(parameter)) {
276        if (e.Item.Checked) {
277          multipleChoiceParameters[parameter].Add((IItem)e.Item.Tag);
278        } else multipleChoiceParameters[parameter].Remove((IItem)e.Item.Tag);
279
280        UpdateVariationsLabel();
281      }
282    }
283
284    private void generateButton_Click(object sender, EventArgs e) {
285      var parameter = (IValueParameter)generateButton.Tag;
286      bool integerOnly = intParameters.ContainsKey(parameter);
287      decimal min = 0, max = 1, step = 1;
288      #region Try to calculate some meaningful values
289      if (integerOnly) {
290        int len = intParameters[parameter].Length;
291        if (len > 0) {
292          min = intParameters[parameter].Min();
293          max = intParameters[parameter].Max();
294          step = len >= 2 ? Math.Abs((intParameters[parameter][len - 1] - intParameters[parameter][len - 2])) : 1;
295        }
296      } else {
297        int len = doubleParameters[parameter].Length;
298        if (len > 0) {
299          min = (decimal)doubleParameters[parameter].Min();
300          max = (decimal)doubleParameters[parameter].Max();
301          step = len >= 2 ? Math.Abs(((decimal)doubleParameters[parameter][len - 1] - (decimal)doubleParameters[parameter][len - 2])) : 1m;
302        }
303      }
304      #endregion
305      using (var dialog = new DefineArithmeticProgressionDialog(integerOnly, min, max, step)) {
306        if (dialog.ShowDialog(this) == DialogResult.OK) {
307          var values = dialog.Values;
308          if (integerOnly) {
309            intParameters[parameter].Reset -= new EventHandler(ValuesArray_Reset);
310            intParameters[parameter] = new IntArray(values.Select(x => (int)x).ToArray());
311            intParameters[parameter].Reset += new EventHandler(ValuesArray_Reset);
312            stringConvertibleArrayView.Content = intParameters[parameter];
313          } else {
314            doubleParameters[parameter].Reset -= new EventHandler(ValuesArray_Reset);
315            doubleParameters[parameter] = new DoubleArray(values.Select(x => (double)x).ToArray());
316            doubleParameters[parameter].Reset += new EventHandler(ValuesArray_Reset);
317            stringConvertibleArrayView.Content = doubleParameters[parameter];
318          }
319          UpdateVariationsLabel();
320        }
321      }
322    }
323
324    private void ValuesArray_Reset(object sender, EventArgs e) {
325      UpdateVariationsLabel();
326    }
327    #endregion
328    #endregion
329
330    #region Instances
331    private void instancesTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
332      if (!suppressTreeViewEventHandling) {
333        if (e.Node.Nodes.Count > 0) { // provider node was (un)checked
334          SyncProviderNode(e.Node);
335        } else { // descriptor node was (un)checked
336          SyncInstanceNode(e.Node);
337        }
338
339        suppressCheckAllNoneEventHandling = true;
340        try {
341          var treeViewNodes = instancesTreeView.Nodes.OfType<TreeNode>().SelectMany(x => x.Nodes.OfType<TreeNode>());
342          selectAllCheckBox.Checked = treeViewNodes.Count() == instances.SelectMany(x => x.Value).Count();
343          selectNoneCheckBox.Checked = !treeViewNodes.Any(x => x.Checked);
344        } finally { suppressCheckAllNoneEventHandling = false; }
345        UpdateVariationsLabel();
346      }
347    }
348
349    private void SyncProviderNode(TreeNode node) {
350      suppressTreeViewEventHandling = true;
351      try {
352        foreach (TreeNode n in node.Nodes) {
353          if (n.Checked != node.Checked) {
354            n.Checked = node.Checked;
355            SyncInstanceNode(n, false);
356          }
357        }
358      } finally { suppressTreeViewEventHandling = false; }
359    }
360
361    private void SyncInstanceNode(TreeNode node, bool providerCheck = true) {
362      var provider = (IProblemInstanceProvider)node.Parent.Tag;
363      var descriptor = (IDataDescriptor)node.Tag;
364      if (node.Checked) {
365        if (!instances.ContainsKey(provider))
366          instances.Add(provider, new HashSet<IDataDescriptor>());
367        instances[provider].Add(descriptor);
368      } else {
369        if (instances.ContainsKey(provider)) {
370          instances[provider].Remove(descriptor);
371          if (instances[provider].Count == 0)
372            instances.Remove(provider);
373        }
374      }
375      if (providerCheck) {
376        bool allChecked = node.Parent.Nodes.OfType<TreeNode>().All(x => x.Checked);
377        suppressTreeViewEventHandling = true;
378        try {
379          node.Parent.Checked = allChecked;
380        } finally { suppressTreeViewEventHandling = false; }
381      }
382    }
383
384    private void selectAllCheckBox_CheckedChanged(object sender, EventArgs e) {
385      if (!suppressCheckAllNoneEventHandling) {
386        if (selectAllCheckBox.Checked) {
387          suppressCheckAllNoneEventHandling = true;
388          try { selectNoneCheckBox.Checked = false; } finally { suppressCheckAllNoneEventHandling = false; }
389          try {
390            suppressTreeViewEventHandling = true;
391            foreach (TreeNode node in instancesTreeView.Nodes) {
392              if (!node.Checked) {
393                node.Checked = true;
394                SyncProviderNode(node);
395              }
396            }
397          } finally { suppressTreeViewEventHandling = false; }
398        }
399        UpdateVariationsLabel();
400      }
401    }
402
403    private void selectNoneCheckBox_CheckedChanged(object sender, EventArgs e) {
404      if (!suppressCheckAllNoneEventHandling) {
405        if (selectNoneCheckBox.Checked) {
406          suppressCheckAllNoneEventHandling = true;
407          try { selectAllCheckBox.Checked = false; } finally { suppressCheckAllNoneEventHandling = false; }
408          try {
409            suppressTreeViewEventHandling = true;
410            foreach (TreeNode node in instancesTreeView.Nodes) {
411              if (node.Checked) {
412                node.Checked = false;
413                SyncProviderNode(node);
414              }
415            }
416          } finally { suppressTreeViewEventHandling = false; }
417        }
418        UpdateVariationsLabel();
419      }
420    }
421    #endregion
422
423    private void createBatchRunCheckBox_CheckedChanged(object sender, EventArgs e) {
424      repetitionsNumericUpDown.Enabled = createBatchRunCheckBox.Checked;
425      createBatchRun = createBatchRunCheckBox.Checked;
426    }
427
428    private void repetitionsNumericUpDown_Validated(object sender, EventArgs e) {
429      if (repetitionsNumericUpDown.Text == string.Empty)
430        repetitionsNumericUpDown.Text = repetitionsNumericUpDown.Value.ToString();
431      repetitions = (int)repetitionsNumericUpDown.Value;
432    }
433
434    private void experimentsLabel_TextChanged(object sender, EventArgs e) {
435      long number;
436      if (long.TryParse(variationsLabel.Text, NumberStyles.AllowThousands, CultureInfo.CurrentCulture.NumberFormat, out number)) {
437        if (number > 1000) warningProvider.SetError(variationsLabel, "Consider reducing the number of variations!");
438        else warningProvider.SetError(variationsLabel, null);
439      }
440    }
441    #endregion
442
443    #region Helpers
444    private void SetTabControlVisibility() {
445      bool isAlgorithm = optimizer != null && optimizer is IAlgorithm;
446      bool instancesAvailable = isAlgorithm
447        && ((IAlgorithm)optimizer).Problem != null
448        && ProblemInstanceManager.GetProviders(((IAlgorithm)optimizer).Problem).Any();
449      if (instancesAvailable && tabControl.TabCount == 1)
450        tabControl.TabPages.Add(instancesTabPage);
451      else if (!instancesAvailable && tabControl.TabCount == 2)
452        tabControl.TabPages.Remove(instancesTabPage);
453      tabControl.Visible = isAlgorithm;
454      if (isAlgorithm) {
455        variationsLabel.Visible = true;
456        experimentsToCreateDescriptionLabel.Visible = true;
457        Height = 450;
458      } else {
459        variationsLabel.Visible = false;
460        experimentsToCreateDescriptionLabel.Visible = false;
461        Height = 130;
462      }
463    }
464
465    private void FillParametersListView() {
466      parametersListView.Items.Clear();
467      intParameters.Clear();
468      doubleParameters.Clear();
469      boolParameters.Clear();
470      multipleChoiceParameters.Clear();
471
472      if (Optimizer is IAlgorithm) {
473        var parameters = ((IAlgorithm)optimizer).Parameters;
474        foreach (var param in parameters) {
475          var valueParam = param as IValueParameter;
476          if (valueParam != null && (valueParam.Value is ValueTypeValue<bool>
477              || valueParam.Value is ValueTypeValue<int>
478              || valueParam.Value is ValueTypeValue<double>
479              || (valueParam.Value != null && valueParam.Value.GetType().IsGenericType
480                    && typeof(EnumValue<>).IsAssignableFrom(valueParam.Value.GetType().GetGenericTypeDefinition())))
481            || typeof(OptionalConstrainedValueParameter<>).IsAssignableFrom(param.GetType().GetGenericTypeDefinition())
482            || typeof(ConstrainedValueParameter<>).IsAssignableFrom(param.GetType().GetGenericTypeDefinition()))
483            parametersListView.Items.Add(new ListViewItem(param.Name) { Tag = param, ToolTipText = param.Description });
484        }
485      }
486    }
487
488    private void FillInstanceTreeViewAsync() {
489      instances.Clear();
490      instancesTreeView.Nodes.Clear();
491
492      if (Optimizer is IAlgorithm && ((IAlgorithm)Optimizer).Problem != null) {
493        SetMode(DialogMode.DiscoveringInstances);
494        instanceDiscoveryBackgroundWorker.RunWorkerAsync();
495      }
496    }
497
498    private void AddOptimizer(IOptimizer optimizer, Experiment experiment) {
499      if (createBatchRun) {
500        var batchRun = new BatchRun(repetitions.ToString() + "x " + optimizer.Name) {
501          Repetitions = repetitions,
502          Optimizer = optimizer
503        };
504        experiment.Optimizers.Add(batchRun);
505      } else {
506        experiment.Optimizers.Add(optimizer);
507      }
508    }
509
510    private int GetNumberOfVariations() {
511      int instancesCount = 1;
512      if (instances.Values.Any())
513        instancesCount = Math.Max(instances.Values.SelectMany(x => x).Count(), 1);
514
515      int intParameterVariations = 1;
516      foreach (var intParam in intParameters.Values) {
517        intParameterVariations *= Math.Max(intParam.Length, 1);
518      }
519      int doubleParameterVariations = 1;
520      foreach (var doubleParam in doubleParameters.Values) {
521        doubleParameterVariations *= Math.Max(doubleParam.Length, 1);
522      }
523      int boolParameterVariations = 1;
524      foreach (var boolParam in boolParameters) {
525        boolParameterVariations *= 2;
526      }
527      int choiceParameterVariations = 1;
528      foreach (var choiceParam in multipleChoiceParameters.Values) {
529        choiceParameterVariations *= Math.Max(choiceParam.Count, 1);
530      }
531
532      return (instancesCount * intParameterVariations * doubleParameterVariations * boolParameterVariations * choiceParameterVariations);
533    }
534
535    private void SetMode(DialogMode mode) {
536      if (InvokeRequired) Invoke((Action<DialogMode>)SetMode, mode);
537      else {
538        createBatchRunCheckBox.Enabled = mode == DialogMode.Normal;
539        repetitionsNumericUpDown.Enabled = mode == DialogMode.Normal;
540        parametersSplitContainer.Enabled = mode == DialogMode.Normal || mode == DialogMode.DiscoveringInstances;
541        selectAllCheckBox.Enabled = mode == DialogMode.Normal;
542        selectNoneCheckBox.Enabled = mode == DialogMode.Normal;
543        instancesTreeView.Enabled = mode == DialogMode.Normal;
544        instancesTreeView.Visible = mode == DialogMode.Normal || mode == DialogMode.CreatingExperiment || mode == DialogMode.PreparingExperiment;
545        okButton.Enabled = mode == DialogMode.Normal;
546        okButton.Visible = mode != DialogMode.CreatingExperiment && mode != DialogMode.PreparingExperiment;
547        cancelButton.Enabled = mode != DialogMode.PreparingExperiment;
548        instanceDiscoveryProgressLabel.Visible = mode == DialogMode.DiscoveringInstances;
549        instanceDiscoveryProgressBar.Visible = mode == DialogMode.DiscoveringInstances;
550        experimentCreationProgressBar.Visible = mode == DialogMode.CreatingExperiment || mode == DialogMode.PreparingExperiment;
551      }
552    }
553
554    private void ClearDetailsView() {
555      stringConvertibleArrayView.Visible = false;
556      stringConvertibleArrayView.Content = null;
557      stringConvertibleArrayView.ReadOnly = true;
558      generateButton.Visible = false;
559      detailsTypeLabel.Visible = false;
560      choicesListView.Items.Clear();
561      choicesListView.Enabled = false;
562      choicesListView.Visible = false;
563    }
564
565    private void UpdateVariationsLabel() {
566      variationsLabel.Text = GetNumberOfVariations().ToString("#,#", CultureInfo.CurrentCulture);
567    }
568
569    #region Retrieve parameter combinations
570    private IEnumerable<Dictionary<IValueParameter, int>> GetIntParameterConfigurations() {
571      var configuration = new Dictionary<IValueParameter, int>();
572      var enumerators = new Dictionary<IValueParameter, IEnumerator<int>>();
573      bool finished;
574      do {
575        foreach (var p in intParameters) {
576          if (!enumerators.ContainsKey(p.Key)) {
577            enumerators[p.Key] = p.Value.GetEnumerator();
578            enumerators[p.Key].MoveNext();
579          }
580          configuration[p.Key] = enumerators[p.Key].Current;
581        }
582        yield return configuration;
583
584        finished = true;
585        foreach (var p in intParameters) {
586          if (!enumerators[p.Key].MoveNext()) {
587            enumerators[p.Key] = p.Value.GetEnumerator();
588            enumerators[p.Key].MoveNext();
589          } else {
590            finished = false;
591            break;
592          }
593        }
594      } while (!finished);
595    }
596
597    private IEnumerable<Dictionary<IValueParameter, double>> GetDoubleParameterConfigurations() {
598      var configuration = new Dictionary<IValueParameter, double>();
599      var enumerators = new Dictionary<IValueParameter, IEnumerator<double>>();
600      bool finished;
601      do {
602        foreach (var p in doubleParameters) {
603          if (!enumerators.ContainsKey(p.Key)) {
604            enumerators[p.Key] = p.Value.GetEnumerator();
605            enumerators[p.Key].MoveNext();
606          }
607          configuration[p.Key] = enumerators[p.Key].Current;
608        }
609        yield return configuration;
610
611        finished = true;
612        foreach (var p in doubleParameters) {
613          if (!enumerators[p.Key].MoveNext()) {
614            enumerators[p.Key] = p.Value.GetEnumerator();
615            enumerators[p.Key].MoveNext();
616          } else {
617            finished = false;
618            break;
619          }
620        }
621      } while (!finished);
622    }
623
624    private IEnumerable<Dictionary<IValueParameter, bool>> GetBoolParameterConfigurations() {
625      var configuration = new Dictionary<IValueParameter, bool>();
626      bool finished;
627      do {
628        foreach (var p in boolParameters) {
629          if (!configuration.ContainsKey(p))
630            configuration.Add(p, false);
631        }
632
633        yield return configuration;
634        finished = true;
635
636        foreach (var p in boolParameters) {
637          if (configuration[p]) {
638            configuration[p] = false;
639          } else {
640            configuration[p] = true;
641            finished = false;
642            break;
643          }
644        }
645      } while (!finished);
646    }
647
648    private IEnumerable<Dictionary<IValueParameter, IItem>> GetMultipleChoiceConfigurations() {
649      var configuration = new Dictionary<IValueParameter, IItem>();
650      var enumerators = new Dictionary<IValueParameter, IEnumerator<IItem>>();
651      bool finished;
652      do {
653        foreach (var p in multipleChoiceParameters.Keys.ToArray()) {
654          if (!enumerators.ContainsKey(p)) {
655            enumerators.Add(p, multipleChoiceParameters[p].GetEnumerator());
656            if (!enumerators[p].MoveNext()) {
657              multipleChoiceParameters.Remove(p);
658              continue;
659            }
660          }
661          configuration[p] = enumerators[p].Current;
662        }
663
664        finished = true;
665        foreach (var p in multipleChoiceParameters.Keys) {
666          if (!enumerators[p].MoveNext()) {
667            enumerators[p] = multipleChoiceParameters[p].GetEnumerator();
668            enumerators[p].MoveNext();
669          } else {
670            finished = false;
671            break;
672          }
673        }
674        yield return configuration;
675      } while (!finished);
676    }
677    #endregion
678
679    #region EnumValueEqualityComparer
680    private class EnumValueEqualityComparer : EqualityComparer<IItem> {
681      public override bool Equals(IItem x, IItem y) {
682        if (typeof(EnumValue<>).IsAssignableFrom(x.GetType().GetGenericTypeDefinition()) &&
683            typeof(EnumValue<>).IsAssignableFrom(y.GetType().GetGenericTypeDefinition())) {
684          dynamic enumValueX = x;
685          dynamic enumValueY = y;
686          return enumValueX.Value.Equals(enumValueY.Value);
687        } else return object.ReferenceEquals(x, y);
688      }
689
690      public override int GetHashCode(IItem obj) {
691        if (typeof(EnumValue<>).IsAssignableFrom(obj.GetType().GetGenericTypeDefinition())) {
692          dynamic enumValue = obj;
693          return enumValue.Value.GetHashCode();
694        } else return obj.GetHashCode();
695      }
696    }
697    #endregion
698
699    #endregion
700
701    #region Background workers
702    #region Instance discovery
703    private void instanceDiscoveryBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
704      instanceDiscoveryBackgroundWorker.ReportProgress(0, "Finding instance providers...");
705      var instanceProviders = ProblemInstanceManager.GetProviders(((IAlgorithm)Optimizer).Problem).ToArray();
706      var nodes = new List<TreeNode>(instanceProviders.Length);
707      for (int i = 0; i < instanceProviders.Length; i++) {
708        var provider = instanceProviders[i];
709        var providerNode = new TreeNode(provider.Name) { Tag = provider };
710        var descriptors = ProblemInstanceManager.GetDataDescriptors(provider);
711        foreach (var desc in descriptors) {
712          #region Check cancellation request
713          if (instanceDiscoveryBackgroundWorker.CancellationPending) {
714            e.Cancel = true;
715            e.Result = nodes.ToArray();
716            return;
717          }
718          #endregion
719          var node = new TreeNode(desc.Name) { Tag = desc };
720          providerNode.Nodes.Add(node);
721        }
722
723        //Do not add instance providers without data descriptors
724        if (providerNode.Nodes.Count > 0) {
725          nodes.Add(providerNode);
726        }
727
728        double progress = nodes.Count > 0 ? i / (double)instanceProviders.Length : 0.0;
729        instanceDiscoveryBackgroundWorker.ReportProgress((int)(100 * progress), provider.Name);
730      }
731      e.Result = nodes.ToArray();
732      instanceDiscoveryBackgroundWorker.ReportProgress(100, string.Empty);
733    }
734
735    private void instanceDiscoveryBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
736      if (instanceDiscoveryProgressBar.Value != e.ProgressPercentage)
737        instanceDiscoveryProgressBar.Value = e.ProgressPercentage;
738      instanceDiscoveryProgressLabel.Text = (string)e.UserState;
739    }
740
741    private void instanceDiscoveryBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
742      try {
743        if (((TreeNode[])e.Result).Length > 0) {
744          instancesTreeView.Nodes.AddRange((TreeNode[])e.Result);
745          foreach (TreeNode node in instancesTreeView.Nodes)
746            node.Collapse();
747        }
748        selectNoneCheckBox.Checked = true;
749      } catch { }
750      try {
751        SetMode(DialogMode.Normal);
752        if (e.Error != null) MessageBox.Show(e.Error.Message, "Error occurred", MessageBoxButtons.OK, MessageBoxIcon.Error);
753      } catch { }
754    }
755    #endregion
756
757    #region Experiment creation
758    private void experimentCreationBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
759      failedInstances = new StringBuilder();
760      var localExperiment = new Experiment();
761
762      int counter = 0, totalVariations = GetNumberOfVariations();
763      int totalInstances = instances.Values.SelectMany(x => x).Count();
764      if (totalInstances == 0) {
765        try {
766          AddParameterVariations(Optimizer, localExperiment, ref counter, totalVariations);
767        } catch (OperationCanceledException) {
768          e.Cancel = true;
769          return;
770        }
771        experimentCreationBackgroundWorker.ReportProgress(100, string.Empty);
772      } else {
773        foreach (var provider in instances.Keys) {
774          foreach (var descriptor in instances[provider]) {
775            var algorithm = (IAlgorithm)Optimizer.Clone();
776            bool failed = false;
777            try {
778              ProblemInstanceManager.LoadData(provider, descriptor, (IProblemInstanceConsumer)algorithm.Problem);
779            } catch (Exception ex) {
780              failedInstances.AppendLine(descriptor.Name + ": " + ex.Message);
781              failed = true;
782            }
783            if (!failed) {
784              try {
785                if (totalInstances > 1 && totalVariations / totalInstances > 1) {
786                  var experiment = new Experiment(descriptor.Name);
787                  AddParameterVariations(algorithm, experiment, ref counter, totalVariations);
788                  localExperiment.Optimizers.Add(experiment);
789                } else {
790                  AddParameterVariations(algorithm, localExperiment, ref counter, totalVariations);
791                }
792              } catch (OperationCanceledException) {
793                e.Cancel = true;
794                return;
795              }
796            } else experimentCreationBackgroundWorker.ReportProgress((int)Math.Round((100.0 * counter) / totalVariations), "Loading failed (" + descriptor.Name + ")");
797          }
798        }
799      }
800      // this step can take some time
801      SetMode(DialogMode.PreparingExperiment);
802      experimentCreationBackgroundWorker.ReportProgress(-1);
803      localExperiment.Prepare(true);
804      experimentCreationBackgroundWorker.ReportProgress(100);
805      Experiment = localExperiment;
806    }
807
808    private void AddParameterVariations(IOptimizer optimizer, Experiment localExperiment, ref int counter, int totalVariations) {
809      var variations = CalculateParameterVariations(optimizer);
810      foreach (var v in variations) {
811        if (experimentCreationBackgroundWorker.CancellationPending)
812          throw new OperationCanceledException();
813        AddOptimizer(v, localExperiment);
814        counter++;
815        experimentCreationBackgroundWorker.ReportProgress((int)Math.Round((100.0 * counter) / totalVariations), string.Empty);
816      }
817    }
818
819    private IEnumerable<IOptimizer> CalculateParameterVariations(IOptimizer optimizer) {
820      if (!boolParameters.Any() && !intParameters.Any() && !doubleParameters.Any() && !multipleChoiceParameters.Any()) {
821        var o = (IOptimizer)optimizer.Clone();
822        o.Runs.Clear();
823        yield return o;
824        yield break;
825      }
826      bool finished;
827      var mcEnumerator = GetMultipleChoiceConfigurations().GetEnumerator();
828      var boolEnumerator = GetBoolParameterConfigurations().GetEnumerator();
829      var intEnumerator = GetIntParameterConfigurations().GetEnumerator();
830      var doubleEnumerator = GetDoubleParameterConfigurations().GetEnumerator();
831      mcEnumerator.MoveNext(); boolEnumerator.MoveNext(); intEnumerator.MoveNext(); doubleEnumerator.MoveNext();
832      do {
833        var variant = (IAlgorithm)optimizer.Clone();
834        variant.Runs.Clear();
835        variant.Name += " {";
836        finished = true;
837        if (doubleParameters.Any()) {
838          foreach (var d in doubleEnumerator.Current) {
839            var value = (ValueTypeValue<double>)((IValueParameter)variant.Parameters[d.Key.Name]).Value;
840            value.Value = d.Value;
841            variant.Name += d.Key.Name + "=" + d.Value.ToString() + ", ";
842          }
843          if (finished) {
844            if (doubleEnumerator.MoveNext()) {
845              finished = false;
846            } else {
847              doubleEnumerator = GetDoubleParameterConfigurations().GetEnumerator();
848              doubleEnumerator.MoveNext();
849            }
850          }
851        }
852        if (intParameters.Any()) {
853          foreach (var i in intEnumerator.Current) {
854            var value = (ValueTypeValue<int>)((IValueParameter)variant.Parameters[i.Key.Name]).Value;
855            value.Value = i.Value;
856            variant.Name += i.Key.Name + "=" + i.Value.ToString() + ", ";
857          }
858          if (finished) {
859            if (intEnumerator.MoveNext()) {
860              finished = false;
861            } else {
862              intEnumerator = GetIntParameterConfigurations().GetEnumerator();
863              intEnumerator.MoveNext();
864            }
865          }
866        }
867        if (boolParameters.Any()) {
868          foreach (var b in boolEnumerator.Current) {
869            var value = (ValueTypeValue<bool>)((IValueParameter)variant.Parameters[b.Key.Name]).Value;
870            value.Value = b.Value;
871            variant.Name += b.Key.Name + "=" + b.Value.ToString() + ", ";
872          }
873          if (finished) {
874            if (boolEnumerator.MoveNext()) {
875              finished = false;
876            } else {
877              boolEnumerator = GetBoolParameterConfigurations().GetEnumerator();
878              boolEnumerator.MoveNext();
879            }
880          }
881        }
882        if (multipleChoiceParameters.Any()) {
883          foreach (var m in mcEnumerator.Current) {
884            if (m.Key.Value != null && m.Key.Value.GetType().IsGenericType
885                && typeof(EnumValue<>).IsAssignableFrom(m.Key.Value.GetType().GetGenericTypeDefinition())) {
886              var valueParam = (IValueParameter)variant.Parameters[m.Key.Name];
887              dynamic targetEnumValue = valueParam.Value;
888              dynamic sourceEnumValue = m.Value;
889              targetEnumValue.Value = sourceEnumValue.Value;
890              variant.Name += m.Key.Name + "=" + m.Value + ", ";
891            } else {
892              dynamic variantParam = variant.Parameters[m.Key.Name];
893              if (m.Value == optionalNullChoice) {
894                variantParam.Value = null;
895                variant.Name += m.Key.Name + "=null, ";
896                continue;
897              }
898              var variantEnumerator = ((IEnumerable<object>)variantParam.ValidValues).GetEnumerator();
899              var originalEnumerator = ((IEnumerable<object>)((dynamic)m.Key).ValidValues).GetEnumerator();
900              while (variantEnumerator.MoveNext() && originalEnumerator.MoveNext()) {
901                if (m.Value == (IItem)originalEnumerator.Current) {
902                  variantParam.Value = (dynamic)variantEnumerator.Current;
903                  if (m.Value is INamedItem)
904                    variant.Name += m.Key.Name + "=" + ((INamedItem)m.Value).Name + ", ";
905                  else variant.Name += m.Key.Name + "=" + m.Value.ToString() + ", ";
906                  break;
907                }
908              }
909            }
910          }
911          if (finished) {
912            if (mcEnumerator.MoveNext()) {
913              finished = false;
914            } else {
915              mcEnumerator = GetMultipleChoiceConfigurations().GetEnumerator();
916              mcEnumerator.MoveNext();
917            }
918          }
919        }
920        variant.Name = variant.Name.Substring(0, variant.Name.Length - 2) + "}";
921        yield return variant;
922      } while (!finished);
923    }
924
925    private void experimentCreationBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
926      if (e.ProgressPercentage >= 0 && e.ProgressPercentage <= 100) {
927        experimentCreationProgressBar.Style = ProgressBarStyle.Continuous;
928        experimentCreationProgressBar.Value = e.ProgressPercentage;
929      } else {
930        experimentCreationProgressBar.Style = ProgressBarStyle.Marquee;
931      }
932    }
933
934    private void experimentCreationBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
935      try {
936        SetMode(DialogMode.Normal);
937        if (e.Error != null) MessageBox.Show(e.Error.Message, "Error occurred", MessageBoxButtons.OK, MessageBoxIcon.Error);
938        if (failedInstances.Length > 0) MessageBox.Show("Some instances could not be loaded: " + Environment.NewLine + failedInstances.ToString(), "Some instances failed to load", MessageBoxButtons.OK, MessageBoxIcon.Error);
939        if (!e.Cancelled && e.Error == null) {
940          DialogResult = System.Windows.Forms.DialogResult.OK;
941          Close();
942        }
943      } catch { }
944    }
945    #endregion
946    #endregion
947  }
948}
Note: See TracBrowser for help on using the repository browser.