source: trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs @ 12504

Last change on this file since 12504 was 12504, checked in by mkommend, 4 years ago

#2025: Changed categories for all creatables.

File size: 18.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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.Drawing;
25using HeuristicLab.Collections;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Data;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30
31namespace HeuristicLab.Optimization {
32  internal enum BatchRunAction { None, Prepare, Start, Pause, Stop };
33
34  /// <summary>
35  /// A run in which an optimizer is executed a given number of times.
36  /// </summary>
37  [Item("Batch Run", "A run in which an optimizer is executed a given number of times.")]
38  [Creatable(CreatableAttribute.Categories.TestingAndAnalysis, Priority = 110)]
39  [StorableClass]
40  public sealed class BatchRun : NamedItem, IOptimizer, IStorableContent {
41    public string Filename { get; set; }
42
43    public static new Image StaticItemImage {
44      get { return HeuristicLab.Common.Resources.VSImageLibrary.Event; }
45    }
46    public override Image ItemImage {
47      get {
48        if (ExecutionState == ExecutionState.Prepared) return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunPrepared;
49        else if (ExecutionState == ExecutionState.Started) return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunStarted;
50        else if (ExecutionState == ExecutionState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunPaused;
51        else if (ExecutionState == ExecutionState.Stopped) return HeuristicLab.Common.Resources.VSImageLibrary.BatchRunStopped;
52        else return base.ItemImage;
53      }
54    }
55
56    [Storable]
57    private ExecutionState executionState;
58    public ExecutionState ExecutionState {
59      get { return executionState; }
60      private set {
61        if (executionState != value) {
62          executionState = value;
63          OnExecutionStateChanged();
64          OnItemImageChanged();
65        }
66      }
67    }
68
69    [Storable]
70    private TimeSpan executionTime;
71    public TimeSpan ExecutionTime {
72      get {
73        if ((Optimizer != null) && (Optimizer.ExecutionState != ExecutionState.Stopped))
74          return executionTime + Optimizer.ExecutionTime;
75        else
76          return executionTime;
77      }
78      private set {
79        executionTime = value;
80        OnExecutionTimeChanged();
81      }
82    }
83
84    [Storable]
85    private TimeSpan runsExecutionTime;
86
87    [Storable]
88    private IOptimizer optimizer;
89    public IOptimizer Optimizer {
90      get { return optimizer; }
91      set {
92        if (optimizer != value) {
93          if (optimizer != null) {
94            DeregisterOptimizerEvents();
95            IEnumerable<IRun> runs = optimizer.Runs;
96            optimizer = null; //necessary to avoid removing the runs from the old optimizer
97            Runs.RemoveRange(runs);
98          }
99          optimizer = value;
100          if (optimizer != null) {
101            RegisterOptimizerEvents();
102            Runs.AddRange(optimizer.Runs);
103          }
104          OnOptimizerChanged();
105          Prepare();
106        }
107      }
108    }
109    // BackwardsCompatibility3.3
110    #region Backwards compatible code (remove with 3.4)
111    [Storable(AllowOneWay = true)]
112    private IAlgorithm algorithm {
113      set { optimizer = value; }
114    }
115    #endregion
116
117    [Storable]
118    private int repetitions;
119    public int Repetitions {
120      get { return repetitions; }
121      set {
122        if (repetitions != value) {
123          repetitions = value;
124          OnRepetitionsChanged();
125          if ((Optimizer != null) && (Optimizer.ExecutionState == ExecutionState.Stopped))
126            Prepare();
127        }
128      }
129    }
130    [Storable]
131    private int repetitionsCounter;
132    public int RepetitionsCounter {
133      get { return repetitionsCounter; }
134      private set {
135        if (value != repetitionsCounter) {
136          repetitionsCounter = value;
137          OnRepetitionsCounterChanged();
138        }
139      }
140    }
141
142    [Storable]
143    private RunCollection runs;
144    public RunCollection Runs {
145      get { return runs; }
146      private set {
147        if (value == null) throw new ArgumentNullException();
148        if (runs != value) {
149          if (runs != null) DeregisterRunsEvents();
150          runs = value;
151          if (runs != null) RegisterRunsEvents();
152        }
153      }
154    }
155
156    public IEnumerable<IOptimizer> NestedOptimizers {
157      get {
158        if (Optimizer == null) yield break;
159
160        yield return Optimizer;
161        foreach (IOptimizer opt in Optimizer.NestedOptimizers)
162          yield return opt;
163      }
164    }
165
166    private BatchRunAction batchRunAction = BatchRunAction.None;
167
168    public BatchRun()
169      : base() {
170      name = ItemName;
171      description = ItemDescription;
172      executionState = ExecutionState.Stopped;
173      executionTime = TimeSpan.Zero;
174      runsExecutionTime = TimeSpan.Zero;
175      repetitions = 10;
176      repetitionsCounter = 0;
177      Runs = new RunCollection { OptimizerName = Name };
178    }
179    public BatchRun(string name)
180      : base(name) {
181      description = ItemDescription;
182      executionState = ExecutionState.Stopped;
183      executionTime = TimeSpan.Zero;
184      runsExecutionTime = TimeSpan.Zero;
185      repetitions = 10;
186      repetitionsCounter = 0;
187      Runs = new RunCollection { OptimizerName = Name };
188    }
189    public BatchRun(string name, string description)
190      : base(name, description) {
191      executionState = ExecutionState.Stopped;
192      executionTime = TimeSpan.Zero;
193      runsExecutionTime = TimeSpan.Zero;
194      repetitions = 10;
195      repetitionsCounter = 0;
196      Runs = new RunCollection { OptimizerName = Name };
197    }
198    [StorableConstructor]
199    private BatchRun(bool deserializing) : base(deserializing) { }
200    [StorableHook(HookType.AfterDeserialization)]
201    private void AfterDeserialization() {
202      Initialize();
203    }
204
205    private BatchRun(BatchRun original, Cloner cloner)
206      : base(original, cloner) {
207      executionState = original.executionState;
208      executionTime = original.executionTime;
209      runsExecutionTime = original.runsExecutionTime;
210      optimizer = cloner.Clone(original.optimizer);
211      repetitions = original.repetitions;
212      repetitionsCounter = original.repetitionsCounter;
213      runs = cloner.Clone(original.runs);
214      batchRunAction = original.batchRunAction;
215      Initialize();
216    }
217    public override IDeepCloneable Clone(Cloner cloner) {
218      if (ExecutionState == ExecutionState.Started) throw new InvalidOperationException(string.Format("Clone not allowed in execution state \"{0}\".", ExecutionState));
219      return new BatchRun(this, cloner);
220    }
221
222    private void Initialize() {
223      if (optimizer != null) RegisterOptimizerEvents();
224      if (runs != null) RegisterRunsEvents();
225    }
226
227    public void Prepare() {
228      Prepare(false);
229    }
230    public void Prepare(bool clearRuns) {
231      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused) && (ExecutionState != ExecutionState.Stopped))
232        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
233      if (Optimizer != null) {
234        ExecutionTime = TimeSpan.Zero;
235        RepetitionsCounter = 0;
236        if (clearRuns) runs.Clear();
237        batchRunAction = BatchRunAction.Prepare;
238        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
239        try { Optimizer.Prepare(clearRuns); }
240        catch (InvalidOperationException) { }
241      } else {
242        ExecutionState = ExecutionState.Stopped;
243      }
244    }
245    public void Start() {
246      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
247        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
248      if (Optimizer == null) return;
249      batchRunAction = BatchRunAction.Start;
250      if (Optimizer.ExecutionState == ExecutionState.Stopped) Optimizer.Prepare();
251      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
252      try { Optimizer.Start(); }
253      catch (InvalidOperationException) { }
254    }
255    public void Pause() {
256      if (ExecutionState != ExecutionState.Started)
257        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
258      if (Optimizer == null) return;
259      batchRunAction = BatchRunAction.Pause;
260      if (Optimizer.ExecutionState != ExecutionState.Started) return;
261      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
262      try { Optimizer.Pause(); }
263      catch (InvalidOperationException) { }
264    }
265    public void Stop() {
266      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
267        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
268      if (Optimizer == null) return;
269      batchRunAction = BatchRunAction.Stop;
270      if (Optimizer.ExecutionState != ExecutionState.Started && Optimizer.ExecutionState != ExecutionState.Paused) {
271        OnStopped();
272        return;
273      }
274      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
275      try { Optimizer.Stop(); }
276      catch (InvalidOperationException) { }
277    }
278
279    #region Events
280    protected override void OnNameChanged() {
281      base.OnNameChanged();
282      runs.OptimizerName = Name;
283    }
284
285    public event EventHandler ExecutionStateChanged;
286    private void OnExecutionStateChanged() {
287      EventHandler handler = ExecutionStateChanged;
288      if (handler != null) handler(this, EventArgs.Empty);
289    }
290    public event EventHandler ExecutionTimeChanged;
291    private void OnExecutionTimeChanged() {
292      EventHandler handler = ExecutionTimeChanged;
293      if (handler != null) handler(this, EventArgs.Empty);
294    }
295    public event EventHandler OptimizerChanged;
296    private void OnOptimizerChanged() {
297      EventHandler handler = OptimizerChanged;
298      if (handler != null) handler(this, EventArgs.Empty);
299    }
300    public event EventHandler RepetitionsChanged;
301    private void OnRepetitionsChanged() {
302      EventHandler handler = RepetitionsChanged;
303      if (handler != null) handler(this, EventArgs.Empty);
304    }
305    public event EventHandler RepetetionsCounterChanged;
306    private void OnRepetitionsCounterChanged() {
307      EventHandler handler = RepetetionsCounterChanged;
308      if (handler != null) handler(this, EventArgs.Empty);
309    }
310    public event EventHandler Prepared;
311    private void OnPrepared() {
312      batchRunAction = BatchRunAction.None;
313      ExecutionState = ExecutionState.Prepared;
314      EventHandler handler = Prepared;
315      if (handler != null) handler(this, EventArgs.Empty);
316    }
317    public event EventHandler Started;
318    private void OnStarted() {
319      // no reset of BatchRunAction.Started, because we need to differ which of the two was started by the user
320      ExecutionState = ExecutionState.Started;
321      EventHandler handler = Started;
322      if (handler != null) handler(this, EventArgs.Empty);
323    }
324    public event EventHandler Paused;
325    private void OnPaused() {
326      batchRunAction = BatchRunAction.None;
327      ExecutionState = ExecutionState.Paused;
328      EventHandler handler = Paused;
329      if (handler != null) handler(this, EventArgs.Empty);
330    }
331    public event EventHandler Stopped;
332    private void OnStopped() {
333      batchRunAction = BatchRunAction.None;
334      ExecutionState = ExecutionState.Stopped;
335      EventHandler handler = Stopped;
336      if (handler != null) handler(this, EventArgs.Empty);
337    }
338    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
339    private void OnExceptionOccurred(Exception exception) {
340      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
341      if (handler != null) handler(this, new EventArgs<Exception>(exception));
342    }
343
344    private void RegisterOptimizerEvents() {
345      optimizer.ExceptionOccurred += new EventHandler<EventArgs<Exception>>(Optimizer_ExceptionOccurred);
346      optimizer.ExecutionTimeChanged += new EventHandler(Optimizer_ExecutionTimeChanged);
347      optimizer.Paused += new EventHandler(Optimizer_Paused);
348      optimizer.Prepared += new EventHandler(Optimizer_Prepared);
349      optimizer.Started += new EventHandler(Optimizer_Started);
350      optimizer.Stopped += new EventHandler(Optimizer_Stopped);
351      optimizer.Runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_CollectionReset);
352      optimizer.Runs.ItemsAdded += new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_ItemsAdded);
353      optimizer.Runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_ItemsRemoved);
354    }
355    private void DeregisterOptimizerEvents() {
356      optimizer.ExceptionOccurred -= new EventHandler<EventArgs<Exception>>(Optimizer_ExceptionOccurred);
357      optimizer.ExecutionTimeChanged -= new EventHandler(Optimizer_ExecutionTimeChanged);
358      optimizer.Paused -= new EventHandler(Optimizer_Paused);
359      optimizer.Prepared -= new EventHandler(Optimizer_Prepared);
360      optimizer.Started -= new EventHandler(Optimizer_Started);
361      optimizer.Stopped -= new EventHandler(Optimizer_Stopped);
362      optimizer.Runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_CollectionReset);
363      optimizer.Runs.ItemsAdded -= new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_ItemsAdded);
364      optimizer.Runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_ItemsRemoved);
365    }
366    private void Optimizer_ExceptionOccurred(object sender, EventArgs<Exception> e) {
367      OnExceptionOccurred(e.Value);
368    }
369    private void Optimizer_ExecutionTimeChanged(object sender, EventArgs e) {
370      OnExecutionTimeChanged();
371    }
372    private void Optimizer_Paused(object sender, EventArgs e) {
373      if (ExecutionState == ExecutionState.Started) {
374        OnPaused();
375      }
376    }
377    private void Optimizer_Prepared(object sender, EventArgs e) {
378      if (batchRunAction == BatchRunAction.Prepare || ExecutionState == ExecutionState.Stopped) {
379        ExecutionTime = TimeSpan.Zero;
380        runsExecutionTime = TimeSpan.Zero;
381        RepetitionsCounter = 0;
382        OnPrepared();
383      }
384    }
385    private void Optimizer_Started(object sender, EventArgs e) {
386      if (ExecutionState != ExecutionState.Started)
387        OnStarted();
388    }
389    private void Optimizer_Stopped(object sender, EventArgs e) {
390      RepetitionsCounter++;
391      ExecutionTime += runsExecutionTime;
392      runsExecutionTime = TimeSpan.Zero;
393
394      if (batchRunAction == BatchRunAction.Stop) OnStopped();
395      else if (repetitionsCounter >= repetitions) OnStopped();
396      else if (batchRunAction == BatchRunAction.Pause) OnPaused();
397      else if (batchRunAction == BatchRunAction.Start) {
398        Optimizer.Prepare();
399        Optimizer.Start();
400      } else if (executionState == ExecutionState.Started) {
401        // if the batch run hasn't been started but the inner optimizer was run then pause
402        OnPaused();
403      } else OnStopped();
404    }
405    private void Optimizer_Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
406      Runs.RemoveRange(e.OldItems);
407      Runs.AddRange(e.Items);
408    }
409    private void Optimizer_Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
410      Runs.AddRange(e.Items);
411    }
412    private void Optimizer_Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
413      Runs.RemoveRange(e.Items);
414    }
415
416    private void RegisterRunsEvents() {
417      runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
418      runs.ItemsAdded += new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsAdded);
419      runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
420    }
421
422    private void DeregisterRunsEvents() {
423      runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
424      runs.ItemsAdded -= new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsAdded);
425      runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
426    }
427    private void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
428      if (Optimizer != null) Optimizer.Runs.RemoveRange(e.OldItems);
429      foreach (IRun run in e.Items) {
430        IItem item;
431        run.Results.TryGetValue("Execution Time", out item);
432        TimeSpanValue executionTime = item as TimeSpanValue;
433        if (executionTime != null) ExecutionTime += executionTime.Value;
434      }
435    }
436    private void Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
437      foreach (IRun run in e.Items) {
438        IItem item;
439        run.Results.TryGetValue("Execution Time", out item);
440        TimeSpanValue executionTime = item as TimeSpanValue;
441        if (executionTime != null) {
442          if (Optimizer.ExecutionState == ExecutionState.Started)
443            runsExecutionTime += executionTime.Value;
444          else
445            ExecutionTime += executionTime.Value;
446        }
447      }
448    }
449    private void Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
450      if (Optimizer != null) Optimizer.Runs.RemoveRange(e.Items);
451    }
452    #endregion
453  }
454}
Note: See TracBrowser for help on using the repository browser.