[15171] | 1 | #region License Information
|
---|
| 2 | /* HeuristicLab
|
---|
| 3 | * Copyright (C) 2002-2017 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;
|
---|
| 24 | using System.ComponentModel;
|
---|
| 25 | using System.Linq;
|
---|
| 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;
|
---|
| 34 | using HeuristicLab.Problems.Instances;
|
---|
| 35 |
|
---|
| 36 | namespace HeuristicLab.Encodings.ParameterConfigurationEncoding.Views {
|
---|
| 37 | [View("CreateExperiment View")]
|
---|
| 38 | [Content(typeof(IAlgorithm), false)]
|
---|
| 39 | public partial class CreateExperimentView : AsynchronousContentView {
|
---|
| 40 | private readonly ExperimentFactory experimentFactory;
|
---|
| 41 | private readonly Progress progress;
|
---|
| 42 | private ParameterConfigurationTree parameterConfigurationTree;
|
---|
| 43 | private bool createBatchRun;
|
---|
| 44 | private int repetitions;
|
---|
| 45 | private IEngine engine;
|
---|
| 46 | private Task experimentGenerator;
|
---|
| 47 | private CancellationTokenSource cts;
|
---|
| 48 | private Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>> problemInstanceProviders;
|
---|
| 49 | private Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>> selectedProblemInstanceProviders;
|
---|
| 50 |
|
---|
| 51 | public new IAlgorithm Content {
|
---|
| 52 | get { return (IAlgorithm)base.Content; }
|
---|
| 53 | set { base.Content = value; }
|
---|
| 54 | }
|
---|
| 55 |
|
---|
| 56 | public CreateExperimentView() {
|
---|
| 57 | InitializeComponent();
|
---|
| 58 | engineComboBox.DataSource = ApplicationManager.Manager.GetInstances<IEngine>().ToArray();
|
---|
| 59 | if (engineComboBox.SelectedItem == null) {
|
---|
| 60 | engineComboBox.SelectedIndex = 0;
|
---|
| 61 | engine = (IEngine)engineComboBox.SelectedItem;
|
---|
| 62 | }
|
---|
| 63 |
|
---|
| 64 | createBatchRun = createBatchRunCheckBox.Checked;
|
---|
| 65 | repetitions = (int)repetitionsNumericUpDown.Value;
|
---|
| 66 | selectedProblemInstanceProviders = new Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>>();
|
---|
| 67 |
|
---|
| 68 | progress = new Progress { CanBeCanceled = true };
|
---|
| 69 | progress.CancelRequested += (sender, args) => cts.Cancel();
|
---|
| 70 | progress.ProgressValueChanged += (sender, args) => progress.Status = string.Format("Generating experiment. Please be patient. ({0} %)", (int)(progress.ProgressValue * 100));
|
---|
| 71 |
|
---|
| 72 | experimentFactory = new ExperimentFactory();
|
---|
| 73 | cts = new CancellationTokenSource();
|
---|
| 74 | }
|
---|
| 75 |
|
---|
| 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(Content.Problem))
|
---|
| 80 | instanceProviders[provider] = new HashSet<IDataDescriptor>(ProblemInstanceManager.GetDataDescriptors(provider));
|
---|
| 81 | e.Result = instanceProviders;
|
---|
| 82 | }
|
---|
| 83 |
|
---|
| 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;
|
---|
| 89 | }
|
---|
| 90 | #endregion
|
---|
| 91 |
|
---|
| 92 | protected override void OnContentChanged() {
|
---|
| 93 | base.OnContentChanged();
|
---|
| 94 | if (Content != null && Content.Problem != null) {
|
---|
| 95 | parameterConfigurationTreeView.Content = parameterConfigurationTree = new ParameterConfigurationTree(Content, Content.Problem);
|
---|
| 96 | parameterConfigurationTree.CombinationsCountChanged += (o, args) => UpdateCombinationsCount();
|
---|
| 97 | experimentFactory.ExperimentGenerationProgressChanged += (o, args) => progress.ProgressValue = experimentFactory.ExperimentGenerationProgress;
|
---|
| 98 | } else {
|
---|
| 99 | configurationTabControl.TabPages.Remove(problemInstancesTabPage);
|
---|
| 100 | SetEnabledStateOfControls();
|
---|
| 101 | }
|
---|
| 102 | }
|
---|
| 103 |
|
---|
| 104 | protected override void OnClosing(FormClosingEventArgs e) {
|
---|
| 105 | cts.Cancel();
|
---|
| 106 | base.OnClosing(e);
|
---|
| 107 | }
|
---|
| 108 |
|
---|
| 109 | #region Events
|
---|
| 110 | private void createBatchRunCheckBox_CheckedChanged(object sender, EventArgs e) {
|
---|
| 111 | repetitionsNumericUpDown.Enabled = createBatchRun = createBatchRunCheckBox.Checked;
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 | private void repetitionsNumericUpDown_Validated(object sender, EventArgs e) {
|
---|
| 115 | if (repetitionsNumericUpDown.Text == string.Empty)
|
---|
| 116 | repetitionsNumericUpDown.Text = repetitionsNumericUpDown.Value.ToString();
|
---|
| 117 | repetitions = (int)repetitionsNumericUpDown.Value;
|
---|
| 118 | }
|
---|
| 119 |
|
---|
| 120 | private void engineComboBox_SelectedIndexChanged(object sender, EventArgs e) {
|
---|
| 121 | engine = (IEngine)engineComboBox.SelectedItem;
|
---|
| 122 | }
|
---|
| 123 |
|
---|
| 124 | private void configurationTabControl_SelectedIndexChanged(object sender, EventArgs e) {
|
---|
| 125 | if (configurationTabControl.SelectedTab == problemInstancesTabPage && problemInstanceProviders == null) {
|
---|
| 126 | libraryComboBox.Enabled = false;
|
---|
| 127 | instanceDiscoveryBackgroundWorker.RunWorkerAsync();
|
---|
| 128 | }
|
---|
| 129 | }
|
---|
| 130 |
|
---|
| 131 | private void libraryComboBox_SelectedIndexChanged(object sender, EventArgs e) {
|
---|
| 132 | UpdateTreeView((IProblemInstanceProvider)libraryComboBox.SelectedItem);
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | private void instanceTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
|
---|
| 136 | if (e.Action != TreeViewAction.Unknown) {
|
---|
| 137 | var provider = e.Node.Tag as IProblemInstanceProvider;
|
---|
| 138 | if (provider != null) {
|
---|
| 139 | if (e.Node.Checked) {
|
---|
| 140 | if (!selectedProblemInstanceProviders.ContainsKey(provider))
|
---|
| 141 | selectedProblemInstanceProviders[provider] = new HashSet<IDataDescriptor>();
|
---|
| 142 | foreach (TreeNode node in e.Node.Nodes) {
|
---|
| 143 | selectedProblemInstanceProviders[provider].Add((IDataDescriptor)node.Tag);
|
---|
| 144 | node.Checked = e.Node.Checked;
|
---|
| 145 | }
|
---|
| 146 | } else {
|
---|
| 147 | selectedProblemInstanceProviders[provider].Clear();
|
---|
| 148 | foreach (TreeNode node in e.Node.Nodes) {
|
---|
| 149 | node.Checked = e.Node.Checked;
|
---|
| 150 | }
|
---|
| 151 | }
|
---|
| 152 | } else {
|
---|
| 153 | provider = (IProblemInstanceProvider)e.Node.Parent.Tag;
|
---|
| 154 | if (!selectedProblemInstanceProviders.ContainsKey(provider))
|
---|
| 155 | selectedProblemInstanceProviders[provider] = new HashSet<IDataDescriptor>();
|
---|
| 156 | if (e.Node.Checked) {
|
---|
| 157 | selectedProblemInstanceProviders[provider].Add((IDataDescriptor)e.Node.Tag);
|
---|
| 158 | var instances = new TreeNode[e.Node.Parent.Nodes.Count];
|
---|
| 159 | e.Node.Parent.Nodes.CopyTo(instances, 0);
|
---|
| 160 | e.Node.Parent.Checked = instances.All(x => x.Checked);
|
---|
| 161 | } else {
|
---|
| 162 | selectedProblemInstanceProviders[provider].Remove((IDataDescriptor)e.Node.Tag);
|
---|
| 163 | e.Node.Parent.Checked = e.Node.Checked;
|
---|
| 164 | }
|
---|
| 165 | }
|
---|
| 166 | UpdateCombinationsCount();
|
---|
| 167 | }
|
---|
| 168 | }
|
---|
| 169 |
|
---|
| 170 | private void generateButton_Click(object sender, EventArgs e) {
|
---|
| 171 | experimentGenerator = Task.Factory.StartNew(() => {
|
---|
| 172 | StartProgressView();
|
---|
| 173 | var engineAlgorithm = Content as EngineAlgorithm;
|
---|
| 174 | if (engineAlgorithm != null) engineAlgorithm.Engine = engine;
|
---|
| 175 |
|
---|
| 176 | try {
|
---|
| 177 | var experiment = experimentFactory.GenerateExperiment(
|
---|
| 178 | Content, parameterConfigurationTree, createBatchRun,
|
---|
| 179 | createBatchRun ? repetitions : 0, selectedProblemInstanceProviders, cts.Token);
|
---|
| 180 |
|
---|
| 181 | MainFormManager.MainForm.ShowContent(experiment);
|
---|
| 182 | } finally {
|
---|
| 183 | FinishProgressView();
|
---|
| 184 | }
|
---|
| 185 | }, cts.Token);
|
---|
| 186 |
|
---|
| 187 | experimentGenerator.ContinueWith(t => {
|
---|
| 188 | experimentGenerator = null;
|
---|
| 189 | }, TaskContinuationOptions.OnlyOnRanToCompletion);
|
---|
| 190 |
|
---|
| 191 | experimentGenerator.ContinueWith(t => {
|
---|
| 192 | experimentGenerator = null;
|
---|
| 193 | if (t.IsCanceled) cts = new CancellationTokenSource();
|
---|
| 194 | if (t.IsFaulted) {
|
---|
| 195 | ReportError(t.Exception.Flatten());
|
---|
| 196 | t.Exception.Flatten().Handle(ex => true);
|
---|
| 197 | }
|
---|
| 198 | }, TaskContinuationOptions.NotOnRanToCompletion);
|
---|
| 199 | }
|
---|
| 200 | #endregion
|
---|
| 201 |
|
---|
| 202 | #region Helpers
|
---|
| 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 |
|
---|
| 221 | private void UpdateCombinationsCount() {
|
---|
| 222 | var combinationsCount = parameterConfigurationTree.CombinationsCount;
|
---|
| 223 | var instanceCount = Math.Max(1, selectedProblemInstanceProviders.Values.Sum(x => x.Count));
|
---|
| 224 | generateButton.Text = string.Format("&Create Experiment (Combinations: {0})", combinationsCount * instanceCount);
|
---|
| 225 | }
|
---|
| 226 |
|
---|
| 227 | private void StartProgressView() {
|
---|
| 228 | progress.Start();
|
---|
| 229 | var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
|
---|
| 230 | mainForm.AddOperationProgressToView(this, progress);
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | private void FinishProgressView() {
|
---|
| 234 | var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
|
---|
| 235 | mainForm.RemoveOperationProgressFromView(this);
|
---|
| 236 | progress.Finish();
|
---|
| 237 | }
|
---|
| 238 |
|
---|
| 239 | private void ReportError(Exception e) {
|
---|
| 240 | if (InvokeRequired) {
|
---|
| 241 | Invoke(new Action<Exception>(ReportError), e);
|
---|
| 242 | } else {
|
---|
| 243 | ErrorHandling.ShowErrorDialog(this, "An error occurred generating the experiment.", e);
|
---|
| 244 | }
|
---|
| 245 | }
|
---|
| 246 | #endregion
|
---|
| 247 | }
|
---|
| 248 | }
|
---|