Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PerformanceComparison/HeuristicLab.Analysis/3.3/Optimizers/IteratedAlgorithm.cs @ 14449

Last change on this file since 14449 was 14058, checked in by abeham, 8 years ago

#2431: Refactored ResultsParameter

File size: 34.2 KB
RevLine 
[8955]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
[13564]22using HeuristicLab.Collections;
[8955]23using HeuristicLab.Common;
24using HeuristicLab.Core;
[12803]25using HeuristicLab.Data;
26using HeuristicLab.Optimization;
[12856]27using HeuristicLab.Parameters;
[8955]28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
[13738]29using System;
30using System.Linq;
31using System.Threading;
32using System.Threading.Tasks;
[8955]33
[12803]34namespace HeuristicLab.Analysis {
[8955]35  /// <summary>
36  /// A run in which an algorithm is executed for a certain maximum time only.
37  /// </summary>
[12859]38  [Item("Iterated Algorithm", "An algorithm that repeats an algorithm until either a certain target value is reached or a maximum budget is exceeded.")]
[12856]39  [Creatable(CreatableAttribute.Categories.TestingAndAnalysis, Priority = 116)]
[8955]40  [StorableClass]
[12859]41  public sealed class IteratedAlgorithm : Algorithm, IStorableContent {
[12804]42    private const string ExecutionTimeResultName = "Execution Time";
43    private const string BestQualityResultName = "BestQuality";
[12808]44    private const string RandomRestartsResultName = "RandomRestarts";
[12825]45    private const string EvaluatedSolutionsResultName = "EvaluatedSolutions";
46    private const string EvaluatedMovesResultName = "EvaluatedMoves";
47    private const string QualityPerClockResultName = "QualityPerClock";
48    private const string QualityPerEvaluationsResultName = "QualityPerEvaluations";
[12856]49    private const string EvaluationsResultName = "Evaluations";
[12804]50
[8955]51    public string Filename { get; set; }
52
[12856]53    public override Type ProblemType { get { return typeof(ISingleObjectiveHeuristicOptimizationProblem); } }
[8955]54
[12856]55    public IValueParameter<TimeSpanValue> MaximumExecutionTimeParameter {
56      get { return (IValueParameter<TimeSpanValue>)Parameters["MaximumExecutionTime"]; }
[8955]57    }
58
[12856]59    public IValueParameter<IntValue> MaximumEvaluationsParameter {
60      get { return (IValueParameter<IntValue>)Parameters["MaximumEvaluations"]; }
[8955]61    }
62
[13568]63    public IValueParameter<DoubleValue> TargetQualityParameter {
64      get { return (IValueParameter<DoubleValue>)Parameters["TargetQuality"]; }
[8955]65    }
66
[12856]67    private IFixedValueParameter<DoubleValue> MoveCostPerSolutionParameter {
68      get { return (IFixedValueParameter<DoubleValue>)Parameters["MoveCostPerSolution"]; }
[12803]69    }
70
[12856]71    private IFixedValueParameter<BoolValue> StoreSolutionInRunParameter {
72      get { return (IFixedValueParameter<BoolValue>)Parameters["StoreSolutionInRun"]; }
[8955]73    }
74
[12856]75    private IValueParameter<IAlgorithm> AlgorithmParameter {
76      get { return (IValueParameter<IAlgorithm>)Parameters["Algorithm"]; }
77    }
78
[13564]79    private IFixedValueParameter<MultiAnalyzer> AnalyzerParameter {
80      get { return (IFixedValueParameter<MultiAnalyzer>)Parameters["Analyzer"]; }
81    }
82
[12804]83    [Storable]
[12856]84    private ResultCollection results;
85    public override ResultCollection Results {
86      get { return results; }
[12825]87    }
88
89    [Storable]
[12804]90    private QualityPerClockAnalyzer perClockAnalyzer;
[13564]91    public QualityPerClockAnalyzer PerClockAnalyzer {
92      get { return perClockAnalyzer; }
93    }
[12804]94    [Storable]
95    private QualityPerEvaluationsAnalyzer perEvaluationsAnalyzer;
[13564]96    public QualityPerEvaluationsAnalyzer PerEvaluationsAnalyzer {
97      get { return perEvaluationsAnalyzer; }
98    }
99    [Storable]
100    private BestScopeSolutionAnalyzer bestSolutionAnalyzer;
101    public BestScopeSolutionAnalyzer BestSolutionAnalyzer {
102      get { return bestSolutionAnalyzer; }
103    }
[12803]104
[12856]105    public double MoveCostPerSolution {
106      get { return MoveCostPerSolutionParameter.Value.Value; }
107      set { MoveCostPerSolutionParameter.Value.Value = value; }
[8955]108    }
109
[12856]110    public bool StoreSolutionInRun {
111      get { return StoreSolutionInRunParameter.Value.Value; }
112      set { StoreSolutionInRunParameter.Value.Value = value; }
[8955]113    }
114
[13564]115    // algorithm will be set in AfterDeserialization to the value of the parameter
[8955]116    private IAlgorithm algorithm;
117    public IAlgorithm Algorithm {
118      get { return algorithm; }
119      set {
120        if (algorithm == value) return;
[12804]121        if (algorithm != null) {
122          DeregisterAlgorithmEvents();
123          RemoveAlgorithmAnalyzers();
124        }
[8955]125        algorithm = value;
126        if (algorithm != null) {
[12856]127          if (algorithm.ExecutionState != ExecutionState.Prepared)
128            algorithm.Prepare(true);
[13564]129          if (Problem != null)
130            algorithm.Problem = Problem;
[8955]131          RegisterAlgorithmEvents();
[12804]132          AddAlgorithmAnalyzers();
[13568]133          HandleAlgorithmMaximumEvaluationsChanged();
134          HandleAlgorithmTargetQualityChanged();
[8955]135        }
[12856]136        if (AlgorithmParameter.Value != algorithm)
137          AlgorithmParameter.Value = algorithm;
[8955]138        Prepare();
139      }
140    }
141
[13564]142    public MultiAnalyzer Analyzer {
143      get { return AnalyzerParameter.Value; }
144    }
145
[12856]146    private bool Maximization {
[13564]147      get { return Problem != null && ((IValueParameter<BoolValue>)((ISingleObjectiveHeuristicOptimizationProblem)Problem).MaximizationParameter).Value.Value; }
[8955]148    }
149
[12803]150    private bool IsFinished {
151      get {
[12856]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);
[13568]156        var targetValue = TargetQualityParameter.Value != null ? TargetQualityParameter.Value.Value
[12856]157                                                             : Maximization ? double.MaxValue : double.MinValue;
[12803]158
[12856]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
[13564]163        return forceStop || timeHit || evalHit || targetHit;
[12803]164      }
165    }
166
[8955]167    [StorableConstructor]
[12859]168    private IteratedAlgorithm(bool deserializing) : base(deserializing) { }
169    private IteratedAlgorithm(IteratedAlgorithm original, Cloner cloner)
[8955]170      : base(original, cloner) {
[12856]171      results = cloner.Clone(original.Results);
[12804]172      perClockAnalyzer = cloner.Clone(original.perClockAnalyzer);
173      perEvaluationsAnalyzer = cloner.Clone(original.perEvaluationsAnalyzer);
[13564]174      bestSolutionAnalyzer = cloner.Clone(original.bestSolutionAnalyzer);
[12864]175      algorithm = cloner.Clone(original.algorithm);
[12856]176      RegisterEventHandlers();
[8955]177    }
[12859]178    public IteratedAlgorithm()
[8955]179      : base() {
[12856]180      results = new ResultCollection();
[13564]181      Parameters.Add(new FixedValueParameter<MultiAnalyzer>("Analyzer", "Analyzers that should be called in addition to the default algorithm analyzers.", new MultiAnalyzer()));
[12856]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)));
[13568]184      Parameters.Add(new OptionalValueParameter<DoubleValue>("TargetQuality", "The target quality that the algorithm should run for."));
[12856]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
[12803]188
[12804]189      perClockAnalyzer = new QualityPerClockAnalyzer();
190      perEvaluationsAnalyzer = new QualityPerEvaluationsAnalyzer();
[13564]191      bestSolutionAnalyzer = new BestScopeSolutionAnalyzer();
192      Analyzer.Operators.Add(perClockAnalyzer, true);
193      Analyzer.Operators.Add(perEvaluationsAnalyzer, true);
194      Analyzer.Operators.Add(bestSolutionAnalyzer, StoreSolutionInRun);
[12804]195
[12856]196      RegisterEventHandlers();
[8955]197    }
[12803]198
[8955]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));
[12859]201      return new IteratedAlgorithm(this, cloner);
[8955]202    }
203
204    [StorableHook(HookType.AfterDeserialization)]
205    private void AfterDeserialization() {
[12864]206      algorithm = AlgorithmParameter.Value;
[13568]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      }
[13564]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      }
[13568]233      if (bestSolutionAnalyzer == null) {
234        bestSolutionAnalyzer = new BestScopeSolutionAnalyzer();
235        Analyzer.Operators.Add(bestSolutionAnalyzer, StoreSolutionInRun);
236      }
237      #endregion
[12856]238      RegisterEventHandlers();
[8955]239    }
240
[12856]241    #region Register Event Handlers
242    protected override void RegisterProblemEvents() {
[13564]243      var bkParam = ((ISingleObjectiveHeuristicOptimizationProblem)Problem).BestKnownQualityParameter as IValueParameter<DoubleValue>;
[12856]244      if (bkParam != null) {
245        bkParam.ValueChanged += Problem_BestKnownQualityParameter_ValueChanged;
246      }
247      base.RegisterProblemEvents();
[8955]248    }
[12856]249    protected override void DeregisterProblemEvents() {
250      base.DeregisterProblemEvents();
[13564]251      var bkParam = ((ISingleObjectiveHeuristicOptimizationProblem)Problem).BestKnownQualityParameter as IValueParameter<DoubleValue>;
[12856]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;
[13568]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
[12856]285    }
[13568]286
[12856]287    private void DeregisterAlgorithmEvents() {
288      Algorithm.ExceptionOccurred -= Algorithm_ExceptionOccurred;
289      Algorithm.Paused -= Algorithm_Paused;
290      Algorithm.Stopped -= Algorithm_Stopped;
291      Algorithm.ProblemChanged -= Algorithm_ProblemChanged;
[13568]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
[12856]316    }
317    #endregion
[8955]318
[12856]319    private void RegisterEventHandlers() {
320      if (Algorithm != null) RegisterAlgorithmEvents();
321      if (Problem != null) RegisterProblemEvents();
322      AlgorithmParameter.ValueChanged += AlgorithmParameterOnValueChanged;
[13564]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;
[13568]328      MaximumEvaluationsParameter.Value.ValueChanged += MaximumEvaluationsParameterOnValueChanged;
329      TargetQualityParameter.ValueChanged += TargetQualityParameterChanged;
330      if (TargetQualityParameter.Value != null) TargetQualityParameter.Value.ValueChanged += TargetQualityParameterOnValueChanged;
[12804]331    }
332
[13564]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
[12856]355    private void AlgorithmParameterOnValueChanged(object sender, EventArgs eventArgs) {
356      Algorithm = AlgorithmParameter.Value;
[8955]357    }
[12803]358
[12856]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();
[8955]367    }
[12804]368
[12856]369    public override void Start() {
370      base.Start();
[12804]371      OnStarted();
[13564]372      Task.Factory.StartNew(Run, null).ContinueWith(t => {
[12856]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();
[13564]385        forceStop = false;
[12856]386      });
[8955]387    }
[12856]388
389    public override void Pause() {
390      base.Pause();
[8955]391      Algorithm.Pause();
392    }
[12804]393
[13564]394    private bool forceStop = false;
[12856]395    public override void Stop() {
396      base.Stop();
[13564]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      }
[12856]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();
[12825]415      try {
[12856]416        Run();
417      } finally {
418        timer.Elapsed -= timer_Elapsed;
419        timer.Stop();
420        ExecutionTime += DateTime.UtcNow - lastUpdateTime;
[12825]421      }
[8955]422    }
423
[12856]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)));
[12804]431
[12856]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++;
[12804]435
[12856]436        Algorithm.Start();
437        algorithmWaitHandle.WaitOne();
[8955]438
[12856]439        if (Algorithm.ExecutionState == ExecutionState.Paused) return;
[8955]440
[13564]441        RoundupResults();
[8955]442
[13564]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;
[12825]475        }
[13564]476      }
[14058]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);
[13564]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();
[12803]485          }
486        }
[13564]487      }
[12825]488
[13564]489      execTime.Value = ExecutionTime;
[8955]490    }
[8975]491
[12856]492    private void UpdateQualityPerClockResult(IndexedDataTable<double> perClock, int restarts) {
[12825]493      IndexedDataTable<double> dt;
[12856]494      if (!Results.ContainsKey(QualityPerClockResultName)) {
[12825]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));
[12856]505        Results.Add(new Result(QualityPerClockResultName, dt));
[12825]506      } else {
[12856]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;
[12825]513        foreach (var tupl in perClock.Rows.First().Values) {
514          if (Maximization && tupl.Item2 > best || !Maximization && tupl.Item2 < best) {
[12856]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));
[12825]523            best = tupl.Item2;
524          }
525        }
[12890]526        if (!improvement) {
527          qualityValues.RemoveAt(qualityValues.Count - 1);
528          restartValues.RemoveAt(restartValues.Count - 1);
[12856]529        }
[12890]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));
[12825]533      }
534    }
[12804]535
[12856]536    private void UpdateQualityPerEvaluationsResult(IndexedDataTable<double> perEvaluations, int restarts) {
[12825]537      IndexedDataTable<double> dt;
[12856]538      if (!Results.ContainsKey(QualityPerEvaluationsResultName)) {
[12825]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));
[12856]549        Results.Add(new Result(QualityPerEvaluationsResultName, dt));
[12825]550      } else {
[12856]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;
[12825]557        foreach (var tupl in perEvaluations.Rows.First().Values) {
558          if (Maximization && tupl.Item2 > best || !Maximization && tupl.Item2 < best) {
[12856]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));
[12825]567            best = tupl.Item2;
568          }
569        }
[12890]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);
[12856]574        }
[12890]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));
[12803]578      }
[12856]579    }
580
581    private void UpdateTargetValueFromBestKnownQuality() {
[13564]582      var bkParam = ((ISingleObjectiveHeuristicOptimizationProblem)Problem).BestKnownQualityParameter as IValueParameter<DoubleValue>;
[12856]583      if (bkParam != null && bkParam.Value != null)
[13568]584        TargetQualityParameter.Value = new DoubleValue(bkParam.Value.Value);
[12856]585      else if (bkParam != null && bkParam.Value == null)
[13568]586        TargetQualityParameter.Value = null;
[12856]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) {
[13564]594        if (analyzerParam.Value.Operators.Contains(Analyzer)) return;
595        analyzerParam.Value.Operators.Add(Analyzer, true);
[12856]596      } else {
597        var analyzerParam2 = Algorithm.Parameters["Analyzer"] as IValueParameter<IMultiAnalyzer>;
598        if (analyzerParam2 == null) return;
[13564]599        if (analyzerParam2.Value.Operators.Contains(Analyzer)) return;
600        analyzerParam2.Value.Operators.Add(Analyzer, true);
[12803]601      }
[8975]602    }
603
[12856]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) {
[13564]609        analyzerParam.Value.Operators.Remove(Analyzer);
[12856]610      } else {
611        var analyzerParam2 = Algorithm.Parameters["Analyzer"] as IValueParameter<IMultiAnalyzer>;
612        if (analyzerParam2 != null) {
[13564]613          analyzerParam2.Value.Operators.Remove(Analyzer);
[12856]614        }
615      }
616    }
[12804]617
[12856]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) {
[13564]623      if (ExecutionState == ExecutionState.Paused) return;
[12856]624      algorithmWaitHandle.Set();
625    }
626    private void Algorithm_Stopped(object sender, EventArgs e) {
[13564]627      if (ExecutionState == ExecutionState.Paused) return;
[12856]628      algorithmWaitHandle.Set();
629    }
[12804]630
[12856]631    private void Algorithm_ProblemChanged(object sender, EventArgs e) {
632      if (Algorithm.Problem != Problem) Problem = (ISingleObjectiveHeuristicOptimizationProblem)Algorithm.Problem;
[12804]633      AddAlgorithmAnalyzers();
[12856]634    }
[12804]635
[13568]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
[12856]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      }
[8975]667    }
[12804]668
[12856]669    private void Problem_BestKnownQualityParameter_Value_ValueChanged(object sender, EventArgs e) {
670      UpdateTargetValueFromBestKnownQuality();
[12804]671    }
672
[12856]673    protected override void Problem_Reset(object sender, EventArgs eventArgs) {
674      if (Algorithm != null) AddAlgorithmAnalyzers();
[12804]675    }
676
[12856]677    protected override void Problem_OperatorsChanged(object sender, EventArgs eventArgs) {
678      if (Algorithm != null) AddAlgorithmAnalyzers();
[12804]679    }
680
[13564]681    protected override void OnProblemChanged() {
682      base.OnProblemChanged();
683      if (Algorithm != null) Algorithm.Problem = Problem;
684      if (Problem != null) UpdateTargetValueFromBestKnownQuality();
685    }
686
[13568]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
[12856]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;
[12804]707    }
[12803]708    #endregion
[13568]709
710    private void HandleAlgorithmTargetQualityChanged() {
[13738]711      if (Algorithm == null) return;
[13568]712      IParameter param;
[13569]713      if (!Algorithm.Parameters.TryGetValue("TargetQuality", out param)) return;
[13568]714      var doubleValueParam = (param as IValueParameter<DoubleValue>);
[13569]715      if (doubleValueParam == null) return;
[13568]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() {
[13738]726      if (Algorithm == null) return;
[13568]727      IParameter param;
[13569]728      if (!Algorithm.Parameters.TryGetValue("MaximumEvaluations", out param)) return;
[13568]729      var intValueParam = (param as IValueParameter<IntValue>);
[13569]730      if (intValueParam == null) return;
[13568]731      var value = intValueParam.Value;
732      if (value.Value > MaximumEvaluationsParameter.Value.Value)
733        value.Value = MaximumEvaluationsParameter.Value.Value;
734    }
735
736    private void SynchronizeMaximumEvaluationsParameter() {
[13738]737      if (Algorithm == null) return;
[13568]738      IParameter param;
[13569]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;
[13568]744    }
[8955]745  }
746}
Note: See TracBrowser for help on using the repository browser.