Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 7624 was 7576, checked in by mkommend, 13 years ago

#1783: Removed questionable source lines in execution state handling in the BatchRun and the Experiment.

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