Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 4144 was 4115, checked in by mkommend, 14 years ago

Added correct handling of adding and removing runs in experiments and batch runs (ticket #1111).

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