#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
}
}