Changeset 14431
- Timestamp:
- 11/30/16 14:49:22 (6 years ago)
- Location:
- branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/Cluster.cs
r14430 r14431 1 1 using System; 2 using System.Collections; 2 3 using System.Collections.Generic; 3 using System.Linq;4 using System.Security.Cryptography.X509Certificates;5 using System.Text;6 using System.Threading.Tasks;7 4 using HeuristicLab.Core; 8 5 using HeuristicLab.Problems.VehicleRouting.Interfaces; 9 using HeuristicLab.Problems.VehicleRouting.Variants;10 6 11 7 namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin { 12 8 13 14 9 public class ClusterAlgorithm<C,CO> where C : Cluster<CO> where CO : ClusterElement { 15 10 16 //public static List<C> KMeans(IVRPProblemInstance instance, IRandom random, List<CO> clusterObjects, int k, double changeThreshold) { 17 // HashSet<int> initMeans = new HashSet<int>(); 18 // int nextMean = -1; 19 20 // for (int i = 0; i < k && i < clusterObjects.Count; i++) { 21 // //C cluster = new C() 22 // } 23 24 25 26 27 //} 28 29 //private static int KMeansRun(List<C> clusters, List<CO> clusterObjects) { 30 31 //} 32 11 public static List<C> KMeans(IRandom random, List<CO> clusterElements, int k, double changeThreshold, bool minimizeImpact) { 12 HashSet<int> initMeans = new HashSet<int>(); 13 int nextMean = -1; 14 15 List<C> clusters = CreateCList(); 16 17 // (1) initialize each cluster with a random element as mean 18 for (int i = 0; i < k && i < clusterElements.Count; i++) { 19 C cluster = (C)Activator.CreateInstance(typeof(C)); 20 cluster.Id = i; 21 22 do { 23 nextMean = random.Next(0, clusterElements.Count); 24 } while (initMeans.Contains(nextMean)); 25 initMeans.Add(nextMean); 26 cluster.SetMean(clusterElements[nextMean]); 27 clusters.Add(cluster); 28 } 29 30 // (2) repeat clustering until change rate is below threshold 31 double changeRate = 0.0; 32 33 do { 34 int changes = KMeansRun(clusters, clusterElements, minimizeImpact); 35 changeRate = (double)changes / clusterElements.Count; 36 } while (changeRate > changeThreshold); 37 38 39 // remove empty clusters 40 clusters.RemoveAll(c => c.Elements.Count.Equals(0)); 41 42 return clusters; 43 } 44 45 private static int KMeansRun(List<C> clusters, List<CO> clusterElements, bool minimizeImpact) { 46 int changes = 0; 47 48 // clear clusters from previous assigned elements 49 foreach (var c in clusters) { 50 c.Elements.Clear(); 51 } 52 53 // assign elements to currently most suitable clusters 54 foreach (var e in clusterElements) { 55 int optClusterIdx = 0; 56 double optImpact = clusters[optClusterIdx].CalculateImpact(e); 57 for (int i = 1; i < clusters.Count; i++) { 58 double impact = clusters[i].CalculateImpact(e); 59 if ( 60 // optimal impact: max variance decrease (biggest negative or smallest positive value) 61 (minimizeImpact && impact < optImpact) || 62 // optimal impact: min variance increase, if no increase possible: min decrease (smallest negative or positive value) 63 //(!minimizeImpact && ((optImpact > 0 && impact < optImpact) || (optImpact < 0 && impact > optImpact)))) { 64 (!minimizeImpact && impact > optImpact) 65 ) { 66 67 optImpact = impact; 68 optClusterIdx = i; 69 } 70 } 71 if (clusters[optClusterIdx].AddObject(e)) { 72 changes++; 73 } 74 } 75 76 // update mean and variance 77 foreach (var c in clusters) { 78 c.CalculateMean(); 79 c.CalculateVariance(); 80 } 81 82 return changes; 83 } 84 85 private static List<C> CreateCList() { 86 var listType = typeof(List<>); 87 var constructedListType = listType.MakeGenericType(typeof(C)); 88 return (List<C>)Activator.CreateInstance(constructedListType); 89 } 33 90 } 34 91 35 92 #region Cluster 36 public interface ICluster<T> where T : IClusterElement { 37 double CalculateImpact(T o); 38 void CalculateMean(); 93 public interface ICluster<T> where T : ClusterElement { 39 94 void SetMean(T o); 40 95 bool AddObject(T o); 96 void CalculateMean(); 97 void CalculateVariance(); 98 double CalculateImpact(T e); 99 double CalculateDistance(T e1, T e2); 100 41 101 } 42 102 public abstract class Cluster<T> : ICluster<T> where T : ClusterElement { 43 103 public int Id; 44 protected readonly IVRPProblemInstance instance; 104 45 105 public List<T> Elements { get; private set; } 46 106 … … 49 109 public double Variance { get; set; } 50 110 51 public Cluster(IVRPProblemInstance instance, int id) { 52 this.instance = instance; 111 protected Cluster() { 112 Elements = new List<T>(); 113 } 114 115 protected Cluster(int id) { 53 116 Id = id; 54 117 Elements = new List<T>(); 55 118 56 119 } 57 public bool AddObject(T o) { 58 Elements.Add(o); 59 60 bool clusterChanged = o.ClusterId != Id; 61 o.ClusterId = Id; 120 121 public bool AddObject(T e) { 122 Elements.Add(e); 123 124 bool clusterChanged = e.ClusterId != Id; 125 e.ClusterId = Id; 62 126 return clusterChanged; 63 127 } 64 128 65 public void SetMean(T o) {66 Mean = o;129 public void SetMean(T e) { 130 Mean = e; 67 131 Mean.ClusterId = Id; 68 132 } … … 70 134 public abstract void CalculateMean(); 71 135 72 public abstract void CalculateVariance(); 73 74 public abstract double CalculateImpact(T o); 75 76 } 77 public class SpatialDistanceCluster : Cluster<SpatialDistanceClusterElement> { 78 public SpatialDistanceCluster(IVRPProblemInstance instance, int id) : base(instance, id) { 79 } 80 81 public override void CalculateMean() { 82 int dimensions = instance.Coordinates.Columns; 83 SpatialDistanceClusterElement mean = new SpatialDistanceClusterElement(-1, dimensions, Id); 84 foreach (SpatialDistanceClusterElement o in Elements) { 85 double[] coordinates = instance.GetCoordinates(o.Id); 86 for (int i = 0; i < coordinates.Length; i++) { 87 mean.Coordinates[i] += (coordinates[i] / Elements.Count); 88 } 89 } 90 Mean = mean; 91 } 92 93 public override void CalculateVariance() { 94 if(Mean == null) 95 CalculateMean(); 96 97 Variance = 0.0; 98 foreach (SpatialDistanceClusterElement o in Elements) { 99 Variance += Math.Pow(Mean.GetDistance(o), 2); 100 } 101 Variance /= Elements.Count; 102 } 103 104 public override double CalculateImpact(SpatialDistanceClusterElement o) { 136 public abstract double CalculateDistance(T e1, T e2); 137 138 public virtual void CalculateVariance() { 105 139 if (Mean == null) 106 140 CalculateMean(); 107 141 108 double newVariance = (Variance*Elements.Count + Math.Pow(Mean.GetDistance(o), 2))/(Elements.Count + 1); 142 Variance = 0.0; 143 foreach (T e in Elements) { 144 Variance += Math.Pow(CalculateDistance(Mean, e), 2); 145 } 146 Variance /= Elements.Count; 147 } 148 149 public virtual double CalculateImpact(T e) { 150 if (Mean == null) 151 CalculateMean(); 152 153 double newVariance = (Variance * Elements.Count + Math.Pow(CalculateDistance(Mean, e), 2)) / (Elements.Count + 1); 109 154 return newVariance - Variance; 110 155 } 156 157 } 158 public class SpatialDistanceCluster : Cluster<SpatialDistanceClusterElement> { 159 public SpatialDistanceCluster() : base() { 160 } 161 162 public SpatialDistanceCluster(int id) : base(id) { 163 } 164 165 public override void CalculateMean() { 166 int dimensions = (Mean != null) ? Mean.Coordinates.Length : (Elements.Count > 0) ? Elements[0].Coordinates.Length : 0; 167 SpatialDistanceClusterElement mean = new SpatialDistanceClusterElement(-1, dimensions, Id); 168 foreach (SpatialDistanceClusterElement e in Elements) { 169 for (int i = 0; i < Mean.Coordinates.Length; i++) { 170 mean.Coordinates[i] += (e.Coordinates[i] / Elements.Count); 171 } 172 } 173 Mean = mean; 174 } 175 176 public override double CalculateDistance(SpatialDistanceClusterElement e1, SpatialDistanceClusterElement e2) { 177 if (!e1.Coordinates.Length.Equals(e2.Coordinates.Length)) { 178 throw new ArgumentException("Distance could not be calculated since number of dimensions is unequal."); 179 } 180 181 double distance = 0.0; 182 for (int i = 0; i < e1.Coordinates.Length; i++) { 183 distance += Math.Pow(e1.Coordinates[i] - e2.Coordinates[i], 2); 184 } 185 186 return Math.Sqrt(distance); 187 } 111 188 } 112 189 113 190 public class TemporalDistanceCluster : Cluster<TemporalDistanceClusterElement> { 114 public TemporalDistanceCluster(ITimeWindowedProblemInstance instance, int id) : base(instance, id) { 115 } 116 191 public TemporalDistanceCluster() : base() { 192 } 193 194 public TemporalDistanceCluster(int id) : base(id) { 195 } 117 196 118 197 public override void CalculateMean() { … … 125 204 } 126 205 127 public override void CalculateVariance() { 128 if (Mean == null) 129 CalculateMean(); 130 131 Variance = 0.0; 132 foreach (TemporalDistanceClusterElement e in Elements) { 133 Variance += Math.Pow(Math.Abs(Mean.ReadyTime - e.ReadyTime) + Math.Abs(Mean.DueTime - e.DueTime), 2); 134 } 135 Variance /= Elements.Count; 136 } 137 138 public override double CalculateImpact(TemporalDistanceClusterElement o) { 139 if(Mean == null) 140 CalculateMean(); 141 142 double newVariance = (Variance * Elements.Count + Math.Pow(Math.Abs(Mean.ReadyTime - o.ReadyTime) + Math.Abs(Mean.DueTime - o.DueTime), 2)) / (Elements.Count + 1); 143 return newVariance - Variance; 144 } 145 } 206 public override double CalculateDistance(TemporalDistanceClusterElement e1, TemporalDistanceClusterElement e2) { 207 double distance = 0.0; 208 distance += Math.Abs(e1.ReadyTime - e2.ReadyTime); 209 distance += Math.Abs(e1.DueTime - e2.DueTime); 210 211 return distance; 212 //return euklid(e1, e2); 213 } 214 215 private double euklid(TemporalDistanceClusterElement e1, TemporalDistanceClusterElement e2) { 216 double distance = 0.0; 217 distance += Math.Pow(e1.ReadyTime - e2.ReadyTime + e1.DueTime - e2.DueTime, 2); 218 219 return Math.Sqrt(distance); 220 } 221 } 222 146 223 #endregion Cluster 147 224 148 149 225 #region ClusterElement 150 public interface IClusterElement { 151 double GetDistance(IClusterElement o); 152 } 153 public abstract class ClusterElement : IClusterElement { 226 public abstract class ClusterElement { 154 227 public int Id { get; set; } 155 228 public int ClusterId { get; set; } 156 229 157 private ClusterElement() { } 230 protected ClusterElement() { 231 ClusterId = -1; 232 } 158 233 159 234 public ClusterElement(int id, int clusterId = -1) { … … 161 236 ClusterId = clusterId; 162 237 } 163 164 public abstract double GetDistance(IClusterElement o);165 238 } 166 239 public class SpatialDistanceClusterElement : ClusterElement { 167 240 168 241 public double[] Coordinates { get; set; } 242 243 public SpatialDistanceClusterElement() : base() { 244 } 169 245 170 246 public SpatialDistanceClusterElement(int id, int clusterId = -1) : base(id, clusterId) { … … 179 255 } 180 256 181 public override double GetDistance(IClusterElement o) {182 var other = o as SpatialDistanceClusterElement;183 if (other == null) {184 throw new ArgumentException(string.Format("Distance calculation between {0} and {1} is not possible.",185 typeof(SpatialDistanceClusterElement), o.GetType()));186 }187 188 double distance = 0.0;189 for (int i = 0; i < other.Coordinates.Length; i++) {190 distance += Math.Pow(Coordinates[i] - other.Coordinates[i], 2);191 }192 193 return Math.Sqrt(distance);194 }195 257 } 196 258 … … 199 261 public double DueTime { get; set; } 200 262 263 public TemporalDistanceClusterElement() : base() { 264 } 265 201 266 public TemporalDistanceClusterElement(int id, int clusterId = -1) : base(id, clusterId) { 202 267 } … … 206 271 DueTime = dueTime; 207 272 } 208 209 public override double GetDistance(IClusterElement o) {210 var other = o as TemporalDistanceClusterElement;211 if (other == null) {212 throw new ArgumentException(string.Format("Distance calculation between {0} and {1} is not possible.",213 typeof(TemporalDistanceClusterElement), o.GetType()));214 }215 216 double distance = 0.0;217 distance += Math.Abs(ReadyTime - other.ReadyTime);218 distance += Math.Abs(DueTime - other.DueTime);219 220 return distance;221 222 //return GetDistanceEuklid(other);223 }224 225 public double GetDistanceEuklid(TemporalDistanceClusterElement other) {226 double distance = 0.0;227 distance += Math.Pow(ReadyTime - other.ReadyTime, 2);228 distance += Math.Pow(DueTime - other.DueTime, 2);229 230 return Math.Sqrt(distance);231 }232 233 273 } 234 274 -
branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/GeographicDistanceClusterCreator.cs
r14430 r14431 48 48 } 49 49 50 public static List<SpatialDistanceClusterElement> CreateCluster Objects(IVRPProblemInstance instance) {50 public static List<SpatialDistanceClusterElement> CreateClusterElements(IVRPProblemInstance instance) { 51 51 IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance; 52 52 … … 59 59 60 60 // wrap stops in SpatialDistanceClusterElement 61 List<SpatialDistanceClusterElement> cluster Objects = new List<SpatialDistanceClusterElement>();61 List<SpatialDistanceClusterElement> clusterElements = new List<SpatialDistanceClusterElement>(); 62 62 foreach (int customer in customers) { 63 cluster Objects.Add(new SpatialDistanceClusterElement(customer, instance.GetCoordinates(customer)));63 clusterElements.Add(new SpatialDistanceClusterElement(customer, instance.GetCoordinates(customer))); 64 64 } 65 return cluster Objects;65 return clusterElements; 66 66 } 67 67 … … 69 69 PotvinEncoding result = new PotvinEncoding(instance); 70 70 71 List<SpatialDistanceClusterElement> clusterObjects = CreateClusterObjects(instance); 71 // (1) wrap stops in cluster elements 72 List<SpatialDistanceClusterElement> clusterElements = CreateClusterElements(instance); 72 73 74 // (2) create a random number k of clusters 73 75 int k = random.Next(minK, maxK); 74 List<SpatialDistanceCluster> clusters = KMeans(instance, random, clusterObjects, k, clusterChangeThreshold); 75 76 // (3) build tours 77 // (a) shuffle 78 // (b) greedy 76 List<SpatialDistanceCluster> clusters = ClusterAlgorithm<SpatialDistanceCluster, SpatialDistanceClusterElement> 77 .KMeans(random, clusterElements, k, clusterChangeThreshold, true); 78 79 // (3) build tours with a (a) shuffling (b) greedy tour creation routine 79 80 foreach (var c in clusters) { 80 81 Tour newTour = new Tour(); … … 97 98 98 99 return result; 99 }100 101 private static List<SpatialDistanceCluster> KMeans(IVRPProblemInstance instance, IRandom random, List<SpatialDistanceClusterElement> objects, int k, double changeTreshold) {102 103 List<SpatialDistanceCluster> clusters = new List<SpatialDistanceCluster>();104 HashSet<int> initMeans = new HashSet<int>();105 int nextMean = -1;106 107 // (1) initialize each cluster with a random first object (i.e. mean)108 for (int i = 0; i < k && i < objects.Count; i++) {109 SpatialDistanceCluster cluster = new SpatialDistanceCluster(instance, i);110 111 do {112 nextMean = random.Next(0, objects.Count);113 } while (initMeans.Contains(nextMean));114 initMeans.Add(nextMean);115 cluster.SetMean(objects[nextMean]);116 clusters.Add(cluster);117 }118 119 // (2) repeat clustering until change rate is below threshold120 int changes = 0;121 double changeRate = 1.0;122 123 do {124 changes = KMeansRun(clusters, objects);125 changeRate = changes / objects.Count;126 127 } while (changeRate > changeTreshold);128 129 // remove empty clusters130 clusters.RemoveAll(c => c.Elements.Count.Equals(0));131 132 return clusters;133 }134 135 private static int KMeansRun(List<SpatialDistanceCluster> clusters, List<SpatialDistanceClusterElement> objects) {136 int changes = 0;137 138 foreach (var c in clusters) {139 c.Elements.Clear();140 }141 142 foreach (var o in objects) {143 int bestClusterIdx = 0;144 double minImpact = clusters[0].CalculateImpact(o);145 for (int i = 1; i < clusters.Count; i++) {146 double impact = clusters[i].CalculateImpact(o);147 if (impact < minImpact) {148 minImpact = impact;149 bestClusterIdx = i;150 }151 }152 if (clusters[bestClusterIdx].AddObject(o))153 changes++;154 }155 156 foreach (var c in clusters) {157 c.CalculateMean();158 c.CalculateVariance();159 }160 161 return changes;162 100 } 163 101 -
branches/HeuristicLab.VRPEnhancements/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Potvin/Creators/TemporalDistanceClusterCreator.cs
r14430 r14431 49 49 } 50 50 51 public static List<TemporalDistanceClusterElement> CreateCluster Objects(ITimeWindowedProblemInstance instance) {51 public static List<TemporalDistanceClusterElement> CreateClusterElements(ITimeWindowedProblemInstance instance) { 52 52 IPickupAndDeliveryProblemInstance pdp = instance as IPickupAndDeliveryProblemInstance; 53 53 … … 70 70 PotvinEncoding result = new PotvinEncoding(instance); 71 71 72 List<TemporalDistanceClusterElement> clusterObjects = CreateClusterObjects(instance); 72 // (1) wrap stops in cluster elements 73 List<TemporalDistanceClusterElement> clusterElements = CreateClusterElements(instance); 73 74 75 // (2) create a random number k of clusters 74 76 int k = random.Next(minK, maxK); 75 List<TemporalDistanceCluster> clusters = KMeans(instance, random, clusterObjects, k, clusterChangeThreshold); 77 List<TemporalDistanceCluster> clusters = ClusterAlgorithm<TemporalDistanceCluster, TemporalDistanceClusterElement> 78 .KMeans(random, clusterElements, k, clusterChangeThreshold, false); 76 79 77 // (3) build tours 78 // (a) shuffle 79 // (b) greedy 80 // (3) build tours with a (a) shuffling (b) greedy tour creation routine 80 81 foreach (var c in clusters) { 81 82 Tour newTour = new Tour(); … … 93 94 newTour.Stops.Add(o.Id); 94 95 } 95 GreedyTourCreation(instance, result, newTour, false);96 GreedyTourCreation(instance, result, newTour, true); // "true" means include costs 96 97 } 97 98 } 98 99 99 100 return result; 100 }101 102 private static List<TemporalDistanceCluster> KMeans(ITimeWindowedProblemInstance instance, IRandom random, List<TemporalDistanceClusterElement> objects, int k, double changeTreshold) {103 104 List<TemporalDistanceCluster> clusters = new List<TemporalDistanceCluster>();105 HashSet<int> initMeans = new HashSet<int>();106 int nextMean = -1;107 108 // (1) initialize each cluster with a random first object (i.e. mean)109 for (int i = 0; i < k && i < objects.Count; i++) {110 TemporalDistanceCluster cluster = new TemporalDistanceCluster(instance, i);111 112 do {113 nextMean = random.Next(0, objects.Count);114 } while (initMeans.Contains(nextMean));115 initMeans.Add(nextMean);116 cluster.SetMean(objects[nextMean]);117 clusters.Add(cluster);118 }119 120 // (2) repeat clustering until change rate is below threshold121 int changes = 0;122 double changeRate = 1.0;123 124 do {125 changes = KMeansRun(clusters, objects);126 changeRate = changes / objects.Count;127 128 } while (changeRate > changeTreshold);129 130 // remove empty clusters131 clusters.RemoveAll(c => c.Elements.Count.Equals(0));132 133 return clusters;134 }135 136 private static int KMeansRun(List<TemporalDistanceCluster> clusters, List<TemporalDistanceClusterElement> objects) {137 int changes = 0;138 139 foreach (var c in clusters) {140 c.Elements.Clear();141 }142 143 foreach (var o in objects) {144 int bestClusterIdx = 0;145 double minImpact = clusters[0].CalculateImpact(o);146 for (int i = 1; i < clusters.Count; i++) {147 double impact = clusters[i].CalculateImpact(o);148 if ((minImpact > 0 && impact < minImpact) || (minImpact < 0 && impact > minImpact)) { // V1: min positive impact149 //if(impact > minImpact) { // V2: max impact150 minImpact = impact;151 bestClusterIdx = i;152 }153 }154 if (clusters[bestClusterIdx].AddObject(o))155 changes++;156 }157 158 foreach (var c in clusters) {159 c.CalculateMean();160 c.CalculateVariance();161 }162 163 return changes;164 101 } 165 102
Note: See TracChangeset
for help on using the changeset viewer.