Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PersistenceReintegration/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs @ 15689

Last change on this file since 15689 was 15018, checked in by gkronber, 8 years ago

#2520 introduced StorableConstructorFlag type for StorableConstructors

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