#region License Information /* HeuristicLab * Copyright (C) 2002-2016 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.Windows.Forms; using HeuristicLab.Common; using HeuristicLab.MainForm; using HeuristicLab.Optimization; using HeuristicLab.Problems.DataAnalysis; namespace HeuristicLab.VariableInteractionNetworks { public partial class CreateTargetVariationExperimentDialog : Form { public Experiment Experiment { get; private set; } public CreateTargetVariationExperimentDialog() : this(null) { } public CreateTargetVariationExperimentDialog(IAlgorithm alg) { InitializeComponent(); var problem = alg.Problem as IDataAnalysisProblem; var inputCount = problem.ProblemData.AllowedInputVariables.Count() - 1; // -1 because one will be the target if (combinationGroupSizeNumericUpDown.Value > inputCount) combinationGroupSizeNumericUpDown.Value = inputCount; var combinationGroupSize = (int)combinationGroupSizeNumericUpDown.Value; combinationCountLabel.Text = ((inputCount + 1) * EnumerableExtensions.BinomialCoefficient(inputCount, combinationGroupSize)).ToString(); Experiment = null; okButton.Enabled = alg != null; } public static IEnumerable CreateVariableCombinations(IAlgorithm algorithm, int combinationGroupSize, int repetitions) { if (algorithm == null) throw new ArgumentNullException("The algorithm parameter must be a valid IAlgorithm instance."); var problem = (IDataAnalysisProblem)algorithm.Problem; var problemData = problem.ProblemData; var variables = problemData.AllowedInputVariables.ToList(); int count = 1; foreach (var target in variables) { var inputs = variables.Where(x => x != target).ToList(); var combinations = inputs.Combinations(combinationGroupSize); foreach (var combination in combinations) { var h = new HashSet(combination); var alg = (IAlgorithm)algorithm.Clone(); alg.Name += " {Target = " + target + ", Inputs = (" + combination.Aggregate((a, b) => a + "," + b) + ")}"; problem = (IDataAnalysisProblem)alg.Problem; problemData = problem.ProblemData; foreach (var item in problemData.InputVariables) { problemData.InputVariables.SetItemCheckedState(item, h.Contains(item.Value)); } SetTargetName(problemData, target); var batchRun = new BatchRun(string.Format("Batchrun {0}", count++)) { Repetitions = repetitions, Optimizer = alg }; yield return batchRun; } } } private static string GetTargetName(IDataAnalysisProblemData problemData) { var regressionProblemData = problemData as IRegressionProblemData; if (regressionProblemData != null) return regressionProblemData.TargetVariable; var classificationProblemData = problemData as IClassificationProblemData; if (classificationProblemData != null) return classificationProblemData.TargetVariable; throw new ArgumentException("The provided argument must be either a regression or classification problem data."); } private static void SetTargetName(IDataAnalysisProblemData problemData, string targetName) { var regressionProblemData = problemData as IRegressionProblemData; if (regressionProblemData != null) { regressionProblemData.TargetVariable = targetName; return; } var classificationProblemData = problemData as IClassificationProblemData; if (classificationProblemData != null) { classificationProblemData.TargetVariable = targetName; return; } throw new ArgumentException("The provided argument must be either a regression or classification problem data."); } #region events private void CreateTargetVariationExperimentDialog_FormClosing(object sender, FormClosingEventArgs e) { if (worker.IsBusy) { if (DialogResult != DialogResult.OK) { if (worker.IsBusy) worker.CancelAsync(); } e.Cancel = true; } } private void repetitionsNumericUpDown_Validated(object sender, EventArgs e) { if (repetitionsNumericUpDown.Text == string.Empty) repetitionsNumericUpDown.Text = repetitionsNumericUpDown.Value.ToString(); } private void combinationGroupSizeNumericUpDown_Validating(object sender, System.ComponentModel.CancelEventArgs e) { IContentView activeView = MainFormManager.MainForm.ActiveView as IContentView; if (activeView == null) return; var algorithm = (IAlgorithm)activeView.Content; var problem = algorithm.Problem as IDataAnalysisProblem; if (problem == null) return; var inputCount = problem.ProblemData.AllowedInputVariables.Count() - 1; if (combinationGroupSizeNumericUpDown.Value > inputCount) combinationGroupSizeNumericUpDown.Value = inputCount; } private void combinationGroupSizeNumericUpDown_Validated(object sender, EventArgs e) { if (combinationGroupSizeNumericUpDown.Text == string.Empty) combinationGroupSizeNumericUpDown.Text = combinationGroupSizeNumericUpDown.Value.ToString(); IContentView activeView = MainFormManager.MainForm.ActiveView as IContentView; if (activeView == null) return; var algorithm = (IAlgorithm)activeView.Content; var problem = (IDataAnalysisProblem)algorithm.Problem; var inputCount = problem.ProblemData.AllowedInputVariables.Count() - 1; if (combinationGroupSizeNumericUpDown.Value > inputCount) combinationGroupSizeNumericUpDown.Value = inputCount; combinationCountLabel.Text = ((inputCount + 1) * EnumerableExtensions.BinomialCoefficient(inputCount, (int)combinationGroupSizeNumericUpDown.Value)).ToString(); } private void worker_DoWork(object sender, DoWorkEventArgs e) { IContentView activeView = (IContentView)MainFormManager.MainForm.ActiveView; var algorithm = (IAlgorithm)activeView.Content; var problem = (IDataAnalysisProblem)algorithm.Problem; var experiment = new Experiment("Target Variation Experiment"); var repetitions = (int)repetitionsNumericUpDown.Value; var inputCount = problem.ProblemData.AllowedInputVariables.Count() - 1; var combinationGroupSize = (int)combinationGroupSizeNumericUpDown.Value; var totalNumberOfCombinations = (inputCount + 1) * EnumerableExtensions.BinomialCoefficient(inputCount, combinationGroupSize); int progress = 0; try { foreach (var optimizer in CreateVariableCombinations(algorithm, combinationGroupSize, repetitions)) { if (worker.CancellationPending) throw new OperationCanceledException(); experiment.Optimizers.Add(optimizer); progress++; worker.ReportProgress((int)Math.Round(100d * progress / totalNumberOfCombinations)); } Experiment = experiment; } catch (OperationCanceledException) { e.Cancel = true; UpdateProgress(0); progressBar.Visible = false; okButton.Enabled = true; combinationsLabel.Visible = true; combinationCountLabel.Visible = true; } } private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { if (InvokeRequired) { Invoke((Action)UpdateProgress, e.ProgressPercentage); } else { UpdateProgress(e.ProgressPercentage); } } private void UpdateProgress(int percentage) { progressBar.Value = percentage; } private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled || e.Error != null) return; DialogResult = DialogResult.OK; Close(); } private void okButton_Click(object sender, EventArgs args) { IContentView activeView = MainFormManager.MainForm.ActiveView as IContentView; if ((activeView != null) && (activeView.Content != null) && (activeView.Content is IAlgorithm) && !activeView.Locked) { okButton.Enabled = false; combinationsLabel.Visible = false; combinationCountLabel.Visible = false; progressBar.Visible = true; worker.RunWorkerAsync(); } } private void cancelButton_Click(object sender, EventArgs e) { if (worker.IsBusy) worker.CancelAsync(); } #endregion } }