#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
}
}