#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 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")); } 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) { ItemList totalCounts = TotalCountsParameter.ActualValue; while (bin >= totalCounts.Count) totalCounts.Add(new IntValue(0)); totalCounts[bin].Value = totalCounts[bin].Value + 1; if (!Exists(bin)) ResultParameter.ActualValue = new BoolValue(true); else ResultParameter.ActualValue = new BoolValue(IsNotFull(bin)); } else { double leftQuality = LeftSideParameter.ActualValue.Value; ResultParameter.ActualValue = new BoolValue(Accept(size, bin, leftQuality)); } } return base.Apply(); } 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; if (acceptedBinQualities.Count == 0) { acceptedBinQualities.Add(new DoubleValue(solutionQuality)); acceptedCounts[binIndex].Value = acceptedCounts[binIndex].Value + 1; } else { // insert at beginning if it is a new best or add at end bool maximization = MaximizationParameter.ActualValue.Value; if ((maximization && solutionQuality > acceptedBinQualities[0].Value) || (!maximization && solutionQuality < acceptedBinQualities[0].Value)) { acceptedBinQualities.Insert(0, new DoubleValue(solutionQuality)); } else { 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; } } }