Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Benchmarking/sources/HeuristicLab.Algorithms.Benchmarks/3.3/Benchmark.cs @ 6934

Last change on this file since 6934 was 6934, checked in by ascheibe, 12 years ago

on behalf of spimming:
#1659

  • implemented abstract base class for benchmarking algorithms
  • added License information
  • corrected plugin dependencies
  • corrected descriptions
File size: 17.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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 System.Threading;
27using System.Threading.Tasks;
28using HeuristicLab.Collections;
29using HeuristicLab.Common;
30using HeuristicLab.Core;
31using HeuristicLab.Data;
32using HeuristicLab.Optimization;
33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34
35namespace HeuristicLab.Algorithms.Benchmarks {
36  /// <summary>
37  /// A base class for benchmarks.
38  /// </summary>
39  [Item("Benchmark", "A base class for benchmarks.")]
40  [StorableClass]
41  public abstract class Benchmark : IAlgorithm {
42
43    private DateTime lastUpdateTime;
44
45    [Storable]
46    private ExecutionState executionState;
47    public ExecutionState ExecutionState {
48      get { return executionState; }
49      private set {
50        if (executionState != value) {
51          executionState = value;
52          OnExecutionStateChanged();
53          OnItemImageChanged();
54        }
55      }
56    }
57
58    [Storable]
59    private TimeSpan executionTime;
60    public TimeSpan ExecutionTime {
61      get { return executionTime; }
62      protected set {
63        executionTime = value;
64        OnExecutionTimeChanged();
65      }
66    }
67
68    [Storable]
69    private bool storeAlgorithmInEachRun;
70    public bool StoreAlgorithmInEachRun {
71      get { return storeAlgorithmInEachRun; }
72      set {
73        if (storeAlgorithmInEachRun != value) {
74          storeAlgorithmInEachRun = value;
75          OnStoreAlgorithmInEachRunChanged();
76        }
77      }
78    }
79
80    [Storable]
81    protected int runsCounter;
82
83    [Storable]
84    private RunCollection runs = new RunCollection();
85    public RunCollection Runs {
86      get { return runs; }
87      protected 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    [Storable]
98    private ResultCollection results;
99    public ResultCollection Results {
100      get { return results; }
101    }
102
103    [Storable]
104    private IProblem problem;
105    public IProblem Problem {
106      get { return problem; }
107      set {
108        if (problem != value) {
109          if ((value != null) && !ProblemType.IsInstanceOfType(value)) throw new ArgumentException("Invalid problem type.");
110          if (problem != null) DeregisterProblemEvents();
111          problem = value;
112          if (problem != null) RegisterProblemEvents();
113          OnProblemChanged();
114          Prepare();
115        }
116      }
117    }
118
119    public Type ProblemType {
120      get { return typeof(IProblem); }
121    }
122
123    [Storable]
124    protected string name;
125
126    public string Name {
127      get { return name; }
128      set {
129        if (!CanChangeName) throw new NotSupportedException("Name cannot be changed.");
130        if (!(name.Equals(value) || (value == null) && (name == string.Empty))) {
131          CancelEventArgs<string> e = value == null ? new CancelEventArgs<string>(string.Empty) : new CancelEventArgs<string>(value);
132          OnNameChanging(e);
133          if (!e.Cancel) {
134            name = value == null ? string.Empty : value;
135            OnNameChanged();
136          }
137        }
138      }
139    }
140
141    public bool CanChangeName {
142      get { return false; }
143    }
144
145    [Storable]
146    protected string description;
147    public string Description {
148      get { return description; }
149      set {
150        if (!CanChangeDescription) throw new NotSupportedException("Description cannot be changed.");
151        if (!(description.Equals(value) || (value == null) && (description == string.Empty))) {
152          description = value == null ? string.Empty : value;
153          OnDescriptionChanged();
154        }
155      }
156    }
157
158    public bool CanChangeDescription {
159      get { return false; }
160    }
161
162    public string ItemName {
163      get { return ItemAttribute.GetName(this.GetType()); }
164    }
165
166    public string ItemDescription {
167      get { return ItemAttribute.GetDescription(this.GetType()); }
168    }
169
170    public Version ItemVersion {
171      get { return ItemAttribute.GetVersion(this.GetType()); }
172    }
173
174    public Image ItemImage {
175      get {
176        if (ExecutionState == ExecutionState.Prepared) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePrepared;
177        else if (ExecutionState == ExecutionState.Started) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
178        else if (ExecutionState == ExecutionState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePaused;
179        else if (ExecutionState == ExecutionState.Stopped) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
180        else return HeuristicLab.Common.Resources.VSImageLibrary.Event;
181      }
182    }
183
184    [Storable]
185    private ParameterCollection parameters = new ParameterCollection();
186
187    public IKeyedItemCollection<string, IParameter> Parameters {
188      get { return parameters; }
189    }
190
191    private ReadOnlyKeyedItemCollection<string, IParameter> readOnlyParameters;
192
193    IKeyedItemCollection<string, IParameter> IParameterizedItem.Parameters {
194      get {
195        if (readOnlyParameters == null) readOnlyParameters = parameters.AsReadOnly();
196        return readOnlyParameters;
197      }
198    }
199
200    public IEnumerable<IOptimizer> NestedOptimizers {
201      get { return Enumerable.Empty<IOptimizer>(); }
202    }
203
204    #region Constructors
205
206    protected Benchmark() {
207      name = ItemName;
208      description = ItemDescription;
209      parameters = new ParameterCollection();
210      readOnlyParameters = null;
211      executionState = ExecutionState.Stopped;
212      executionTime = TimeSpan.Zero;
213      storeAlgorithmInEachRun = false;
214      runsCounter = 0;
215      Runs = new RunCollection();
216      results = new ResultCollection();
217      Prepare();
218    }
219
220    protected Benchmark(Benchmark original, Cloner cloner) {
221      cloner.RegisterClonedObject(original, this);
222      name = original.name;
223      description = original.description;
224      parameters = cloner.Clone(original.parameters);
225      readOnlyParameters = null;
226      if (ExecutionState == ExecutionState.Started) throw new InvalidOperationException(string.Format("Clone not allowed in execution state \"{0}\".", ExecutionState));
227      executionState = original.executionState;
228      executionTime = original.executionTime;
229      storeAlgorithmInEachRun = original.storeAlgorithmInEachRun;
230      runsCounter = original.runsCounter;
231      runs = cloner.Clone(original.runs);
232      Initialize();
233
234      results = new ResultCollection();
235      Prepare();
236    }
237
238    #endregion
239
240    private void Initialize() {
241      if (problem != null) RegisterProblemEvents();
242      if (runs != null) RegisterRunsEvents();
243    }
244
245    public virtual void Prepare() {
246      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused) && (ExecutionState != ExecutionState.Stopped))
247        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
248      results.Clear();
249      OnPrepared();
250    }
251
252    public void Prepare(bool clearRuns) {
253      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused) && (ExecutionState != ExecutionState.Stopped))
254        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
255      if (clearRuns) runs.Clear();
256      Prepare();
257    }
258
259    public virtual void Pause() {
260      if (ExecutionState != ExecutionState.Started)
261        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
262    }
263    public virtual void Stop() {
264      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
265        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
266    }
267
268    public virtual void Start() {
269      var cancellationTokenSource = new CancellationTokenSource();
270      OnStarted();
271      Task task = Task.Factory.StartNew(Run, cancellationTokenSource.Token, cancellationTokenSource.Token);
272      task.ContinueWith(t => {
273        try {
274          t.Wait();
275        }
276        catch (AggregateException ex) {
277          try {
278            ex.Flatten().Handle(x => x is OperationCanceledException);
279          }
280          catch (AggregateException remaining) {
281            if (remaining.InnerExceptions.Count == 1) OnExceptionOccurred(remaining.InnerExceptions[0]);
282            else OnExceptionOccurred(remaining);
283          }
284        }
285        cancellationTokenSource.Dispose();
286        cancellationTokenSource = null;
287        OnStopped();
288      });
289    }
290
291    protected virtual void Run(object state) {
292      CancellationToken cancellationToken = (CancellationToken)state;
293      lastUpdateTime = DateTime.Now;
294      System.Timers.Timer timer = new System.Timers.Timer(250);
295      timer.AutoReset = true;
296      timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
297      timer.Start();
298      try {
299        RunBenchmark();
300      }
301      finally {
302        timer.Elapsed -= new System.Timers.ElapsedEventHandler(timer_Elapsed);
303        timer.Stop();
304        ExecutionTime += DateTime.Now - lastUpdateTime;
305      }
306
307      cancellationToken.ThrowIfCancellationRequested();
308    }
309
310    protected abstract void RunBenchmark();
311
312    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
313      System.Timers.Timer timer = (System.Timers.Timer)sender;
314      timer.Enabled = false;
315      DateTime now = DateTime.Now;
316      ExecutionTime += now - lastUpdateTime;
317      lastUpdateTime = now;
318      timer.Enabled = true;
319    }
320
321    public virtual void CollectResultValues(IDictionary<string, IItem> values) {
322      values.Add("Execution Time", new TimeSpanValue(ExecutionTime));
323      CollectResultsRecursively("", Results, values);
324    }
325
326    private void CollectResultsRecursively(string path, ResultCollection results, IDictionary<string, IItem> values) {
327      foreach (IResult result in results) {
328        values.Add(path + result.Name, result.Value);
329        ResultCollection childCollection = result.Value as ResultCollection;
330        if (childCollection != null) {
331          CollectResultsRecursively(path + result.Name + ".", childCollection, values);
332        }
333      }
334    }
335
336    public virtual void CollectParameterValues(IDictionary<string, IItem> values) {
337      foreach (IValueParameter param in parameters.OfType<IValueParameter>()) {
338        if (param.GetsCollected && param.Value != null) values.Add(param.Name, param.Value);
339        if (param.Value is IParameterizedItem) {
340          Dictionary<string, IItem> children = new Dictionary<string, IItem>();
341          ((IParameterizedItem)param.Value).CollectParameterValues(children);
342          foreach (string key in children.Keys)
343            values.Add(param.Name + "." + key, children[key]);
344        }
345      }
346      values.Add("Benchmark Name", new StringValue(Name));
347      values.Add("Benchmark Type", new StringValue(this.GetType().GetPrettyName()));
348    }
349
350    #region Events
351
352    public event EventHandler ExecutionStateChanged;
353    protected virtual void OnExecutionStateChanged() {
354      EventHandler handler = ExecutionStateChanged;
355      if (handler != null) handler(this, EventArgs.Empty);
356    }
357    public event EventHandler ExecutionTimeChanged;
358    protected virtual void OnExecutionTimeChanged() {
359      EventHandler handler = ExecutionTimeChanged;
360      if (handler != null) handler(this, EventArgs.Empty);
361    }
362    public event EventHandler ProblemChanged;
363    protected virtual void OnProblemChanged() {
364      EventHandler handler = ProblemChanged;
365      if (handler != null) handler(this, EventArgs.Empty);
366    }
367    public event EventHandler StoreAlgorithmInEachRunChanged;
368    protected virtual void OnStoreAlgorithmInEachRunChanged() {
369      EventHandler handler = StoreAlgorithmInEachRunChanged;
370      if (handler != null) handler(this, EventArgs.Empty);
371    }
372    public event EventHandler Prepared;
373    protected virtual void OnPrepared() {
374      ExecutionState = ExecutionState.Prepared;
375      ExecutionTime = TimeSpan.Zero;
376      foreach (IStatefulItem statefulObject in this.GetObjectGraphObjects().OfType<IStatefulItem>()) {
377        statefulObject.InitializeState();
378      }
379      EventHandler handler = Prepared;
380      if (handler != null) handler(this, EventArgs.Empty);
381    }
382    public event EventHandler Started;
383    protected virtual void OnStarted() {
384      ExecutionState = ExecutionState.Started;
385      EventHandler handler = Started;
386      if (handler != null) handler(this, EventArgs.Empty);
387    }
388    public event EventHandler Paused;
389    protected virtual void OnPaused() {
390      ExecutionState = ExecutionState.Paused;
391      EventHandler handler = Paused;
392      if (handler != null) handler(this, EventArgs.Empty);
393    }
394    public event EventHandler Stopped;
395    protected virtual void OnStopped() {
396      ExecutionState = ExecutionState.Stopped;
397      foreach (IStatefulItem statefulObject in this.GetObjectGraphObjects().OfType<IStatefulItem>()) {
398        statefulObject.ClearState();
399      }
400      runsCounter++;
401      runs.Add(new Run(string.Format("{0} Run {1}", Name, runsCounter), this));
402      EventHandler handler = Stopped;
403      if (handler != null) handler(this, EventArgs.Empty);
404    }
405    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
406    protected virtual void OnExceptionOccurred(Exception exception) {
407      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
408      if (handler != null) handler(this, new EventArgs<Exception>(exception));
409    }
410
411    public event EventHandler<CancelEventArgs<string>> NameChanging;
412    protected virtual void OnNameChanging(CancelEventArgs<string> e) {
413      var handler = NameChanging;
414      if (handler != null) handler(this, e);
415    }
416
417    public event EventHandler NameChanged;
418    protected virtual void OnNameChanged() {
419      var handler = NameChanged;
420      if (handler != null) handler(this, EventArgs.Empty);
421      OnToStringChanged();
422    }
423
424    public event EventHandler DescriptionChanged;
425    protected virtual void OnDescriptionChanged() {
426      var handler = DescriptionChanged;
427      if (handler != null) handler(this, EventArgs.Empty);
428    }
429
430    public event EventHandler ItemImageChanged;
431    protected virtual void OnItemImageChanged() {
432      EventHandler handler = ItemImageChanged;
433      if (handler != null) handler(this, EventArgs.Empty);
434    }
435    public event EventHandler ToStringChanged;
436    protected virtual void OnToStringChanged() {
437      EventHandler handler = ToStringChanged;
438      if (handler != null) handler(this, EventArgs.Empty);
439    }
440
441    protected virtual void DeregisterProblemEvents() {
442      problem.OperatorsChanged -= new EventHandler(Problem_OperatorsChanged);
443      problem.Reset -= new EventHandler(Problem_Reset);
444    }
445    protected virtual void RegisterProblemEvents() {
446      problem.OperatorsChanged += new EventHandler(Problem_OperatorsChanged);
447      problem.Reset += new EventHandler(Problem_Reset);
448    }
449    protected virtual void Problem_OperatorsChanged(object sender, EventArgs e) { }
450    protected virtual void Problem_Reset(object sender, EventArgs e) {
451      Prepare();
452    }
453
454    protected virtual void DeregisterRunsEvents() {
455      runs.CollectionReset -= new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
456    }
457    protected virtual void RegisterRunsEvents() {
458      runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
459    }
460    protected virtual void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
461      runsCounter = runs.Count;
462    }
463
464    #endregion
465
466    #region IDeepCloneable Members
467
468    public abstract IDeepCloneable Clone(Cloner cloner);
469
470    #endregion
471
472    #region ICloneable Members
473
474    public object Clone() {
475      return Clone(new Cloner());
476    }
477
478    #endregion
479  }
480}
Note: See TracBrowser for help on using the repository browser.