public ClustersModel GetKmeanClusters(VrpData data, int clustersCount) { var centers = new Point2DReal[clustersCount]; var perm = Permutations.GetRandomPermutation(data.N - 1); for (int i = 0; i < clustersCount; i++) { centers[i] = data.Customers[perm[i] + 1].Point; } var colors = new int[data.N]; var count = new int[clustersCount]; var changed = true; while (changed) { changed = false; count = new int[clustersCount]; for (int i = 1; i < data.N; i++) { var bestCenter = -1; var bestDist = 0D; for (int j = 0; j < clustersCount; j++) { if (bestCenter == -1 || centers[j].Dist(data.Customers[i].Point) < bestDist) { bestCenter = j; bestDist = centers[j].Dist(data.Customers[i].Point); } } if (colors[i] != bestCenter) { colors[i] = bestCenter; changed = true; } } for (int j = 0; j < clustersCount; j++) { var center = new Point2DReal(0, 0); for (int i = 1; i < data.N; i++) { if (colors[i] == j) { center = center + data.Customers[i].Point; count[j]++; } } centers[j] = center * (1D / count[j]); } } var result = new ClustersModel(); result.Color = colors; result.Count = count; result.Centers = centers; return result; }
private bool UpdateClustersWarehouse(VrpData data, ClustersModel clusters, int v) { var solver = new GreedyHeuristic(); var warehouseData = new WarehouseInputData(); warehouseData.N = v; warehouseData.M = data.N; warehouseData.T = new double[data.N,v]; for (int i = 0; i < data.N; i++) { for (int j = 0; j < v; j++) { warehouseData.T[i, j] = clusters.Centers[j].Dist(data.Customers[i].Point); } } warehouseData.Consumers = data.Customers.Select(c => new Consumer {Demand = c.Demand, Id = c.Id}).ToArray(); warehouseData.Warehouses = new global::Warehouse.Warehouse[v]; for (int i = 0; i < v; i++) { warehouseData.Warehouses[i] = new global::Warehouse.Warehouse {Cap = data.C, Id = i, S = 0}; } var result = solver.Solve(warehouseData); if (result.SolutionFound) { clusters.Color = result.Solution; return true; } return false; }
private bool UpdateClustersMIP(VrpData data, ClustersModel baseClusters, int v) { throw new NotImplementedException(); }
// burn private static bool UpdateClustersBurn(VrpData data, ClustersModel baseClusters, int v) { var rnd = new Random(); var found = false; for (int count = 0; count < 10; count++) { var clusters = new ClustersModel(); clusters.Color = new int[data.N]; Array.Copy(baseClusters.Color, clusters.Color, data.N); clusters.Count = new int[v]; Array.Copy(baseClusters.Count, clusters.Count, v); clusters.Centers = new Point2DReal[v]; for (int i = 0; i < v; i++) { clusters.Centers[i] = new Point2DReal(baseClusters.Centers[i]); } var w = new int[v]; for (int i = 0; i < data.N; i++) { w[clusters.Color[i]] += data.Customers[i].Demand; } var baseOverweight = w.Sum(x => x > data.C ? x - data.C : 0); var overweight = baseOverweight; var radiuses = new double[v]; for (int i = 0; i < data.N; i++) { var color = clusters.Color[i]; var dist = data.Customers[i].Point.Dist(clusters.Centers[color]); if (dist > radiuses[color]) { radiuses[color] = dist; } } var baseRadius = radiuses.Sum(); var radius = baseRadius; var E = 1D; var minE = double.MaxValue; var bestColors = new int[data.N]; var bestW = new int[v]; for (int k = 0; k < 1000; k++) { if (E < minE) { minE = E; Array.Copy(clusters.Color, bestColors, data.N); Array.Copy(w, bestW, v); } var id = rnd.Next(data.N); var weight = data.Customers[id].Demand; var newColor = rnd.Next(v - 1); var oldColor = clusters.Color[id]; if (oldColor <= newColor) { newColor++; } var weightDelta = -(w[newColor] + weight > data.C ? w[newColor] + weight - data.C : 0) + (w[newColor] > data.C ? w[newColor] - data.C : 0) - (w[oldColor] - weight > data.C ? w[oldColor] - weight - data.C : 0) + (w[oldColor] > data.C ? w[oldColor] - data.C : 0); var newOverweight = overweight - weightDelta; var point = data.Customers[id].Point; var newCenter = (clusters.Centers[newColor] * clusters.Count[newColor] + point) * (1D / (clusters.Count[newColor] + 1)); var newDist = point.Dist(newCenter); var newRadius = radius; if (newDist > radiuses[newColor]) { newRadius += newDist - radiuses[newColor]; } var newE = (double) newOverweight / baseOverweight + K * (newRadius - baseRadius) / baseRadius; var alpha = rnd.NextDouble(); var T = 10 / (k + 1); var h = Math.Exp(-(newE - E) / T); if (alpha < h) { E = newE; overweight = newOverweight; radius = newRadius; w[newColor] += weight; w[oldColor] -= weight; clusters.Color[id] = newColor; clusters.Centers[newColor] = newCenter; clusters.Centers[oldColor] = (clusters.Centers[oldColor] * clusters.Count[oldColor] - point) * (1D / (clusters.Count[oldColor] - 1)); clusters.Count[newColor]++; clusters.Count[oldColor]--; if (newDist > radiuses[newColor]) { radiuses[newColor] = newDist; } } } if (bestW.All(x => x <= data.C)) { found = true; baseClusters.Color = bestColors; break; } } return found; }