using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using HeuristicLab.Core; using HeuristicLab.Common.Resources; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Common; using HeuristicLab.Encodings.PermutationEncoding; using HeuristicLab.Problems.VehicleRouting; namespace HeuristicLab.Analysis.FitnessLandscape.DistanceCalculators.VRP { [Item("VRPDistanceCalculator", "Calculates the distance of two VRP solution candidates.")] [StorableClass] public class VRPDistanceCalculator : 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 VRPDistanceCalculator(bool deserializing) : base(deserializing) { } protected VRPDistanceCalculator(VRPDistanceCalculator original, Cloner cloner) : base(original, cloner) { } public VRPDistanceCalculator() { name = ItemName; description = ItemDescription; } public override IDeepCloneable Clone(Cloner cloner) { return new VRPDistanceCalculator(this, cloner); } #endregion #region IItemDistanceCalculator Members public Type ItemType { get { return typeof(Permutation); } } public double Distance(IItem x, IItem y) { var a = GetEdgeSet((IVRPEncoding)x); var b = GetEdgeSet((IVRPEncoding)y); var aCount = a.Count; a.IntersectWith(b); return Math.Max(aCount, b.Count) - a.Count; } private HashSet GetEdgeSet(IVRPEncoding vrpSolution) { HashSet edges = new HashSet(); foreach (var tour in vrpSolution.GetTours(null)) { if (tour.Cities.Count > 0) { edges.Add(CreateUndirectedEdge(0, tour.Cities[0])); for (int i = 0; i < tour.Cities.Count - 1; i++) { edges.Add(CreateUndirectedEdge(tour.Cities[i], tour.Cities[i + 1])); } edges.Add(CreateUndirectedEdge(tour.Cities.Last(), 0)); } } return edges; } private Point CreateUndirectedEdge(int x, int y) { return new Point(Math.Min(x, y), Math.Max(x, y)); } #endregion } }