Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 12940 was 12504, checked in by mkommend, 9 years ago

#2025: Changed categories for all creatables.

File size: 18.3 KB
RevLine 
[3267]1#region License Information
2/* HeuristicLab
[12012]3 * Copyright (C) 2002-2015 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.")]
[12504]36  [Creatable(CreatableAttribute.Categories.TestingAndAnalysis, Priority = 100)]
[3267]37  [StorableClass]
[4419]38  public sealed class Experiment : NamedItem, IOptimizer, IStorableContent {
39    public string Filename { get; set; }
40
[7201]41    public static new Image StaticItemImage {
42      get { return HeuristicLab.Common.Resources.VSImageLibrary.Event; }
43    }
[3267]44    public override Image ItemImage {
[3351]45      get {
[6534]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;
[7201]50        else return base.ItemImage;
[3351]51      }
[3267]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();
[3351]62          OnItemImageChanged();
[3267]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
[3280]77    [Storable]
[3274]78    private OptimizerList optimizers;
79    public OptimizerList Optimizers {
80      get { return optimizers; }
[3267]81    }
82
[3275]83    [Storable]
84    private RunCollection runs;
85    public RunCollection Runs {
86      get { return runs; }
[3716]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      }
[3275]95    }
96
[5419]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
[6767]109    private bool experimentStarted = false;
110    private bool experimentStopped = false;
[3267]111
112    public Experiment()
113      : base() {
[3280]114      name = ItemName;
115      description = ItemDescription;
[3267]116      executionState = ExecutionState.Stopped;
117      executionTime = TimeSpan.Zero;
[3280]118      optimizers = new OptimizerList();
[8975]119      Runs = new RunCollection { OptimizerName = Name };
[3280]120      Initialize();
[3267]121    }
[3280]122    public Experiment(string name)
123      : base(name) {
124      description = ItemDescription;
[3267]125      executionState = ExecutionState.Stopped;
126      executionTime = TimeSpan.Zero;
[3280]127      optimizers = new OptimizerList();
[8975]128      Runs = new RunCollection { OptimizerName = Name };
[3280]129      Initialize();
[3267]130    }
[3280]131    public Experiment(string name, string description)
132      : base(name, description) {
[3267]133      executionState = ExecutionState.Stopped;
134      executionTime = TimeSpan.Zero;
[3280]135      optimizers = new OptimizerList();
[8975]136      Runs = new RunCollection { OptimizerName = Name };
[3280]137      Initialize();
[3267]138    }
[3280]139    [StorableConstructor]
[6767]140    private Experiment(bool deserializing) : base(deserializing) { }
[4722]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);
[6767]151
152      experimentStarted = original.experimentStarted;
153      experimentStopped = original.experimentStopped;
[4722]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    }
[3267]160
[3280]161    private void Initialize() {
162      RegisterOptimizersEvents();
163      foreach (IOptimizer optimizer in optimizers)
164        RegisterOptimizerEvents(optimizer);
[3716]165      if (runs != null) RegisterRunsEvents();
[3280]166    }
167
[3267]168    public void Prepare() {
[3275]169      Prepare(false);
[3267]170    }
[3275]171    public void Prepare(bool clearRuns) {
[3267]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));
[6767]174      if (Optimizers.Count == 0) return;
175
176      if (clearRuns) runs.Clear();
[7241]177
178      experimentStarted = false;
179      experimentStopped = false;
[8194]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
[12504]182        try { optimizer.Prepare(clearRuns); }
183        catch (InvalidOperationException) { }
[8194]184      }
[3267]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));
[6767]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));
[8194]194      if (optimizer != null) {
195        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
[12504]196        try { optimizer.Start(); }
197        catch (InvalidOperationException) { }
[8194]198      }
[3267]199    }
200    public void Pause() {
201      if (ExecutionState != ExecutionState.Started)
202        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
[6767]203      if (Optimizers.Count == 0) return;
204
205      experimentStarted = false;
206      experimentStopped = false;
[8194]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
[12504]209        try { optimizer.Pause(); }
210        catch (InvalidOperationException) { }
[8194]211      }
[3267]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));
[6767]216      if (Optimizers.Count == 0) return;
217
218      experimentStarted = false;
219      experimentStopped = true;
[7241]220      if (Optimizers.Any(x => (x.ExecutionState == ExecutionState.Started) || (x.ExecutionState == ExecutionState.Paused))) {
[8194]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
[12504]223          try { optimizer.Stop(); }
224          catch (InvalidOperationException) { }
[8194]225        }
[7241]226      } else {
227        OnStopped();
228      }
[3267]229    }
230
231    #region Events
[8738]232    protected override void OnNameChanged() {
233      base.OnNameChanged();
[8975]234      Runs.OptimizerName = Name;
[8738]235    }
236
[3267]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
[3274]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);
[3267]282    }
[3274]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);
[3267]288    }
[3274]289    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
[4115]290      foreach (IndexedItem<IOptimizer> item in e.OldItems)
291        RemoveOptimizer(item.Value);
[4110]292      foreach (IndexedItem<IOptimizer> item in e.Items)
293        AddOptimizer(item.Value);
[3267]294    }
[3274]295    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
[4110]296      foreach (IndexedItem<IOptimizer> item in e.Items)
297        AddOptimizer(item.Value);
[3267]298    }
[3274]299    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
[4115]300      foreach (IndexedItem<IOptimizer> item in e.Items)
301        RemoveOptimizer(item.Value);
[3267]302    }
[3274]303    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
[4115]304      foreach (IndexedItem<IOptimizer> item in e.OldItems)
305        RemoveOptimizer(item.Value);
[4110]306      foreach (IndexedItem<IOptimizer> item in e.Items)
307        AddOptimizer(item.Value);
[3267]308    }
[4110]309    private void AddOptimizer(IOptimizer optimizer) {
310      RegisterOptimizerEvents(optimizer);
311      Runs.AddRange(optimizer.Runs);
312      optimizer.Prepare();
[4551]313      if (ExecutionState == ExecutionState.Stopped && optimizer.ExecutionState == ExecutionState.Prepared)
314        OnPrepared();
[4110]315    }
[4115]316    private void RemoveOptimizer(IOptimizer optimizer) {
317      DeregisterOptimizerEvents(optimizer);
318      Runs.RemoveRange(optimizer.Runs);
[4551]319      if (ExecutionState == ExecutionState.Prepared && !optimizers.Any(opt => opt.ExecutionState == ExecutionState.Prepared))
320        OnStopped();
[4115]321    }
[3267]322
[3274]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);
[3280]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);
[3267]333    }
[3274]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);
[3280]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);
[3267]344    }
[8170]345
346    private readonly object locker = new object();
[3274]347    private void optimizer_ExceptionOccurred(object sender, EventArgs<Exception> e) {
[8170]348      lock (locker)
349        OnExceptionOccurred(e.Value);
[3267]350    }
[3274]351    private void optimizer_ExecutionTimeChanged(object sender, EventArgs e) {
[8170]352      lock (locker)
353        ExecutionTime = Optimizers.Aggregate(TimeSpan.Zero, (t, o) => t + o.ExecutionTime);
[3274]354    }
355    private void optimizer_Paused(object sender, EventArgs e) {
[8170]356      lock (locker)
357        if (Optimizers.All(x => x.ExecutionState != ExecutionState.Started)) OnPaused();
[3267]358    }
[3274]359    private void optimizer_Prepared(object sender, EventArgs e) {
[8170]360      lock (locker)
361        if (Optimizers.All(x => x.ExecutionState == ExecutionState.Prepared)) OnPrepared();
[3267]362    }
[3274]363    private void optimizer_Started(object sender, EventArgs e) {
[8170]364      lock (locker)
365        if (ExecutionState != ExecutionState.Started) OnStarted();
[3267]366    }
[3274]367    private void optimizer_Stopped(object sender, EventArgs e) {
[8129]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        }
[3267]377      }
378    }
[3280]379    private void optimizer_Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
[8170]380      lock (locker) {
381        Runs.RemoveRange(e.OldItems);
382        Runs.AddRange(e.Items);
383      }
[3275]384    }
[3280]385    private void optimizer_Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRun> e) {
[8170]386      lock (locker)
387        Runs.AddRange(e.Items);
[3275]388    }
[3280]389    private void optimizer_Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
[8170]390      lock (locker)
391        Runs.RemoveRange(e.Items);
[3275]392    }
[3716]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    }
[3267]410    #endregion
411  }
412}
Note: See TracBrowser for help on using the repository browser.