Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs @ 17105

Last change on this file since 17105 was 17105, checked in by mkommend, 5 years ago

#2520: Merged 16584, 16585,16594,16595, 16625, 16658, 16659, 16672, 16707, 16729, 16792, 16796, 16797, 16799, 16819, 16906, 16907, 16908, 16933, 16945, 16992, 16994, 16995, 16996, 16997, 17014, 17015, 17017, 17020, 17021, 17022, 17023, 17024, 17029, 17086, 17087, 17088, 17089 into stable.

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