#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 = "StringVariable", Description = "")] public class StringVariable : Variable, IActionVariable { public override int VirtualLength { get { return 1; } } [Storable] public bool Wildcard { get; set; } [Storable] protected IEnumerable possibleFeatures; public IEnumerable PossibleFeatures { get { return possibleFeatures; } } [Storable] protected IDictionary featureMapping; public IDictionary FeatureMapping { get { return featureMapping; } } [Storable] protected int currentValue; public int CurrentValue { get { return currentValue; } set { if (!possibleFeatures.Contains(value)) { throw new ArgumentException("Value is not a possible feature of this variable."); } currentValue = value; } } public string CurrentStringValue { get { return featureMapping[currentValue]; } } [StorableConstructor] protected StringVariable(bool deserializing) : base(deserializing) { } protected StringVariable(StringVariable original, Cloner cloner) : base(original, cloner) { this.possibleFeatures = new List(original.possibleFeatures); this.featureMapping = new Dictionary(original.featureMapping); this.Wildcard = original.Wildcard; this.currentValue = original.currentValue; } public StringVariable() : base() { Wildcard = false; } public StringVariable(string variableName, IEnumerable variableValues) : base(variableName) { if (variableValues.Count() != variableValues.Distinct().Count()) { throw new ArgumentException("variableValues have to be distinct."); } featureMapping = new Dictionary(); var distinctValuesEnumerator = variableValues.Distinct().GetEnumerator(); possibleFeatures = Enumerable.Range(0, variableValues.Count()).ToList(); var possibleFeaturesEnumerator = possibleFeatures.GetEnumerator(); while (possibleFeaturesEnumerator.MoveNext() && distinctValuesEnumerator.MoveNext()) { featureMapping.Add(possibleFeaturesEnumerator.Current, distinctValuesEnumerator.Current); } Wildcard = false; } public StringVariable(string variableName, IEnumerable variableValues, string currentValue) : this(variableName, variableValues) { int index = 0; foreach (var feature in featureMapping) { if (feature.Equals(currentValue)) { break; } index++; } if (index > featureMapping.Count()) { throw new ArgumentException("variableValues do not contain currentValue."); } CurrentValue = index; } public StringVariable(string variableName, IDictionary featureMapping) : base(variableName) { if (featureMapping.Values.Count != featureMapping.Values.Distinct().Count()) { throw new ArgumentException("featureMapping values have to be distinct."); } this.possibleFeatures = featureMapping.Keys.ToList(); this.featureMapping = featureMapping; Wildcard = false; } public StringVariable(string variableName, IDictionary featureMapping, string currentValue) : this(variableName, featureMapping) { bool found = false; foreach (var pair in featureMapping) { if (pair.Value.Equals(currentValue)) { CurrentValue = pair.Key; found = true; break; } } if (!found) { throw new ArgumentException("variableValues do not contain currentValue."); } } public override IDeepCloneable Clone(Cloner cloner) { return new StringVariable(this, cloner); } public override string ToString() { return Wildcard ? "#" : CurrentStringValue; } public override bool MatchInput(string target) { return Wildcard || featureMapping[CurrentValue].Equals(target); } public override bool Match(string target) { return MatchInput(target); } public override bool MatchVariable(IVariable target) { var targetCast = target as StringVariable; return targetCast != null && this.variableName.Equals(targetCast.VariableName) && Match(targetCast.CurrentStringValue); } public override IVariable GetEmptyCopy() { return new StringVariable(variableName, featureMapping); } public override IVariable GetSetCopy() { StringVariable copy = (StringVariable)GetEmptyCopy(); copy.Wildcard = this.Wildcard; copy.CurrentValue = this.CurrentValue; return copy; } IActionVariable IActionVariable.GetEmptyCopy() { return (StringVariable)GetEmptyCopy(); } IActionVariable IActionVariable.GetSetCopy() { return (StringVariable)GetSetCopy(); } public void RandomizeAction(IRandom random) { int index = random.Next(possibleFeatures.Count()); currentValue = possibleFeatures.ElementAt(index); } public override void Randomize(IRandom random, double changeSymbolProbability) { Wildcard = random.NextDouble() < changeSymbolProbability; int index = random.Next(possibleFeatures.Count()); currentValue = possibleFeatures.ElementAt(index); } public override bool Identical(IVariable target) { var targetCast = target as StringVariable; if (targetCast == null) { return false; } if (variableName != targetCast.variableName || Wildcard != targetCast.Wildcard || currentValue != targetCast.currentValue) { return false; } var thisEnumerator = featureMapping.GetEnumerator(); var castEnumerator = targetCast.featureMapping.GetEnumerator(); while (thisEnumerator.MoveNext() && castEnumerator.MoveNext()) { if (thisEnumerator.Current.Key != castEnumerator.Current.Key || thisEnumerator.Current.Value != castEnumerator.Current.Value) return false; } return !thisEnumerator.MoveNext() && !castEnumerator.MoveNext(); } public override double GetGenerality() { return Wildcard ? 1 : 0; } public override bool IsGreaterThanOrEquallyGeneral(IVariable target) { var targetCast = target as StringVariable; if (targetCast == null) { return false; } return Wildcard || (currentValue == targetCast.currentValue && CurrentStringValue.Equals(targetCast.CurrentStringValue)); } public override IVariable CrossParentsAtPosition(IVariable parent2, int pos) { var parent2Cast = parent2 as StringVariable; if (parent2Cast == null) { throw new ArgumentException("Argument is not of the correct type."); } if (pos != 0) { throw new ArgumentOutOfRangeException(); } return (StringVariable)parent2.GetSetCopy(); } public override void Manipulate(IRandom random, string stringValue, int pos, double spreadPercentage) { Manipulate(random, stringValue, pos); } public override void Manipulate(IRandom random, string stringValue, int pos) { if (pos != 0) { throw new ArgumentOutOfRangeException(); } Wildcard = !Wildcard; if (!Wildcard) { currentValue = featureMapping.First(x => x.Value.Equals(stringValue)).Key; } } public override void Cover(IRandom random, string stringValue, double changeSymbolProbability) { Wildcard = random.NextDouble() < changeSymbolProbability; if (!Wildcard) { currentValue = featureMapping.First(x => x.Value.Equals(stringValue)).Key; } } public override int GetHashCode() { int result = 1; int wildcardInt = Wildcard ? 1 : 0; result = 37 * result + wildcardInt; result = 37 * result + currentValue; foreach (var feature in featureMapping) { result = 37 * result + feature.Key; result = 37 * result + feature.Value.GetHashCode(); } return result; } #region IActionVariable Members public void SetTo(string value) { currentValue = featureMapping.First(x => x.Value.Equals(value)).Key; } public IEnumerable GetAllPossibleActions() { return featureMapping.Values; } #endregion } }