#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
}
}