#region License Information /* HeuristicLab * Copyright (C) 2002-2016 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; using System.Collections.Generic; using System.Linq; using System.Threading; using HeuristicLab.Analysis; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Optimization; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.DataAnalysis; namespace HeuristicLab.Algorithms.SAPBA.Strategies { [StorableClass] public abstract class StrategyBase : ParameterizedNamedItem, ISurrogateStrategy { #region Properties [Storable] protected SurrogateAssistedPopulationBasedAlgorithm Algorithm; [Storable] private List> Samples; [Storable] protected IRegressionSolution RegressionSolution; protected CancellationToken Cancellation; private IEnumerable> TruncatedSamples => Samples.Count > Algorithm.MaximalDatasetSize && Algorithm.MaximalDatasetSize > 0 ? Samples.Skip(Samples.Count - Algorithm.MaximalDatasetSize) : Samples; #endregion #region ResultName private const string BestQualityResultName = "Best Quality"; private const string BestSolutionResultName = "Best Solution"; private const string QualityTableResultName = "Qualities"; private const string BestQualityRowName = "Best Quality"; private const string WorstQualityRowName = "Worst Quality"; private const string CurrentQualityRowName = "Current Quality"; private const string MedianQualityRowName = "Median Quality"; private const string AverageQualityRowName = "Average Quality"; private const string RegressionSolutionResultName = "Model"; private const string EvaluatedSoultionsResultName = "EvaluatedSolutions"; private const string IterationsResultName = "Iterations"; #endregion #region constructors [StorableConstructor] protected StrategyBase(bool deserializing) : base(deserializing) { } protected StrategyBase(StrategyBase original, Cloner cloner) : base(original, cloner) { if (original.Samples != null) Samples = original.Samples.Select(x => new Tuple(cloner.Clone(x.Item1), x.Item2)).ToList(); RegressionSolution = cloner.Clone(original.RegressionSolution); } protected StrategyBase() { } #endregion public abstract double Evaluate(RealVector r, IRandom random); protected abstract void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, ResultCollection globalResults, IRandom random); protected abstract void ProcessPopulation(Individual[] individuals, double[] qualities, IRandom random); protected abstract void Initialize(); public void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) { Algorithm.Problem.Analyze(individuals, qualities, results, random); ProcessPopulation(individuals, qualities, random); var globalResults = Algorithm.Results; if (!globalResults.ContainsKey(EvaluatedSoultionsResultName)) globalResults.Add(new Result(EvaluatedSoultionsResultName, new IntValue(Samples.Count))); else ((IntValue)globalResults[EvaluatedSoultionsResultName].Value).Value = Samples.Count; if (!globalResults.ContainsKey(IterationsResultName)) globalResults.Add(new Result(IterationsResultName, new IntValue(0))); else ((IntValue)globalResults[IterationsResultName].Value).Value++; if (Samples.Count != 0) { var min = Samples.Min(x => x.Item2); var max = Samples.Max(x => x.Item2); var bestIdx = Algorithm.Problem.Maximization ? Samples.ArgMax(x => x.Item2) : Samples.ArgMin(x => x.Item2); if (!globalResults.ContainsKey(BestQualityResultName)) globalResults.Add(new Result(BestQualityResultName, new DoubleValue(0.0))); ((DoubleValue)globalResults[BestQualityResultName].Value).Value = Samples[bestIdx].Item2; if (!globalResults.ContainsKey(BestSolutionResultName)) globalResults.Add(new Result(BestSolutionResultName, new RealVector())); globalResults[BestSolutionResultName].Value = Samples[bestIdx].Item1; DataTable table; if (!globalResults.ContainsKey(QualityTableResultName)) { table = new DataTable("Qualites", "Qualites over iteration"); globalResults.Add(new Result(QualityTableResultName, table)); table.Rows.Add(new DataRow(BestQualityRowName, "Best Quality")); table.Rows.Add(new DataRow(WorstQualityRowName, "Worst Quality")); table.Rows.Add(new DataRow(CurrentQualityRowName, "Current Quality")); table.Rows.Add(new DataRow(MedianQualityRowName, "Median Quality")); table.Rows.Add(new DataRow(AverageQualityRowName, "Average Quality")); } table = (DataTable)globalResults[QualityTableResultName].Value; table.Rows[BestQualityResultName].Values.Add(Algorithm.Problem.Maximization ? max : min); table.Rows[WorstQualityRowName].Values.Add(Algorithm.Problem.Maximization ? min : max); table.Rows[CurrentQualityRowName].Values.Add(Samples[Samples.Count - 1].Item2); table.Rows[AverageQualityRowName].Values.Add(Samples.Average(x => x.Item2)); table.Rows[MedianQualityRowName].Values.Add(Samples.Select(x => x.Item2).Median()); } if (RegressionSolution != null) { if (!globalResults.ContainsKey(RegressionSolutionResultName)) globalResults.Add(new Result(RegressionSolutionResultName, RegressionSolution)); else globalResults[RegressionSolutionResultName].Value = RegressionSolution; } Analyze(individuals, qualities, results, globalResults, random); } public void Initialize(SurrogateAssistedPopulationBasedAlgorithm algorithm) { Algorithm = algorithm; Samples = algorithm.InitialSamples?.ToList() ?? new List>(); RegressionSolution = null; Initialize(); } #region Helpers for Subclasses protected void BuildRegressionSolution(IRandom random) { RegressionSolution = EgoUtilities.BuildModel(Cancellation, TruncatedSamples, Algorithm.RegressionAlgorithm, random, Algorithm.RemoveDuplicates, RegressionSolution); } protected Tuple EvaluateSample(RealVector point, IRandom random) { Cancellation.ThrowIfCancellationRequested(); if (Samples.Count >= Algorithm.MaximumEvaluations) { Algorithm.OptimizationAlgorithm.Stop(); return new Tuple(point, 0.0); } var p = new Tuple(point, Algorithm.Problem.Evaluate(GetIndividual(point), random)); Samples.Add(p); return p; } protected Tuple EstimateSample(RealVector point, IRandom random) { if (Samples.Count == Algorithm.InitialEvaluations && RegressionSolution == null) BuildRegressionSolution(random); return Samples.Count < Algorithm.InitialEvaluations ? EvaluateSample(point, random) : new Tuple(point, RegressionSolution.Model.GetEstimation(point)); } #endregion #region Helpers private Individual GetIndividual(RealVector r) { var scope = new Scope(); scope.Variables.Add(new Variable(Algorithm.Problem.Encoding.Name, r)); return new SingleEncodingIndividual(Algorithm.Problem.Encoding, scope); } public void UpdateCancellation(CancellationToken cancellationToken) { Cancellation = cancellationToken; } #endregion } }