#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; using System.Linq; using alglib; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Operators; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using System.Collections.Generic; using HeuristicLab.Problems.DataAnalysis.Evaluators; using HeuristicLab.Analysis; namespace HeuristicLab.Problems.DataAnalysis.Operators { [Item("Covariant Parsimony Pressure", "Covariant Parsimony Pressure.")] [StorableClass] public class CovariantParsimonyPressure : SingleSuccessorOperator { public IScopeTreeLookupParameter SymbolicExpressionTreeParameter { get { return (IScopeTreeLookupParameter)Parameters["SymbolicExpressionTree"]; } } public IScopeTreeLookupParameter QualityParameter { get { return (IScopeTreeLookupParameter)Parameters["Quality"]; } } public IScopeTreeLookupParameter AdjustedQualityParameter { get { return (IScopeTreeLookupParameter)Parameters["AdjustedQuality"]; } } public ILookupParameter MaximizationParameter { get { return (ILookupParameter)Parameters["Maximization"]; } } public IValueLookupParameter KParameter { get { return (IValueLookupParameter)Parameters["K"]; } } public ILookupParameter CParameter { get { return (ILookupParameter)Parameters["C"]; } } public ILookupParameter GenerationsParameter { get { return (ILookupParameter)Parameters["Generations"]; } } public IValueLookupParameter FirstGenerationParameter { get { return (IValueLookupParameter)Parameters["FirstGenerationParameter"]; } } public IValueLookupParameter ApplyParsimonyPressureParameter { get { return (IValueLookupParameter)Parameters["ApplyParsimonyPressure"]; } } public ILookupParameter LengthCorrelationParameter { get { return (ILookupParameter)Parameters["Correlation(Length, AdjustedFitness)"]; } } public ILookupParameter FitnessCorrelationParameter { get { return (ILookupParameter)Parameters["Correlation(Fitness, AdjustedFitness)"]; } } public IValueLookupParameter ComplexityAdaptionParameter { get { return (IValueLookupParameter)Parameters["ComplexityAdaption"]; } } public IValueLookupParameter InvertComplexityAdaptionParameter { get { return (IValueLookupParameter)Parameters["InvertComplexityAdaption"]; } } public IValueLookupParameter MinAverageSizeParameter { get { return (IValueLookupParameter)Parameters["MinAverageSize"]; } } public CovariantParsimonyPressure(bool deserializing) : base(deserializing) { } public CovariantParsimonyPressure() : base() { Parameters.Add(new ScopeTreeLookupParameter("SymbolicExpressionTree")); Parameters.Add(new ScopeTreeLookupParameter("Quality")); Parameters.Add(new ScopeTreeLookupParameter("AdjustedQuality")); Parameters.Add(new LookupParameter("Maximization")); Parameters.Add(new ValueLookupParameter("K", new DoubleValue(1.0))); Parameters.Add(new LookupParameter("Generations")); Parameters.Add(new ValueLookupParameter("FirstGenerationParameter", new IntValue(1))); Parameters.Add(new ValueLookupParameter("ApplyParsimonyPressure")); Parameters.Add(new ValueLookupParameter("ComplexityAdaption", new PercentValue(-0.01))); Parameters.Add(new LookupParameter("Correlation(Length, AdjustedFitness)")); Parameters.Add(new LookupParameter("Correlation(Fitness, AdjustedFitness)")); Parameters.Add(new ValueLookupParameter("MinAverageSize", new DoubleValue(15))); Parameters.Add(new LookupParameter("C")); Parameters.Add(new ValueLookupParameter("InvertComplexityAdaption")); } [StorableHook(Persistence.Default.CompositeSerializers.Storable.HookType.AfterDeserialization)] private void AfterDeserialization() { if (!Parameters.ContainsKey("Maximization")) Parameters.Add(new LookupParameter("Maximization")); if (!Parameters.ContainsKey("K")) Parameters.Add(new ValueLookupParameter("K", new DoubleValue(1.0))); if (!Parameters.ContainsKey("AdjustedQuality")) { Parameters.Add(new ScopeTreeLookupParameter("AdjustedQuality")); } if (!Parameters.ContainsKey("Generations")) { Parameters.Add(new LookupParameter("Generations")); } if (!Parameters.ContainsKey("FirstGenerationParameter")) { Parameters.Add(new ValueLookupParameter("FirstGenerationParameter", new IntValue(1))); } if (!Parameters.ContainsKey("ApplyParsimonyPressure")) { Parameters.Add(new ValueLookupParameter("ApplyParsimonyPressure")); } if (!Parameters.ContainsKey("ComplexityAdaption")) { Parameters.Add(new ValueLookupParameter("ComplexityAdaption", new PercentValue(-0.01))); } if (!Parameters.ContainsKey("MinAverageSize")) { Parameters.Add(new ValueLookupParameter("MinAverageSize", new DoubleValue(15))); } if (!Parameters.ContainsKey("C")) { Parameters.Add(new LookupParameter("C")); } if (!Parameters.ContainsKey("InvertComplexityAdaption")) { Parameters.Add(new ValueLookupParameter("InvertComplexityAdaption")); } } public override IOperation Apply() { ItemArray trees = SymbolicExpressionTreeParameter.ActualValue; ItemArray qualities = QualityParameter.ActualValue; // always apply Parsimony pressure if overfitting has been detected // otherwise appliy PP only when we are currently overfitting if (GenerationsParameter.ActualValue != null && GenerationsParameter.ActualValue.Value >= FirstGenerationParameter.ActualValue.Value && ApplyParsimonyPressureParameter.ActualValue.Value == true) { var lengths = from tree in trees select tree.Size; double k = KParameter.ActualValue.Value; // calculate cov(f, l) and cov(l, l^k) OnlineCovarianceEvaluator lengthFitnessCovEvaluator = new OnlineCovarianceEvaluator(); OnlineCovarianceEvaluator lengthAdjLengthCovEvaluator = new OnlineCovarianceEvaluator(); OnlineMeanAndVarianceCalculator lengthMeanCalculator = new OnlineMeanAndVarianceCalculator(); OnlineMeanAndVarianceCalculator fitnessMeanCalculator = new OnlineMeanAndVarianceCalculator(); OnlineMeanAndVarianceCalculator adjLengthMeanCalculator = new OnlineMeanAndVarianceCalculator(); var lengthEnumerator = lengths.GetEnumerator(); var qualityEnumerator = qualities.GetEnumerator(); while (lengthEnumerator.MoveNext() & qualityEnumerator.MoveNext()) { double fitness = qualityEnumerator.Current.Value; if (!MaximizationParameter.ActualValue.Value) { // use f = 1 / (1 + quality) for minimization problems fitness = 1.0 / (1.0 + fitness); } lengthFitnessCovEvaluator.Add(lengthEnumerator.Current, fitness); lengthAdjLengthCovEvaluator.Add(lengthEnumerator.Current, Math.Pow(lengthEnumerator.Current, k)); lengthMeanCalculator.Add(lengthEnumerator.Current); fitnessMeanCalculator.Add(fitness); adjLengthMeanCalculator.Add(Math.Pow(lengthEnumerator.Current, k)); } //double sizeAdaption = lengthMeanCalculator.Mean * ComplexityAdaptionParameter.ActualValue.Value; double sizeAdaption = 100.0 * ComplexityAdaptionParameter.ActualValue.Value; if (InvertComplexityAdaptionParameter.ActualValue != null && InvertComplexityAdaptionParameter.ActualValue.Value) { sizeAdaption = -sizeAdaption; } if (lengthMeanCalculator.Mean + sizeAdaption < MinAverageSizeParameter.ActualValue.Value) sizeAdaption = MinAverageSizeParameter.ActualValue.Value - lengthMeanCalculator.Mean; // cov(l, f) - (g(t+1) - mu(t)) avgF // c(t) = -------------------------------------------- // cov(l, l^k) - (g(t+1) - mu(t)) E[l^k] double c = lengthFitnessCovEvaluator.Covariance - sizeAdaption * fitnessMeanCalculator.Mean; c /= lengthAdjLengthCovEvaluator.Covariance - sizeAdaption * adjLengthMeanCalculator.Mean; CParameter.ActualValue = new DoubleValue(c); // adjust fitness bool maximization = MaximizationParameter.ActualValue.Value; lengthEnumerator = lengths.GetEnumerator(); qualityEnumerator = qualities.GetEnumerator(); int i = 0; ItemArray adjQualities = new ItemArray(qualities.Length); while (lengthEnumerator.MoveNext() & qualityEnumerator.MoveNext()) { adjQualities[i++] = new DoubleValue(qualityEnumerator.Current.Value - c * Math.Pow(lengthEnumerator.Current, k)); } AdjustedQualityParameter.ActualValue = adjQualities; double[] lengthArr = lengths.Select(x => (double)x).ToArray(); double[] adjFitess = (from f in AdjustedQualityParameter.ActualValue select f.Value).ToArray(); double[] fitnessArr = (from f in QualityParameter.ActualValue let normFit = maximization ? f.Value : 1.0 / (1.0 + f.Value) select normFit).ToArray(); LengthCorrelationParameter.ActualValue = new DoubleValue(alglib.correlation.spearmanrankcorrelation(lengthArr, adjFitess, lengthArr.Length)); FitnessCorrelationParameter.ActualValue = new DoubleValue(alglib.correlation.spearmanrankcorrelation(fitnessArr, adjFitess, lengthArr.Length)); } else { CParameter.ActualValue = new DoubleValue(0.0); // adjusted fitness is equal to fitness AdjustedQualityParameter.ActualValue = (ItemArray)QualityParameter.ActualValue.Clone(); FitnessCorrelationParameter.ActualValue = new DoubleValue(1.0); double[] lengths = (from tree in trees select (double)tree.Size).ToArray(); double[] fitess = (from f in AdjustedQualityParameter.ActualValue select f.Value).ToArray(); LengthCorrelationParameter.ActualValue = new DoubleValue(alglib.correlation.spearmanrankcorrelation(lengths, fitess, lengths.Length)); } return base.Apply(); } } }