#region License Information /* HeuristicLab * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using HeuristicLab.Core; using HeuristicLab.MainForm; using HeuristicLab.MainForm.WindowsForms; using HeuristicLab.Optimization; using HeuristicLab.PluginInfrastructure; using HeuristicLab.Problems.Instances; namespace HeuristicLab.Encodings.ParameterConfigurationEncoding.Views { public partial class CreateExperimentDialogV2 : Form { private readonly IAlgorithm algorithm; private readonly Progress progress; private ParameterConfigurationTree parameterConfigurationTree; private bool createBatchRun; private int repetitions; private IEngine engine; private Task experimentGenerator; private CancellationTokenSource cts; private Dictionary> problemInstanceProviders; private Dictionary> selectedProblemInstanceProviders; public Experiment Experiment { get; private set; } public CreateExperimentDialogV2() : this(null, null) { } public CreateExperimentDialogV2(IAlgorithm algorithm, IEnumerable engines) { InitializeComponent(); if (algorithm != null && engines != null) { this.algorithm = (IAlgorithm)algorithm.Clone(); foreach (var engine in engines) engineComboBox.Items.Add(engine); if (engineComboBox.SelectedItem == null) { engineComboBox.SelectedIndex = 0; engine = (IEngine)engineComboBox.SelectedItem; } } createBatchRun = createBatchRunCheckBox.Checked; repetitions = (int)repetitionsNumericUpDown.Value; selectedProblemInstanceProviders = new Dictionary>(); progress = new Progress { CanBeCanceled = true, ProgressState = ProgressState.Finished }; progress.CancelRequested += (sender, args) => cts.Cancel(); progress.ProgressValueChanged += (sender, args) => progress.Status = string.Format("Generating experiment. Please be patient. ({0} %)", (int)(progress.ProgressValue * 100)); cts = new CancellationTokenSource(); } #region Background worker private void instanceDiscoveryBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { var instanceProviders = new Dictionary>(); foreach (var provider in ProblemInstanceManager.GetProviders(algorithm.Problem)) instanceProviders[provider] = new HashSet(ProblemInstanceManager.GetDataDescriptors(provider)); e.Result = instanceProviders; } private void instanceDiscoveryBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { problemInstanceProviders = (Dictionary>)e.Result; libraryComboBox.DisplayMember = "Name"; libraryComboBox.DataSource = problemInstanceProviders.Keys.ToList(); libraryComboBox.Enabled = true; } #endregion #region Events private void CreateExperimentDialogV2_Load(object sender, System.EventArgs e) { if (algorithm.Problem != null) { parameterConfigurationTreeView.Content = parameterConfigurationTree = new ParameterConfigurationTree(algorithm, algorithm.Problem); parameterConfigurationTree.ExperimentGenerationProgressChanged += (o, args) => progress.ProgressValue = parameterConfigurationTree.ExperimentGenerationProgress; parameterConfigurationTree.CombinationsCountChanged += (o, args) => UpdateCombinationsCount(); new ProgressView(parameterConfigurationTreeView, progress) { CancelTimeoutMs = 10000 }; } else { configurationTabControl.TabPages.Remove(problemInstancesTabPage); SetEnabledStateOfControls(false); } } private void CreateExperimentDialogV2_FormClosing(object sender, FormClosingEventArgs e) { if (experimentGenerator != null) e.Cancel = true; } private void createBatchRunCheckBox_CheckedChanged(object sender, System.EventArgs e) { repetitionsNumericUpDown.Enabled = createBatchRun = createBatchRunCheckBox.Checked; } private void repetitionsNumericUpDown_Validated(object sender, System.EventArgs e) { if (repetitionsNumericUpDown.Text == string.Empty) repetitionsNumericUpDown.Text = repetitionsNumericUpDown.Value.ToString(); repetitions = (int)repetitionsNumericUpDown.Value; } private void engineComboBox_SelectedIndexChanged(object sender, System.EventArgs e) { engine = (IEngine)engineComboBox.SelectedItem; } private void configurationTabControl_SelectedIndexChanged(object sender, EventArgs e) { if (configurationTabControl.SelectedTab == problemInstancesTabPage && problemInstanceProviders == null) { libraryComboBox.Enabled = false; instanceDiscoveryBackgroundWorker.RunWorkerAsync(); } } private void libraryComboBox_SelectedIndexChanged(object sender, EventArgs e) { UpdateTreeView((IProblemInstanceProvider)libraryComboBox.SelectedItem); } private void instanceTreeView_AfterCheck(object sender, TreeViewEventArgs e) { if (e.Action != TreeViewAction.Unknown) { var provider = e.Node.Tag as IProblemInstanceProvider; if (provider != null) { if (e.Node.Checked) { if (!selectedProblemInstanceProviders.ContainsKey(provider)) selectedProblemInstanceProviders[provider] = new HashSet(); foreach (TreeNode node in e.Node.Nodes) { selectedProblemInstanceProviders[provider].Add((IDataDescriptor)node.Tag); node.Checked = e.Node.Checked; } } else { selectedProblemInstanceProviders[provider].Clear(); foreach (TreeNode node in e.Node.Nodes) { node.Checked = e.Node.Checked; } } } else { provider = (IProblemInstanceProvider)e.Node.Parent.Tag; if (!selectedProblemInstanceProviders.ContainsKey(provider)) selectedProblemInstanceProviders[provider] = new HashSet(); if (e.Node.Checked) { selectedProblemInstanceProviders[provider].Add((IDataDescriptor)e.Node.Tag); var instances = new TreeNode[e.Node.Parent.Nodes.Count]; e.Node.Parent.Nodes.CopyTo(instances, 0); e.Node.Parent.Checked = instances.All(x => x.Checked); } else { selectedProblemInstanceProviders[provider].Remove((IDataDescriptor)e.Node.Tag); e.Node.Parent.Checked = e.Node.Checked; } } UpdateCombinationsCount(); } } private void okButton_Click(object sender, System.EventArgs e) { configurationTabControl.SelectedTab = parameterConfigurationTabPage; experimentGenerator = Task.Factory.StartNew(() => { StartProgressView(); var engineAlgorithm = algorithm as EngineAlgorithm; if (engineAlgorithm != null) engineAlgorithm.Engine = engine; try { Experiment = createBatchRun ? parameterConfigurationTree.GenerateExperiment(engineAlgorithm, true, repetitions, selectedProblemInstanceProviders, cts.Token) : parameterConfigurationTree.GenerateExperiment(engineAlgorithm, false, 0, selectedProblemInstanceProviders, cts.Token); } finally { FinishProgressView(); } }, cts.Token); experimentGenerator.ContinueWith(t => { experimentGenerator = null; CloseDialog(); }, TaskContinuationOptions.OnlyOnRanToCompletion); experimentGenerator.ContinueWith(t => { experimentGenerator = null; if (t.IsCanceled) cts = new CancellationTokenSource(); if (t.IsFaulted) { ReportError(t.Exception.Flatten()); t.Exception.Flatten().Handle(ex => true); } }, TaskContinuationOptions.NotOnRanToCompletion); } #endregion #region Helpers private void SetEnabledStateOfControls(bool state) { createBatchRunCheckBox.Enabled = state; repetitionsNumericUpDown.Enabled = state; engineComboBox.Enabled = state; okButton.Enabled = state; cancelButton.Enabled = state; } private void UpdateTreeView(IProblemInstanceProvider provider) { instanceTreeView.Nodes.Clear(); var rootNode = new TreeNode("All") { Tag = provider }; TreeNode[] instances = problemInstanceProviders[provider] .Select(x => new TreeNode(x.Name) { Tag = x, Checked = selectedProblemInstanceProviders.ContainsKey(provider) && selectedProblemInstanceProviders[provider].Contains(x) }) .ToArray(); rootNode.Checked = instances.All(x => x.Checked); rootNode.Nodes.AddRange(instances); rootNode.ExpandAll(); instanceTreeView.Nodes.Add(rootNode); } private void UpdateCombinationsCount() { var combinationsCount = parameterConfigurationTree.CombinationsCount; var instanceCount = 1 + selectedProblemInstanceProviders.Values.Sum(x => x.Count); combinationsCountLabel.Text = (combinationsCount * instanceCount).ToString(); } private void StartProgressView() { if (InvokeRequired) { Invoke(new Action(StartProgressView)); } else { SetEnabledStateOfControls(false); problemInstancesTabPage.Enabled = false; progress.ProgressValue = 0; progress.ProgressState = ProgressState.Started; } } private void FinishProgressView() { if (InvokeRequired) { Invoke(new Action(FinishProgressView)); } else { progress.Finish(); problemInstancesTabPage.Enabled = true; SetEnabledStateOfControls(true); } } private void ReportError(Exception e) { if (InvokeRequired) { Invoke(new Action(ReportError), e); } else { ErrorHandling.ShowErrorDialog(this, "An error occurred generating the experiment.", e); } } private void CloseDialog() { if (InvokeRequired) { Invoke(new Action(CloseDialog)); } else { this.DialogResult = DialogResult.OK; this.Close(); } } #endregion } }