[8517] | 1 | #region License Information
|
---|
| 2 | /* HeuristicLab
|
---|
| 3 | * Copyright (C) 2002-2012 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 |
|
---|
| 22 | using System;
|
---|
| 23 | using System.Collections.Generic;
|
---|
[8524] | 24 | using System.ComponentModel;
|
---|
| 25 | using System.Linq;
|
---|
[8517] | 26 | using System.Threading;
|
---|
| 27 | using System.Threading.Tasks;
|
---|
| 28 | using System.Windows.Forms;
|
---|
| 29 | using HeuristicLab.Core;
|
---|
| 30 | using HeuristicLab.MainForm;
|
---|
| 31 | using HeuristicLab.MainForm.WindowsForms;
|
---|
| 32 | using HeuristicLab.Optimization;
|
---|
| 33 | using HeuristicLab.PluginInfrastructure;
|
---|
[8524] | 34 | using HeuristicLab.Problems.Instances;
|
---|
[8517] | 35 |
|
---|
| 36 | namespace HeuristicLab.Encodings.ParameterConfigurationEncoding.Views {
|
---|
| 37 | public partial class CreateExperimentDialogV2 : Form {
|
---|
[8535] | 38 | private readonly IAlgorithm algorithm;
|
---|
[8574] | 39 | private readonly ExperimentFactory experimentFactory;
|
---|
[8517] | 40 | private readonly Progress progress;
|
---|
| 41 | private ParameterConfigurationTree parameterConfigurationTree;
|
---|
| 42 | private bool createBatchRun;
|
---|
| 43 | private int repetitions;
|
---|
| 44 | private IEngine engine;
|
---|
[8535] | 45 | private Task experimentGenerator;
|
---|
[8517] | 46 | private CancellationTokenSource cts;
|
---|
[8524] | 47 | private Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>> problemInstanceProviders;
|
---|
| 48 | private Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>> selectedProblemInstanceProviders;
|
---|
[8517] | 49 |
|
---|
| 50 | public Experiment Experiment { get; private set; }
|
---|
| 51 |
|
---|
| 52 | public CreateExperimentDialogV2() : this(null, null) { }
|
---|
| 53 | public CreateExperimentDialogV2(IAlgorithm algorithm, IEnumerable<IEngine> engines) {
|
---|
| 54 | InitializeComponent();
|
---|
| 55 | if (algorithm != null && engines != null) {
|
---|
| 56 | this.algorithm = (IAlgorithm)algorithm.Clone();
|
---|
| 57 | foreach (var engine in engines) engineComboBox.Items.Add(engine);
|
---|
| 58 | if (engineComboBox.SelectedItem == null) {
|
---|
| 59 | engineComboBox.SelectedIndex = 0;
|
---|
| 60 | engine = (IEngine)engineComboBox.SelectedItem;
|
---|
| 61 | }
|
---|
| 62 | }
|
---|
| 63 | createBatchRun = createBatchRunCheckBox.Checked;
|
---|
| 64 | repetitions = (int)repetitionsNumericUpDown.Value;
|
---|
[8524] | 65 | selectedProblemInstanceProviders = new Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>>();
|
---|
[8517] | 66 | progress = new Progress {
|
---|
| 67 | CanBeCanceled = true,
|
---|
| 68 | ProgressState = ProgressState.Finished
|
---|
| 69 | };
|
---|
| 70 | progress.CancelRequested += (sender, args) => cts.Cancel();
|
---|
| 71 | progress.ProgressValueChanged += (sender, args) => progress.Status = string.Format("Generating experiment. Please be patient. ({0} %)", (int)(progress.ProgressValue * 100));
|
---|
[8574] | 72 | experimentFactory = new ExperimentFactory();
|
---|
[8517] | 73 | cts = new CancellationTokenSource();
|
---|
| 74 | }
|
---|
| 75 |
|
---|
[8524] | 76 | #region Background worker
|
---|
| 77 | private void instanceDiscoveryBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
|
---|
| 78 | var instanceProviders = new Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>>();
|
---|
| 79 | foreach (var provider in ProblemInstanceManager.GetProviders(algorithm.Problem))
|
---|
| 80 | instanceProviders[provider] = new HashSet<IDataDescriptor>(ProblemInstanceManager.GetDataDescriptors(provider));
|
---|
| 81 | e.Result = instanceProviders;
|
---|
[8517] | 82 | }
|
---|
| 83 |
|
---|
[8524] | 84 | private void instanceDiscoveryBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
|
---|
| 85 | problemInstanceProviders = (Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>>)e.Result;
|
---|
| 86 | libraryComboBox.DisplayMember = "Name";
|
---|
| 87 | libraryComboBox.DataSource = problemInstanceProviders.Keys.ToList();
|
---|
| 88 | libraryComboBox.Enabled = true;
|
---|
[8517] | 89 | }
|
---|
[8524] | 90 | #endregion
|
---|
[8517] | 91 |
|
---|
[8524] | 92 | #region Events
|
---|
[8517] | 93 | private void CreateExperimentDialogV2_Load(object sender, System.EventArgs e) {
|
---|
| 94 | if (algorithm.Problem != null) {
|
---|
| 95 | parameterConfigurationTreeView.Content = parameterConfigurationTree = new ParameterConfigurationTree(algorithm, algorithm.Problem);
|
---|
[8535] | 96 | parameterConfigurationTree.CombinationsCountChanged += (o, args) => UpdateCombinationsCount();
|
---|
[8574] | 97 | experimentFactory.ExperimentGenerationProgressChanged += (o, args) => progress.ProgressValue = experimentFactory.ExperimentGenerationProgress;
|
---|
[8517] | 98 | new ProgressView(parameterConfigurationTreeView, progress) { CancelTimeoutMs = 10000 };
|
---|
[8524] | 99 | } else {
|
---|
| 100 | configurationTabControl.TabPages.Remove(problemInstancesTabPage);
|
---|
| 101 | SetEnabledStateOfControls(false);
|
---|
[8517] | 102 | }
|
---|
| 103 | }
|
---|
| 104 |
|
---|
| 105 | private void CreateExperimentDialogV2_FormClosing(object sender, FormClosingEventArgs e) {
|
---|
[8535] | 106 | if (experimentGenerator != null) e.Cancel = true;
|
---|
[8517] | 107 | }
|
---|
| 108 |
|
---|
| 109 | private void createBatchRunCheckBox_CheckedChanged(object sender, System.EventArgs e) {
|
---|
| 110 | repetitionsNumericUpDown.Enabled = createBatchRun = createBatchRunCheckBox.Checked;
|
---|
| 111 | }
|
---|
| 112 |
|
---|
| 113 | private void repetitionsNumericUpDown_Validated(object sender, System.EventArgs e) {
|
---|
| 114 | if (repetitionsNumericUpDown.Text == string.Empty)
|
---|
| 115 | repetitionsNumericUpDown.Text = repetitionsNumericUpDown.Value.ToString();
|
---|
| 116 | repetitions = (int)repetitionsNumericUpDown.Value;
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | private void engineComboBox_SelectedIndexChanged(object sender, System.EventArgs e) {
|
---|
| 120 | engine = (IEngine)engineComboBox.SelectedItem;
|
---|
| 121 | }
|
---|
| 122 |
|
---|
[8524] | 123 | private void configurationTabControl_SelectedIndexChanged(object sender, EventArgs e) {
|
---|
| 124 | if (configurationTabControl.SelectedTab == problemInstancesTabPage && problemInstanceProviders == null) {
|
---|
| 125 | libraryComboBox.Enabled = false;
|
---|
| 126 | instanceDiscoveryBackgroundWorker.RunWorkerAsync();
|
---|
| 127 | }
|
---|
| 128 | }
|
---|
| 129 |
|
---|
| 130 | private void libraryComboBox_SelectedIndexChanged(object sender, EventArgs e) {
|
---|
| 131 | UpdateTreeView((IProblemInstanceProvider)libraryComboBox.SelectedItem);
|
---|
| 132 | }
|
---|
| 133 |
|
---|
| 134 | private void instanceTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
|
---|
| 135 | if (e.Action != TreeViewAction.Unknown) {
|
---|
| 136 | var provider = e.Node.Tag as IProblemInstanceProvider;
|
---|
| 137 | if (provider != null) {
|
---|
| 138 | if (e.Node.Checked) {
|
---|
| 139 | if (!selectedProblemInstanceProviders.ContainsKey(provider))
|
---|
| 140 | selectedProblemInstanceProviders[provider] = new HashSet<IDataDescriptor>();
|
---|
| 141 | foreach (TreeNode node in e.Node.Nodes) {
|
---|
| 142 | selectedProblemInstanceProviders[provider].Add((IDataDescriptor)node.Tag);
|
---|
| 143 | node.Checked = e.Node.Checked;
|
---|
| 144 | }
|
---|
| 145 | } else {
|
---|
| 146 | selectedProblemInstanceProviders[provider].Clear();
|
---|
| 147 | foreach (TreeNode node in e.Node.Nodes) {
|
---|
| 148 | node.Checked = e.Node.Checked;
|
---|
| 149 | }
|
---|
| 150 | }
|
---|
| 151 | } else {
|
---|
| 152 | provider = (IProblemInstanceProvider)e.Node.Parent.Tag;
|
---|
| 153 | if (!selectedProblemInstanceProviders.ContainsKey(provider))
|
---|
| 154 | selectedProblemInstanceProviders[provider] = new HashSet<IDataDescriptor>();
|
---|
| 155 | if (e.Node.Checked) {
|
---|
| 156 | selectedProblemInstanceProviders[provider].Add((IDataDescriptor)e.Node.Tag);
|
---|
| 157 | var instances = new TreeNode[e.Node.Parent.Nodes.Count];
|
---|
| 158 | e.Node.Parent.Nodes.CopyTo(instances, 0);
|
---|
| 159 | e.Node.Parent.Checked = instances.All(x => x.Checked);
|
---|
| 160 | } else {
|
---|
| 161 | selectedProblemInstanceProviders[provider].Remove((IDataDescriptor)e.Node.Tag);
|
---|
| 162 | e.Node.Parent.Checked = e.Node.Checked;
|
---|
| 163 | }
|
---|
| 164 | }
|
---|
[8535] | 165 | UpdateCombinationsCount();
|
---|
[8524] | 166 | }
|
---|
| 167 | }
|
---|
| 168 |
|
---|
[8517] | 169 | private void okButton_Click(object sender, System.EventArgs e) {
|
---|
[8524] | 170 | configurationTabControl.SelectedTab = parameterConfigurationTabPage;
|
---|
[8535] | 171 | experimentGenerator = Task.Factory.StartNew(() => {
|
---|
[8517] | 172 | StartProgressView();
|
---|
| 173 | var engineAlgorithm = algorithm as EngineAlgorithm;
|
---|
| 174 | if (engineAlgorithm != null) engineAlgorithm.Engine = engine;
|
---|
| 175 | try {
|
---|
[8574] | 176 | Experiment = createBatchRun ? experimentFactory.GenerateExperiment(engineAlgorithm, parameterConfigurationTree, true, repetitions, selectedProblemInstanceProviders, cts.Token)
|
---|
| 177 | : experimentFactory.GenerateExperiment(engineAlgorithm, parameterConfigurationTree, false, 0, selectedProblemInstanceProviders, cts.Token);
|
---|
[8517] | 178 | }
|
---|
| 179 | finally { FinishProgressView(); }
|
---|
| 180 | }, cts.Token);
|
---|
[8535] | 181 | experimentGenerator.ContinueWith(t => {
|
---|
| 182 | experimentGenerator = null;
|
---|
[8519] | 183 | CloseDialog();
|
---|
[8517] | 184 | }, TaskContinuationOptions.OnlyOnRanToCompletion);
|
---|
[8535] | 185 | experimentGenerator.ContinueWith(t => {
|
---|
| 186 | experimentGenerator = null;
|
---|
[8517] | 187 | if (t.IsCanceled) cts = new CancellationTokenSource();
|
---|
| 188 | if (t.IsFaulted) {
|
---|
| 189 | ReportError(t.Exception.Flatten());
|
---|
| 190 | t.Exception.Flatten().Handle(ex => true);
|
---|
| 191 | }
|
---|
| 192 | }, TaskContinuationOptions.NotOnRanToCompletion);
|
---|
| 193 | }
|
---|
[8524] | 194 | #endregion
|
---|
| 195 |
|
---|
| 196 | #region Helpers
|
---|
| 197 | private void SetEnabledStateOfControls(bool state) {
|
---|
| 198 | createBatchRunCheckBox.Enabled = state;
|
---|
| 199 | repetitionsNumericUpDown.Enabled = state;
|
---|
| 200 | engineComboBox.Enabled = state;
|
---|
| 201 | okButton.Enabled = state;
|
---|
| 202 | cancelButton.Enabled = state;
|
---|
| 203 | }
|
---|
| 204 |
|
---|
| 205 | private void UpdateTreeView(IProblemInstanceProvider provider) {
|
---|
| 206 | instanceTreeView.Nodes.Clear();
|
---|
| 207 | var rootNode = new TreeNode("All") { Tag = provider };
|
---|
| 208 | TreeNode[] instances = problemInstanceProviders[provider]
|
---|
| 209 | .Select(x => new TreeNode(x.Name) {
|
---|
| 210 | Tag = x,
|
---|
| 211 | Checked = selectedProblemInstanceProviders.ContainsKey(provider)
|
---|
| 212 | && selectedProblemInstanceProviders[provider].Contains(x)
|
---|
| 213 | })
|
---|
| 214 | .ToArray();
|
---|
| 215 | rootNode.Checked = instances.All(x => x.Checked);
|
---|
| 216 | rootNode.Nodes.AddRange(instances);
|
---|
| 217 | rootNode.ExpandAll();
|
---|
| 218 | instanceTreeView.Nodes.Add(rootNode);
|
---|
| 219 | }
|
---|
| 220 |
|
---|
[8535] | 221 | private void UpdateCombinationsCount() {
|
---|
| 222 | var combinationsCount = parameterConfigurationTree.CombinationsCount;
|
---|
| 223 | var instanceCount = 1 + selectedProblemInstanceProviders.Values.Sum(x => x.Count);
|
---|
| 224 | combinationsCountLabel.Text = (combinationsCount * instanceCount).ToString();
|
---|
| 225 | }
|
---|
| 226 |
|
---|
[8524] | 227 | private void StartProgressView() {
|
---|
| 228 | if (InvokeRequired) {
|
---|
| 229 | Invoke(new Action(StartProgressView));
|
---|
| 230 | } else {
|
---|
| 231 | SetEnabledStateOfControls(false);
|
---|
| 232 | problemInstancesTabPage.Enabled = false;
|
---|
| 233 | progress.ProgressValue = 0;
|
---|
| 234 | progress.ProgressState = ProgressState.Started;
|
---|
| 235 | }
|
---|
| 236 | }
|
---|
| 237 |
|
---|
| 238 | private void FinishProgressView() {
|
---|
| 239 | if (InvokeRequired) {
|
---|
| 240 | Invoke(new Action(FinishProgressView));
|
---|
| 241 | } else {
|
---|
| 242 | progress.Finish();
|
---|
| 243 | problemInstancesTabPage.Enabled = true;
|
---|
| 244 | SetEnabledStateOfControls(true);
|
---|
| 245 | }
|
---|
| 246 | }
|
---|
| 247 |
|
---|
| 248 | private void ReportError(Exception e) {
|
---|
| 249 | if (InvokeRequired) {
|
---|
| 250 | Invoke(new Action<Exception>(ReportError), e);
|
---|
| 251 | } else {
|
---|
| 252 | ErrorHandling.ShowErrorDialog(this, "An error occurred generating the experiment.", e);
|
---|
| 253 | }
|
---|
| 254 | }
|
---|
| 255 |
|
---|
| 256 | private void CloseDialog() {
|
---|
| 257 | if (InvokeRequired) {
|
---|
| 258 | Invoke(new Action(CloseDialog));
|
---|
| 259 | } else {
|
---|
| 260 | this.DialogResult = DialogResult.OK;
|
---|
| 261 | this.Close();
|
---|
| 262 | }
|
---|
| 263 | }
|
---|
| 264 | #endregion
|
---|
[8517] | 265 | }
|
---|
| 266 | }
|
---|