#region License Information /* HeuristicLab * Copyright (C) 2002-2012 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.Collections.Generic; using System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Encodings.VariableVector { [StorableClass] [Item(Name = "DoubleVariable", Description = "")] public class DoubleVariable : Variable { public override int VirtualLength { get { return 2; } } [Storable] protected double min; public double Min { get { return min; } } [Storable] protected double max; public double Max { get { return max; } } [Storable] protected double currentCenter; public double CurrentCenter { get { return currentCenter; } set { currentCenter = value; } } [Storable] protected double currentSpread; public double CurrentSpread { get { return currentSpread; } set { currentSpread = value; } } [StorableConstructor] protected DoubleVariable(bool deserializing) : base(deserializing) { } protected DoubleVariable(DoubleVariable original, Cloner cloner) : base(original, cloner) { min = original.min; max = original.max; currentSpread = original.currentSpread; currentCenter = original.currentCenter; } public DoubleVariable() : base() { } public DoubleVariable(string variableName, IEnumerable variableValues) : base(variableName) { min = variableValues.Min(); max = variableValues.Max(); } protected DoubleVariable(string variableName, double min, double max) : base(variableName) { this.min = min; this.max = max; } public DoubleVariable(string variableName, IEnumerable variableValues, double center, double spread) : this(variableName, variableValues) { CurrentCenter = center; CurrentSpread = spread; } public override IDeepCloneable Clone(Cloner cloner) { return new DoubleVariable(this, cloner); } public override string ToString() { return (currentCenter - currentSpread) + " - " + (currentCenter + currentSpread); } public override bool MatchInput(string target) { return Match(Double.Parse(target)); } public override bool Match(double target) { return currentCenter - currentSpread <= target && target <= currentCenter + currentSpread; } public override IVariable GetEmptyCopy() { return new DoubleVariable(variableName, min, max); } public override IVariable GetSetCopy() { DoubleVariable copy = (DoubleVariable)GetEmptyCopy(); copy.CurrentCenter = this.CurrentCenter; copy.CurrentSpread = this.CurrentSpread; return copy; } // this method is not implemented on purpose, because it may lead to confusion or errors if the wrong parameter would be used (changeSymbolProbability instead of spreadPercentage) public override void Randomize(IRandom random, double changeSymbolProbability) { throw new NotImplementedException("The method DoubleVariable.Randomize(IRandom, double) should not be used. Use DoubleVariable.Randomize(IRandom, double, double) instead."); } // changeSymbolProbability is not used on purpose public void Randomize(IRandom random, double changeSymbolProbability, double spreadPercentage) { if (spreadPercentage < 0 || spreadPercentage > 100) { throw new ArgumentException("Spread percentage has to be between 0 and 100."); } double delta = Max - Min; CurrentCenter = random.NextDouble() * delta + Min; CurrentSpread = random.NextDouble() * (delta * spreadPercentage); } public override bool Identical(IVariable target) { var targetCast = target as DoubleVariable; if (targetCast == null) { return false; } if (variableName != targetCast.variableName || !currentCenter.IsAlmost(targetCast.currentCenter) || !currentSpread.IsAlmost(targetCast.currentSpread) || !max.IsAlmost(targetCast.max) || !min.IsAlmost(targetCast.min)) { return false; } return true; } public override double GetGenerality() { double delta = max - min; double intervalInBoundsWidth = Math.Min(max, currentCenter + currentSpread) - Math.Max(min, currentCenter - currentSpread); double generality = intervalInBoundsWidth / delta; return generality > 1 ? 1 : generality; } public override bool IsGreaterThanOrEquallyGeneral(IVariable target) { var targetCast = target as DoubleVariable; if (targetCast == null) { return false; } return currentCenter - currentSpread < targetCast.currentCenter - targetCast.currentSpread && currentCenter + currentSpread > targetCast.currentCenter + targetCast.currentSpread; } public override IVariable CrossParentsAtPosition(IVariable parent2, int pos) { DoubleVariable parent2Cast = parent2 as DoubleVariable; if (parent2Cast == null) { throw new ArgumentException("Argument is not of the correct type."); } if (pos > 1 || pos < 0) { throw new ArgumentOutOfRangeException(); } DoubleVariable crossed = (DoubleVariable)this.GetSetCopy(); if (pos == 1) { crossed.CurrentSpread = parent2Cast.CurrentSpread; } return crossed; } public override void Manipulate(IRandom random, string stringValue, int pos, double spreadPercentage) { Manipulate(random, pos, spreadPercentage); } public override void Manipulate(IRandom random, string stringValue, int pos) { throw new NotImplementedException("DoubleVariable.Manipulate(IRandom, string, int) cannot be used. Use DoubleVariable.Manipulate(IRandom, string, int, double) or DoubleVariable.Manipulate(IRandom, int, double) instead."); } public void Manipulate(IRandom random, int pos, double percentage) { if (pos > 1 || pos < 0) { throw new ArgumentOutOfRangeException(); } double delta = max - min; double maxChange = delta * percentage; double actualChange = (random.NextDouble() * maxChange * 2) - maxChange; if (pos == 0) { currentCenter += actualChange; } else if (pos == 1) { currentSpread += actualChange; //otherwise the interval could be corrupt and no input could match the rule. currentSpread = currentSpread > 0 ? currentSpread : 0; } } public override void Cover(IRandom random, string stringValue, double changeSymbolProbability) { CoverWithSpreadPercentage(random, stringValue, changeSymbolProbability); } public void CoverWithSpreadPercentage(IRandom random, string stringValue, double spreadPercentage) { currentCenter = double.Parse(stringValue); double delta = max - min; currentSpread = random.NextDouble() * (delta * spreadPercentage); } } }