diff --git a/CHANGELOG.md b/CHANGELOG.md index fa825925..44bc1b68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ Please see [here](https://github.com/hrntsm/Tunny/releases) for the data release - Mode that works faster instead of saving optimization results during optimization. - Support Journal storage. - Since saving to the sqlite storage format that had been used up to now sometimes resulted in errors during optimization, a different storage format was supported. +- Checkbox to toggle whether results are shown in the UI in Realtime. + - There was a problem that the display of results on the UI in Realtime, which was added in v0.6, caused the optimization speed to gradually slow down. ### Changed @@ -32,6 +34,8 @@ Please see [here](https://github.com/hrntsm/Tunny/releases) for the data release ### Security +- Bump torch from 1.12.0 to 1.13.1 + ## [v0.6.0] -2022-12-23 ### Added diff --git a/Tunny/Settings/Optimize.cs b/Tunny/Settings/Optimize.cs index 12415056..00bee256 100644 --- a/Tunny/Settings/Optimize.cs +++ b/Tunny/Settings/Optimize.cs @@ -12,5 +12,6 @@ public class Optimize public int SelectSampler { get; set; } public double Timeout { get; set; } public GcAfterTrial GcAfterTrial { get; set; } = GcAfterTrial.HasGeometry; + public bool ShowRealtimeResult { get; set; } } } diff --git a/Tunny/Solver/Algorithm.cs b/Tunny/Solver/Algorithm.cs index df3b1a00..72d342b8 100644 --- a/Tunny/Solver/Algorithm.cs +++ b/Tunny/Solver/Algorithm.cs @@ -23,7 +23,7 @@ public class Algorithm private string[] ObjNickName { get; set; } private TunnySettings Settings { get; set; } private Func EvalFunc { get; set; } - private double[] XOpt { get; set; } + public double[] XOpt { get; private set; } private double[] FxOpt { get; set; } public EndState EndState { get; set; } public Dictionary FishEgg { get; set; } @@ -189,28 +189,14 @@ private void RunOptimize(int nTrials, double timeout, dynamic study, dynamic sto result = new EvaluatedGHResult(); int trialNum = 0; DateTime startTime = DateTime.Now; - EnqueueTrial(study, enqueueItems); while (true) { - if (trialNum >= nTrials) - { - EndState = EndState.AllTrialCompleted; - break; - } - else if (timeout > 0 && (DateTime.Now - startTime).TotalSeconds >= timeout) - { - EndState = EndState.Timeout; - break; - } - else if (OptimizeLoop.IsForcedStopOptimize) + if (CheckOptimizeComplete(nTrials, timeout, trialNum, startTime)) { - EndState = EndState.StoppedByUser; - OptimizeLoop.IsForcedStopOptimize = false; break; } - int progress = trialNum * 100 / nTrials; dynamic trial = study.ask(); @@ -225,19 +211,7 @@ private void RunOptimize(int nTrials, double timeout, dynamic study, dynamic sto : trial.suggest_float(Variables[j].NickName, Variables[j].LowerBond, Variables[j].UpperBond, step: Variables[j].Epsilon); } - dynamic[] bestTrials = study.best_trials; - double[][] bestValues = bestTrials.Select(t => (double[])t.values).ToArray(); - var pState = new ProgressState - { - TrialNumber = trialNum, - ObjectiveNum = ObjNickName.Length, - BestValues = bestValues, - Values = xTest.Select(v => (decimal)v).ToList(), - HypervolumeRatio = trialNum == 0 ? 0 : trialNum == 1 || ObjNickName.Length == 1 ? 1 : Hypervolume.Compute2dHypervolumeRatio(study), - EstimatedTimeRemaining = timeout <= 0 - ? TimeSpan.FromSeconds((DateTime.Now - startTime).TotalSeconds * (nTrials - trialNum) / (trialNum + 1)) - : TimeSpan.FromSeconds(timeout - (DateTime.Now - startTime).TotalSeconds) - }; + ProgressState pState = SetProgressState(nTrials, timeout, xTest, trialNum, startTime, study); result = EvalFunc(pState, progress); if (result.ObjectiveValues.Contains(double.NaN)) @@ -273,6 +247,60 @@ private void RunOptimize(int nTrials, double timeout, dynamic study, dynamic sto } } + private bool CheckOptimizeComplete(int nTrials, double timeout, int trialNum, DateTime startTime) + { + bool isOptimizeCompleted = false; + if (trialNum >= nTrials) + { + EndState = EndState.AllTrialCompleted; + isOptimizeCompleted = true; + } + else if (timeout > 0 && (DateTime.Now - startTime).TotalSeconds >= timeout) + { + EndState = EndState.Timeout; + isOptimizeCompleted = true; + } + else if (OptimizeLoop.IsForcedStopOptimize) + { + EndState = EndState.StoppedByUser; + OptimizeLoop.IsForcedStopOptimize = false; + isOptimizeCompleted = true; + } + + return isOptimizeCompleted; + } + + private ProgressState SetProgressState(int nTrials, double timeout, double[] xTest, int trialNum, DateTime startTime, dynamic study) + { + ComputeBestValues(study, trialNum, out double[][] bestValues, out double hypervolumeRatio); + return new ProgressState + { + TrialNumber = trialNum, + ObjectiveNum = ObjNickName.Length, + BestValues = bestValues, + Values = xTest.Select(v => (decimal)v).ToList(), + HypervolumeRatio = hypervolumeRatio, + EstimatedTimeRemaining = timeout <= 0 + ? TimeSpan.FromSeconds((DateTime.Now - startTime).TotalSeconds * (nTrials - trialNum) / (trialNum + 1)) + : TimeSpan.FromSeconds(timeout - (DateTime.Now - startTime).TotalSeconds) + }; + } + + private void ComputeBestValues(dynamic study, int trialNum, out double[][] bestValues, out double hypervolumeRatio) + { + if (Settings.Optimize.ShowRealtimeResult) + { + dynamic[] bestTrials = study.best_trials; + bestValues = bestTrials.Select(t => (double[])t.values).ToArray(); + hypervolumeRatio = trialNum == 0 ? 0 : trialNum == 1 || ObjNickName.Length == 1 ? 1 : Hypervolume.Compute2dHypervolumeRatio(study); + } + else + { + bestValues = null; + hypervolumeRatio = 0; + } + } + private void CopyInMemoryStudy(dynamic storage) { dynamic optuna = Py.Import("optuna"); @@ -393,17 +421,6 @@ private dynamic SetSamplerSettings(int samplerType, ref int nTrials, dynamic opt } return sampler; } - - public double[] GetXOptimum() - { - return XOpt; - } - - public double[] GetFxOptimum() - { - return FxOpt; - } - } public enum GcAfterTrial diff --git a/Tunny/Solver/Optuna.cs b/Tunny/Solver/Optuna.cs index ebb7fba4..bb32caa7 100644 --- a/Tunny/Solver/Optuna.cs +++ b/Tunny/Solver/Optuna.cs @@ -48,7 +48,7 @@ EvaluatedGHResult Eval(ProgressState pState, int progress) { var optimize = new Algorithm(variables, _hasConstraint, objNickName, fishEggs, _settings, Eval); optimize.Solve(); - XOpt = optimize.GetXOptimum(); + XOpt = optimize.XOpt; ShowEndMessages(optimize); return true; diff --git a/Tunny/UI/OptimizationWindow.Designer.cs b/Tunny/UI/OptimizationWindow.Designer.cs index e4494391..6b495014 100644 --- a/Tunny/UI/OptimizationWindow.Designer.cs +++ b/Tunny/UI/OptimizationWindow.Designer.cs @@ -44,6 +44,7 @@ private void InitializeComponent() this.studyNameTextBox = new System.Windows.Forms.TextBox(); this.optimizeTabControl = new System.Windows.Forms.TabControl(); this.optimizeTabPage = new System.Windows.Forms.TabPage(); + this.ShowRealtimeResultCheckBox = new System.Windows.Forms.CheckBox(); this.EstimatedTimeRemainingLabel = new System.Windows.Forms.Label(); this.optimizeBestValueLabel = new System.Windows.Forms.Label(); this.optimizeTrialNumLabel = new System.Windows.Forms.Label(); @@ -319,6 +320,7 @@ private void InitializeComponent() // // optimizeTabPage // + this.optimizeTabPage.Controls.Add(this.ShowRealtimeResultCheckBox); this.optimizeTabPage.Controls.Add(this.EstimatedTimeRemainingLabel); this.optimizeTabPage.Controls.Add(this.optimizeBestValueLabel); this.optimizeTabPage.Controls.Add(this.optimizeTrialNumLabel); @@ -341,10 +343,21 @@ private void InitializeComponent() this.optimizeTabPage.Text = "Optimize"; this.optimizeTabPage.UseVisualStyleBackColor = true; // + // ShowRealtimeResultCheckBox + // + this.ShowRealtimeResultCheckBox.AutoSize = true; + this.ShowRealtimeResultCheckBox.Location = new System.Drawing.Point(141, 382); + this.ShowRealtimeResultCheckBox.Name = "ShowRealtimeResultCheckBox"; + this.ShowRealtimeResultCheckBox.Size = new System.Drawing.Size(22, 21); + this.ShowRealtimeResultCheckBox.TabIndex = 17; + this.toolTip1.SetToolTip(this.ShowRealtimeResultCheckBox, "Enable real-time display of BestValue during optimization.\r\nIf enabled, optimizat" + + "ion will slow down as the number of trials increases."); + this.ShowRealtimeResultCheckBox.UseVisualStyleBackColor = true; + // // EstimatedTimeRemainingLabel // this.EstimatedTimeRemainingLabel.AutoSize = true; - this.EstimatedTimeRemainingLabel.Location = new System.Drawing.Point(44, 411); + this.EstimatedTimeRemainingLabel.Location = new System.Drawing.Point(21, 411); this.EstimatedTimeRemainingLabel.Name = "EstimatedTimeRemainingLabel"; this.EstimatedTimeRemainingLabel.Size = new System.Drawing.Size(272, 23); this.EstimatedTimeRemainingLabel.TabIndex = 16; @@ -353,7 +366,7 @@ private void InitializeComponent() // optimizeBestValueLabel // this.optimizeBestValueLabel.AutoSize = true; - this.optimizeBestValueLabel.Location = new System.Drawing.Point(153, 380); + this.optimizeBestValueLabel.Location = new System.Drawing.Point(169, 380); this.optimizeBestValueLabel.Name = "optimizeBestValueLabel"; this.optimizeBestValueLabel.Size = new System.Drawing.Size(129, 23); this.optimizeBestValueLabel.TabIndex = 15; @@ -362,7 +375,7 @@ private void InitializeComponent() // optimizeTrialNumLabel // this.optimizeTrialNumLabel.AutoSize = true; - this.optimizeTrialNumLabel.Location = new System.Drawing.Point(44, 380); + this.optimizeTrialNumLabel.Location = new System.Drawing.Point(21, 380); this.optimizeTrialNumLabel.Name = "optimizeTrialNumLabel"; this.optimizeTrialNumLabel.Size = new System.Drawing.Size(80, 23); this.optimizeTrialNumLabel.TabIndex = 14; @@ -1890,6 +1903,7 @@ private void InitializeComponent() private System.Windows.Forms.Label EstimatedTimeRemainingLabel; private System.Windows.Forms.CheckBox inMemoryCheckBox; private System.Windows.Forms.CheckBox checkPythonLibrariesCheckBox; + private System.Windows.Forms.CheckBox ShowRealtimeResultCheckBox; } } diff --git a/Tunny/UI/OptimizationWindow.cs b/Tunny/UI/OptimizationWindow.cs index b70a9948..f11c4ebf 100644 --- a/Tunny/UI/OptimizationWindow.cs +++ b/Tunny/UI/OptimizationWindow.cs @@ -34,7 +34,7 @@ public OptimizationWindow(FishingComponent component) FormClosingXButton(this, null); } LoadSettingJson(); - InitializeUIValues(); + SetUIValues(); RunPythonInstaller(); SetOptimizeBackgroundWorker(); SetOutputResultBackgroundWorker(); @@ -99,26 +99,6 @@ private void LoadSettingJson() } } - private void InitializeUIValues() - { - samplerComboBox.SelectedIndex = _settings.Optimize.SelectSampler; - nTrialNumUpDown.Value = _settings.Optimize.NumberOfTrials; - timeoutNumUpDown.Value = (decimal)_settings.Optimize.Timeout; - - // Study Name GroupBox - studyNameTextBox.Text = _settings.StudyName; - continueStudyCheckBox.Checked = _settings.Optimize.ContinueStudy; - existingStudyComboBox.Enabled = continueStudyCheckBox.Checked; - studyNameTextBox.Enabled = !continueStudyCheckBox.Checked; - copyStudyCheckBox.Enabled = _settings.Optimize.CopyStudy; - UpdateStudyComboBox(); - - outputModelNumTextBox.Text = _settings.Result.OutputNumberString; - visualizeTypeComboBox.SelectedIndex = _settings.Result.SelectVisualizeType; - visualizeClusterNumUpDown.Value = _settings.Result.NumberOfClusters; - InitializeSamplerSettings(); - } - private void UpdateGrasshopper(IList parameters) { GrasshopperStatus = GrasshopperStates.RequestProcessing; @@ -148,6 +128,26 @@ private void FormClosingXButton(object sender, FormClosingEventArgs e) outputResultBackgroundWorker?.Dispose(); } + private void SetUIValues() + { + samplerComboBox.SelectedIndex = _settings.Optimize.SelectSampler; + nTrialNumUpDown.Value = _settings.Optimize.NumberOfTrials; + timeoutNumUpDown.Value = (decimal)_settings.Optimize.Timeout; + + // Study Name GroupBox + studyNameTextBox.Text = _settings.StudyName; + continueStudyCheckBox.Checked = _settings.Optimize.ContinueStudy; + existingStudyComboBox.Enabled = continueStudyCheckBox.Checked; + studyNameTextBox.Enabled = !continueStudyCheckBox.Checked; + copyStudyCheckBox.Enabled = _settings.Optimize.CopyStudy; + UpdateStudyComboBox(); + ShowRealtimeResultCheckBox.Checked = _settings.Optimize.ShowRealtimeResult; + + outputModelNumTextBox.Text = _settings.Result.OutputNumberString; + visualizeTypeComboBox.SelectedIndex = _settings.Result.SelectVisualizeType; + visualizeClusterNumUpDown.Value = _settings.Result.NumberOfClusters; + InitializeSamplerSettings(); + } private void GetUIValues() { _settings.Optimize.SelectSampler = samplerComboBox.SelectedIndex; @@ -155,6 +155,7 @@ private void GetUIValues() _settings.Optimize.Timeout = (double)timeoutNumUpDown.Value; _settings.Optimize.ContinueStudy = continueStudyCheckBox.Checked; _settings.Optimize.CopyStudy = copyStudyCheckBox.Checked; + _settings.Optimize.ShowRealtimeResult = ShowRealtimeResultCheckBox.Checked; _settings.Storage.Type = inMemoryCheckBox.Checked ? StorageType.InMemory : _settings.Storage.Type; _settings.StudyName = studyNameTextBox.Text; _settings.Result.OutputNumberString = outputModelNumTextBox.Text; diff --git a/Tunny/UI/OptimizationWindow.resx b/Tunny/UI/OptimizationWindow.resx index a9924921..bc95beb2 100644 --- a/Tunny/UI/OptimizationWindow.resx +++ b/Tunny/UI/OptimizationWindow.resx @@ -123,9 +123,6 @@ 633, 17 - - 633, 17 - If this is True, the covariance matrix is constrained to be diagonal. diff --git a/Tunny/UI/OptimizeWindowTab/OptimizeTab.cs b/Tunny/UI/OptimizeWindowTab/OptimizeTab.cs index 1218bc3f..bf9831b1 100644 --- a/Tunny/UI/OptimizeWindowTab/OptimizeTab.cs +++ b/Tunny/UI/OptimizeWindowTab/OptimizeTab.cs @@ -66,6 +66,7 @@ private void OptimizeRunButton_Click(object sender, EventArgs e) optimizeRunButton.Enabled = false; GetUIValues(); + ShowRealtimeResultCheckBox.Enabled = false; OptimizeLoop.Settings = _settings; if (!CheckInputValue(ghCanvas)) @@ -133,50 +134,13 @@ private bool CheckObjectivesCount(GH_DocumentEditor ghCanvas) return true; } - private bool CmaEsSupportOneObjectiveMessage(GH_DocumentEditor ghCanvas) - { - TunnyMessageBox.Show( - "CMA-ES samplers only support single objective optimization.", - "Tunny", - MessageBoxButtons.OK, - MessageBoxIcon.Error - ); - ghCanvas.EnableUI(); - optimizeRunButton.Enabled = true; - return false; - } - - private bool SameStudyNameMassage(GH_DocumentEditor ghCanvas) - { - TunnyMessageBox.Show( - "Please choose any study name.", - "Tunny", - MessageBoxButtons.OK, - MessageBoxIcon.Error - ); - ghCanvas.EnableUI(); - optimizeRunButton.Enabled = true; - return false; - } - - private bool NameAlreadyExistMessage(GH_DocumentEditor ghCanvas) - { - TunnyMessageBox.Show( - "New study name already exists. Please choose another name. Or check 'Continue' checkbox.", - "Tunny", - MessageBoxButtons.OK, - MessageBoxIcon.Error - ); - ghCanvas.EnableUI(); - optimizeRunButton.Enabled = true; - return false; - } private void OptimizeStopButton_Click(object sender, EventArgs e) { optimizeRunButton.Enabled = true; optimizeStopButton.Enabled = false; OptimizeLoop.IsForcedStopOptimize = true; + ShowRealtimeResultCheckBox.Enabled = true; optimizeBackgroundWorker?.Dispose(); UpdateStudyComboBox(); @@ -257,8 +221,22 @@ private void OptimizeProgressChangedHandler(object sender, ProgressChangedEventA optimizeTrialNumLabel.Text = e.ProgressPercentage == 100 ? trialNumLabel + "#" : trialNumLabel + (pState.TrialNumber + 1); + SetBestValues(e, pState); - if (e.ProgressPercentage == 0 || e.ProgressPercentage == 100) + EstimatedTimeRemainingLabel.Text = pState.EstimatedTimeRemaining.TotalSeconds != 0 + ? $"Estimated Time Remaining: " + new DateTime(0).Add(pState.EstimatedTimeRemaining).ToString("HH:mm:ss", CultureInfo.InvariantCulture) + : $"Estimated Time Remaining: 00:00:00"; + optimizeProgressBar.Value = e.ProgressPercentage; + optimizeProgressBar.Update(); + } + + private void SetBestValues(ProgressChangedEventArgs e, ProgressState pState) + { + if (pState.BestValues == null) + { + optimizeBestValueLabel.Text = "BestValue: #"; + } + else if (e.ProgressPercentage == 0 || e.ProgressPercentage == 100) { optimizeBestValueLabel.Text = pState.ObjectiveNum == 1 ? "BestValue: #" @@ -267,15 +245,9 @@ private void OptimizeProgressChangedHandler(object sender, ProgressChangedEventA else if (pState.BestValues.Length > 0) { optimizeBestValueLabel.Text = pState.ObjectiveNum == 1 - ? "BestValue: " + pState.BestValues[0][0] + ? $"BestValue: {pState.BestValues[0][0]:e4}" : $"Hypervolume Ratio: {pState.HypervolumeRatio:0.000}"; } - - EstimatedTimeRemainingLabel.Text = pState.EstimatedTimeRemaining.TotalSeconds != 0 - ? $"Estimated Time Remaining: " + new DateTime(0).Add(pState.EstimatedTimeRemaining).ToString("HH:mm:ss", CultureInfo.InvariantCulture) - : $"Estimated Time Remaining: 00:00:00"; - optimizeProgressBar.Value = e.ProgressPercentage; - optimizeProgressBar.Update(); } } } diff --git a/Tunny/UI/OptimizeWindowTab/OutputTab.cs b/Tunny/UI/OptimizeWindowTab/OutputTab.cs index 960fe058..b7c482c0 100644 --- a/Tunny/UI/OptimizeWindowTab/OutputTab.cs +++ b/Tunny/UI/OptimizeWindowTab/OutputTab.cs @@ -87,8 +87,7 @@ private bool ParseModelNumberInput(ref List indices) } catch (Exception) { - TunnyMessageBox.Show("The model number format of the input is incorrect. \nPlease use a comma separator as follows.\n\"1,2,3\"", "Tunny"); - result = false; + result = IncorrectParseModeNumberInputMessage(); } return result; } @@ -97,10 +96,7 @@ private static void CheckIndicesLength(int[] indices) { if (indices.Length > 1) { - TunnyMessageBox.Show( - "You input multi model numbers, but this function only reflect variables to slider or gene pool to first one.", - "Tunny" - ); + UseFirstModelNumberToReflectMessage(); } } diff --git a/Tunny/UI/OptimizeWindowTab/UITunnyMessages.cs b/Tunny/UI/OptimizeWindowTab/UITunnyMessages.cs new file mode 100644 index 00000000..30049d98 --- /dev/null +++ b/Tunny/UI/OptimizeWindowTab/UITunnyMessages.cs @@ -0,0 +1,122 @@ +using System.Windows.Forms; + +using Grasshopper.GUI; + +namespace Tunny.UI +{ + public partial class OptimizationWindow : Form + { + // OptimizationTab ========================== + private bool CmaEsSupportOneObjectiveMessage(GH_DocumentEditor ghCanvas) + { + TunnyMessageBox.Show( + "CMA-ES samplers only support single objective optimization.", + "Tunny", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + ghCanvas.EnableUI(); + optimizeRunButton.Enabled = true; + return false; + } + + private bool SameStudyNameMassage(GH_DocumentEditor ghCanvas) + { + TunnyMessageBox.Show( + "Please choose any study name.", + "Tunny", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + ghCanvas.EnableUI(); + optimizeRunButton.Enabled = true; + return false; + } + + private bool NameAlreadyExistMessage(GH_DocumentEditor ghCanvas) + { + TunnyMessageBox.Show( + "New study name already exists. Please choose another name. Or check 'Continue' checkbox.", + "Tunny", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + ghCanvas.EnableUI(); + optimizeRunButton.Enabled = true; + return false; + } + + // OutputTab ========================== + private static bool IncorrectParseModeNumberInputMessage() + { + TunnyMessageBox.Show( + "The model number format of the input is incorrect. \nPlease use a comma separator as follows.\n\"1,2,3\"", + "Tunny"); + return false; + } + + private static void UseFirstModelNumberToReflectMessage() + { + TunnyMessageBox.Show( + "You input multi model numbers, but this function only reflect variables to slider or gene pool to first one.", + "Tunny" + ); + } + + // VisualizeTab ========================== + private static void ResultFileNotExistErrorMessage() + { + TunnyMessageBox.Show( + "Please set exist result file path.", + "Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + } + + private static bool HandleOnly1ObjectiveMessage() + { + TunnyMessageBox.Show( + "This plot can only handle one objective function.", + "Tunny" + ); + return false; + } + + private static bool HandleOnly2ObjectivesMessage() + { + TunnyMessageBox.Show( + "This plot can only handle 2 objective functions.", + "Tunny" + ); + return false; + } + + private static bool HandleOnly2or3ObjectiveMessage() + { + TunnyMessageBox.Show( + "This plot can only handle 2 or 3 objective function.", + "Tunny" + ); + return false; + } + + private static bool RequireLeast1VariableMessage() + { + TunnyMessageBox.Show( + "This plot requires at least one variable.", + "Tunny" + ); + return false; + } + + private static bool RequireLeast2VariableMessage() + { + TunnyMessageBox.Show( + "This plot requires at least two variables.", + "Tunny" + ); + return false; + } + } +} diff --git a/Tunny/UI/OptimizeWindowTab/VisualizeTab.cs b/Tunny/UI/OptimizeWindowTab/VisualizeTab.cs index 90c26aeb..12f78917 100644 --- a/Tunny/UI/OptimizeWindowTab/VisualizeTab.cs +++ b/Tunny/UI/OptimizeWindowTab/VisualizeTab.cs @@ -17,7 +17,7 @@ private void DashboardButton_Click(object sender, EventArgs e) { if (File.Exists(_settings.Storage.Path) == false) { - TunnyMessageBox.Show("Please set exist result file path.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + ResultFileNotExistErrorMessage(); return; } @@ -129,7 +129,6 @@ private static bool CheckTargetValues(PlotSettings pSettings) switch (pSettings.PlotTypeName) { case "contour": - return CheckContourTargets(pSettings); case "parallel coordinate": case "slice": return CheckOneObjSomeVarTargets(pSettings); @@ -148,12 +147,7 @@ private static bool CheckOneObjectives(PlotSettings pSettings) bool result = true; if (pSettings.TargetObjectiveName.Length > 1) { - TunnyMessageBox.Show("This plot can only handle one objective function.", "Tunny"); - result = false; - } - else if (pSettings.TargetVariableName.Length == 0) - { - + result = HandleOnly1ObjectiveMessage(); } return result; @@ -164,8 +158,7 @@ private static bool CheckHypervolumeTargets(PlotSettings pSettings) bool result = true; if (pSettings.TargetObjectiveName.Length != 2) { - TunnyMessageBox.Show("This plot can only handle 2 objective function.", "Tunny"); - result = false; + result = HandleOnly2ObjectivesMessage(); } return result; } @@ -175,8 +168,7 @@ private static bool CheckParetoFrontTargets(PlotSettings pSettings) bool result = true; if (pSettings.TargetObjectiveName.Length > 3 || pSettings.TargetObjectiveName.Length < 2) { - TunnyMessageBox.Show("This plot can only handle 2 or 3 objective function.", "Tunny"); - result = false; + result = HandleOnly2or3ObjectiveMessage(); } return result; @@ -187,30 +179,15 @@ private static bool CheckOneObjSomeVarTargets(PlotSettings pSettings) bool result = true; if (pSettings.TargetObjectiveName.Length > 1) { - TunnyMessageBox.Show("This plot can only handle one objective function.", "Tunny"); - result = false; + result = HandleOnly1ObjectiveMessage(); } - else if (pSettings.TargetVariableName.Length == 0) + else if (pSettings.PlotTypeName == "contour" && pSettings.TargetVariableName.Length < 2) { - TunnyMessageBox.Show("This plot requires at least one variables.", "Tunny"); - result = false; + result = RequireLeast2VariableMessage(); } - - return result; - } - - private static bool CheckContourTargets(PlotSettings pSettings) - { - bool result = true; - if (pSettings.TargetObjectiveName.Length > 1) - { - TunnyMessageBox.Show("This plot can only handle one objective function.", "Tunny"); - result = false; - } - else if (pSettings.TargetVariableName.Length < 2) + else if (pSettings.TargetVariableName.Length == 0) { - TunnyMessageBox.Show("Contour requires at least two variables.", "Tunny"); - result = false; + result = RequireLeast1VariableMessage(); } return result;