Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 8738 was 8738, checked in by mkommend, 12 years ago

#1673: Added new property AlgorithmName to the RunCollection and synced the property with the name of the surrounding IOptimizer. The AlgorithmName is used by the RunCollectionViews as prefix for its caption if it was set.

File size: 18.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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("Testing & Analysis")]
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 { AlgorithmName = 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 { AlgorithmName = 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 { AlgorithmName = 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.AlgorithmName = 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.