Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/TimeLimitRun.cs @ 9079

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

#1985:

  • Added camera icon
  • Rewrote time matching to use regular expressions
  • Changed item name of TimeLimitRun
File size: 14.5 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.Tasks;
28using HeuristicLab.Collections;
29using HeuristicLab.Common;
30using HeuristicLab.Common.Resources;
31using HeuristicLab.Core;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33
34namespace HeuristicLab.Optimization {
35  internal enum TimeLimitedRunAction { None, Prepare, Start, Pause, Stop };
36
37  /// <summary>
38  /// A run in which an algorithm is executed for a certain maximum time only.
39  /// </summary>
40  [Item("TimeLimit Run", "A run in which an optimizer is executed a certain maximum time.")]
41  [Creatable("Testing & Analysis")]
42  [StorableClass]
43  public sealed class TimeLimitRun : NamedItem, IOptimizer, IStorableContent, INotifyPropertyChanged {
44    public string Filename { get; set; }
45
46    #region ItemImage
47    public static new Image StaticItemImage {
48      get { return VSImageLibrary.Event; }
49    }
50    public override Image ItemImage {
51      get { return (Algorithm != null) ? Algorithm.ItemImage : VSImageLibrary.ExecutableStopped; }
52    }
53    #endregion
54
55    private bool pausedForSnapshot = false;
56    private bool pausedForTermination = false;
57
58    [Storable]
59    private TimeSpan maximumExecutionTime;
60    public TimeSpan MaximumExecutionTime {
61      get { return maximumExecutionTime; }
62      set {
63        if (maximumExecutionTime == value) return;
64        maximumExecutionTime = value;
65        OnPropertyChanged("MaximumExecutionTime");
66      }
67    }
68
69    [Storable]
70    private int snapshotTimesIndex;
71    [Storable]
72    private ObservableList<TimeSpan> snapshotTimes;
73    public ObservableList<TimeSpan> SnapshotTimes {
74      get { return snapshotTimes; }
75      set {
76        if (snapshotTimes == value) return;
77        snapshotTimes = value;
78        snapshotTimes.Sort();
79        FindNextSnapshotTimeIndex(ExecutionTime);
80        OnPropertyChanged("SnapshotTimes");
81      }
82    }
83
84    [Storable]
85    private bool storeAlgorithmInEachSnapshot;
86    [Storable]
87    public bool StoreAlgorithmInEachSnapshot {
88      get { return storeAlgorithmInEachSnapshot; }
89      set {
90        if (storeAlgorithmInEachSnapshot == value) return;
91        storeAlgorithmInEachSnapshot = value;
92        OnPropertyChanged("StoreAlgorithmInEachSnapshot");
93      }
94    }
95
96    [Storable]
97    private RunCollection snapshots;
98    public RunCollection Snapshots {
99      get { return snapshots; }
100      set {
101        if (snapshots == value) return;
102        snapshots = value;
103        OnPropertyChanged("Snapshots");
104      }
105    }
106
107    #region Inherited Properties
108    public ExecutionState ExecutionState {
109      get { return (Algorithm != null) ? Algorithm.ExecutionState : ExecutionState.Stopped; }
110    }
111
112    public TimeSpan ExecutionTime {
113      get { return (Algorithm != null) ? Algorithm.ExecutionTime : TimeSpan.FromSeconds(0); }
114    }
115
116    [Storable]
117    private IAlgorithm algorithm;
118    public IAlgorithm Algorithm {
119      get { return algorithm; }
120      set {
121        if (algorithm == value) return;
122        if (algorithm != null) DeregisterAlgorithmEvents();
123        algorithm = value;
124        if (algorithm != null) {
125          RegisterAlgorithmEvents();
126        }
127        OnPropertyChanged("Algorithm");
128        Prepare();
129      }
130    }
131
132    [Storable]
133    private RunCollection runs;
134    public RunCollection Runs {
135      get { return runs; }
136      private set {
137        if (value == null) throw new ArgumentNullException();
138        if (runs == value) return;
139        runs = value;
140        OnPropertyChanged("Runs");
141      }
142    }
143
144    public IEnumerable<IOptimizer> NestedOptimizers {
145      get {
146        if (Algorithm == null) yield break;
147        yield return Algorithm;
148        foreach (var opt in Algorithm.NestedOptimizers)
149          yield return opt;
150      }
151    }
152    #endregion
153
154    [StorableConstructor]
155    private TimeLimitRun(bool deserializing) : base(deserializing) { }
156    private TimeLimitRun(TimeLimitRun original, Cloner cloner)
157      : base(original, cloner) {
158      maximumExecutionTime = original.maximumExecutionTime;
159      snapshotTimes = new ObservableList<TimeSpan>(original.snapshotTimes);
160      snapshotTimesIndex = original.snapshotTimesIndex;
161      snapshots = cloner.Clone(original.snapshots);
162      storeAlgorithmInEachSnapshot = original.storeAlgorithmInEachSnapshot;
163      algorithm = cloner.Clone(original.algorithm);
164      runs = cloner.Clone(original.runs);
165
166      Initialize();
167    }
168    public TimeLimitRun()
169      : base() {
170      name = ItemName;
171      description = ItemDescription;
172      maximumExecutionTime = TimeSpan.FromMinutes(.5);
173      snapshotTimes = new ObservableList<TimeSpan>(new[] {
174          TimeSpan.FromSeconds(5),
175          TimeSpan.FromSeconds(10),
176          TimeSpan.FromSeconds(15) });
177      snapshotTimesIndex = 0;
178      snapshots = new RunCollection();
179      Runs = new RunCollection { OptimizerName = Name };
180      Initialize();
181    }
182    public TimeLimitRun(string name)
183      : base(name) {
184      description = ItemDescription;
185      maximumExecutionTime = TimeSpan.FromMinutes(.5);
186      snapshotTimes = new ObservableList<TimeSpan>(new[] {
187          TimeSpan.FromSeconds(5),
188          TimeSpan.FromSeconds(10),
189          TimeSpan.FromSeconds(15) });
190      snapshotTimesIndex = 0;
191      Runs = new RunCollection { OptimizerName = Name };
192      Initialize();
193    }
194    public TimeLimitRun(string name, string description)
195      : base(name, description) {
196      maximumExecutionTime = TimeSpan.FromMinutes(.5);
197      snapshotTimes = new ObservableList<TimeSpan>(new[] {
198          TimeSpan.FromSeconds(5),
199          TimeSpan.FromSeconds(10),
200          TimeSpan.FromSeconds(15) });
201      snapshotTimesIndex = 0;
202      Runs = new RunCollection { OptimizerName = Name };
203      Initialize();
204    }
205
206    public override IDeepCloneable Clone(Cloner cloner) {
207      if (ExecutionState == ExecutionState.Started) throw new InvalidOperationException(string.Format("Clone not allowed in execution state \"{0}\".", ExecutionState));
208      return new TimeLimitRun(this, cloner);
209    }
210
211    [StorableHook(HookType.AfterDeserialization)]
212    private void AfterDeserialization() {
213      Initialize();
214    }
215
216    private void Initialize() {
217      if (algorithm != null) RegisterAlgorithmEvents();
218      snapshotTimes.ItemsAdded += snapshotTimes_Changed;
219      snapshotTimes.ItemsMoved += snapshotTimes_Changed;
220      snapshotTimes.ItemsRemoved += snapshotTimes_Changed;
221      snapshotTimes.ItemsReplaced += snapshotTimes_Changed;
222      snapshotTimes.CollectionReset += snapshotTimes_Changed;
223    }
224
225    private void snapshotTimes_Changed(object sender, CollectionItemsChangedEventArgs<IndexedItem<TimeSpan>> e) {
226      if (e.Items.Any()) snapshotTimes.Sort();
227      FindNextSnapshotTimeIndex(ExecutionTime);
228    }
229
230    public void Snapshot() {
231      if (Algorithm == null || Algorithm.ExecutionState != ExecutionState.Paused) throw new InvalidOperationException("Snapshot not allowed in execution states other than Paused");
232      Task.Factory.StartNew(MakeSnapshot);
233    }
234
235    public void Prepare() {
236      Prepare(false);
237    }
238    public void Prepare(bool clearRuns) {
239      Algorithm.Prepare(clearRuns);
240    }
241    public void Start() {
242      Algorithm.Start();
243    }
244    public void Pause() {
245      Algorithm.Pause();
246    }
247    public void Stop() {
248      Algorithm.Stop();
249    }
250
251    #region Events
252    protected override void OnNameChanged() {
253      base.OnNameChanged();
254      runs.OptimizerName = Name;
255    }
256
257    public event PropertyChangedEventHandler PropertyChanged;
258    private void OnPropertyChanged(string property) {
259      var handler = PropertyChanged;
260      if (handler != null) handler(this, new PropertyChangedEventArgs(property));
261    }
262
263    #region IExecutable Events
264    public event EventHandler ExecutionStateChanged;
265    private void OnExecutionStateChanged() {
266      var handler = ExecutionStateChanged;
267      if (handler != null) handler(this, EventArgs.Empty);
268    }
269    public event EventHandler ExecutionTimeChanged;
270    private void OnExecutionTimeChanged() {
271      var handler = ExecutionTimeChanged;
272      if (handler != null) handler(this, EventArgs.Empty);
273    }
274    public event EventHandler Prepared;
275    private void OnPrepared() {
276      var handler = Prepared;
277      if (handler != null) handler(this, EventArgs.Empty);
278    }
279    public event EventHandler Started;
280    private void OnStarted() {
281      var handler = Started;
282      if (handler != null) handler(this, EventArgs.Empty);
283    }
284    public event EventHandler Paused;
285    private void OnPaused() {
286      var handler = Paused;
287      if (handler != null) handler(this, EventArgs.Empty);
288    }
289    public event EventHandler Stopped;
290    private void OnStopped() {
291      var handler = Stopped;
292      if (handler != null) handler(this, EventArgs.Empty);
293    }
294    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
295    private void OnExceptionOccurred(Exception exception) {
296      var handler = ExceptionOccurred;
297      if (handler != null) handler(this, new EventArgs<Exception>(exception));
298    }
299    #endregion
300
301    #region Algorithm Events
302    private void RegisterAlgorithmEvents() {
303      algorithm.ExceptionOccurred += Algorithm_ExceptionOccurred;
304      algorithm.ExecutionTimeChanged += Algorithm_ExecutionTimeChanged;
305      algorithm.ExecutionStateChanged += Algorithm_ExecutionStateChanged;
306      algorithm.Paused += Algorithm_Paused;
307      algorithm.Prepared += Algorithm_Prepared;
308      algorithm.Started += Algorithm_Started;
309      algorithm.Stopped += Algorithm_Stopped;
310    }
311    private void DeregisterAlgorithmEvents() {
312      algorithm.ExceptionOccurred -= Algorithm_ExceptionOccurred;
313      algorithm.ExecutionTimeChanged -= Algorithm_ExecutionTimeChanged;
314      algorithm.ExecutionStateChanged -= Algorithm_ExecutionStateChanged;
315      algorithm.Paused -= Algorithm_Paused;
316      algorithm.Prepared -= Algorithm_Prepared;
317      algorithm.Started -= Algorithm_Started;
318      algorithm.Stopped -= Algorithm_Stopped;
319    }
320    private void Algorithm_ExceptionOccurred(object sender, EventArgs<Exception> e) {
321      OnExceptionOccurred(e.Value);
322    }
323    private void Algorithm_ExecutionTimeChanged(object sender, EventArgs e) {
324      if (snapshotTimesIndex < SnapshotTimes.Count && ExecutionTime >= SnapshotTimes[snapshotTimesIndex]
325        && !pausedForSnapshot) {
326        pausedForSnapshot = true;
327        Algorithm.Pause();
328      }
329      if (ExecutionTime >= MaximumExecutionTime && !pausedForTermination) {
330        pausedForTermination = true;
331        if (!pausedForSnapshot) Algorithm.Pause();
332      }
333      OnExecutionTimeChanged();
334    }
335    private void Algorithm_ExecutionStateChanged(object sender, EventArgs e) {
336      OnExecutionStateChanged();
337    }
338    private void Algorithm_Paused(object sender, EventArgs e) {
339      var action = pausedForTermination ? ExecutionState.Stopped : (pausedForSnapshot ? ExecutionState.Started : ExecutionState.Paused);
340      if (pausedForSnapshot || pausedForTermination) {
341        pausedForSnapshot = pausedForTermination = false;
342        MakeSnapshot();
343        FindNextSnapshotTimeIndex(ExecutionTime);
344      }
345      OnPaused();
346      if (action == ExecutionState.Started) Algorithm.Start();
347      else if (action == ExecutionState.Stopped) Algorithm.Stop();
348    }
349    private void Algorithm_Prepared(object sender, EventArgs e) {
350      snapshotTimesIndex = 0;
351      snapshots.Clear();
352      OnPrepared();
353    }
354    private void Algorithm_Started(object sender, EventArgs e) {
355      OnStarted();
356    }
357    private void Algorithm_Stopped(object sender, EventArgs e) {
358      var cloner = new Cloner();
359      var algRun = cloner.Clone(Algorithm.Runs.Last());
360      var clonedSnapshots = cloner.Clone(snapshots);
361      algRun.Results.Add("TimeLimitRunSnapshots", clonedSnapshots);
362      Runs.Add(algRun);
363      Algorithm.Runs.Clear();
364      OnStopped();
365    }
366    #endregion
367    #endregion
368
369    private void FindNextSnapshotTimeIndex(TimeSpan reference) {
370      var index = 0;
371      while (index < snapshotTimes.Count && snapshotTimes[index] <= reference) {
372        index++;
373      };
374      snapshotTimesIndex = index;
375    }
376
377    private void MakeSnapshot() {
378      string time = Math.Round(ExecutionTime.TotalSeconds, 1).ToString("0.0");
379      string runName = "Snapshot " + time + "s " + algorithm.Name;
380      Run run;
381      if (StoreAlgorithmInEachSnapshot) {
382        var temporarilySetStoreFlag = !Algorithm.StoreAlgorithmInEachRun;
383        if (temporarilySetStoreFlag) Algorithm.StoreAlgorithmInEachRun = true;
384        run = new Run(runName, Algorithm);
385        if (temporarilySetStoreFlag) Algorithm.StoreAlgorithmInEachRun = false;
386      } else {
387        // duplicate code of Run.Initialize - necessary, because Algorithm property doesn't have a setter
388        run = new Run() { Name = runName };
389        var parameters = new Dictionary<string, IItem>();
390        var results = new Dictionary<string, IItem>();
391        algorithm.CollectParameterValues(parameters);
392        algorithm.CollectResultValues(results);
393        var cloner = new Cloner();
394        foreach (var kvp in parameters.Select(x => new KeyValuePair<string, IItem>(x.Key, cloner.Clone(x.Value))).ToDictionary(x => x.Key, x => x.Value))
395          run.Parameters.Add(kvp);
396        foreach (var kvp in results.Select(x => new KeyValuePair<string, IItem>(x.Key, cloner.Clone(x.Value))).ToDictionary(x => x.Key, x => x.Value))
397          run.Results.Add(kvp);
398      }
399      snapshots.Add(run);
400    }
401  }
402}
Note: See TracBrowser for help on using the repository browser.