Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 15381 was 15292, checked in by jkarder, 7 years ago

#2258: merged r15287 into stable

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