#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; namespace HeuristicLab.Problems.DataAnalysis.Operators { [Item("DynOpEqComparator", "Dynamic Operator Equalization.")] [StorableClass] public class DynOpEqComparator : SingleSuccessorOperator, ISubScopesQualityComparator { public IValueLookupParameter MaximizationParameter { get { return (IValueLookupParameter)Parameters["Maximization"]; } } public ILookupParameter ResultParameter { get { return (ILookupParameter)Parameters["Result"]; } } public ILookupParameter LeftSideParameter { get { return (ILookupParameter)Parameters["LeftSide"]; } } public ILookupParameter> RightSideParameter { get { return (ILookupParameter>)Parameters["RightSide"]; } } public ILookupParameter SymbolicExpressionTreeParameter { get { return (ILookupParameter)Parameters["SymbolicExpressionTree"]; } } public ILookupParameter BestQualityParameter { get { return (ILookupParameter)Parameters["BestQuality"]; } } public IValueLookupParameter BinSizeParameter { get { return (IValueLookupParameter)Parameters["BinSize"]; } } public ILookupParameter> BinCapacityParameter { get { return (ILookupParameter>)Parameters["BinCapacity"]; } } public ILookupParameter>> AcceptedBinQualitiesParameter { get { return (ILookupParameter>>)Parameters["AcceptedBinQualities"]; } } public ILookupParameter> AcceptedCountsParameter { get { return (ILookupParameter>)Parameters["AcceptedCounts"]; } } public ILookupParameter> TotalCountsParameter { get { return (ILookupParameter>)Parameters["TotalCounts"]; } } public IValueLookupParameter AntiOverfitParameter { get { return (IValueLookupParameter)Parameters["AntiOverfit"]; } } public ILookupParameter CurrentBestValidationQualityParameter { get { return (ILookupParameter)Parameters["Current best validation quality"]; } } public ILookupParameter BestValidationQualityParameter { get { return (ILookupParameter)Parameters["Best solution quality (validation)"]; } } public DynOpEqComparator() : base() { Parameters.Add(new ValueLookupParameter("Maximization", "True if the problem is a maximization problem, false otherwise")); Parameters.Add(new LookupParameter("Result", "The result of the comparison: True means Quality is better, False means it is worse than parents.")); Parameters.Add(new LookupParameter("LeftSide", "The quality of the child.")); Parameters.Add(new ScopeTreeLookupParameter("RightSide", "The qualities of the parents.")); Parameters.Add(new LookupParameter("SymbolicExpressionTree", "The newly created child.")); Parameters.Add(new LookupParameter("BestQuality")); Parameters.Add(new ValueLookupParameter("BinSize", new IntValue(5))); Parameters.Add(new LookupParameter>("BinCapacity")); Parameters.Add(new LookupParameter>>("AcceptedBinQualities")); Parameters.Add(new LookupParameter>("AcceptedCounts")); Parameters.Add(new LookupParameter>("TotalCounts")); Parameters.Add(new ValueLookupParameter("AntiOverfit", new BoolValue(false))); Parameters.Add(new LookupParameter("Current best validation quality")); Parameters.Add(new LookupParameter("Best solution quality (validation)")); } public override IOperation Apply() { if (ResultParameter.ActualValue == null || ResultParameter.ActualValue.Value == true) { var tree = SymbolicExpressionTreeParameter.ActualValue; int size = tree.Size; int bin = GetBinIndexForSize(size); if (LeftSideParameter.ActualValue == null) { // not yet evaluated #region debugging ItemList totalCounts = TotalCountsParameter.ActualValue; while (bin >= totalCounts.Count) totalCounts.Add(new IntValue(0)); totalCounts[bin].Value = totalCounts[bin].Value + 1; #endregion if (!Exists(bin)) { if (AntiOverfitParameter.ActualValue.Value) { // reject more complex solutions if the current validation quality is worse than the best so far ResultParameter.ActualValue = new BoolValue(!IsOverfitting()); } else { // new bin -> evaluate and check later ResultParameter.ActualValue = new BoolValue(true); } } else { // bin exists: // if bin is full -> reject // otherwise -> evaluate and check success criterion ResultParameter.ActualValue = new BoolValue(IsNotFull(bin)); } } else { double leftQuality = LeftSideParameter.ActualValue.Value; ResultParameter.ActualValue = new BoolValue(Accept(size, bin, leftQuality)); } } return base.Apply(); } private bool IsOverfitting() { bool maximization = MaximizationParameter.ActualValue.Value; if (CurrentBestValidationQualityParameter.ActualValue != null && BestValidationQualityParameter.ActualValue != null) { double currentValidationQuality = CurrentBestValidationQualityParameter.ActualValue.Value; double bestValidationQuality = BestValidationQualityParameter.ActualValue.Value; return maximization ? currentValidationQuality < bestValidationQuality : currentValidationQuality > bestValidationQuality; } else return false; } private int GetBinIndexForSize(int size) { return (int)Math.Floor((size - 3.0) / BinSizeParameter.ActualValue.Value); } private bool Accept(int size, int binIndex, double solutionQuality) { bool accept = false; if (Exists(binIndex)) { //if (IsNotFull(binIndex) /*|| //NewBestOfBin(solutionQuality, binIndex)*/) { AddToBin(solutionQuality, binIndex); accept = true; //} } else if (NewBestOfRun(solutionQuality)) { CreateNewBin(binIndex); AddToBin(solutionQuality, binIndex); accept = true; } return accept; } private void AddToBin(double solutionQuality, int binIndex) { ItemList acceptedBinQualities = AcceptedBinQualitiesParameter.ActualValue[binIndex]; ItemList acceptedCounts = AcceptedCountsParameter.ActualValue; acceptedBinQualities.Add(new DoubleValue(solutionQuality)); acceptedCounts[binIndex].Value = acceptedCounts[binIndex].Value + 1; } private bool NewBestOfRun(double solutionQuality) { bool maximization = MaximizationParameter.ActualValue.Value; double bestQuality = BestQualityParameter.ActualValue.Value; return maximization ? solutionQuality > bestQuality : solutionQuality < bestQuality; } private void CreateNewBin(int binIndex) { ItemList binCapacities = BinCapacityParameter.ActualValue; ItemList> acceptedQualities = AcceptedBinQualitiesParameter.ActualValue; ItemList acceptedCounts = AcceptedCountsParameter.ActualValue; // create empty bins of capacity one up to the newly created bin for (int i = binCapacities.Count; i <= binIndex; i++) { binCapacities.Add(new IntValue(1)); acceptedQualities.Add(new ItemList(10)); acceptedCounts.Add(new IntValue(0)); } } //private bool NewBestOfBin(double solutionQuality, int binIndex) { // ItemList> acceptedQualities = AcceptedBinQualitiesParameter.ActualValue; // if (acceptedQualities[binIndex].Count == 0) return true; // bool maximization = MaximizationParameter.ActualValue.Value; // IEnumerable binQualities = acceptedQualities[binIndex].Select(x => x.Value); // // binQualities are always sorted so that the best is in bin 0 // return maximization ? solutionQuality > binQualities.First() : // solutionQuality < binQualities.First(); //} private bool IsNotFull(int binIndex) { ItemList binCapacities = BinCapacityParameter.ActualValue; ItemList> acceptedQualities = AcceptedBinQualitiesParameter.ActualValue; return acceptedQualities[binIndex].Count < binCapacities[binIndex].Value; } private bool Exists(int binIndex) { // if the bin has a capacity set then it exists ItemList binCapacities = BinCapacityParameter.ActualValue; return binIndex < binCapacities.Count; } } }