#region License Information /* HeuristicLab * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Operators; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HEAL.Fossil; namespace HeuristicLab.Problems.ParameterOptimization { [Item("BestSolutionAnalyzer", "Tracks the best parameter vector solution of the current algorithm run.")] [StorableType("A39363D6-8ACE-44AF-99E1-643928DCA6B9")] public class BestSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer { private const string MaximizationParameterName = "Maximization"; private const string ParameterVectorParameterName = "RealVector"; private const string ParameterNamesParameterName = "ParameterNames"; private const string QualityParameterName = "Quality"; private const string BestQualityParameterName = "BestQuality"; private const string BestKnownQualityParameterName = "BestKnownQuality"; private const string ResultsParameterName = "Results"; private const string BestSolutionResultName = "Best Solution"; public virtual bool EnabledByDefault { get { return true; } } public ILookupParameter MaximizationParameter { get { return (ILookupParameter)Parameters[MaximizationParameterName]; } } public IScopeTreeLookupParameter ParameterVectorParameter { get { return (IScopeTreeLookupParameter)Parameters[ParameterVectorParameterName]; } } public ILookupParameter ParameterNamesParameter { get { return (ILookupParameter)Parameters[ParameterNamesParameterName]; } } public IScopeTreeLookupParameter QualityParameter { get { return (IScopeTreeLookupParameter)Parameters[QualityParameterName]; } } public ILookupParameter BestQualityParameter { get { return (ILookupParameter)Parameters[BestQualityParameterName]; } } public ILookupParameter BestKnownQualityParameter { get { return (ILookupParameter)Parameters[BestKnownQualityParameterName]; } } public IValueLookupParameter ResultsParameter { get { return (IValueLookupParameter)Parameters[ResultsParameterName]; } } [StorableConstructor] protected BestSolutionAnalyzer(StorableConstructorFlag _) : base(_) { } protected BestSolutionAnalyzer(BestSolutionAnalyzer original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new BestSolutionAnalyzer(this, cloner); } public BestSolutionAnalyzer() : base() { Parameters.Add(new LookupParameter(MaximizationParameterName, "True if the problem is a maximization problem.")); Parameters.Add(new ScopeTreeLookupParameter(ParameterVectorParameterName, "The parameter vector which should be evaluated.")); Parameters.Add(new LookupParameter(ParameterNamesParameterName, "The names of the elements in the parameter vector.")); Parameters.Add(new ScopeTreeLookupParameter(QualityParameterName, "The quality name for the parameter vectors.")); Parameters.Add(new LookupParameter(BestQualityParameterName, "The best quality found so far.")); Parameters.Add(new LookupParameter(BestKnownQualityParameterName, "The quality of the best known solution.")); Parameters.Add(new ValueLookupParameter(ResultsParameterName, "The result collection where the results should be stored.")); } public override IOperation Apply() { ItemArray parameterVectors = ParameterVectorParameter.ActualValue; ItemArray qualities = QualityParameter.ActualValue; bool max = MaximizationParameter.ActualValue.Value; DoubleValue bestKnownQuality = BestKnownQualityParameter.ActualValue; int indexOfBest = -1; if (!max) indexOfBest = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index; else indexOfBest = qualities.Select((x, index) => new { index, x.Value }).OrderByDescending(x => x.Value).First().index; var bestQuality = qualities[indexOfBest].Value; var bestParameterVector = (RealVector)parameterVectors[indexOfBest].Clone(); ResultCollection results = ResultsParameter.ActualValue; if (BestQualityParameter.ActualValue == null) { if (max) BestQualityParameter.ActualValue = new DoubleValue(double.MinValue); else BestQualityParameter.ActualValue = new DoubleValue(double.MaxValue); } if (!results.ContainsKey(BestSolutionResultName)) { results.Add(new Result(BestSolutionResultName, new DoubleArray(bestParameterVector.ToArray()))); var bestSolution = (DoubleArray)results[BestSolutionResultName].Value; bestSolution.ElementNames = ParameterNamesParameter.ActualValue; BestQualityParameter.ActualValue.Value = bestQuality; } else if (max && bestQuality > BestQualityParameter.ActualValue.Value || !max && bestQuality < BestQualityParameter.ActualValue.Value) { var bestSolution = (DoubleArray)results[BestSolutionResultName].Value; bestSolution.ElementNames = ParameterNamesParameter.ActualValue; for (int i = 0; i < bestParameterVector.Length; i++) bestSolution[i] = bestParameterVector[i]; BestQualityParameter.ActualValue.Value = bestQuality; } //update best known quality if (bestKnownQuality == null || max && bestQuality > bestKnownQuality.Value || !max && bestQuality < bestKnownQuality.Value) { BestKnownQualityParameter.ActualValue = new DoubleValue(bestQuality); } return base.Apply(); } } }