#region License Information /* HeuristicLab * Copyright (C) 2002-2017 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 { [View("CreateExperiment View")] [Content(typeof(IAlgorithm), false)] public partial class CreateExperimentView : AsynchronousContentView { private readonly ExperimentFactory experimentFactory; 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 new IAlgorithm Content { get { return (IAlgorithm)base.Content; } set { base.Content = value; } } public CreateExperimentView() { InitializeComponent(); engineComboBox.DataSource = ApplicationManager.Manager.GetInstances().ToArray(); 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 }; progress.CancelRequested += (sender, args) => cts.Cancel(); progress.ProgressValueChanged += (sender, args) => progress.Status = string.Format("Generating experiment. Please be patient. ({0} %)", (int)(progress.ProgressValue * 100)); experimentFactory = new ExperimentFactory(); cts = new CancellationTokenSource(); } #region Background worker private void instanceDiscoveryBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { var instanceProviders = new Dictionary>(); foreach (var provider in ProblemInstanceManager.GetProviders(Content.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 protected override void OnContentChanged() { base.OnContentChanged(); if (Content != null && Content.Problem != null) { parameterConfigurationTreeView.Content = parameterConfigurationTree = new ParameterConfigurationTree(Content, Content.Problem); parameterConfigurationTree.CombinationsCountChanged += (o, args) => UpdateCombinationsCount(); experimentFactory.ExperimentGenerationProgressChanged += (o, args) => progress.ProgressValue = experimentFactory.ExperimentGenerationProgress; } else { configurationTabControl.TabPages.Remove(problemInstancesTabPage); SetEnabledStateOfControls(); } } protected override void OnClosing(FormClosingEventArgs e) { cts.Cancel(); base.OnClosing(e); } #region Events private void createBatchRunCheckBox_CheckedChanged(object sender, EventArgs e) { repetitionsNumericUpDown.Enabled = createBatchRun = createBatchRunCheckBox.Checked; } private void repetitionsNumericUpDown_Validated(object sender, EventArgs e) { if (repetitionsNumericUpDown.Text == string.Empty) repetitionsNumericUpDown.Text = repetitionsNumericUpDown.Value.ToString(); repetitions = (int)repetitionsNumericUpDown.Value; } private void engineComboBox_SelectedIndexChanged(object sender, 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 generateButton_Click(object sender, EventArgs e) { experimentGenerator = Task.Factory.StartNew(() => { StartProgressView(); var engineAlgorithm = Content as EngineAlgorithm; if (engineAlgorithm != null) engineAlgorithm.Engine = engine; try { var experiment = experimentFactory.GenerateExperiment( Content, parameterConfigurationTree, createBatchRun, createBatchRun ? repetitions : 0, selectedProblemInstanceProviders, cts.Token); MainFormManager.MainForm.ShowContent(experiment); } finally { FinishProgressView(); } }, cts.Token); experimentGenerator.ContinueWith(t => { experimentGenerator = null; }, 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 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 = Math.Max(1, selectedProblemInstanceProviders.Values.Sum(x => x.Count)); generateButton.Text = string.Format("&Create Experiment (Combinations: {0})", combinationsCount * instanceCount); } private void StartProgressView() { progress.Start(); var mainForm = MainFormManager.GetMainForm(); mainForm.AddOperationProgressToView(this, progress); } private void FinishProgressView() { var mainForm = MainFormManager.GetMainForm(); mainForm.RemoveOperationProgressFromView(this); progress.Finish(); } private void ReportError(Exception e) { if (InvokeRequired) { Invoke(new Action(ReportError), e); } else { ErrorHandling.ShowErrorDialog(this, "An error occurred generating the experiment.", e); } } #endregion } }