#region License Information
/* HeuristicLab
* Copyright (C) 2002-2010 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.Collections.Generic;
using System.Linq;
using HeuristicLab.Analysis;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
using HeuristicLab.Operators;
using HeuristicLab.Optimization;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Problems.DataAnalysis.MultiVariate.Regression.Symbolic.Evaluators;
using HeuristicLab.Problems.DataAnalysis.Symbolic;
using HeuristicLab.Problems.DataAnalysis.MultiVariate.Regression.Symbolic.Interfaces;
using HeuristicLab.Common;
namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.Regression.Symbolic.Analyzers {
///
/// An operator that analyzes the validation best scaled symbolic vector regression solution.
///
[Item("ValidationBestScaledSymbolicVectorRegressionSolutionAnalyzer", "An operator that analyzes the validation best scaled symbolic vector regression solution.")]
[StorableClass]
public sealed class ValidationBestScaledSymbolicVectorRegressionSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer {
private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree";
private const string ScaledSymbolicExpressionTreeParameterName = "ScaledSymbolicExpressionTree";
private const string SymbolicExpressionTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter";
private const string ProblemDataParameterName = "ProblemData";
private const string ValidationSamplesStartParameterName = "ValidationSamplesStart";
private const string ValidationSamplesEndParameterName = "ValidationSamplesEnd";
private const string EvaluatorParameterName = "Evaluator";
private const string MaximizationParameterName = "Maximization";
private const string UpperEstimationLimitParameterName = "UpperEstimationLimit";
private const string LowerEstimationLimitParameterName = "LowerEstimationLimit";
private const string AlphaParameterName = "Alpha";
private const string BetaParameterName = "Beta";
private const string BestSolutionParameterName = "Best solution (validation)";
private const string BestSolutionQualityParameterName = "Best solution quality (validation)";
private const string CurrentBestValidationQualityParameterName = "Current best validation quality";
private const string BestSolutionQualityValuesParameterName = "Validation Quality";
private const string ResultsParameterName = "Results";
private const string BestKnownQualityParameterName = "BestKnownQuality";
#region parameter properties
public ScopeTreeLookupParameter SymbolicExpressionTreeParameter {
get { return (ScopeTreeLookupParameter)Parameters[SymbolicExpressionTreeParameterName]; }
}
public ScopeTreeLookupParameter AlphaParameter {
get { return (ScopeTreeLookupParameter)Parameters[AlphaParameterName]; }
}
public ScopeTreeLookupParameter BetaParameter {
get { return (ScopeTreeLookupParameter)Parameters[BetaParameterName]; }
}
public IValueLookupParameter SymbolicExpressionTreeInterpreterParameter {
get { return (IValueLookupParameter)Parameters[SymbolicExpressionTreeInterpreterParameterName]; }
}
public IValueLookupParameter ProblemDataParameter {
get { return (IValueLookupParameter)Parameters[ProblemDataParameterName]; }
}
public IValueLookupParameter ValidationSamplesStartParameter {
get { return (IValueLookupParameter)Parameters[ValidationSamplesStartParameterName]; }
}
public IValueLookupParameter ValidationSamplesEndParameter {
get { return (IValueLookupParameter)Parameters[ValidationSamplesEndParameterName]; }
}
public IValueLookupParameter EvaluatorParameter {
get { return (IValueLookupParameter)Parameters[EvaluatorParameterName]; }
}
public IValueLookupParameter MaximizationParameter {
get { return (IValueLookupParameter)Parameters[MaximizationParameterName]; }
}
public IValueLookupParameter UpperEstimationLimitParameter {
get { return (IValueLookupParameter)Parameters[UpperEstimationLimitParameterName]; }
}
public IValueLookupParameter LowerEstimationLimitParameter {
get { return (IValueLookupParameter)Parameters[LowerEstimationLimitParameterName]; }
}
public ILookupParameter BestSolutionParameter {
get { return (ILookupParameter)Parameters[BestSolutionParameterName]; }
}
public ILookupParameter BestSolutionQualityParameter {
get { return (ILookupParameter)Parameters[BestSolutionQualityParameterName]; }
}
public ILookupParameter ResultsParameter {
get { return (ILookupParameter)Parameters[ResultsParameterName]; }
}
public ILookupParameter BestKnownQualityParameter {
get { return (ILookupParameter)Parameters[BestKnownQualityParameterName]; }
}
#endregion
#region properties
public MultiVariateDataAnalysisProblemData ProblemData {
get { return ProblemDataParameter.ActualValue; }
}
public ItemArray Alpha {
get { return AlphaParameter.ActualValue; }
}
public ItemArray Beta {
get { return BetaParameter.ActualValue; }
}
public DoubleArray LowerEstimationLimit {
get { return LowerEstimationLimitParameter.ActualValue; }
}
public DoubleArray UpperEstimationLimit {
get { return UpperEstimationLimitParameter.ActualValue; }
}
public ISingleObjectiveSymbolicVectorRegressionEvaluator Evaluator {
get { return EvaluatorParameter.ActualValue; }
}
public BoolValue Maximization {
get { return MaximizationParameter.ActualValue; }
}
public DoubleValue BestSolutionQuality {
get { return BestSolutionQualityParameter.ActualValue; }
}
#endregion
[StorableConstructor]
protected ValidationBestScaledSymbolicVectorRegressionSolutionAnalyzer(bool deserializing) : base(deserializing) { }
protected ValidationBestScaledSymbolicVectorRegressionSolutionAnalyzer(ValidationBestScaledSymbolicVectorRegressionSolutionAnalyzer original, Cloner cloner)
: base(original, cloner) {
}
public ValidationBestScaledSymbolicVectorRegressionSolutionAnalyzer()
: base() {
Parameters.Add(new ScopeTreeLookupParameter(SymbolicExpressionTreeParameterName, "The symbolic expression trees to analyze."));
Parameters.Add(new ScopeTreeLookupParameter(AlphaParameterName, "The alpha parameter for linear scaling."));
Parameters.Add(new ScopeTreeLookupParameter(BetaParameterName, "The beta parameter for linear scaling."));
Parameters.Add(new ValueLookupParameter(SymbolicExpressionTreeInterpreterParameterName, "The interpreter that should be used for the analysis of symbolic expression trees."));
Parameters.Add(new ValueLookupParameter(ProblemDataParameterName, "The problem data for which the symbolic expression tree is a solution."));
Parameters.Add(new ValueLookupParameter(ValidationSamplesStartParameterName, "The first index of the validation partition of the data set."));
Parameters.Add(new ValueLookupParameter(ValidationSamplesEndParameterName, "The last index of the validation partition of the data set."));
Parameters.Add(new ValueLookupParameter(EvaluatorParameterName, "The evaluator which should be used to evaluate the solution on the validation set."));
Parameters.Add(new ValueLookupParameter(MaximizationParameterName, "The direction of optimization."));
Parameters.Add(new ValueLookupParameter(UpperEstimationLimitParameterName, "The upper estimation limit that was set for the evaluation of the symbolic expression trees."));
Parameters.Add(new ValueLookupParameter(LowerEstimationLimitParameterName, "The lower estimation limit that was set for the evaluation of the symbolic expression trees."));
Parameters.Add(new LookupParameter(BestSolutionParameterName, "The best symbolic regression solution."));
Parameters.Add(new LookupParameter(BestSolutionQualityParameterName, "The quality of the best symbolic regression solution."));
Parameters.Add(new LookupParameter(ResultsParameterName, "The result collection where the best symbolic regression solution should be stored."));
Parameters.Add(new LookupParameter(BestKnownQualityParameterName, "The best known (validation) quality achieved on the data set."));
}
public override IDeepCloneable Clone(Cloner cloner) {
return new ValidationBestScaledSymbolicVectorRegressionSolutionAnalyzer(this, cloner);
}
public override IOperation Apply() {
var trees = SymbolicExpressionTreeParameter.ActualValue;
IEnumerable scaledTrees;
if (Alpha.Length == trees.Length) {
scaledTrees = from i in Enumerable.Range(0, trees.Length)
select SymbolicVectorRegressionSolutionLinearScaler.Scale(trees[i], Beta[i].ToArray(), Alpha[i].ToArray());
} else {
scaledTrees = trees;
}
IEnumerable selectedTargetVariables = from item in ProblemData.TargetVariables.CheckedItems
select item.Value.Value;
var interpreter = SymbolicExpressionTreeInterpreterParameter.ActualValue;
int validationStart = ValidationSamplesStartParameter.ActualValue.Value;
int validationEnd = ValidationSamplesEndParameter.ActualValue.Value;
IEnumerable rows = Enumerable.Range(validationStart, validationEnd - validationStart);
SymbolicExpressionTree bestTree = null;
double bestQuality = Maximization.Value ? double.NegativeInfinity : double.PositiveInfinity;
foreach (var tree in scaledTrees) {
// calculate quality on validation set
double quality = Evaluator.Evaluate(tree, interpreter, ProblemData, selectedTargetVariables, rows, LowerEstimationLimit, UpperEstimationLimit);
if ((Maximization.Value && quality > bestQuality) ||
(!Maximization.Value && quality < bestQuality)) {
bestQuality = quality;
bestTree = tree;
}
}
bool newBest =
BestSolutionQualityParameter.ActualValue == null ||
(Maximization.Value && bestQuality > BestSolutionQuality.Value) ||
(!Maximization.Value && bestQuality < BestSolutionQuality.Value);
if (newBest) {
var bestSolution = bestTree;
//bestSolution.Name = BestSolutionParameterName;
//solution.Description = "Best solution on validation partition found over the whole run.";
BestSolutionParameter.ActualValue = bestSolution;
BestSolutionQualityParameter.ActualValue = new DoubleValue(bestQuality);
}
// update results
var results = ResultsParameter.ActualValue;
if (!results.ContainsKey(BestSolutionQualityValuesParameterName)) {
results.Add(new Result(BestSolutionParameterName, BestSolutionParameter.ActualValue));
results.Add(new Result(BestSolutionQualityValuesParameterName, new DataTable(BestSolutionQualityValuesParameterName, BestSolutionQualityValuesParameterName)));
results.Add(new Result(BestSolutionQualityParameterName, new DoubleValue()));
results.Add(new Result(CurrentBestValidationQualityParameterName, new DoubleValue()));
}
results[BestSolutionParameterName].Value = BestSolutionParameter.ActualValue;
results[BestSolutionQualityParameterName].Value = new DoubleValue(BestSolutionQualityParameter.ActualValue.Value);
results[CurrentBestValidationQualityParameterName].Value = new DoubleValue(bestQuality);
DataTable validationValues = (DataTable)results[BestSolutionQualityValuesParameterName].Value;
AddValue(validationValues, BestSolutionQualityParameter.ActualValue.Value, BestSolutionQualityParameterName, BestSolutionQualityParameterName);
AddValue(validationValues, bestQuality, CurrentBestValidationQualityParameterName, CurrentBestValidationQualityParameterName);
return base.Apply();
}
private static void AddValue(DataTable table, double data, string name, string description) {
DataRow row;
table.Rows.TryGetValue(name, out row);
if (row == null) {
row = new DataRow(name, description);
row.Values.Add(data);
table.Rows.Add(row);
} else {
row.Values.Add(data);
}
}
}
}