Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs @ 12075

Last change on this file since 12075 was 12012, checked in by ascheibe, 10 years ago

#2212 merged r12008, r12009, r12010 back into trunk

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