#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; namespace HeuristicLab.Problems.DataAnalysis.Operators { [Item("DynamicDepthLimitComparator", "As implemented by Ciprian.")] [StorableClass] public class DynamicDepthLimitComparator : 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 IValueLookupParameter DynamicDepthLimitParameter { get { return (IValueLookupParameter)Parameters["DynamicDepthLimit"]; } } public IValueLookupParameter InitialDepthLimitParameter { get { return (IValueLookupParameter)Parameters["InitialDepthLimit"]; } } public IValueParameter CLowerParameter { get { return (IValueParameter)Parameters["cLower"]; } } public IValueParameter CRaiseParameter { get { return (IValueParameter)Parameters["cRaise"]; } } public ILookupParameter BestQualityParameter { get { return (ILookupParameter)Parameters["BestQuality"]; } } public DynamicDepthLimitComparator() : 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 ValueLookupParameter("DynamicDepthLimit", "The current depth limit.")); Parameters.Add(new ValueLookupParameter("InitialDepthLimit")); Parameters.Add(new LookupParameter("SymbolicExpressionTree", "The newly created child.")); Parameters.Add(new LookupParameter("BestQuality")); Parameters.Add(new ValueParameter("cLower", "", new DoubleValue(0.03))); Parameters.Add(new ValueParameter("cRaise", "", new DoubleValue(0.015))); } public override IOperation Apply() { if (ResultParameter.ActualValue.Value) { double leftQuality = LeftSideParameter.ActualValue.Value; ItemArray rightQualities = RightSideParameter.ActualValue; if (rightQualities.Length < 1) throw new InvalidOperationException(Name + ": No subscopes found."); bool maximization = MaximizationParameter.ActualValue.Value; int bestParentIndex; double bestParentQuality; if (maximization) bestParentQuality = rightQualities.Max(x => x.Value); else bestParentQuality = rightQualities.Min(x => x.Value); bestParentIndex = rightQualities.FindIndex(x => x.Value == bestParentQuality); SymbolicExpressionTree tree = SymbolicExpressionTreeParameter.ActualValue; int ddl = DynamicDepthLimitParameter.ActualValue.Value; double cRaise = CRaiseParameter.Value.Value; double cLower = CLowerParameter.Value.Value; double bestQuality = BestQualityParameter.ActualValue.Value; double qualityPercentageChange = maximization ? -(bestQuality / leftQuality - 1) : (bestQuality / leftQuality - 1); if (tree.Height <= ddl) { // height is smaller than ddl => check improvement and reduce ddl if (qualityPercentageChange >= (ddl - tree.Height) * cLower) { ddl = Math.Max(tree.Height, InitialDepthLimitParameter.Value.Value); } } else { // height is larger than dll => check improvement and increase ddl if (qualityPercentageChange >= (tree.Height - ddl) * cRaise) { ddl = tree.Height; } else { // height is larger but no improvment => reject ResultParameter.ActualValue.Value = false; } } DynamicDepthLimitParameter.ActualValue.Value = ddl; } return base.Apply(); } } }