Free cookie consent management tool by TermsFeed Policy Generator

source: branches/GeneralizedQAP/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs @ 15603

Last change on this file since 15603 was 15603, checked in by abeham, 6 years ago

#1614: Implemented changed behavior to measure execution time (cf. #2869)

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