source: trunk/sources/HeuristicLab.ES/ESEditor.cs @ 1112

Last change on this file since 1112 was 1112, checked in by abeham, 11 years ago

Updated ES to automatically calculate LearningRate parameters based on the problem dimension (ticket #84)

File size: 12.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.ComponentModel;
25using System.Drawing;
26using System.Data;
27using System.Text;
28using System.Windows.Forms;
29using HeuristicLab.PluginInfrastructure;
30using HeuristicLab.Core;
31
32namespace HeuristicLab.ES {
33  /// <summary>
34  /// Class for visual representation of an <see cref="ES"/>.
35  /// </summary>
36  public partial class ESEditor : EditorBase {
37    private ChooseOperatorDialog chooseOperatorDialog;
38
39    /// <summary>
40    /// Gets or sets the evolution strategy to display.
41    /// </summary>
42    /// <remarks>Uses property <see cref="ViewBase.Item"/> of base class <see cref="EditorBase"/>.
43    /// No own data storage present.</remarks>
44    public ES ES {
45      get { return (ES)Item; }
46      set { base.Item = value; }
47    }
48
49    /// <summary>
50    /// Initializes a new instance of <see cref="ESEditor"/>.
51    /// </summary>
52    public ESEditor() {
53      InitializeComponent();
54      problemDimensionTextBox.Text = "1";
55    }
56    /// <summary>
57    /// Initializes a new instance of <see cref="ESEditor"/> with the given <paramref name="es"/>.
58    /// </summary>
59    /// <param name="es">The evolution strategy to display.</param>
60    public ESEditor(ES es)
61      : this() {
62      ES = es;
63      int dimension = es.ShakingFactors.Length;
64      problemDimensionTextBox.Text = dimension.ToString();
65    }
66
67    /// <summary>
68    /// Removes all event handlers from the underlying <see cref="ES"/>.
69    /// </summary>
70    /// <remarks>Calls <see cref="ViewBase.RemoveItemEvents"/> of base class <see cref="EditorBase"/>.</remarks>
71    protected override void RemoveItemEvents() {
72      ES.Engine.ExceptionOccurred -= new EventHandler<ExceptionEventArgs>(Engine_ExceptionOccurred);
73      ES.Engine.Finished -= new EventHandler(Engine_Finished);
74      ES.Changed -= new EventHandler(ES_Changed);
75      scopeView.Scope = null;
76      base.RemoveItemEvents();
77    }
78    /// <summary>
79    /// Adds event handlers to the underlying <see cref="ES"/>.
80    /// </summary>
81    /// <remarks>Calls <see cref="ViewBase.AddItemEvents"/> of base class <see cref="EditorBase"/>.</remarks>
82    protected override void AddItemEvents() {
83      base.AddItemEvents();
84      ES.Engine.ExceptionOccurred += new EventHandler<ExceptionEventArgs>(Engine_ExceptionOccurred);
85      ES.Engine.Finished += new EventHandler(Engine_Finished);
86      ES.Changed += new EventHandler(ES_Changed);
87      SetDataBinding();
88      scopeView.Scope = ES.Engine.GlobalScope;
89    }
90
91    void ES_Changed(object sender, EventArgs e) {
92      // neither Refresh() nor Update() work
93      randomSeedTextBox.Text = ES.Seed.ToString();
94      muTextBox.Text = ES.Mu.ToString();
95      rhoTextBox.Text = ES.Rho.ToString();
96      lambdaTextBox.Text = ES.Lambda.ToString();
97      learningRateTextBox.Text = ES.LearningRate.ToString();
98      generalLearningRateTextBox.Text = ES.GeneralLearningRate.ToString();
99    }
100
101    /// <summary>
102    /// Updates all controls with the latest data of the model.
103    /// </summary>
104    /// <remarks>Calls <see cref="ViewBase.UpdateControls"/> of base class <see cref="EditorBase"/>.</remarks>
105    protected override void UpdateControls() {
106      base.UpdateControls();
107      if (ES == null) {
108        tabControl.Enabled = false;
109      } else {
110        tabControl.Enabled = true;
111        problemInitializationTextBox.Text = ES.ProblemInjector.GetType().Name;
112        solutionGenerationTextBox.Text = ES.SolutionGenerator.GetType().Name;
113        mutationTextBox.Text = ES.Mutator.GetType().Name;
114        evaluationTextBox.Text = ES.Evaluator.GetType().Name;
115        recombinationTextBox.Text = ES.Recombinator.GetType().Name;
116        initialMutationStrengthVectorTextBox.Text = ArrayToString<double>(ES.ShakingFactors);
117      }
118    }
119
120    private void SetDataBinding() {
121      setRandomSeedRandomlyCheckBox.DataBindings.Add("Checked", ES, "SetSeedRandomly");
122      randomSeedTextBox.DataBindings.Add("Text", ES, "Seed");
123      muTextBox.DataBindings.Add("Text", ES, "Mu");
124      rhoTextBox.DataBindings.Add("Text", ES, "Rho");
125      lambdaTextBox.DataBindings.Add("Text", ES, "Lambda");
126      maximumGenerationsTextBox.DataBindings.Add("Text", ES, "MaximumGenerations");
127      generalLearningRateTextBox.DataBindings.Add("Text", ES, "GeneralLearningRate");
128      learningRateTextBox.DataBindings.Add("Text", ES, "LearningRate");
129    }
130
131    #region Button Events
132    private void viewProblemInitializationButton_Click(object sender, EventArgs e) {
133      IView view = ES.ProblemInjector.CreateView();
134      if (view != null)
135        PluginManager.ControlManager.ShowControl(view);
136    }
137    private void viewSolutionGenerationButton_Click(object sender, EventArgs e) {
138      IView view = ES.SolutionGenerator.CreateView();
139      if (view != null)
140        PluginManager.ControlManager.ShowControl(view);
141    }
142    private void viewMutationButton_Click(object sender, EventArgs e) {
143      IView view = ES.Mutator.CreateView();
144      if (view != null)
145        PluginManager.ControlManager.ShowControl(view);
146    }
147    private void viewEvaluationButton_Click(object sender, EventArgs e) {
148      IView view = ES.Evaluator.CreateView();
149      if (view != null)
150        PluginManager.ControlManager.ShowControl(view);
151    }
152    private void viewRecombinationButton_Click(object sender, EventArgs e) {
153      IView view = ES.Recombinator.CreateView();
154      if (view != null)
155        PluginManager.ControlManager.ShowControl(view);
156    }
157    private void setProblemInitializationButton_Click(object sender, EventArgs e) {
158      if (chooseOperatorDialog == null) chooseOperatorDialog = new ChooseOperatorDialog();
159      if (chooseOperatorDialog.ShowDialog(this) == DialogResult.OK) {
160        ES.ProblemInjector = chooseOperatorDialog.Operator;
161        problemInitializationTextBox.Text = ES.ProblemInjector.GetType().Name;
162      }
163    }
164    private void setSolutionGenerationButton_Click(object sender, EventArgs e) {
165      if (chooseOperatorDialog == null) chooseOperatorDialog = new ChooseOperatorDialog();
166      if (chooseOperatorDialog.ShowDialog(this) == DialogResult.OK) {
167        ES.SolutionGenerator= chooseOperatorDialog.Operator;
168        solutionGenerationTextBox.Text = ES.SolutionGenerator.GetType().Name;
169      }
170    }
171    private void setMutationButton_Click(object sender, EventArgs e) {
172      if (chooseOperatorDialog == null) chooseOperatorDialog = new ChooseOperatorDialog();
173      if (chooseOperatorDialog.ShowDialog(this) == DialogResult.OK) {
174        ES.Mutator = chooseOperatorDialog.Operator;
175        mutationTextBox.Text = ES.Mutator.GetType().Name;
176      }
177    }
178    private void setEvaluationButton_Click(object sender, EventArgs e) {
179      if (chooseOperatorDialog == null) chooseOperatorDialog = new ChooseOperatorDialog();
180      if (chooseOperatorDialog.ShowDialog(this) == DialogResult.OK) {
181        ES.Evaluator = chooseOperatorDialog.Operator;
182        evaluationTextBox.Text = ES.Evaluator.GetType().Name;
183      }
184    }
185    private void setRecombinationButton_Click(object sender, EventArgs e) {
186      if (chooseOperatorDialog == null) chooseOperatorDialog = new ChooseOperatorDialog();
187      if (chooseOperatorDialog.ShowDialog(this) == DialogResult.OK) {
188        ES.Recombinator = chooseOperatorDialog.Operator;
189        recombinationTextBox.Text = ES.Recombinator.GetType().Name;
190      }
191    }
192    private void executeButton_Click(object sender, EventArgs e) {
193      executeButton.Enabled = false;
194      abortButton.Enabled = true;
195      ES.Engine.Execute();
196    }
197    private void abortButton_Click(object sender, EventArgs e) {
198      ES.Engine.Abort();
199    }
200    private void resetButton_Click(object sender, EventArgs e) {
201      ES.Engine.Reset();
202    }
203    private void cloneEngineButton_Click(object sender, EventArgs e) {
204      IEngine clone = (IEngine)ES.Engine.Clone();
205      IEditor editor = ((IEditable)clone).CreateEditor();
206      PluginManager.ControlManager.ShowControl(editor);
207    }
208    #endregion
209
210    #region Engine Events
211    private delegate void OnExceptionEventDelegate(object sender, ExceptionEventArgs e);
212    private void Engine_ExceptionOccurred(object sender, ExceptionEventArgs e) {
213      if (InvokeRequired)
214        Invoke(new OnExceptionEventDelegate(Engine_ExceptionOccurred), sender, e);
215      else
216        Auxiliary.ShowErrorMessageBox(e.Exception);
217    }
218    private void Engine_Finished(object sender, EventArgs e) {
219      scopeView.Refresh();
220      if (executeButton.InvokeRequired) {
221        executeButton.Invoke(new MethodInvoker(EnableExecute));
222      } else {
223        executeButton.Enabled = true;
224        abortButton.Enabled = false;
225      }
226    }
227    private void EnableExecute() {
228      executeButton.Enabled = true;
229      abortButton.Enabled = false;
230    }
231    #endregion
232
233    #region RadioButton Events
234    private void plusRadioButton_CheckedChanged(object sender, EventArgs e) {
235      if (plusRadioButton.Checked) ES.PlusNotation = true;
236    }
237
238    private void commaRadioButton_CheckedChanged(object sender, EventArgs e) {
239      if (commaRadioButton.Checked) ES.PlusNotation = false;
240    }
241    #endregion
242
243    private string ArrayToString<T>(T[] array) {
244      StringBuilder s = new StringBuilder();
245      foreach (T element in array)
246        s.Append(element + "; ");
247      s.Remove(s.Length - 2, 2);
248      return s.ToString();
249    }
250
251    private double[] StringToDoubleArray(string str) {
252     
253      string[] s = str.Split(new char[] { ';' });
254      double[] tmp = new double[s.Length];
255      try {
256        for (int i = 0; i < s.Length; i++) {
257          tmp[i] = double.Parse(s[i]);
258        }
259      } catch (FormatException) {       
260        return null;
261      }
262      return tmp;
263    }
264
265    private void initialMutationStrengthVectorTextBox_Validated(object sender, EventArgs e) {
266      double[] tmp = StringToDoubleArray(initialMutationStrengthVectorTextBox.Text);
267      if (tmp != null) ES.ShakingFactors = tmp;
268      else MessageBox.Show("Please use colons \";\" (without the quotes) to delimite the items like this: " + (1.2).ToString() + ";" + (1.1).ToString() + ";" + (3.453).ToString());
269      int dim = int.Parse(problemDimensionTextBox.Text);
270      if (ES.ShakingFactors.Length != dim) {
271        problemDimensionTextBox.Text = ES.ShakingFactors.Length.ToString();
272        UpdateLearningRates();
273      }
274      Refresh();
275    }
276
277    private void problemDimensionTextBox_Validated(object sender, EventArgs e) {
278      double[] tmp = StringToDoubleArray(initialMutationStrengthVectorTextBox.Text);
279      if (tmp != null) {
280        int dim = 0;
281        try {
282          dim = int.Parse(problemDimensionTextBox.Text);
283          if (dim < 1) throw new FormatException();
284        } catch (FormatException) {
285          MessageBox.Show("Problem Dimension must contain an integer > 0");
286        }
287        double[] shakingFactors = new double[dim];
288        for (int i = 0; i < dim; i++) {
289          shakingFactors[i] = tmp[i % tmp.Length];
290        }
291        ES.ShakingFactors = shakingFactors;
292        UpdateLearningRates();
293        Refresh();
294      }
295    }
296
297    private void UpdateLearningRates() {
298      if (ES != null) {
299        int dimension = int.Parse(problemDimensionTextBox.Text);
300        ES.GeneralLearningRate = 1 / Math.Sqrt(2 * dimension);
301        ES.LearningRate = 1 / Math.Sqrt(2 * Math.Sqrt(dimension));
302      }
303    }
304  }
305}
Note: See TracBrowser for help on using the repository browser.