Free cookie consent management tool by TermsFeed Policy Generator

source: branches/WebJobManager/HeuristicLab.Optimization/3.3/MetaOptimizers/TimeLimitRun.cs @ 13847

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

#2582 created branch for Hive Web Job Manager

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