using System; using System.Collections.Generic; using HeuristicLab.Core; using HeuristicLab.Common.Resources; using HeuristicLab.Common; using HeuristicLab.Encodings.PermutationEncoding; using System.Drawing; using HEAL.Attic; namespace HeuristicLab.Analysis.FitnessLandscape.DistanceCalculators { [Item("PermutationDistanceCalculator", "Calculates the distance of two permutations")] [StorableType("F2B93749-3059-4D37-91A5-FAE2DC9DB794")] public class PermutationDistanceCalculator : NamedItem, IItemDistanceCalculator { #region Properties public override bool CanChangeName { get { return false; } } public override bool CanChangeDescription { get { return false; } } public static new Image StaticItemImage { get { return VSImageLibrary.Function; } } #endregion #region Construction & Cloning [StorableConstructor] protected PermutationDistanceCalculator(StorableConstructorFlag _) : base(_) { } protected PermutationDistanceCalculator(PermutationDistanceCalculator original, Cloner cloner) : base(original, cloner) { } public PermutationDistanceCalculator() { name = ItemName; description = ItemDescription; } public override IDeepCloneable Clone(Cloner cloner) { return new PermutationDistanceCalculator(this, cloner); } #endregion #region IItemDistanceCalculator Members public Type ItemType { get { return typeof(Permutation); } } public double Distance(IItem x, IItem y) { Permutation a = (Permutation)x; Permutation b = (Permutation)y; if (a.PermutationType != b.PermutationType) throw new InvalidOperationException("Cannot compare two permutations of different type"); if (a.Length != b.Length) throw new InvalidOperationException("Cannot compare vectors of different lengths"); switch (a.PermutationType) { case PermutationTypes.Absolute: return AbsoluteDistance(a, b); case PermutationTypes.RelativeDirected: return RelativeDistance(a, b); case PermutationTypes.RelativeUndirected: return RelativeDistance(a, b); default: throw new NotImplementedException("Unknown permutation type " + a.PermutationType); } } private double AbsoluteDistance(Permutation a, Permutation b) { int mismatches = 0; for (int i = 0; i edges = new HashSet(); for (int i = 0; i < a.Length; i++) edges.Add(GetEdge(a, i)); int nCommonEdges = 0; for (int i = 0; i < b.Length; i++) { if (edges.Contains(GetEdge(b, i))) nCommonEdges++; } return Math.Max(a.Length, b.Length) - nCommonEdges; } private static Point GetEdge(Permutation a, int index) { int start = a[index]; int end = a[(index + 1)%a.Length]; switch (a.PermutationType) { case PermutationTypes.RelativeDirected: return new Point(start, end); case PermutationTypes.RelativeUndirected: return new Point(Math.Min(start, end), Math.Max(start, end)); default: throw new ArgumentException("cannot derive edge from non-relative permutation type"); } } #endregion } }