Free cookie consent management tool by TermsFeed Policy Generator

source: branches/WebJobManager/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs @ 17877

Last change on this file since 17877 was 13656, checked in by ascheibe, 9 years ago

#2582 created branch for Hive Web Job Manager

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