Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CloningRefactoring/HeuristicLab.Algorithms.DataAnalysis/3.3/CrossValidation.cs @ 4666

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

Refactored Algorithms.DataAnalysis (ticket #922).

File size: 25.7 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.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using HeuristicLab.Collections;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Optimization;
31using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
32using HeuristicLab.Problems.DataAnalysis;
33
34namespace HeuristicLab.Algorithms.DataAnalysis {
35  [Item("Cross Validation", "Cross Validation wrapper for data analysis algorithms.")]
36  [Creatable("Data Analysis")]
37  [StorableClass]
38  public sealed class CrossValidation : ParameterizedNamedItem, IAlgorithm, IStorableContent {
39    public CrossValidation()
40      : base() {
41      name = ItemName;
42      description = ItemDescription;
43
44      executionState = ExecutionState.Stopped;
45      runs = new RunCollection();
46      runsCounter = 0;
47
48      algorithm = null;
49      clonedAlgorithms = new ItemCollection<IAlgorithm>();
50      readOnlyClonedAlgorithms = null;
51      results = new ResultCollection();
52
53      folds = new IntValue(2);
54      numberOfWorkers = new IntValue(1);
55      samplesStart = new IntValue(0);
56      samplesEnd = new IntValue(0);
57      storeAlgorithmInEachRun = false;
58
59      RegisterEvents();
60    }
61
62    public string Filename { get; set; }
63
64    #region persistence and cloning
65    [StorableConstructor]
66    private CrossValidation(bool deserializing)
67      : base(deserializing) {
68    }
69    [StorableHook(HookType.AfterDeserialization)]
70    private void AfterDeserialization() {
71      RegisterEvents();
72    }
73
74    private CrossValidation(CrossValidation original, Cloner cloner)
75      : base(original, cloner) {
76      executionState = original.executionState;
77      storeAlgorithmInEachRun = original.storeAlgorithmInEachRun;
78      runs = cloner.Clone(original.runs);
79      runsCounter = original.runsCounter;
80      algorithm = cloner.Clone(original.algorithm);
81      clonedAlgorithms = cloner.Clone(original.clonedAlgorithms);
82      folds = cloner.Clone(original.folds);
83      numberOfWorkers = cloner.Clone(original.numberOfWorkers);
84      samplesStart = cloner.Clone(original.samplesStart);
85      samplesEnd = cloner.Clone(original.samplesEnd);
86      RegisterEvents();
87    }
88    public override IDeepCloneable Clone(Cloner cloner) {
89      return new CrossValidation(this, cloner);
90    }
91
92    #endregion
93
94    #region properties
95    [Storable]
96    private IAlgorithm algorithm;
97    public IAlgorithm Algorithm {
98      get { return algorithm; }
99      set {
100        if (ExecutionState != ExecutionState.Prepared && ExecutionState != ExecutionState.Stopped)
101          throw new InvalidOperationException("Changing the algorithm is only allowed if the CrossValidation is stopped or prepared.");
102        if (algorithm != value) {
103          if (value != null && value.Problem != null && !(value.Problem is IDataAnalysisProblem))
104            throw new ArgumentException("Only algorithms with a DataAnalysisProblem could be used for the cross validation.");
105          if (algorithm != null) DeregisterAlgorithmEvents();
106          algorithm = value;
107          Parameters.Clear();
108
109          if (algorithm != null) {
110            algorithm.StoreAlgorithmInEachRun = false;
111            RegisterAlgorithmEvents();
112            algorithm.Prepare(true);
113            Parameters.AddRange(algorithm.Parameters);
114          }
115          OnAlgorithmChanged();
116          if (algorithm != null) OnProblemChanged();
117          Prepare();
118        }
119      }
120    }
121
122
123    [Storable]
124    private ISingleObjectiveDataAnalysisProblem problem;
125    public ISingleObjectiveDataAnalysisProblem Problem {
126      get {
127        if (algorithm == null)
128          return null;
129        return (ISingleObjectiveDataAnalysisProblem)algorithm.Problem;
130      }
131      set {
132        if (ExecutionState != ExecutionState.Prepared && ExecutionState != ExecutionState.Stopped)
133          throw new InvalidOperationException("Changing the problem is only allowed if the CrossValidation is stopped or prepared.");
134        if (algorithm == null) throw new ArgumentNullException("Could not set a problem before an algorithm was set.");
135        algorithm.Problem = value;
136        problem = value;
137      }
138    }
139
140    IProblem IAlgorithm.Problem {
141      get { return Problem; }
142      set {
143        if (value != null && !ProblemType.IsInstanceOfType(value))
144          throw new ArgumentException("Only DataAnalysisProblems could be used for the cross validation.");
145        Problem = (ISingleObjectiveDataAnalysisProblem)value;
146      }
147    }
148    public Type ProblemType {
149      get { return typeof(ISingleObjectiveDataAnalysisProblem); }
150    }
151
152    [Storable]
153    private ItemCollection<IAlgorithm> clonedAlgorithms;
154    private ReadOnlyItemCollection<IAlgorithm> readOnlyClonedAlgorithms;
155    public IItemCollection<IAlgorithm> ClonedAlgorithms {
156      get {
157        if (readOnlyClonedAlgorithms == null) readOnlyClonedAlgorithms = clonedAlgorithms.AsReadOnly();
158        return readOnlyClonedAlgorithms;
159      }
160    }
161
162    [Storable]
163    private ResultCollection results;
164    public ResultCollection Results {
165      get { return results; }
166    }
167
168    [Storable]
169    private IntValue folds;
170    public IntValue Folds {
171      get { return folds; }
172    }
173    [Storable]
174    private IntValue samplesStart;
175    public IntValue SamplesStart {
176      get { return samplesStart; }
177    }
178    [Storable]
179    private IntValue samplesEnd;
180    public IntValue SamplesEnd {
181      get { return samplesEnd; }
182    }
183    [Storable]
184    private IntValue numberOfWorkers;
185    public IntValue NumberOfWorkers {
186      get { return numberOfWorkers; }
187    }
188
189    [Storable]
190    private bool storeAlgorithmInEachRun;
191    public bool StoreAlgorithmInEachRun {
192      get { return storeAlgorithmInEachRun; }
193      set {
194        if (storeAlgorithmInEachRun != value) {
195          storeAlgorithmInEachRun = value;
196          OnStoreAlgorithmInEachRunChanged();
197        }
198      }
199    }
200
201    [Storable]
202    private int runsCounter;
203    [Storable]
204    private RunCollection runs;
205    public RunCollection Runs {
206      get { return runs; }
207    }
208
209    [Storable]
210    private ExecutionState executionState;
211    public ExecutionState ExecutionState {
212      get { return executionState; }
213      private set {
214        if (executionState != value) {
215          executionState = value;
216          OnExecutionStateChanged();
217          OnItemImageChanged();
218        }
219      }
220    }
221    public override Image ItemImage {
222      get {
223        if (ExecutionState == ExecutionState.Prepared) return HeuristicLab.Common.Resources.VS2008ImageLibrary.ExecutablePrepared;
224        else if (ExecutionState == ExecutionState.Started) return HeuristicLab.Common.Resources.VS2008ImageLibrary.ExecutableStarted;
225        else if (ExecutionState == ExecutionState.Paused) return HeuristicLab.Common.Resources.VS2008ImageLibrary.ExecutablePaused;
226        else if (ExecutionState == ExecutionState.Stopped) return HeuristicLab.Common.Resources.VS2008ImageLibrary.ExecutableStopped;
227        else return HeuristicLab.Common.Resources.VS2008ImageLibrary.Event;
228      }
229    }
230
231    public TimeSpan ExecutionTime {
232      get {
233        if (ExecutionState != ExecutionState.Prepared)
234          return TimeSpan.FromMilliseconds(clonedAlgorithms.Select(x => x.ExecutionTime.TotalMilliseconds).Sum());
235        return TimeSpan.Zero;
236      }
237    }
238    #endregion
239
240    public void Prepare() {
241      if (ExecutionState == ExecutionState.Started)
242        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
243      results.Clear();
244      clonedAlgorithms.Clear();
245      if (Algorithm != null) {
246        Algorithm.Prepare();
247        if (Algorithm.ExecutionState == ExecutionState.Prepared) OnPrepared();
248      }
249    }
250    public void Prepare(bool clearRuns) {
251      if (clearRuns) runs.Clear();
252      Prepare();
253    }
254
255    private bool startPending;
256    public void Start() {
257      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
258        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
259
260      if (Algorithm != null && !startPending) {
261        startPending = true;
262        //create cloned algorithms
263        if (clonedAlgorithms.Count == 0) {
264          int testSamplesCount = (SamplesEnd.Value - SamplesStart.Value) / Folds.Value;
265          for (int i = 0; i < Folds.Value; i++) {
266            IAlgorithm clonedAlgorithm = (IAlgorithm)algorithm.Clone();
267            clonedAlgorithm.Name = algorithm.Name + " Fold " + i;
268            IDataAnalysisProblem problem = clonedAlgorithm.Problem as IDataAnalysisProblem;
269            problem.DataAnalysisProblemData.TestSamplesEnd.Value = (i + 1) == Folds.Value ? SamplesEnd.Value : (i + 1) * testSamplesCount + SamplesStart.Value;
270            problem.DataAnalysisProblemData.TestSamplesStart.Value = (i * testSamplesCount) + SamplesStart.Value;
271            clonedAlgorithms.Add(clonedAlgorithm);
272          }
273        }
274
275        //start prepared or paused cloned algorithms
276        int startedAlgorithms = 0;
277        foreach (IAlgorithm clonedAlgorithm in clonedAlgorithms) {
278          if (startedAlgorithms < NumberOfWorkers.Value) {
279            if (clonedAlgorithm.ExecutionState == ExecutionState.Prepared ||
280                clonedAlgorithm.ExecutionState == ExecutionState.Paused) {
281              clonedAlgorithm.Start();
282              startedAlgorithms++;
283            }
284          }
285        }
286        OnStarted();
287      }
288    }
289
290    private bool pausePending;
291    public void Pause() {
292      if (ExecutionState != ExecutionState.Started)
293        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
294      if (!pausePending) {
295        pausePending = true;
296        if (!startPending) PauseAllClonedAlgorithms();
297      }
298    }
299    private void PauseAllClonedAlgorithms() {
300      foreach (IAlgorithm clonedAlgorithm in ClonedAlgorithms) {
301        if (clonedAlgorithm.ExecutionState == ExecutionState.Started)
302          clonedAlgorithm.Pause();
303      }
304    }
305
306    private bool stopPending;
307    public void Stop() {
308      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
309        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".",
310                                                          ExecutionState));
311      if (!stopPending) {
312        stopPending = true;
313        if (!startPending) StopAllClonedAlgorithms();
314      }
315    }
316    private void StopAllClonedAlgorithms() {
317      foreach (IAlgorithm clonedAlgorithm in ClonedAlgorithms) {
318        if (clonedAlgorithm.ExecutionState == ExecutionState.Started ||
319            clonedAlgorithm.ExecutionState == ExecutionState.Paused)
320          clonedAlgorithm.Stop();
321      }
322    }
323
324    #region collect parameters and results
325    public override void CollectParameterValues(IDictionary<string, IItem> values) {
326      values.Add("Algorithm Name", new StringValue(Name));
327      values.Add("Algorithm Type", new StringValue(GetType().GetPrettyName()));
328      values.Add("Folds", new IntValue(Folds.Value));
329
330      if (algorithm != null) {
331        values.Add("CrossValidation Algorithm Name", new StringValue(Algorithm.Name));
332        values.Add("CrossValidation Algorithm Type", new StringValue(Algorithm.GetType().GetPrettyName()));
333        base.CollectParameterValues(values);
334      }
335      if (Problem != null) {
336        values.Add("Problem Name", new StringValue(Problem.Name));
337        values.Add("Problem Type", new StringValue(Problem.GetType().GetPrettyName()));
338        Problem.CollectParameterValues(values);
339      }
340    }
341
342    public void CollectResultValues(IDictionary<string, IItem> results) {
343      Dictionary<string, List<double>> resultValues = new Dictionary<string, List<double>>();
344      IEnumerable<IRun> runs = ClonedAlgorithms.Select(alg => alg.Runs.FirstOrDefault()).Where(run => run != null);
345      IEnumerable<KeyValuePair<string, IItem>> resultCollections = runs.Where(x => x != null).SelectMany(x => x.Results).ToList();
346
347      foreach (IResult result in ExtractAndAggregateResults<IntValue>(resultCollections))
348        results.Add(result.Name, result.Value);
349      foreach (IResult result in ExtractAndAggregateResults<DoubleValue>(resultCollections))
350        results.Add(result.Name, result.Value);
351      foreach (IResult result in ExtractAndAggregateResults<PercentValue>(resultCollections))
352        results.Add(result.Name, result.Value);
353
354      results.Add("Execution Time", new TimeSpanValue(this.ExecutionTime));
355      results.Add("CrossValidation Folds", new RunCollection(runs));
356    }
357
358    private static IEnumerable<IResult> ExtractAndAggregateResults<T>(IEnumerable<KeyValuePair<string, IItem>> results)
359  where T : class, IItem, new() {
360      Dictionary<string, List<double>> resultValues = new Dictionary<string, List<double>>();
361      foreach (var resultValue in results.Where(r => r.Value.GetType() == typeof(T))) {
362        if (!resultValues.ContainsKey(resultValue.Key))
363          resultValues[resultValue.Key] = new List<double>();
364        resultValues[resultValue.Key].Add(ConvertToDouble(resultValue.Value));
365      }
366
367      DoubleValue doubleValue;
368      if (typeof(T) == typeof(PercentValue))
369        doubleValue = new PercentValue();
370      else if (typeof(T) == typeof(DoubleValue))
371        doubleValue = new DoubleValue();
372      else if (typeof(T) == typeof(IntValue))
373        doubleValue = new DoubleValue();
374      else
375        throw new NotSupportedException();
376
377      List<IResult> aggregatedResults = new List<IResult>();
378      foreach (KeyValuePair<string, List<double>> resultValue in resultValues) {
379        doubleValue.Value = resultValue.Value.Average();
380        aggregatedResults.Add(new Result(resultValue.Key, (IItem)doubleValue.Clone()));
381        doubleValue.Value = resultValue.Value.StandardDeviation();
382        aggregatedResults.Add(new Result(resultValue.Key + " StdDev", (IItem)doubleValue.Clone()));
383      }
384      return aggregatedResults;
385    }
386
387    private static double ConvertToDouble(IItem item) {
388      if (item is DoubleValue) return ((DoubleValue)item).Value;
389      else if (item is IntValue) return ((IntValue)item).Value;
390      else throw new NotSupportedException("Could not convert any item type to double");
391    }
392    #endregion
393
394    #region events
395    private void RegisterEvents() {
396      Folds.ValueChanged += new EventHandler(Folds_ValueChanged);
397      SamplesStart.ValueChanged += new EventHandler(SamplesStart_ValueChanged);
398      SamplesEnd.ValueChanged += new EventHandler(SamplesEnd_ValueChanged);
399      RegisterClonedAlgorithmsEvents();
400    }
401    private void Folds_ValueChanged(object sender, EventArgs e) {
402      if (ExecutionState != ExecutionState.Prepared)
403        throw new InvalidOperationException("Can not change number of folds if the execution state is not prepared.");
404    }
405    private void SamplesStart_ValueChanged(object sender, EventArgs e) {
406      if (Problem != null) Problem.DataAnalysisProblemData.TrainingSamplesStart.Value = SamplesStart.Value;
407    }
408    private void SamplesEnd_ValueChanged(object sender, EventArgs e) {
409      if (Problem != null) Problem.DataAnalysisProblemData.TrainingSamplesEnd.Value = SamplesEnd.Value;
410    }
411
412    #region template algorithms events
413    public event EventHandler AlgorithmChanged;
414    private void OnAlgorithmChanged() {
415      EventHandler handler = AlgorithmChanged;
416      if (handler != null) handler(this, EventArgs.Empty);
417      OnProblemChanged();
418      if (Problem == null) ExecutionState = ExecutionState.Stopped;
419    }
420    private void RegisterAlgorithmEvents() {
421      algorithm.ProblemChanged += new EventHandler(Algorithm_ProblemChanged);
422      algorithm.ExecutionStateChanged += new EventHandler(Algorithm_ExecutionStateChanged);
423    }
424    private void DeregisterAlgorithmEvents() {
425      algorithm.ProblemChanged -= new EventHandler(Algorithm_ProblemChanged);
426      algorithm.ExecutionStateChanged -= new EventHandler(Algorithm_ExecutionStateChanged);
427    }
428    private void Algorithm_ProblemChanged(object sender, EventArgs e) {
429      if (algorithm.Problem != null && !(algorithm.Problem is ISingleObjectiveDataAnalysisProblem)) {
430        algorithm.Problem = problem;
431        throw new ArgumentException("A cross validation algorithm can only contain DataAnalysisProblems.");
432      }
433      problem = (ISingleObjectiveDataAnalysisProblem)algorithm.Problem;
434      OnProblemChanged();
435    }
436    public event EventHandler ProblemChanged;
437    private void OnProblemChanged() {
438      EventHandler handler = ProblemChanged;
439      if (handler != null) handler(this, EventArgs.Empty);
440
441      SamplesStart.Value = 0;
442      if (Problem != null)
443        SamplesEnd.Value = Problem.DataAnalysisProblemData.Dataset.Rows;
444      else
445        SamplesEnd.Value = 0;
446    }
447
448    private void Algorithm_ExecutionStateChanged(object sender, EventArgs e) {
449      switch (Algorithm.ExecutionState) {
450        case ExecutionState.Prepared: OnPrepared();
451          break;
452        case ExecutionState.Started: throw new InvalidOperationException("Algorithm template can not be started.");
453        case ExecutionState.Paused: throw new InvalidOperationException("Algorithm template can not be paused.");
454        case ExecutionState.Stopped: OnStopped();
455          break;
456      }
457    }
458    #endregion
459
460    #region clonedAlgorithms events
461    private void RegisterClonedAlgorithmsEvents() {
462      clonedAlgorithms.ItemsAdded += new CollectionItemsChangedEventHandler<IAlgorithm>(ClonedAlgorithms_ItemsAdded);
463      clonedAlgorithms.ItemsRemoved += new CollectionItemsChangedEventHandler<IAlgorithm>(ClonedAlgorithms_ItemsRemoved);
464      clonedAlgorithms.CollectionReset += new CollectionItemsChangedEventHandler<IAlgorithm>(ClonedAlgorithms_CollectionReset);
465      foreach (IAlgorithm algorithm in clonedAlgorithms)
466        RegisterClonedAlgorithmEvents(algorithm);
467    }
468    private void DeregisterClonedAlgorithmsEvents() {
469      clonedAlgorithms.ItemsAdded -= new CollectionItemsChangedEventHandler<IAlgorithm>(ClonedAlgorithms_ItemsAdded);
470      clonedAlgorithms.ItemsRemoved -= new CollectionItemsChangedEventHandler<IAlgorithm>(ClonedAlgorithms_ItemsRemoved);
471      clonedAlgorithms.CollectionReset -= new CollectionItemsChangedEventHandler<IAlgorithm>(ClonedAlgorithms_CollectionReset);
472      foreach (IAlgorithm algorithm in clonedAlgorithms)
473        DeregisterClonedAlgorithmEvents(algorithm);
474    }
475    private void ClonedAlgorithms_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IAlgorithm> e) {
476      foreach (IAlgorithm algorithm in e.Items)
477        RegisterClonedAlgorithmEvents(algorithm);
478    }
479    private void ClonedAlgorithms_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IAlgorithm> e) {
480      foreach (IAlgorithm algorithm in e.Items)
481        DeregisterClonedAlgorithmEvents(algorithm);
482    }
483    private void ClonedAlgorithms_CollectionReset(object sender, CollectionItemsChangedEventArgs<IAlgorithm> e) {
484      foreach (IAlgorithm algorithm in e.OldItems)
485        DeregisterClonedAlgorithmEvents(algorithm);
486      foreach (IAlgorithm algorithm in e.Items)
487        RegisterClonedAlgorithmEvents(algorithm);
488    }
489    private void RegisterClonedAlgorithmEvents(IAlgorithm algorithm) {
490      algorithm.ExceptionOccurred += new EventHandler<EventArgs<Exception>>(ClonedAlgorithm_ExceptionOccurred);
491      algorithm.ExecutionTimeChanged += new EventHandler(ClonedAlgorithm_ExecutionTimeChanged);
492      algorithm.Started += new EventHandler(ClonedAlgorithm_Started);
493      algorithm.Paused += new EventHandler(ClonedAlgorithm_Paused);
494      algorithm.Stopped += new EventHandler(ClonedAlgorithm_Stopped);
495    }
496    private void DeregisterClonedAlgorithmEvents(IAlgorithm algorithm) {
497      algorithm.ExceptionOccurred -= new EventHandler<EventArgs<Exception>>(ClonedAlgorithm_ExceptionOccurred);
498      algorithm.ExecutionTimeChanged -= new EventHandler(ClonedAlgorithm_ExecutionTimeChanged);
499      algorithm.Started -= new EventHandler(ClonedAlgorithm_Started);
500      algorithm.Paused -= new EventHandler(ClonedAlgorithm_Paused);
501      algorithm.Stopped -= new EventHandler(ClonedAlgorithm_Stopped);
502    }
503    private void ClonedAlgorithm_ExceptionOccurred(object sender, EventArgs<Exception> e) {
504      OnExceptionOccurred(e.Value);
505    }
506    private void ClonedAlgorithm_ExecutionTimeChanged(object sender, EventArgs e) {
507      OnExecutionTimeChanged();
508    }
509
510    private readonly object locker = new object();
511    private void ClonedAlgorithm_Started(object sender, EventArgs e) {
512      lock (locker) {
513        IAlgorithm algorithm = sender as IAlgorithm;
514        if (algorithm != null && !results.ContainsKey(algorithm.Name))
515          results.Add(new Result(algorithm.Name, "Contains results for the specific fold.", algorithm.Results));
516
517        if (startPending) {
518          int startedAlgorithms = clonedAlgorithms.Count(alg => alg.ExecutionState == ExecutionState.Started);
519          if (startedAlgorithms == NumberOfWorkers.Value ||
520             clonedAlgorithms.All(alg => alg.ExecutionState != ExecutionState.Prepared))
521            startPending = false;
522
523          if (pausePending) PauseAllClonedAlgorithms();
524          if (stopPending) StopAllClonedAlgorithms();
525        }
526      }
527    }
528
529    private void ClonedAlgorithm_Paused(object sender, EventArgs e) {
530      lock (locker) {
531        if (pausePending && clonedAlgorithms.All(alg => alg.ExecutionState != ExecutionState.Started))
532          OnPaused();
533      }
534    }
535
536    private void ClonedAlgorithm_Stopped(object sender, EventArgs e) {
537      lock (locker) {
538        if (!stopPending && ExecutionState == ExecutionState.Started) {
539          IAlgorithm preparedAlgorithm = clonedAlgorithms.Where(alg => alg.ExecutionState == ExecutionState.Prepared ||
540                                                                       alg.ExecutionState == ExecutionState.Paused).FirstOrDefault();
541          if (preparedAlgorithm != null) preparedAlgorithm.Start();
542        }
543        if (ExecutionState != ExecutionState.Stopped) {
544          if (clonedAlgorithms.All(alg => alg.ExecutionState == ExecutionState.Stopped))
545            OnStopped();
546          else if (stopPending &&
547                   clonedAlgorithms.All(
548                     alg => alg.ExecutionState == ExecutionState.Prepared || alg.ExecutionState == ExecutionState.Stopped))
549            OnStopped();
550        }
551      }
552    }
553    #endregion
554    #endregion
555
556    #region event firing
557    public event EventHandler ExecutionStateChanged;
558    private void OnExecutionStateChanged() {
559      EventHandler handler = ExecutionStateChanged;
560      if (handler != null) handler(this, EventArgs.Empty);
561    }
562    public event EventHandler ExecutionTimeChanged;
563    private void OnExecutionTimeChanged() {
564      EventHandler handler = ExecutionTimeChanged;
565      if (handler != null) handler(this, EventArgs.Empty);
566    }
567    public event EventHandler Prepared;
568    private void OnPrepared() {
569      ExecutionState = ExecutionState.Prepared;
570      EventHandler handler = Prepared;
571      if (handler != null) handler(this, EventArgs.Empty);
572      OnExecutionTimeChanged();
573    }
574    public event EventHandler Started;
575    private void OnStarted() {
576      startPending = false;
577      ExecutionState = ExecutionState.Started;
578      EventHandler handler = Started;
579      if (handler != null) handler(this, EventArgs.Empty);
580    }
581    public event EventHandler Paused;
582    private void OnPaused() {
583      pausePending = false;
584      ExecutionState = ExecutionState.Paused;
585      EventHandler handler = Paused;
586      if (handler != null) handler(this, EventArgs.Empty);
587    }
588    public event EventHandler Stopped;
589    private void OnStopped() {
590      stopPending = false;
591      Dictionary<string, IItem> collectedResults = new Dictionary<string, IItem>();
592      CollectResultValues(collectedResults);
593      results.AddRange(collectedResults.Select(x => new Result(x.Key, x.Value)).Cast<IResult>().ToArray());
594      runsCounter++;
595      runs.Add(new Run(string.Format("{0} Run {1}", Name, runsCounter), this));
596      ExecutionState = ExecutionState.Stopped;
597      EventHandler handler = Stopped;
598      if (handler != null) handler(this, EventArgs.Empty);
599    }
600    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
601    private void OnExceptionOccurred(Exception exception) {
602      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
603      if (handler != null) handler(this, new EventArgs<Exception>(exception));
604    }
605    public event EventHandler StoreAlgorithmInEachRunChanged;
606    private void OnStoreAlgorithmInEachRunChanged() {
607      EventHandler handler = StoreAlgorithmInEachRunChanged;
608      if (handler != null) handler(this, EventArgs.Empty);
609    }
610    #endregion
611  }
612}
Note: See TracBrowser for help on using the repository browser.