Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 8738 was 8738, checked in by mkommend, 12 years ago

#1673: Added new property AlgorithmName to the RunCollection and synced the property with the name of the surrounding IOptimizer. The AlgorithmName is used by the RunCollectionViews as prefix for its caption if it was set.

File size: 18.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 { AlgorithmName = Name };
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 { AlgorithmName = Name };
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 { AlgorithmName = Name };
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        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
182        try { optimizer.Prepare(clearRuns); }
183        catch (InvalidOperationException) { }
184      }
185    }
186    public void Start() {
187      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
188        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
189      if (Optimizers.Count == 0) return;
190
191      experimentStarted = true;
192      experimentStopped = false;
193      IOptimizer optimizer = Optimizers.FirstOrDefault(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused));
194      if (optimizer != null) {
195        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
196        try { optimizer.Start(); }
197        catch (InvalidOperationException) { }
198      }
199    }
200    public void Pause() {
201      if (ExecutionState != ExecutionState.Started)
202        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
203      if (Optimizers.Count == 0) return;
204
205      experimentStarted = false;
206      experimentStopped = false;
207      foreach (IOptimizer optimizer in Optimizers.Where(x => x.ExecutionState == ExecutionState.Started)) {
208        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
209        try { optimizer.Pause(); }
210        catch (InvalidOperationException) { }
211      }
212    }
213    public void Stop() {
214      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
215        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
216      if (Optimizers.Count == 0) return;
217
218      experimentStarted = false;
219      experimentStopped = true;
220      if (Optimizers.Any(x => (x.ExecutionState == ExecutionState.Started) || (x.ExecutionState == ExecutionState.Paused))) {
221        foreach (var optimizer in Optimizers.Where(x => (x.ExecutionState == ExecutionState.Started) || (x.ExecutionState == ExecutionState.Paused))) {
222          // a race-condition may occur when the optimizer has changed the state by itself in the meantime
223          try { optimizer.Stop(); }
224          catch (InvalidOperationException) { }
225        }
226      } else {
227        OnStopped();
228      }
229    }
230
231    #region Events
232    protected override void OnNameChanged() {
233      base.OnNameChanged();
234      Runs.AlgorithmName = Name;
235    }
236
237    public event EventHandler ExecutionStateChanged;
238    private void OnExecutionStateChanged() {
239      EventHandler handler = ExecutionStateChanged;
240      if (handler != null) handler(this, EventArgs.Empty);
241    }
242    public event EventHandler ExecutionTimeChanged;
243    private void OnExecutionTimeChanged() {
244      EventHandler handler = ExecutionTimeChanged;
245      if (handler != null) handler(this, EventArgs.Empty);
246    }
247    public event EventHandler Prepared;
248    private void OnPrepared() {
249      ExecutionState = ExecutionState.Prepared;
250      EventHandler handler = Prepared;
251      if (handler != null) handler(this, EventArgs.Empty);
252    }
253    public event EventHandler Started;
254    private void OnStarted() {
255      ExecutionState = ExecutionState.Started;
256      EventHandler handler = Started;
257      if (handler != null) handler(this, EventArgs.Empty);
258    }
259    public event EventHandler Paused;
260    private void OnPaused() {
261      ExecutionState = ExecutionState.Paused;
262      EventHandler handler = Paused;
263      if (handler != null) handler(this, EventArgs.Empty);
264    }
265    public event EventHandler Stopped;
266    private void OnStopped() {
267      ExecutionState = ExecutionState.Stopped;
268      EventHandler handler = Stopped;
269      if (handler != null) handler(this, EventArgs.Empty);
270    }
271    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
272    private void OnExceptionOccurred(Exception exception) {
273      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
274      if (handler != null) handler(this, new EventArgs<Exception>(exception));
275    }
276
277    private void RegisterOptimizersEvents() {
278      Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
279      Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
280      Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
281      Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
282    }
283    private void DeregisterOptimizersEvents() {
284      Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
285      Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
286      Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
287      Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
288    }
289    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
290      foreach (IndexedItem<IOptimizer> item in e.OldItems)
291        RemoveOptimizer(item.Value);
292      foreach (IndexedItem<IOptimizer> item in e.Items)
293        AddOptimizer(item.Value);
294    }
295    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
296      foreach (IndexedItem<IOptimizer> item in e.Items)
297        AddOptimizer(item.Value);
298    }
299    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
300      foreach (IndexedItem<IOptimizer> item in e.Items)
301        RemoveOptimizer(item.Value);
302    }
303    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
304      foreach (IndexedItem<IOptimizer> item in e.OldItems)
305        RemoveOptimizer(item.Value);
306      foreach (IndexedItem<IOptimizer> item in e.Items)
307        AddOptimizer(item.Value);
308    }
309    private void AddOptimizer(IOptimizer optimizer) {
310      RegisterOptimizerEvents(optimizer);
311      Runs.AddRange(optimizer.Runs);
312      optimizer.Prepare();
313      if (ExecutionState == ExecutionState.Stopped && optimizer.ExecutionState == ExecutionState.Prepared)
314        OnPrepared();
315    }
316    private void RemoveOptimizer(IOptimizer optimizer) {
317      DeregisterOptimizerEvents(optimizer);
318      Runs.RemoveRange(optimizer.Runs);
319      if (ExecutionState == ExecutionState.Prepared && !optimizers.Any(opt => opt.ExecutionState == ExecutionState.Prepared))
320        OnStopped();
321    }
322
323    private void RegisterOptimizerEvents(IOptimizer optimizer) {
324      optimizer.ExceptionOccurred += new EventHandler<EventArgs<Exception>>(optimizer_ExceptionOccurred);
325      optimizer.ExecutionTimeChanged += new EventHandler(optimizer_ExecutionTimeChanged);
326      optimizer.Paused += new EventHandler(optimizer_Paused);
327      optimizer.Prepared += new EventHandler(optimizer_Prepared);
328      optimizer.Started += new EventHandler(optimizer_Started);
329      optimizer.Stopped += new EventHandler(optimizer_Stopped);
330      optimizer.Runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_CollectionReset);
331      optimizer.Runs.ItemsAdded += new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsAdded);
332      optimizer.Runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsRemoved);
333    }
334    private void DeregisterOptimizerEvents(IOptimizer optimizer) {
335      optimizer.ExceptionOccurred -= new EventHandler<EventArgs<Exception>>(optimizer_ExceptionOccurred);
336      optimizer.ExecutionTimeChanged -= new EventHandler(optimizer_ExecutionTimeChanged);
337      optimizer.Paused -= new EventHandler(optimizer_Paused);
338      optimizer.Prepared -= new EventHandler(optimizer_Prepared);
339      optimizer.Started -= new EventHandler(optimizer_Started);
340      optimizer.Stopped -= new EventHandler(optimizer_Stopped);
341      optimizer.Runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_CollectionReset);
342      optimizer.Runs.ItemsAdded -= new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsAdded);
343      optimizer.Runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(optimizer_Runs_ItemsRemoved);
344    }
345
346    private readonly object locker = new object();
347    private void optimizer_ExceptionOccurred(object sender, EventArgs<Exception> e) {
348      lock (locker)
349        OnExceptionOccurred(e.Value);
350    }
351    private void optimizer_ExecutionTimeChanged(object sender, EventArgs e) {
352      lock (locker)
353        ExecutionTime = Optimizers.Aggregate(TimeSpan.Zero, (t, o) => t + o.ExecutionTime);
354    }
355    private void optimizer_Paused(object sender, EventArgs e) {
356      lock (locker)
357        if (Optimizers.All(x => x.ExecutionState != ExecutionState.Started)) OnPaused();
358    }
359    private void optimizer_Prepared(object sender, EventArgs e) {
360      lock (locker)
361        if (Optimizers.All(x => x.ExecutionState == ExecutionState.Prepared)) OnPrepared();
362    }
363    private void optimizer_Started(object sender, EventArgs e) {
364      lock (locker)
365        if (ExecutionState != ExecutionState.Started) OnStarted();
366    }
367    private void optimizer_Stopped(object sender, EventArgs e) {
368      lock (locker) {
369        if (experimentStopped) {
370          if (Optimizers.All(x => (x.ExecutionState == ExecutionState.Stopped) || (x.ExecutionState == ExecutionState.Prepared))) OnStopped();
371        } else {
372          if (experimentStarted && Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused))) {
373            Optimizers.First(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused)).Start();
374          } else if (Optimizers.All(x => x.ExecutionState == ExecutionState.Stopped)) OnStopped();
375          else if (Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused)) && Optimizers.All(o => o.ExecutionState != ExecutionState.Started)) OnPaused();
376        }
377      }
378    }
379    private void optimizer_Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
380      lock (locker) {
381        Runs.RemoveRange(e.OldItems);
382        Runs.AddRange(e.Items);
383      }
384    }
385    private void optimizer_Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
386      lock (locker)
387        Runs.AddRange(e.Items);
388    }
389    private void optimizer_Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
390      lock (locker)
391        Runs.RemoveRange(e.Items);
392    }
393
394    private void RegisterRunsEvents() {
395      runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
396      runs.ItemsRemoved += new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
397    }
398    private void DeregisterRunsEvents() {
399      runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
400      runs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IRun>(Runs_ItemsRemoved);
401    }
402    private void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
403      foreach (IOptimizer optimizer in Optimizers)
404        optimizer.Runs.RemoveRange(e.OldItems);
405    }
406    private void Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
407      foreach (IOptimizer optimizer in Optimizers)
408        optimizer.Runs.RemoveRange(e.Items);
409    }
410    #endregion
411  }
412}
Note: See TracBrowser for help on using the repository browser.