Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Optimization/3.3/Experiment.cs @ 7082

Last change on this file since 7082 was 6767, checked in by mkommend, 13 years ago

#1573, #1574: Decoupled execution states of Experiment and BatchRun with the nested optimizers.

File size: 16.8 KB
RevLine 
[3267]1#region License Information
2/* HeuristicLab
[5445]3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[3267]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;
[5419]23using System.Collections.Generic;
[3267]24using System.Drawing;
25using System.Linq;
26using HeuristicLab.Collections;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30
31namespace HeuristicLab.Optimization {
32  /// <summary>
[5300]33  /// An experiment which contains multiple algorithms, batch runs or other experiments.
[3267]34  /// </summary>
[5300]35  [Item("Experiment", "An experiment which contains multiple algorithms, batch runs or other experiments.")]
[3267]36  [Creatable("Testing & Analysis")]
37  [StorableClass]
[4419]38  public sealed class Experiment : NamedItem, IOptimizer, IStorableContent {
39    public string Filename { get; set; }
40
[3267]41    public override Image ItemImage {
[3351]42      get {
[6534]43        if (ExecutionState == ExecutionState.Prepared) return HeuristicLab.Common.Resources.VSImageLibrary.ExperimentPrepared;
44        else if (ExecutionState == ExecutionState.Started) return HeuristicLab.Common.Resources.VSImageLibrary.ExperimentStarted;
45        else if (ExecutionState == ExecutionState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.ExperimentPaused;
46        else if (ExecutionState == ExecutionState.Stopped) return HeuristicLab.Common.Resources.VSImageLibrary.ExperimentStopped;
[5287]47        else return HeuristicLab.Common.Resources.VSImageLibrary.Event;
[3351]48      }
[3267]49    }
50
51    [Storable]
52    private ExecutionState executionState;
53    public ExecutionState ExecutionState {
54      get { return executionState; }
55      private set {
56        if (executionState != value) {
57          executionState = value;
58          OnExecutionStateChanged();
[3351]59          OnItemImageChanged();
[3267]60        }
61      }
62    }
63
64    [Storable]
65    private TimeSpan executionTime;
66    public TimeSpan ExecutionTime {
67      get { return executionTime; }
68      private set {
69        executionTime = value;
70        OnExecutionTimeChanged();
71      }
72    }
73
[3280]74    [Storable]
[3274]75    private OptimizerList optimizers;
76    public OptimizerList Optimizers {
77      get { return optimizers; }
[3267]78    }
79
[3275]80    [Storable]
81    private RunCollection runs;
82    public RunCollection Runs {
83      get { return runs; }
[3716]84      private set {
85        if (value == null) throw new ArgumentNullException();
86        if (runs != value) {
87          if (runs != null) DeregisterRunsEvents();
88          runs = value;
89          if (runs != null) RegisterRunsEvents();
90        }
91      }
[3275]92    }
93
[5419]94    public IEnumerable<IOptimizer> NestedOptimizers {
95      get {
96        if (Optimizers == null) yield break;
97
98        foreach (IOptimizer opt in Optimizers) {
99          yield return opt;
100          foreach (IOptimizer nestedOpt in opt.NestedOptimizers)
101            yield return nestedOpt;
102        }
103      }
104    }
105
[6767]106    private bool experimentStarted = false;
107    private bool experimentStopped = false;
[3267]108
109    public Experiment()
110      : base() {
[3280]111      name = ItemName;
112      description = ItemDescription;
[3267]113      executionState = ExecutionState.Stopped;
114      executionTime = TimeSpan.Zero;
[3280]115      optimizers = new OptimizerList();
[3716]116      Runs = new RunCollection();
[3280]117      Initialize();
[3267]118    }
[3280]119    public Experiment(string name)
120      : base(name) {
121      description = ItemDescription;
[3267]122      executionState = ExecutionState.Stopped;
123      executionTime = TimeSpan.Zero;
[3280]124      optimizers = new OptimizerList();
[3716]125      Runs = new RunCollection();
[3280]126      Initialize();
[3267]127    }
[3280]128    public Experiment(string name, string description)
129      : base(name, description) {
[3267]130      executionState = ExecutionState.Stopped;
131      executionTime = TimeSpan.Zero;
[3280]132      optimizers = new OptimizerList();
[3716]133      Runs = new RunCollection();
[3280]134      Initialize();
[3267]135    }
[3280]136    [StorableConstructor]
[6767]137    private Experiment(bool deserializing) : base(deserializing) { }
[4722]138    [StorableHook(HookType.AfterDeserialization)]
139    private void AfterDeserialization() {
140      Initialize();
141    }
142    private Experiment(Experiment original, Cloner cloner)
143      : base(original, cloner) {
144      executionState = original.executionState;
145      executionTime = original.executionTime;
146      optimizers = cloner.Clone(original.optimizers);
147      runs = cloner.Clone(original.runs);
[6767]148
149      experimentStarted = original.experimentStarted;
150      experimentStopped = original.experimentStopped;
[4722]151      Initialize();
152    }
153    public override IDeepCloneable Clone(Cloner cloner) {
154      if (ExecutionState == ExecutionState.Started) throw new InvalidOperationException(string.Format("Clone not allowed in execution state \"{0}\".", ExecutionState));
155      return new Experiment(this, cloner);
156    }
[3267]157
[3280]158    private void Initialize() {
159      RegisterOptimizersEvents();
160      foreach (IOptimizer optimizer in optimizers)
161        RegisterOptimizerEvents(optimizer);
[3716]162      if (runs != null) RegisterRunsEvents();
[3280]163    }
164
[3267]165    public void Prepare() {
[3275]166      Prepare(false);
[3267]167    }
[3275]168    public void Prepare(bool clearRuns) {
[3267]169      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused) && (ExecutionState != ExecutionState.Stopped))
170        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
[6767]171      if (Optimizers.Count == 0) return;
172
173      if (clearRuns) runs.Clear();
174      foreach (IOptimizer optimizer in Optimizers.Where(x => x.ExecutionState != ExecutionState.Started))
175        if (clearRuns || optimizer.ExecutionState != ExecutionState.Prepared)
[3275]176          optimizer.Prepare(clearRuns);
[3267]177    }
178    public void Start() {
179      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
180        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
[6767]181      if (Optimizers.Count == 0) return;
182
183      experimentStarted = true;
184      experimentStopped = false;
185      IOptimizer optimizer = Optimizers.FirstOrDefault(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused));
186      if (optimizer != null) optimizer.Start();
[3267]187    }
188    public void Pause() {
189      if (ExecutionState != ExecutionState.Started)
190        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
[6767]191      if (Optimizers.Count == 0) return;
192
193      experimentStarted = false;
194      experimentStopped = false;
195      foreach (IOptimizer optimizer in Optimizers.Where(x => x.ExecutionState == ExecutionState.Started))
196        optimizer.Pause();
[3267]197    }
198    public void Stop() {
199      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
200        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
[6767]201      if (Optimizers.Count == 0) return;
202
203      experimentStarted = false;
204      experimentStopped = true;
205      foreach (IOptimizer optimizer in Optimizers.Where(x => (x.ExecutionState == ExecutionState.Started) || (x.ExecutionState == ExecutionState.Paused)))
206        optimizer.Stop();
[3267]207    }
208
209    #region Events
210    public event EventHandler ExecutionStateChanged;
211    private void OnExecutionStateChanged() {
212      EventHandler handler = ExecutionStateChanged;
213      if (handler != null) handler(this, EventArgs.Empty);
214    }
215    public event EventHandler ExecutionTimeChanged;
216    private void OnExecutionTimeChanged() {
217      EventHandler handler = ExecutionTimeChanged;
218      if (handler != null) handler(this, EventArgs.Empty);
219    }
220    public event EventHandler Prepared;
221    private void OnPrepared() {
222      ExecutionState = ExecutionState.Prepared;
223      EventHandler handler = Prepared;
224      if (handler != null) handler(this, EventArgs.Empty);
225    }
226    public event EventHandler Started;
227    private void OnStarted() {
228      ExecutionState = ExecutionState.Started;
229      EventHandler handler = Started;
230      if (handler != null) handler(this, EventArgs.Empty);
231    }
232    public event EventHandler Paused;
233    private void OnPaused() {
234      ExecutionState = ExecutionState.Paused;
235      EventHandler handler = Paused;
236      if (handler != null) handler(this, EventArgs.Empty);
237    }
238    public event EventHandler Stopped;
239    private void OnStopped() {
240      ExecutionState = ExecutionState.Stopped;
241      EventHandler handler = Stopped;
242      if (handler != null) handler(this, EventArgs.Empty);
243    }
244    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
245    private void OnExceptionOccurred(Exception exception) {
246      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
247      if (handler != null) handler(this, new EventArgs<Exception>(exception));
248    }
249
[3274]250    private void RegisterOptimizersEvents() {
251      Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
252      Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
253      Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
254      Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
[3267]255    }
[3274]256    private void DeregisterOptimizersEvents() {
257      Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
258      Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
259      Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
260      Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
[3267]261    }
[3274]262    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
[4115]263      foreach (IndexedItem<IOptimizer> item in e.OldItems)
264        RemoveOptimizer(item.Value);
[4110]265      foreach (IndexedItem<IOptimizer> item in e.Items)
266        AddOptimizer(item.Value);
[3267]267    }
[3274]268    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
[4110]269      foreach (IndexedItem<IOptimizer> item in e.Items)
270        AddOptimizer(item.Value);
[3267]271    }
[3274]272    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
[4115]273      foreach (IndexedItem<IOptimizer> item in e.Items)
274        RemoveOptimizer(item.Value);
[3267]275    }
[3274]276    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
[4115]277      foreach (IndexedItem<IOptimizer> item in e.OldItems)
278        RemoveOptimizer(item.Value);
[4110]279      foreach (IndexedItem<IOptimizer> item in e.Items)
280        AddOptimizer(item.Value);
[3267]281    }
[4110]282    private void AddOptimizer(IOptimizer optimizer) {
283      RegisterOptimizerEvents(optimizer);
284      Runs.AddRange(optimizer.Runs);
285      optimizer.Prepare();
[4551]286      if (ExecutionState == ExecutionState.Stopped && optimizer.ExecutionState == ExecutionState.Prepared)
287        OnPrepared();
[4110]288    }
[4115]289    private void RemoveOptimizer(IOptimizer optimizer) {
290      DeregisterOptimizerEvents(optimizer);
291      Runs.RemoveRange(optimizer.Runs);
[4551]292      if (ExecutionState == ExecutionState.Prepared && !optimizers.Any(opt => opt.ExecutionState == ExecutionState.Prepared))
293        OnStopped();
[4115]294    }
[3267]295
[3274]296    private void RegisterOptimizerEvents(IOptimizer optimizer) {
297      optimizer.ExceptionOccurred += new EventHandler<EventArgs<Exception>>(optimizer_ExceptionOccurred);
298      optimizer.ExecutionTimeChanged += new EventHandler(optimizer_ExecutionTimeChanged);
299      optimizer.Paused += new EventHandler(optimizer_Paused);
300      optimizer.Prepared += new EventHandler(optimizer_Prepared);
301      optimizer.Started += new EventHandler(optimizer_Started);
302      optimizer.Stopped += new EventHandler(optimizer_Stopped);
[3280]303      optimizer.Runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_CollectionReset);
304      optimizer.Runs.ItemsAdded += new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsAdded);
305      optimizer.Runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsRemoved);
[3267]306    }
[3274]307    private void DeregisterOptimizerEvents(IOptimizer optimizer) {
308      optimizer.ExceptionOccurred -= new EventHandler<EventArgs<Exception>>(optimizer_ExceptionOccurred);
309      optimizer.ExecutionTimeChanged -= new EventHandler(optimizer_ExecutionTimeChanged);
310      optimizer.Paused -= new EventHandler(optimizer_Paused);
311      optimizer.Prepared -= new EventHandler(optimizer_Prepared);
312      optimizer.Started -= new EventHandler(optimizer_Started);
313      optimizer.Stopped -= new EventHandler(optimizer_Stopped);
[3280]314      optimizer.Runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_CollectionReset);
315      optimizer.Runs.ItemsAdded -= new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsAdded);
316      optimizer.Runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsRemoved);
[3267]317    }
[3274]318    private void optimizer_ExceptionOccurred(object sender, EventArgs<Exception> e) {
[3267]319      OnExceptionOccurred(e.Value);
320    }
[3274]321    private void optimizer_ExecutionTimeChanged(object sender, EventArgs e) {
322      ExecutionTime = Optimizers.Aggregate(TimeSpan.Zero, (t, o) => t + o.ExecutionTime);
323    }
324    private void optimizer_Paused(object sender, EventArgs e) {
325      if (Optimizers.All(x => x.ExecutionState != ExecutionState.Started))
[3267]326        OnPaused();
327    }
[3274]328    private void optimizer_Prepared(object sender, EventArgs e) {
[3267]329      if (ExecutionState == ExecutionState.Stopped)
330        OnPrepared();
331    }
[3274]332    private void optimizer_Started(object sender, EventArgs e) {
[3267]333      if (ExecutionState != ExecutionState.Started)
334        OnStarted();
335    }
[3274]336    private void optimizer_Stopped(object sender, EventArgs e) {
[6767]337      if (experimentStopped && Optimizers.All(o => o.ExecutionState == ExecutionState.Stopped || o.ExecutionState == ExecutionState.Prepared)) OnStopped();
338      else if (Optimizers.All(o => o.ExecutionState == ExecutionState.Stopped)) OnStopped();
339      else if (Optimizers.Any(o => o.ExecutionState == ExecutionState.Paused) && Optimizers.All(o => o.ExecutionState != ExecutionState.Started)) OnPaused();
340      else if (experimentStarted && !experimentStopped && Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused))) {
[3276]341        Optimizers.First(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused)).Start();
[3267]342      }
343    }
[3280]344    private void optimizer_Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
[3275]345      Runs.RemoveRange(e.OldItems);
346      Runs.AddRange(e.Items);
347    }
[3280]348    private void optimizer_Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
[3275]349      Runs.AddRange(e.Items);
350    }
[3280]351    private void optimizer_Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
[3275]352      Runs.RemoveRange(e.Items);
353    }
[3716]354
355    private void RegisterRunsEvents() {
356      runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
357      runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
358    }
359    private void DeregisterRunsEvents() {
360      runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
361      runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
362    }
363    private void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
364      foreach (IOptimizer optimizer in Optimizers)
365        optimizer.Runs.RemoveRange(e.OldItems);
366    }
367    private void Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
368      foreach (IOptimizer optimizer in Optimizers)
369        optimizer.Runs.RemoveRange(e.Items);
370    }
[3267]371    #endregion
372  }
373}
Note: See TracBrowser for help on using the repository browser.