Free cookie consent management tool by TermsFeed Policy Generator

source: branches/RuntimeOptimizer/HeuristicLab.Optimization/3.3/MetaOptimizers/TimeLimitRun.cs @ 8955

Last change on this file since 8955 was 8955, checked in by abeham, 11 years ago

#1985: Added optimizer and view

File size: 16.7 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.ComponentModel;
25using System.Drawing;
26using System.Linq;
27using System.Threading;
28using System.Timers;
29using HeuristicLab.Collections;
30using HeuristicLab.Common;
31using HeuristicLab.Common.Resources;
32using HeuristicLab.Core;
33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34using Timer = System.Timers.Timer;
35
36namespace HeuristicLab.Optimization {
37  internal enum TimeLimitedRunAction { None, Prepare, Start, Pause, Stop };
38
39  /// <summary>
40  /// A run in which an algorithm is executed for a certain maximum time only.
41  /// </summary>
42  [Item("TimeLimitRun", "A run in which an optimizer is executed a certain maximum time.")]
43  [Creatable("Testing & Analysis")]
44  [StorableClass]
45  public sealed class TimeLimitRun : NamedItem, IOptimizer, IStorableContent, INotifyPropertyChanged {
46    public string Filename { get; set; }
47
48    #region ItemImage
49    public static new Image StaticItemImage {
50      get { return VSImageLibrary.Event; }
51    }
52    public override Image ItemImage {
53      get { return (Algorithm != null) ? Algorithm.ItemImage : VSImageLibrary.ExecutableStopped; }
54    }
55    #endregion
56
57    private readonly Timer snapTimer;
58    private readonly Timer runTimer;
59    private readonly ManualResetEvent algorithmPaused = new ManualResetEvent(false);
60    private readonly ManualResetEvent algorithmStopped = new ManualResetEvent(false);
61
62    [Storable]
63    private TimeSpan maximumExecutionTime;
64    public TimeSpan MaximumExecutionTime {
65      get { return maximumExecutionTime; }
66      set {
67        if (maximumExecutionTime == value) return;
68        maximumExecutionTime = value;
69        runTimer.Interval = (maximumExecutionTime - ExecutionTime).TotalMilliseconds;
70        OnPropertyChanged("MaximumExecutionTime");
71      }
72    }
73
74    [Storable]
75    private int snapshotTimesIndex;
76    [Storable]
77    private ObservableList<double> snapshotTimes;
78    public ObservableList<double> SnapshotTimes {
79      get { return snapshotTimes; }
80      set {
81        if (snapshotTimes == value) return;
82        snapshotTimes = value;
83        snapshotTimesIndex = 0;
84        OnPropertyChanged("SnapshotTimes");
85      }
86    }
87
88    [Storable]
89    private bool storeAlgorithmInEachSnapshot;
90    [Storable]
91    public bool StoreAlgorithmInEachSnapshot {
92      get { return storeAlgorithmInEachSnapshot; }
93      set {
94        if (storeAlgorithmInEachSnapshot == value) return;
95        storeAlgorithmInEachSnapshot = value;
96        OnPropertyChanged("StoreAlgorithmInEachSnapshot");
97      }
98    }
99
100    [Storable]
101    private RunCollection snapshots;
102    public RunCollection Snapshots {
103      get { return snapshots; }
104      set {
105        if (snapshots == value) return;
106        snapshots = value;
107        OnPropertyChanged("Snapshots");
108      }
109    }
110
111    #region Inherited Properties
112    public ExecutionState ExecutionState {
113      get { return (Algorithm != null) ? Algorithm.ExecutionState : ExecutionState.Stopped; }
114    }
115
116    public TimeSpan ExecutionTime {
117      get { return (Algorithm != null) ? Algorithm.ExecutionTime : TimeSpan.FromSeconds(0); }
118    }
119
120    [Storable]
121    private IAlgorithm algorithm;
122    public IAlgorithm Algorithm {
123      get { return algorithm; }
124      set {
125        if (algorithm == value) return;
126        if (algorithm != null) {
127          DeregisterAlgorithmEvents();
128          var runs = algorithm.Runs;
129          algorithm = null; //necessary to avoid removing the runs from the old algorithm
130          Runs.RemoveRange(runs);
131        }
132        algorithm = value;
133        if (algorithm != null) {
134          RegisterAlgorithmEvents();
135          Runs.AddRange(algorithm.Runs);
136          if (algorithm.ExecutionState == ExecutionState.Paused) algorithmPaused.Set();
137          else algorithmPaused.Reset();
138          if (algorithm.ExecutionState == ExecutionState.Stopped) algorithmStopped.Set();
139          else algorithmStopped.Reset();
140        }
141        OnPropertyChanged("Algorithm");
142        Prepare();
143      }
144    }
145
146    [Storable]
147    private RunCollection runs;
148    public RunCollection Runs {
149      get { return runs; }
150      private set {
151        if (value == null) throw new ArgumentNullException();
152        if (runs == value) return;
153        runs = value;
154        OnPropertyChanged("Runs");
155      }
156    }
157
158    public IEnumerable<IOptimizer> NestedOptimizers {
159      get {
160        if (Algorithm == null) yield break;
161        yield return Algorithm;
162        foreach (var opt in Algorithm.NestedOptimizers)
163          yield return opt;
164      }
165    }
166    #endregion
167
168    [StorableConstructor]
169    private TimeLimitRun(bool deserializing)
170      : base(deserializing) {
171      // the timer will not be serialized
172      snapTimer = new Timer() {
173        AutoReset = false,
174        Enabled = false,
175        Interval = double.MaxValue
176      };
177      runTimer = new Timer() {
178        AutoReset = false,
179        Enabled = false,
180        Interval = double.MaxValue
181      };
182    }
183    private TimeLimitRun(TimeLimitRun original, Cloner cloner)
184      : base(original, cloner) {
185      maximumExecutionTime = original.maximumExecutionTime;
186      snapshotTimes = new ObservableList<double>(original.snapshotTimes);
187      snapshotTimesIndex = original.snapshotTimesIndex;
188      snapTimer = new Timer() {
189        AutoReset = original.snapTimer.AutoReset,
190        Enabled = original.snapTimer.Enabled,
191        Interval = original.snapTimer.Interval
192      };
193      runTimer = new Timer() {
194        AutoReset = original.runTimer.AutoReset,
195        Enabled = original.runTimer.Enabled,
196        Interval = original.runTimer.Interval
197      };
198      snapshots = cloner.Clone(original.snapshots);
199      storeAlgorithmInEachSnapshot = original.storeAlgorithmInEachSnapshot;
200      algorithm = cloner.Clone(original.algorithm);
201      runs = cloner.Clone(original.runs);
202      Initialize();
203    }
204    public TimeLimitRun()
205      : base() {
206      name = ItemName;
207      description = ItemDescription;
208      maximumExecutionTime = TimeSpan.FromMinutes(1);
209      snapshotTimes = new ObservableList<double>(new[] {
210          TimeSpan.FromSeconds(5).TotalMilliseconds,
211          TimeSpan.FromSeconds(10).TotalMilliseconds,
212          TimeSpan.FromSeconds(30).TotalMilliseconds });
213      snapshotTimesIndex = 0;
214      snapTimer = new Timer() {
215        AutoReset = false,
216        Enabled = false,
217        Interval = snapshotTimes[snapshotTimesIndex]
218      };
219      runTimer = new Timer() {
220        AutoReset = false,
221        Enabled = false,
222        Interval = MaximumExecutionTime.TotalMilliseconds
223      };
224      snapshots = new RunCollection();
225      Runs = new RunCollection { AlgorithmName = Name };
226    }
227    public TimeLimitRun(string name)
228      : base(name) {
229      description = ItemDescription;
230      maximumExecutionTime = TimeSpan.FromMinutes(1);
231      snapshotTimes = new ObservableList<double>(new[] {
232          TimeSpan.FromSeconds(5).TotalMilliseconds,
233          TimeSpan.FromSeconds(10).TotalMilliseconds,
234          TimeSpan.FromSeconds(30).TotalMilliseconds });
235      snapshotTimesIndex = 0;
236      snapTimer = new Timer() {
237        AutoReset = false,
238        Enabled = false,
239        Interval = snapshotTimes[snapshotTimesIndex]
240      };
241      snapshots = new RunCollection();
242      runTimer = new Timer() {
243        AutoReset = false,
244        Enabled = false,
245        Interval = MaximumExecutionTime.TotalMilliseconds
246      };
247      Runs = new RunCollection { AlgorithmName = Name };
248    }
249    public TimeLimitRun(string name, string description)
250      : base(name, description) {
251      maximumExecutionTime = TimeSpan.FromMinutes(1);
252      snapshotTimes = new ObservableList<double>(new[] {
253          TimeSpan.FromSeconds(5).TotalMilliseconds,
254          TimeSpan.FromSeconds(10).TotalMilliseconds,
255          TimeSpan.FromSeconds(30).TotalMilliseconds });
256      snapshotTimesIndex = 0;
257      snapTimer = new Timer() {
258        AutoReset = false,
259        Enabled = false,
260        Interval = snapshotTimes[snapshotTimesIndex]
261      };
262      snapshots = new RunCollection();
263      runTimer = new Timer() {
264        AutoReset = false,
265        Enabled = false,
266        Interval = MaximumExecutionTime.TotalMilliseconds
267      };
268      Runs = new RunCollection { AlgorithmName = Name };
269    }
270
271    public override IDeepCloneable Clone(Cloner cloner) {
272      if (ExecutionState == ExecutionState.Started) throw new InvalidOperationException(string.Format("Clone not allowed in execution state \"{0}\".", ExecutionState));
273      return new TimeLimitRun(this, cloner);
274    }
275
276    [StorableHook(HookType.AfterDeserialization)]
277    private void AfterDeserialization() {
278      Initialize();
279    }
280
281    private void Initialize() {
282      if (algorithm != null) RegisterAlgorithmEvents();
283      snapTimer.Elapsed += snapshotTimer_Elapsed;
284      runTimer.Elapsed += runTimer_Elapsed;
285    }
286
287    private readonly object timerLock = new object();
288    private void snapshotTimer_Elapsed(object sender, ElapsedEventArgs e) {
289      lock (timerLock) {
290        runTimer.Stop();
291        if (Algorithm == null) return;
292        if (ExecutionState != ExecutionState.Started) return;
293        var error = false;
294        try { Algorithm.Pause(); } catch (InvalidOperationException) { error = true; }
295        if (error && ExecutionState != ExecutionState.Paused) return; // Algorithm is either stopped or prepared
296
297        algorithmPaused.WaitOne();
298        MakeSnapshot();
299        try { Algorithm.Start(); } catch (InvalidOperationException) { }
300      }
301    }
302
303    private void runTimer_Elapsed(object sender, ElapsedEventArgs e) {
304      lock (timerLock) {
305        runTimer.Stop();
306        snapTimer.Stop();
307        try { Algorithm.Stop(); } catch (InvalidOperationException) { }
308      }
309    }
310
311    private double? GetNextInterval(TimeSpan reference) {
312      double interval;
313      while ((interval = snapshotTimes[snapshotTimesIndex] - reference.TotalMilliseconds) <= 0) {
314        snapshotTimesIndex++;
315        if (snapshotTimesIndex >= snapshotTimes.Count) return null;
316      };
317      return interval;
318    }
319
320    private void MakeSnapshot() {
321      string runName = ExecutionTime.ToString() + " " + algorithm.Name + " Snapshot";
322      Run run;
323      if (StoreAlgorithmInEachSnapshot) {
324        run = new Run(runName, algorithm);
325      } else {
326        // duplicate code of Run.Initialize - necessary, because Algorithm property doesn't have a setter
327        run = new Run() { Name = runName };
328        var parameters = new Dictionary<string, IItem>();
329        var results = new Dictionary<string, IItem>();
330        algorithm.CollectParameterValues(parameters);
331        algorithm.CollectResultValues(results);
332        var cloner = new Cloner();
333        foreach (var kvp in parameters.Select(x => new KeyValuePair<string, IItem>(x.Key, cloner.Clone(x.Value))).ToDictionary(x => x.Key, x => x.Value))
334          run.Parameters.Add(kvp);
335        foreach (var kvp in results.Select(x => new KeyValuePair<string, IItem>(x.Key, cloner.Clone(x.Value))).ToDictionary(x => x.Key, x => x.Value))
336          run.Results.Add(kvp);
337      }
338      snapshots.Add(run);
339    }
340
341    public void Prepare() {
342      Prepare(false);
343    }
344    public void Prepare(bool clearRuns) {
345      Algorithm.Prepare(clearRuns);
346    }
347    public void Start() {
348      Algorithm.Start();
349    }
350    public void Pause() {
351      Algorithm.Pause();
352    }
353    public void Stop() {
354      Algorithm.Stop();
355    }
356
357    #region Events
358    protected override void OnNameChanged() {
359      base.OnNameChanged();
360      runs.AlgorithmName = Name;
361    }
362
363    public event PropertyChangedEventHandler PropertyChanged;
364    private void OnPropertyChanged(string property) {
365      var handler = PropertyChanged;
366      if (handler != null) handler(this, new PropertyChangedEventArgs(property));
367    }
368
369    #region IExecutable Events
370    public event EventHandler ExecutionStateChanged;
371    private void OnExecutionStateChanged() {
372      var handler = ExecutionStateChanged;
373      if (handler != null) handler(this, EventArgs.Empty);
374    }
375    public event EventHandler ExecutionTimeChanged;
376    private void OnExecutionTimeChanged() {
377      var handler = ExecutionTimeChanged;
378      if (handler != null) handler(this, EventArgs.Empty);
379    }
380    public event EventHandler Prepared;
381    private void OnPrepared() {
382      var handler = Prepared;
383      if (handler != null) handler(this, EventArgs.Empty);
384    }
385    public event EventHandler Started;
386    private void OnStarted() {
387      var handler = Started;
388      if (handler != null) handler(this, EventArgs.Empty);
389    }
390    public event EventHandler Paused;
391    private void OnPaused() {
392      var handler = Paused;
393      if (handler != null) handler(this, EventArgs.Empty);
394    }
395    public event EventHandler Stopped;
396    private void OnStopped() {
397      var handler = Stopped;
398      if (handler != null) handler(this, EventArgs.Empty);
399    }
400    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
401    private void OnExceptionOccurred(Exception exception) {
402      var handler = ExceptionOccurred;
403      if (handler != null) handler(this, new EventArgs<Exception>(exception));
404    }
405    #endregion
406
407    #region Algorithm Events
408    private void RegisterAlgorithmEvents() {
409      algorithm.ExceptionOccurred += Algorithm_ExceptionOccurred;
410      algorithm.ExecutionTimeChanged += Algorithm_ExecutionTimeChanged;
411      algorithm.ExecutionStateChanged += Algorithm_ExecutionStateChanged;
412      algorithm.Paused += Algorithm_Paused;
413      algorithm.Prepared += Algorithm_Prepared;
414      algorithm.Started += Algorithm_Started;
415      algorithm.Stopped += Algorithm_Stopped;
416    }
417    private void DeregisterAlgorithmEvents() {
418      algorithm.ExceptionOccurred -= Algorithm_ExceptionOccurred;
419      algorithm.ExecutionTimeChanged -= Algorithm_ExecutionTimeChanged;
420      algorithm.ExecutionStateChanged -= Algorithm_ExecutionStateChanged;
421      algorithm.Paused -= Algorithm_Paused;
422      algorithm.Prepared -= Algorithm_Prepared;
423      algorithm.Started -= Algorithm_Started;
424      algorithm.Stopped -= Algorithm_Stopped;
425    }
426    private void Algorithm_ExceptionOccurred(object sender, EventArgs<Exception> e) {
427      OnExceptionOccurred(e.Value);
428    }
429    private void Algorithm_ExecutionTimeChanged(object sender, EventArgs e) {
430      OnExecutionTimeChanged();
431    }
432    private void Algorithm_ExecutionStateChanged(object sender, EventArgs e) {
433      OnExecutionStateChanged();
434    }
435    private void Algorithm_Paused(object sender, EventArgs e) {
436      algorithmPaused.Set();
437      algorithmStopped.Reset();
438      OnPaused();
439    }
440    private void Algorithm_Prepared(object sender, EventArgs e) {
441      algorithmPaused.Reset();
442      algorithmStopped.Reset();
443      snapTimer.Stop();
444      runTimer.Stop();
445      snapshotTimesIndex = 0;
446      snapshots.Clear();
447      OnPrepared();
448    }
449    private void Algorithm_Started(object sender, EventArgs e) {
450      algorithmPaused.Reset();
451      algorithmStopped.Reset();
452      var execTime = ExecutionTime;
453      var interval = GetNextInterval(execTime);
454      if (interval.HasValue) {
455        snapTimer.Interval = interval.Value;
456        snapTimer.Start();
457      }
458      runTimer.Interval = (MaximumExecutionTime - execTime).TotalMilliseconds;
459      runTimer.Start();
460      OnStarted();
461    }
462    private void Algorithm_Stopped(object sender, EventArgs e) {
463      algorithmPaused.Reset();
464      algorithmStopped.Set();
465      snapTimer.Stop();
466      runTimer.Stop();
467      MakeSnapshot();
468      var snapshotsRun = new Run() { Name = algorithm.Runs.Last().Name };
469      foreach (var s in snapshots)
470        snapshotsRun.Parameters.Add(s.Name, s);
471      Runs.Add(snapshotsRun);
472      OnStopped();
473    }
474    #endregion
475    #endregion
476  }
477}
Note: See TracBrowser for help on using the repository browser.