Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2457_ExpertSystem/HeuristicLab.Analysis/3.3/Optimizers/IteratedAlgorithm.cs @ 18183

Last change on this file since 18183 was 16958, checked in by abeham, 6 years ago

#2457: adapted to trunk

File size: 34.2 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.Linq;
24using System.Threading;
25using System.Threading.Tasks;
26using HEAL.Attic;
27using HeuristicLab.Collections;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Optimization;
32using HeuristicLab.Parameters;
33
34namespace HeuristicLab.Analysis {
35  /// <summary>
36  /// A run in which an algorithm is executed for a certain maximum time only.
37  /// </summary>
38  [Item("Iterated Algorithm", "An algorithm that repeats an algorithm until either a certain target value is reached or a maximum budget is exceeded.")]
39  [Creatable(CreatableAttribute.Categories.TestingAndAnalysis, Priority = 116)]
40  [StorableType("787AF25E-46FF-4FBF-A2ED-011E7F41AF58")]
41  public sealed class IteratedAlgorithm : Algorithm, IStorableContent {
42    private const string ExecutionTimeResultName = "Execution Time";
43    private const string BestQualityResultName = "BestQuality";
44    private const string RandomRestartsResultName = "RandomRestarts";
45    private const string EvaluatedSolutionsResultName = "EvaluatedSolutions";
46    private const string EvaluatedMovesResultName = "EvaluatedMoves";
47    private const string QualityPerClockResultName = "QualityPerClock";
48    private const string QualityPerEvaluationsResultName = "QualityPerEvaluations";
49    private const string EvaluationsResultName = "Evaluations";
50
51    public string Filename { get; set; }
52
53    public override Type ProblemType { get { return typeof(ISingleObjectiveHeuristicOptimizationProblem); } }
54
55    public IValueParameter<TimeSpanValue> MaximumExecutionTimeParameter {
56      get { return (IValueParameter<TimeSpanValue>)Parameters["MaximumExecutionTime"]; }
57    }
58
59    public IValueParameter<IntValue> MaximumEvaluationsParameter {
60      get { return (IValueParameter<IntValue>)Parameters["MaximumEvaluations"]; }
61    }
62
63    public IValueParameter<DoubleValue> TargetQualityParameter {
64      get { return (IValueParameter<DoubleValue>)Parameters["TargetQuality"]; }
65    }
66
67    private IFixedValueParameter<DoubleValue> MoveCostPerSolutionParameter {
68      get { return (IFixedValueParameter<DoubleValue>)Parameters["MoveCostPerSolution"]; }
69    }
70
71    private IFixedValueParameter<BoolValue> StoreSolutionInRunParameter {
72      get { return (IFixedValueParameter<BoolValue>)Parameters["StoreSolutionInRun"]; }
73    }
74
75    private IValueParameter<IAlgorithm> AlgorithmParameter {
76      get { return (IValueParameter<IAlgorithm>)Parameters["Algorithm"]; }
77    }
78
79    private IFixedValueParameter<MultiAnalyzer> AnalyzerParameter {
80      get { return (IFixedValueParameter<MultiAnalyzer>)Parameters["Analyzer"]; }
81    }
82
83    [Storable]
84    private ResultCollection results;
85    public override ResultCollection Results {
86      get { return results; }
87    }
88
89    [Storable]
90    private QualityPerClockAnalyzer perClockAnalyzer;
91    public QualityPerClockAnalyzer PerClockAnalyzer {
92      get { return perClockAnalyzer; }
93    }
94    [Storable]
95    private QualityPerEvaluationsAnalyzer perEvaluationsAnalyzer;
96    public QualityPerEvaluationsAnalyzer PerEvaluationsAnalyzer {
97      get { return perEvaluationsAnalyzer; }
98    }
99    [Storable]
100    private BestScopeSolutionAnalyzer bestSolutionAnalyzer;
101    public BestScopeSolutionAnalyzer BestSolutionAnalyzer {
102      get { return bestSolutionAnalyzer; }
103    }
104
105    public double MoveCostPerSolution {
106      get { return MoveCostPerSolutionParameter.Value.Value; }
107      set { MoveCostPerSolutionParameter.Value.Value = value; }
108    }
109
110    public bool StoreSolutionInRun {
111      get { return StoreSolutionInRunParameter.Value.Value; }
112      set { StoreSolutionInRunParameter.Value.Value = value; }
113    }
114
115    // algorithm will be set in AfterDeserialization to the value of the parameter
116    private IAlgorithm algorithm;
117    public IAlgorithm Algorithm {
118      get { return algorithm; }
119      set {
120        if (algorithm == value) return;
121        if (algorithm != null) {
122          DeregisterAlgorithmEvents();
123          RemoveAlgorithmAnalyzers();
124        }
125        algorithm = value;
126        if (algorithm != null) {
127          if (algorithm.ExecutionState != ExecutionState.Prepared)
128            algorithm.Prepare(true);
129          if (Problem != null)
130            algorithm.Problem = Problem;
131          RegisterAlgorithmEvents();
132          AddAlgorithmAnalyzers();
133          HandleAlgorithmMaximumEvaluationsChanged();
134          HandleAlgorithmTargetQualityChanged();
135        }
136        if (AlgorithmParameter.Value != algorithm)
137          AlgorithmParameter.Value = algorithm;
138        Prepare();
139      }
140    }
141
142    public MultiAnalyzer Analyzer {
143      get { return AnalyzerParameter.Value; }
144    }
145
146    private bool Maximization {
147      get { return Problem != null && ((IValueParameter<BoolValue>)((ISingleObjectiveHeuristicOptimizationProblem)Problem).MaximizationParameter).Value.Value; }
148    }
149
150    private bool IsFinished {
151      get {
152        var executionTime = Results.ContainsKey(ExecutionTimeResultName) ? ((TimeSpanValue)Results[ExecutionTimeResultName].Value).Value : TimeSpan.Zero;
153        var evaluations = Results.ContainsKey(EvaluationsResultName) ? ((DoubleValue)Results[EvaluationsResultName].Value).Value : 0;
154        var bestQuality = Results.ContainsKey(BestQualityResultName) ? ((DoubleValue)Results[BestQualityResultName].Value).Value
155                                                                     : (Maximization ? double.MinValue : double.MaxValue);
156        var targetValue = TargetQualityParameter.Value != null ? TargetQualityParameter.Value.Value
157                                                             : Maximization ? double.MaxValue : double.MinValue;
158
159        var timeHit = MaximumExecutionTimeParameter.Value != null && executionTime >= MaximumExecutionTimeParameter.Value.Value;
160        var evalHit = MaximumEvaluationsParameter.Value != null && evaluations >= MaximumEvaluationsParameter.Value.Value;
161        var targetHit = Maximization && bestQuality >= targetValue || !Maximization && bestQuality <= targetValue;
162
163        return forceStop || timeHit || evalHit || targetHit;
164      }
165    }
166
167    [StorableConstructor]
168    private IteratedAlgorithm(StorableConstructorFlag _) : base(_) { }
169    private IteratedAlgorithm(IteratedAlgorithm original, Cloner cloner)
170      : base(original, cloner) {
171      results = cloner.Clone(original.Results);
172      perClockAnalyzer = cloner.Clone(original.perClockAnalyzer);
173      perEvaluationsAnalyzer = cloner.Clone(original.perEvaluationsAnalyzer);
174      bestSolutionAnalyzer = cloner.Clone(original.bestSolutionAnalyzer);
175      algorithm = cloner.Clone(original.algorithm);
176      RegisterEventHandlers();
177    }
178    public IteratedAlgorithm()
179      : base() {
180      results = new ResultCollection();
181      Parameters.Add(new FixedValueParameter<MultiAnalyzer>("Analyzer", "Analyzers that should be called in addition to the default algorithm analyzers.", new MultiAnalyzer()));
182      Parameters.Add(new OptionalValueParameter<TimeSpanValue>("MaximumExecutionTime", "The maximum wall-clock time that the algorithm should run."));
183      Parameters.Add(new OptionalValueParameter<IntValue>("MaximumEvaluations", "The maximum number of function evaluations that the algorithm should run.", new IntValue(100000000)));
184      Parameters.Add(new OptionalValueParameter<DoubleValue>("TargetQuality", "The target quality that the algorithm should run for."));
185      Parameters.Add(new FixedValueParameter<DoubleValue>("MoveCostPerSolution", "The amount of solution evaluation equivalents of a single move. Use 1 for a black-box scenario.", new DoubleValue(1)));
186      Parameters.Add(new FixedValueParameter<BoolValue>("StoreSolutionInRun", "Whether the solution data types should be kept in the run."));
187      Parameters.Add(new ValueParameter<IAlgorithm>("Algorithm", "The algorithm to iterate.") { GetsCollected = false }); // due to storage efficiency, by default we don't want to store the algorithm instance in the run
188
189      perClockAnalyzer = new QualityPerClockAnalyzer();
190      perEvaluationsAnalyzer = new QualityPerEvaluationsAnalyzer();
191      bestSolutionAnalyzer = new BestScopeSolutionAnalyzer();
192      Analyzer.Operators.Add(perClockAnalyzer, true);
193      Analyzer.Operators.Add(perEvaluationsAnalyzer, true);
194      Analyzer.Operators.Add(bestSolutionAnalyzer, StoreSolutionInRun);
195
196      RegisterEventHandlers();
197    }
198
199    public override IDeepCloneable Clone(Cloner cloner) {
200      if (ExecutionState == ExecutionState.Started) throw new InvalidOperationException(string.Format("Clone not allowed in execution state \"{0}\".", ExecutionState));
201      return new IteratedAlgorithm(this, cloner);
202    }
203
204    [StorableHook(HookType.AfterDeserialization)]
205    private void AfterDeserialization() {
206      algorithm = AlgorithmParameter.Value;
207      // BackwardsCompatibility3.3
208      #region Backwards compatible code, remove with 3.4
209      if (Parameters.ContainsKey("TargetValue")) {
210        var target = ((OptionalValueParameter<DoubleValue>)Parameters["TargetValue"]).Value;
211        Parameters.Remove("TargetValue");
212        Parameters.Add(new OptionalValueParameter<DoubleValue>("TargetQuality", "The target quality that the algorithm should run for.", target));
213      }
214      if (!Parameters.ContainsKey("Analyzer")) {
215        Parameters.Add(new FixedValueParameter<MultiAnalyzer>("Analyzer", "Analyzers that should be called in addition to the default algorithm analyzers.", new MultiAnalyzer()));
216        Analyzer.Operators.Add(perClockAnalyzer, true);
217        Analyzer.Operators.Add(perEvaluationsAnalyzer, true);
218        if (Algorithm != null && Algorithm.Parameters.ContainsKey("Analyzer")) {
219          var analyzerParam = Algorithm.Parameters["Analyzer"] as IValueParameter<MultiAnalyzer>;
220          if (analyzerParam != null) {
221            analyzerParam.Value.Operators.Remove(perClockAnalyzer);
222            analyzerParam.Value.Operators.Remove(perEvaluationsAnalyzer);
223          } else {
224            var analyzerParam2 = Algorithm.Parameters["Analyzer"] as IValueParameter<IMultiAnalyzer>;
225            if (analyzerParam2 != null) {
226              analyzerParam2.Value.Operators.Remove(perClockAnalyzer);
227              analyzerParam2.Value.Operators.Remove(perEvaluationsAnalyzer);
228            }
229          }
230          AddAlgorithmAnalyzers();
231        }
232      }
233      if (bestSolutionAnalyzer == null) {
234        bestSolutionAnalyzer = new BestScopeSolutionAnalyzer();
235        Analyzer.Operators.Add(bestSolutionAnalyzer, StoreSolutionInRun);
236      }
237      #endregion
238      RegisterEventHandlers();
239    }
240
241    #region Register Event Handlers
242    protected override void RegisterProblemEvents() {
243      var bkParam = ((ISingleObjectiveHeuristicOptimizationProblem)Problem).BestKnownQualityParameter as IValueParameter<DoubleValue>;
244      if (bkParam != null) {
245        bkParam.ValueChanged += Problem_BestKnownQualityParameter_ValueChanged;
246      }
247      base.RegisterProblemEvents();
248    }
249    protected override void DeregisterProblemEvents() {
250      base.DeregisterProblemEvents();
251      var bkParam = ((ISingleObjectiveHeuristicOptimizationProblem)Problem).BestKnownQualityParameter as IValueParameter<DoubleValue>;
252      if (bkParam != null) {
253        bkParam.ValueChanged -= Problem_BestKnownQualityParameter_ValueChanged;
254      }
255    }
256    private void RegisterAlgorithmEvents() {
257      Algorithm.ExceptionOccurred += Algorithm_ExceptionOccurred;
258      Algorithm.Paused += Algorithm_Paused;
259      Algorithm.Stopped += Algorithm_Stopped;
260      Algorithm.ProblemChanged += Algorithm_ProblemChanged;
261      #region MaximumEvaluations
262      IParameter param;
263      if (Algorithm.Parameters.TryGetValue("MaximumEvaluations", out param)) {
264        var intFixedValueParam = (param as IFixedValueParameter<IntValue>);
265        if (intFixedValueParam != null) {
266          intFixedValueParam.Value.ValueChanged += AlgorithmMaximumEvaluationsOnValueChanged;
267        } else {
268          var intValueParam = (param as IValueParameter<IntValue>);
269          if (intValueParam != null) {
270            intValueParam.ValueChanged += AlgorithmMaximumEvaluationsParameterOnChanged;
271            if (intValueParam.Value != null) intValueParam.Value.ValueChanged += AlgorithmMaximumEvaluationsOnValueChanged;
272          }
273        }
274      }
275      #endregion
276      #region TargetQuality
277      if (Algorithm.Parameters.TryGetValue("TargetQuality", out param)) {
278        var intValueParam = (param as IValueParameter<IntValue>);
279        if (intValueParam != null) {
280          intValueParam.ValueChanged += AlgorithmTargetQualityParameterOnChanged;
281          if (intValueParam.Value != null) intValueParam.Value.ValueChanged += AlgorithmTargetQualityOnValueChanged;
282        }
283      }
284      #endregion
285    }
286
287    private void DeregisterAlgorithmEvents() {
288      Algorithm.ExceptionOccurred -= Algorithm_ExceptionOccurred;
289      Algorithm.Paused -= Algorithm_Paused;
290      Algorithm.Stopped -= Algorithm_Stopped;
291      Algorithm.ProblemChanged -= Algorithm_ProblemChanged;
292      #region MaximumEvaluations
293      IParameter param;
294      if (Algorithm.Parameters.TryGetValue("MaximumEvaluations", out param)) {
295        var intFixedValueParam = (param as IFixedValueParameter<IntValue>);
296        if (intFixedValueParam != null) {
297          intFixedValueParam.Value.ValueChanged -= AlgorithmMaximumEvaluationsOnValueChanged;
298        } else {
299          var intValueParam = (param as IValueParameter<IntValue>);
300          if (intValueParam != null) {
301            intValueParam.ValueChanged -= AlgorithmMaximumEvaluationsParameterOnChanged;
302            if (intValueParam.Value != null) intValueParam.Value.ValueChanged -= AlgorithmMaximumEvaluationsOnValueChanged;
303          }
304        }
305      }
306      #endregion
307      #region TargetQuality
308      if (Algorithm.Parameters.TryGetValue("TargetQuality", out param)) {
309        var intValueParam = (param as IValueParameter<IntValue>);
310        if (intValueParam != null) {
311          intValueParam.ValueChanged -= AlgorithmTargetQualityParameterOnChanged;
312          if (intValueParam.Value != null) intValueParam.Value.ValueChanged -= AlgorithmTargetQualityOnValueChanged;
313        }
314      }
315      #endregion
316    }
317    #endregion
318
319    private void RegisterEventHandlers() {
320      if (Algorithm != null) RegisterAlgorithmEvents();
321      if (Problem != null) RegisterProblemEvents();
322      AlgorithmParameter.ValueChanged += AlgorithmParameterOnValueChanged;
323      StoreSolutionInRunParameter.Value.ValueChanged += StoreSolutionInRunOnValueChanged;
324      Analyzer.Operators.CollectionReset += AnalyzerOperatorsChanged;
325      Analyzer.Operators.ItemsAdded += AnalyzerOperatorsChanged;
326      Analyzer.Operators.ItemsRemoved += AnalyzerOperatorsChanged;
327      Analyzer.Operators.ItemsReplaced += AnalyzerOperatorsChanged;
328      MaximumEvaluationsParameter.Value.ValueChanged += MaximumEvaluationsParameterOnValueChanged;
329      TargetQualityParameter.ValueChanged += TargetQualityParameterChanged;
330      if (TargetQualityParameter.Value != null) TargetQualityParameter.Value.ValueChanged += TargetQualityParameterOnValueChanged;
331    }
332
333    private bool suppressAnalyzerOperatorEvents = false;
334
335    private void AnalyzerOperatorsChanged(object sender, CollectionItemsChangedEventArgs<IndexedItem<IAnalyzer>> e) {
336      if (suppressAnalyzerOperatorEvents) return;
337      if (!Analyzer.Operators.Contains(perClockAnalyzer)) {
338        suppressAnalyzerOperatorEvents = true;
339        try { Analyzer.Operators.Add(perClockAnalyzer, false); } finally { suppressAnalyzerOperatorEvents = false; }
340      }
341      if (!Analyzer.Operators.Contains(perEvaluationsAnalyzer)) {
342        suppressAnalyzerOperatorEvents = true;
343        try { Analyzer.Operators.Add(perEvaluationsAnalyzer, false); } finally { suppressAnalyzerOperatorEvents = false; }
344      }
345      if (!Analyzer.Operators.Contains(bestSolutionAnalyzer)) {
346        suppressAnalyzerOperatorEvents = true;
347        try { Analyzer.Operators.Add(bestSolutionAnalyzer, false); } finally { suppressAnalyzerOperatorEvents = false; }
348      }
349    }
350
351    private void StoreSolutionInRunOnValueChanged(object sender, EventArgs eventArgs) {
352      Analyzer.Operators.SetItemCheckedState(bestSolutionAnalyzer, StoreSolutionInRun);
353    }
354
355    private void AlgorithmParameterOnValueChanged(object sender, EventArgs eventArgs) {
356      Algorithm = AlgorithmParameter.Value;
357    }
358
359    #region Prepare, Start, Pause, Stop
360    public override void Prepare() {
361      if (Problem == null || Algorithm == null) return;
362
363      Algorithm.Prepare(true);
364
365      results.Clear();
366      OnPrepared();
367    }
368
369    public override void Start() {
370      base.Start();
371      OnStarted();
372      Task.Factory.StartNew(Run, null).ContinueWith(t => {
373        try {
374          t.Wait();
375        } catch (AggregateException ex) {
376          try {
377            ex.Flatten().Handle(x => x is OperationCanceledException);
378          } catch (AggregateException remaining) {
379            if (remaining.InnerExceptions.Count == 1) OnExceptionOccurred(remaining.InnerExceptions[0]);
380            else OnExceptionOccurred(remaining);
381          }
382        }
383        if (Algorithm.ExecutionState == ExecutionState.Paused) OnPaused();
384        else OnStopped();
385        forceStop = false;
386      });
387    }
388
389    public override void Pause() {
390      base.Pause();
391      Algorithm.Pause();
392    }
393
394    private bool forceStop = false;
395    public override void Stop() {
396      base.Stop();
397      if (ExecutionState == ExecutionState.Started) {
398        forceStop = true;
399        Algorithm.Stop();
400      } else if (ExecutionState == ExecutionState.Paused) {
401        RoundupResults();
402        Algorithm.Prepare(true);
403        OnStopped();
404      }
405    }
406    #endregion
407
408    private DateTime lastUpdateTime;
409    private void Run(object state) {
410      lastUpdateTime = DateTime.UtcNow;
411      System.Timers.Timer timer = new System.Timers.Timer(250);
412      timer.AutoReset = true;
413      timer.Elapsed += timer_Elapsed;
414      timer.Start();
415      try {
416        Run();
417      } finally {
418        timer.Elapsed -= timer_Elapsed;
419        timer.Stop();
420        ExecutionTime += DateTime.UtcNow - lastUpdateTime;
421      }
422    }
423
424    private readonly AutoResetEvent algorithmWaitHandle = new AutoResetEvent(false);
425    private void Run() {
426      if (!Results.ContainsKey(ExecutionTimeResultName)) Results.Add(new Result(ExecutionTimeResultName, new TimeSpanValue(TimeSpan.Zero)));
427      if (!Results.ContainsKey(EvaluatedSolutionsResultName)) Results.Add(new Result(EvaluatedSolutionsResultName, new DoubleValue(0)));
428      if (!Results.ContainsKey(EvaluatedMovesResultName)) Results.Add(new Result(EvaluatedMovesResultName, new DoubleValue(0)));
429      if (!Results.ContainsKey(EvaluationsResultName)) Results.Add(new Result(EvaluationsResultName, new DoubleValue(0)));
430      if (!Results.ContainsKey(BestQualityResultName)) Results.Add(new Result(BestQualityResultName, new DoubleValue(double.NaN)));
431
432      do {
433        if (!Results.ContainsKey(RandomRestartsResultName)) Results.Add(new Result(RandomRestartsResultName, new IntValue(0)));
434        else if (Algorithm.ExecutionState == ExecutionState.Prepared) ((IntValue)Results[RandomRestartsResultName].Value).Value++;
435
436        Algorithm.Start();
437        algorithmWaitHandle.WaitOne();
438
439        if (Algorithm.ExecutionState == ExecutionState.Paused) return;
440
441        RoundupResults();
442
443        Algorithm.Prepare(true);
444      } while (!IsFinished);
445    }
446
447    private void RoundupResults() {
448      if (Algorithm == null) return;
449      var execTime = ((TimeSpanValue)Results[ExecutionTimeResultName].Value);
450      var solEvals = ((DoubleValue)Results[EvaluatedSolutionsResultName].Value);
451      var movEvals = ((DoubleValue)Results[EvaluatedMovesResultName].Value);
452      var restarts = ((IntValue)Results[RandomRestartsResultName].Value);
453      var evaluations = ((DoubleValue)Results[EvaluationsResultName].Value);
454      var bestQuality = ((DoubleValue)Results[BestQualityResultName].Value);
455      var improvement = false;
456
457      IResult result;
458      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.EvaluatedSolutionsParameter.ActualName, out result)) {
459        var evals = ((IntValue)result.Value).Value;
460        evaluations.Value += evals;
461        solEvals.Value += evals;
462      }
463      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.EvaluatedMovesParameter.ActualName, out result)) {
464        var evals = ((IntValue)result.Value).Value;
465        evaluations.Value += MoveCostPerSolution * evals;
466        movEvals.Value += evals;
467      }
468      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.BestQualityParameter.ActualName, out result)) {
469        var newBestQuality = ((DoubleValue)result.Value).Value;
470        if (double.IsNaN(bestQuality.Value)
471            || Maximization && newBestQuality > bestQuality.Value
472            || !Maximization && newBestQuality < bestQuality.Value) {
473          bestQuality.Value = newBestQuality;
474          improvement = true;
475        }
476      }
477      if (Algorithm.Results.TryGetValue(perClockAnalyzer.QualityPerClockParameter.ActualName, out result)) UpdateQualityPerClockResult((IndexedDataTable<double>)result.Value, restarts.Value);
478      if (Algorithm.Results.TryGetValue(perEvaluationsAnalyzer.QualityPerEvaluationsParameter.ActualName, out result)) UpdateQualityPerEvaluationsResult((IndexedDataTable<double>)result.Value, restarts.Value);
479      if (StoreSolutionInRun) {
480        foreach (var r in Algorithm.Results) {
481          if (r.Name == bestSolutionAnalyzer.BestSolutionResultName || r.Name.ToLower().EndsWith("solution") && improvement) {
482            if (!Results.TryGetValue(r.Name, out result))
483              Results.Add(new Result(r.Name, (IItem)r.Value.Clone()));
484            else result.Value = (IItem)r.Value.Clone();
485          }
486        }
487      }
488
489      execTime.Value = ExecutionTime;
490    }
491
492    private void UpdateQualityPerClockResult(IndexedDataTable<double> perClock, int restarts) {
493      IndexedDataTable<double> dt;
494      if (!Results.ContainsKey(QualityPerClockResultName)) {
495        dt = (IndexedDataTable<double>)perClock.Clone();
496        if (!dt.Rows.ContainsKey("Restarts"))
497          dt.Rows.Add(new IndexedDataRow<double>("Restarts") {
498            VisualProperties = {
499              ChartType = DataRowVisualProperties.DataRowChartType.StepLine,
500              SecondYAxis = true
501            }
502          });
503        foreach (var v in dt.Rows.First().Values)
504          dt.Rows["Restarts"].Values.Add(Tuple.Create(v.Item1, 0.0));
505        Results.Add(new Result(QualityPerClockResultName, dt));
506      } else {
507        dt = (IndexedDataTable<double>)Results[QualityPerClockResultName].Value;
508        var qualityValues = dt.Rows.First().Values;
509        var restartValues = dt.Rows["Restarts"].Values;
510        var best = qualityValues.Last().Item2;
511        var execTime = qualityValues.Last().Item1;
512        var improvement = false;
513        foreach (var tupl in perClock.Rows.First().Values) {
514          if (Maximization && tupl.Item2 > best || !Maximization && tupl.Item2 < best) {
515            if (!improvement) {
516              // the last entry always holds the same value, but with highest execution time
517              qualityValues.RemoveAt(qualityValues.Count - 1);
518              restartValues.RemoveAt(restartValues.Count - 1);
519              improvement = true;
520            }
521            qualityValues.Add(Tuple.Create(execTime + tupl.Item1, tupl.Item2));
522            restartValues.Add(Tuple.Create(execTime + tupl.Item1, (double)restarts));
523            best = tupl.Item2;
524          }
525        }
526        if (!improvement) {
527          qualityValues.RemoveAt(qualityValues.Count - 1);
528          restartValues.RemoveAt(restartValues.Count - 1);
529        }
530        var totalExecTime = execTime + perClock.Rows.First().Values.Last().Item1;
531        qualityValues.Add(Tuple.Create(totalExecTime, best));
532        restartValues.Add(Tuple.Create(totalExecTime, (double)restarts));
533      }
534    }
535
536    private void UpdateQualityPerEvaluationsResult(IndexedDataTable<double> perEvaluations, int restarts) {
537      IndexedDataTable<double> dt;
538      if (!Results.ContainsKey(QualityPerEvaluationsResultName)) {
539        dt = (IndexedDataTable<double>)perEvaluations.Clone();
540        if (!dt.Rows.ContainsKey("Restarts"))
541          dt.Rows.Add(new IndexedDataRow<double>("Restarts") {
542            VisualProperties = {
543              ChartType = DataRowVisualProperties.DataRowChartType.StepLine,
544              SecondYAxis = true
545            }
546          });
547        foreach (var v in dt.Rows.First().Values)
548          dt.Rows["Restarts"].Values.Add(Tuple.Create(v.Item1, 0.0));
549        Results.Add(new Result(QualityPerEvaluationsResultName, dt));
550      } else {
551        dt = (IndexedDataTable<double>)Results[QualityPerEvaluationsResultName].Value;
552        var qualityValues = dt.Rows.First().Values;
553        var restartValues = dt.Rows["Restarts"].Values;
554        var best = qualityValues.Last().Item2;
555        var evaluations = qualityValues.Last().Item1;
556        var improvement = false;
557        foreach (var tupl in perEvaluations.Rows.First().Values) {
558          if (Maximization && tupl.Item2 > best || !Maximization && tupl.Item2 < best) {
559            if (!improvement) {
560              // the last entry always holds the same value, but with highest evaluations
561              qualityValues.RemoveAt(qualityValues.Count - 1);
562              restartValues.RemoveAt(restartValues.Count - 1);
563              improvement = true;
564            }
565            qualityValues.Add(Tuple.Create(evaluations + tupl.Item1, tupl.Item2));
566            restartValues.Add(Tuple.Create(evaluations + tupl.Item1, (double)restarts));
567            best = tupl.Item2;
568          }
569        }
570        if (!improvement) {
571          // add the best quality again as value with highest evaluations
572          qualityValues.RemoveAt(qualityValues.Count - 1);
573          restartValues.RemoveAt(restartValues.Count - 1);
574        }
575        var totalEvaluations = evaluations + perEvaluations.Rows.First().Values.Last().Item1;
576        qualityValues.Add(Tuple.Create(totalEvaluations, best));
577        restartValues.Add(Tuple.Create(totalEvaluations, (double)restarts));
578      }
579    }
580
581    private void UpdateTargetValueFromBestKnownQuality() {
582      var bkParam = ((ISingleObjectiveHeuristicOptimizationProblem)Problem).BestKnownQualityParameter as IValueParameter<DoubleValue>;
583      if (bkParam != null && bkParam.Value != null)
584        TargetQualityParameter.Value = new DoubleValue(bkParam.Value.Value);
585      else if (bkParam != null && bkParam.Value == null)
586        TargetQualityParameter.Value = null;
587    }
588
589    private void AddAlgorithmAnalyzers() {
590      if (Algorithm == null) return;
591      if (!Algorithm.Parameters.ContainsKey("Analyzer")) return;
592      var analyzerParam = Algorithm.Parameters["Analyzer"] as IValueParameter<MultiAnalyzer>;
593      if (analyzerParam != null) {
594        if (analyzerParam.Value.Operators.Contains(Analyzer)) return;
595        analyzerParam.Value.Operators.Add(Analyzer, true);
596      } else {
597        var analyzerParam2 = Algorithm.Parameters["Analyzer"] as IValueParameter<IMultiAnalyzer>;
598        if (analyzerParam2 == null) return;
599        if (analyzerParam2.Value.Operators.Contains(Analyzer)) return;
600        analyzerParam2.Value.Operators.Add(Analyzer, true);
601      }
602    }
603
604    private void RemoveAlgorithmAnalyzers() {
605      if (Algorithm == null) return;
606      if (!Algorithm.Parameters.ContainsKey("Analyzer")) return;
607      var analyzerParam = Algorithm.Parameters["Analyzer"] as IValueParameter<MultiAnalyzer>;
608      if (analyzerParam != null) {
609        analyzerParam.Value.Operators.Remove(Analyzer);
610      } else {
611        var analyzerParam2 = Algorithm.Parameters["Analyzer"] as IValueParameter<IMultiAnalyzer>;
612        if (analyzerParam2 != null) {
613          analyzerParam2.Value.Operators.Remove(Analyzer);
614        }
615      }
616    }
617
618    #region Event Handlers
619    private void Algorithm_ExceptionOccurred(object sender, EventArgs<Exception> e) {
620      OnExceptionOccurred(e.Value);
621    }
622    private void Algorithm_Paused(object sender, EventArgs e) {
623      if (ExecutionState == ExecutionState.Paused) return;
624      algorithmWaitHandle.Set();
625    }
626    private void Algorithm_Stopped(object sender, EventArgs e) {
627      if (ExecutionState == ExecutionState.Paused) return;
628      algorithmWaitHandle.Set();
629    }
630
631    private void Algorithm_ProblemChanged(object sender, EventArgs e) {
632      if (Algorithm.Problem != Problem) Problem = (ISingleObjectiveHeuristicOptimizationProblem)Algorithm.Problem;
633      AddAlgorithmAnalyzers();
634    }
635
636    private void AlgorithmTargetQualityParameterOnChanged(object sender, EventArgs e) {
637      var doubleValueParam = (sender as IValueParameter<DoubleValue>);
638      if (doubleValueParam.Value != null) doubleValueParam.Value.ValueChanged += AlgorithmTargetQualityOnValueChanged;
639      HandleAlgorithmTargetQualityChanged();
640    }
641
642    private void AlgorithmTargetQualityOnValueChanged(object sender, EventArgs e) {
643      HandleAlgorithmTargetQualityChanged();
644    }
645
646    private void AlgorithmMaximumEvaluationsParameterOnChanged(object sender, EventArgs eventArgs) {
647      var intValueParam = (sender as IValueParameter<IntValue>);
648      if (intValueParam.Value == null) {
649        intValueParam.Value = new IntValue();
650        return;
651      }
652      intValueParam.Value.ValueChanged += AlgorithmMaximumEvaluationsOnValueChanged;
653      HandleAlgorithmMaximumEvaluationsChanged();
654    }
655
656    private void AlgorithmMaximumEvaluationsOnValueChanged(object sender, EventArgs eventArgs) {
657      var intValue = (IntValue)sender;
658      HandleAlgorithmMaximumEvaluationsChanged();
659    }
660
661    private void Problem_BestKnownQualityParameter_ValueChanged(object sender, EventArgs e) {
662      var param = sender as IValueParameter<DoubleValue>;
663      if (param != null) {
664        if (param.Value != null) param.Value.ValueChanged += Problem_BestKnownQualityParameter_Value_ValueChanged;
665        UpdateTargetValueFromBestKnownQuality();
666      }
667    }
668
669    private void Problem_BestKnownQualityParameter_Value_ValueChanged(object sender, EventArgs e) {
670      UpdateTargetValueFromBestKnownQuality();
671    }
672
673    protected override void Problem_Reset(object sender, EventArgs eventArgs) {
674      if (Algorithm != null) AddAlgorithmAnalyzers();
675    }
676
677    protected override void Problem_OperatorsChanged(object sender, EventArgs eventArgs) {
678      if (Algorithm != null) AddAlgorithmAnalyzers();
679    }
680
681    protected override void OnProblemChanged() {
682      base.OnProblemChanged();
683      if (Algorithm != null) Algorithm.Problem = Problem;
684      if (Problem != null) UpdateTargetValueFromBestKnownQuality();
685    }
686
687    private void MaximumEvaluationsParameterOnValueChanged(object sender, EventArgs eventArgs) {
688      SynchronizeMaximumEvaluationsParameter();
689    }
690
691    private void TargetQualityParameterChanged(object sender, EventArgs e) {
692      if (TargetQualityParameter.Value != null) TargetQualityParameter.Value.ValueChanged += TargetQualityParameterOnValueChanged;
693      HandleAlgorithmTargetQualityChanged();
694    }
695
696    private void TargetQualityParameterOnValueChanged(object sender, EventArgs eventArgs) {
697      HandleAlgorithmTargetQualityChanged();
698    }
699
700    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
701      System.Timers.Timer timer = (System.Timers.Timer)sender;
702      timer.Enabled = false;
703      DateTime now = DateTime.UtcNow;
704      ExecutionTime += now - lastUpdateTime;
705      lastUpdateTime = now;
706      timer.Enabled = true;
707    }
708    #endregion
709
710    private void HandleAlgorithmTargetQualityChanged() {
711      if (Algorithm == null) return;
712      IParameter param;
713      if (!Algorithm.Parameters.TryGetValue("TargetQuality", out param)) return;
714      var doubleValueParam = (param as IValueParameter<DoubleValue>);
715      if (doubleValueParam == null) return;
716      if (doubleValueParam.Value == null && TargetQualityParameter.Value != null) {
717        doubleValueParam.Value = new DoubleValue(TargetQualityParameter.Value.Value);
718      } else if (doubleValueParam.Value != null && TargetQualityParameter.Value == null) {
719        doubleValueParam.Value = null;
720      } else if (doubleValueParam.Value != null && TargetQualityParameter.Value != null) {
721        doubleValueParam.Value.Value = TargetQualityParameter.Value.Value;
722      }
723    }
724
725    private void HandleAlgorithmMaximumEvaluationsChanged() {
726      if (Algorithm == null) return;
727      IParameter param;
728      if (!Algorithm.Parameters.TryGetValue("MaximumEvaluations", out param)) return;
729      var intValueParam = (param as IValueParameter<IntValue>);
730      if (intValueParam == null) return;
731      var value = intValueParam.Value;
732      if (value.Value > MaximumEvaluationsParameter.Value.Value)
733        value.Value = MaximumEvaluationsParameter.Value.Value;
734    }
735
736    private void SynchronizeMaximumEvaluationsParameter() {
737      if (Algorithm == null) return;
738      IParameter param;
739      if (!Algorithm.Parameters.TryGetValue("MaximumEvaluations", out param)) return;
740      var intValueParam = (param as IValueParameter<IntValue>);
741      if (intValueParam == null) return;
742      if (intValueParam.Value == null) intValueParam.Value = new IntValue(MaximumEvaluationsParameter.Value.Value);
743      else intValueParam.Value.Value = MaximumEvaluationsParameter.Value.Value;
744    }
745  }
746}
Note: See TracBrowser for help on using the repository browser.