Free cookie consent management tool by TermsFeed Policy Generator

source: branches/1614_GeneralizedQAP/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs @ 15677

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

#1614: merged trunk into branch

File size: 17.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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        if (ExecutionState == ExecutionState.Paused || ExecutionState == ExecutionState.Stopped) break;
245      }
246    }
247    public async Task StartAsync() { await StartAsync(CancellationToken.None); }
248    public async Task StartAsync(CancellationToken cancellationToken) {
249      await AsyncHelper.DoAsync(Start, cancellationToken);
250    }
251    public void Pause() {
252      if (ExecutionState != ExecutionState.Started)
253        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
254      if (Optimizer == null) return;
255      batchRunAction = BatchRunAction.Pause;
256      if (Optimizer.ExecutionState != ExecutionState.Started) return;
257      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
258      try { Optimizer.Pause(); } catch (InvalidOperationException) { } catch (NotSupportedException) { }
259    }
260    public void Stop() {
261      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
262        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
263      if (Optimizer == null) return;
264      batchRunAction = BatchRunAction.Stop;
265      if (Optimizer.ExecutionState != ExecutionState.Started && Optimizer.ExecutionState != ExecutionState.Paused) {
266        OnStopped();
267        return;
268      }
269      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
270      try { Optimizer.Stop(); } catch (InvalidOperationException) { }
271    }
272
273    #region Events
274    protected override void OnNameChanged() {
275      base.OnNameChanged();
276      runs.OptimizerName = Name;
277    }
278
279    public event EventHandler ExecutionStateChanged;
280    private void OnExecutionStateChanged() {
281      EventHandler handler = ExecutionStateChanged;
282      if (handler != null) handler(this, EventArgs.Empty);
283    }
284    [Obsolete("Deprecated needs to be removed")]
285    public event EventHandler ExecutionTimeChanged;
286    public event EventHandler OptimizerChanged;
287    private void OnOptimizerChanged() {
288      EventHandler handler = OptimizerChanged;
289      if (handler != null) handler(this, EventArgs.Empty);
290    }
291    public event EventHandler RepetitionsChanged;
292    private void OnRepetitionsChanged() {
293      EventHandler handler = RepetitionsChanged;
294      if (handler != null) handler(this, EventArgs.Empty);
295    }
296    public event EventHandler RepetetionsCounterChanged;
297    private void OnRepetitionsCounterChanged() {
298      EventHandler handler = RepetetionsCounterChanged;
299      if (handler != null) handler(this, EventArgs.Empty);
300    }
301    public event EventHandler Prepared;
302    private void OnPrepared() {
303      batchRunAction = BatchRunAction.None;
304      ExecutionState = ExecutionState.Prepared;
305      EventHandler handler = Prepared;
306      if (handler != null) handler(this, EventArgs.Empty);
307    }
308    public event EventHandler Started;
309    private void OnStarted() {
310      // no reset of BatchRunAction.Started, because we need to differ which of the two was started by the user
311      ExecutionState = ExecutionState.Started;
312      EventHandler handler = Started;
313      if (handler != null) handler(this, EventArgs.Empty);
314    }
315    public event EventHandler Paused;
316    private void OnPaused() {
317      batchRunAction = BatchRunAction.None;
318      ExecutionState = ExecutionState.Paused;
319      EventHandler handler = Paused;
320      if (handler != null) handler(this, EventArgs.Empty);
321    }
322    public event EventHandler Stopped;
323    private void OnStopped() {
324      batchRunAction = BatchRunAction.None;
325      ExecutionState = ExecutionState.Stopped;
326      EventHandler handler = Stopped;
327      if (handler != null) handler(this, EventArgs.Empty);
328    }
329    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
330    private void OnExceptionOccurred(Exception exception) {
331      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
332      if (handler != null) handler(this, new EventArgs<Exception>(exception));
333    }
334
335    private void RegisterOptimizerEvents() {
336      optimizer.ExceptionOccurred += new EventHandler<EventArgs<Exception>>(Optimizer_ExceptionOccurred);
337      optimizer.Paused += new EventHandler(Optimizer_Paused);
338      optimizer.Prepared += new EventHandler(Optimizer_Prepared);
339      optimizer.Started += new EventHandler(Optimizer_Started);
340      optimizer.Stopped += new EventHandler(Optimizer_Stopped);
341      optimizer.Runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_CollectionReset);
342      optimizer.Runs.ItemsAdded += new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_ItemsAdded);
343      optimizer.Runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(Optimizer_Runs_ItemsRemoved);
344    }
345    private void DeregisterOptimizerEvents() {
346      optimizer.ExceptionOccurred -= new EventHandler<EventArgs<Exception>>(Optimizer_ExceptionOccurred);
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 Optimizer_ExceptionOccurred(object sender, EventArgs<Exception> e) {
356      OnExceptionOccurred(e.Value);
357    }
358    private void Optimizer_Paused(object sender, EventArgs e) {
359      if (ExecutionState == ExecutionState.Started) {
360        OnPaused();
361      }
362    }
363    private void Optimizer_Prepared(object sender, EventArgs e) {
364      if (batchRunAction == BatchRunAction.Prepare || ExecutionState == ExecutionState.Stopped) {
365        RepetitionsCounter = 0;
366        OnPrepared();
367      }
368    }
369    private void Optimizer_Started(object sender, EventArgs e) {
370      if (ExecutionState != ExecutionState.Started)
371        OnStarted();
372    }
373    private void Optimizer_Stopped(object sender, EventArgs e) {
374      RepetitionsCounter++;
375
376      if (batchRunAction == BatchRunAction.Stop) OnStopped();
377      else if (repetitionsCounter >= repetitions) OnStopped();
378      else if (batchRunAction == BatchRunAction.Pause) OnPaused();
379      else if (batchRunAction == BatchRunAction.Start) return;
380      else if (executionState == ExecutionState.Started) {
381        // if the batch run hasn't been started but the inner optimizer was run then pause
382        OnPaused();
383      } else OnStopped();
384    }
385    private void Optimizer_Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
386      Runs.RemoveRange(e.OldItems);
387      Runs.AddRange(e.Items);
388    }
389    private void Optimizer_Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
390      Runs.AddRange(e.Items);
391    }
392    private void Optimizer_Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
393      Runs.RemoveRange(e.Items);
394    }
395
396    private void RegisterRunsEvents() {
397      runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
398      runs.ItemsAdded += new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsAdded);
399      runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
400    }
401
402    private void DeregisterRunsEvents() {
403      runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
404      runs.ItemsAdded -= new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsAdded);
405      runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
406    }
407    private void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
408      if (Optimizer != null) Optimizer.Runs.RemoveRange(e.OldItems);
409      executionTime += SumExecutionTimes(e.OldItems);
410      executionTime += SumExecutionTimes(e.Items);
411    }
412    private void Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
413      executionTime += SumExecutionTimes(e.Items);
414    }
415    private void Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
416      if (Optimizer != null) Optimizer.Runs.RemoveRange(e.Items);
417      executionTime -= SumExecutionTimes(e.Items);
418    }
419    private TimeSpan SumExecutionTimes(IEnumerable<IRun> runs) {
420      var sum = TimeSpan.Zero;
421      foreach (IRun run in runs) {
422        IItem item;
423        run.Results.TryGetValue("Execution Time", out item);
424        TimeSpanValue exTime = item as TimeSpanValue;
425        if (exTime != null) sum += exTime.Value;
426      }
427      return sum;
428    }
429    #endregion
430  }
431}
Note: See TracBrowser for help on using the repository browser.