public static VrpData ReadData(string path) { var data = new VrpData(); using (var reader = File.OpenText(path)) { var line = reader.ReadLine().Split(); data.N = int.Parse(line[0]); data.V = int.Parse(line[1]); data.C = int.Parse(line[2]); data.Customers = new Customer[data.N]; for (int i = 0; i < data.N; i++) { line = reader.ReadLine().Split(); data.Customers[i] = new Customer { Id = i, Demand = int.Parse(line[0]), Point = new Point2DReal(double.Parse(line[1]), double.Parse(line[2])) }; } } return data; }
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; }
protected void CalcTotalDist(VrpData data, VrpResult result) { double totalDist = 0; foreach (var route in result.Routes) { for (int i = 0; i < route.Count - 1; i++) { totalDist += data.Customers[route[i]].Point.Dist(data.Customers[route[i + 1]].Point); } } result.Dist = totalDist; }
protected static void ApplyTsp(VrpData data, VrpResult result) { var tspSolver = new Opt2(); for (int i = 0; i < data.V; i++) { var route = result.Routes[i]; if (route.Count > 4) { route.RemoveAt(route.Count - 1); var measure = new MatrixMeasureFactory().CreateMatrixMeasure(route.Select(x => data.Customers[x].Point).ToArray()); var tspRoute = tspSolver.GetPath(route.Count, measure); int startIndex = 0; for (int j = 0; j < tspRoute.Length; j++) { if (tspRoute[j] == 0) { startIndex = j; break; } } result.Routes[i] = new List<int>(); for (int j = startIndex; j < tspRoute.Length; j++) { result.Routes[i].Add(route[tspRoute[j]]); } for (int j = 0; j < startIndex; j++) { result.Routes[i].Add(route[tspRoute[j]]); } result.Routes[i].Add(0); } else { result.Routes[i] = route; } } }
public override VrpResult Solve(VrpData data) { var sortedCustomers = data.Customers.OrderByDescending(c => c.Demand).ToArray(); var result = new VrpResult(); result.Routes = new List<int>[data.V]; var n = data.N; var v = data.V; var used = new bool[n]; used[0] = true; for (int i = 0; i < v; i++) { var route = new List<int> { 0 }; var cap = data.C; foreach (var customer in sortedCustomers.Where(c => !used[c.Id]).ToList()) { if (customer.Demand <= cap) { cap -= customer.Demand; route.Add(customer.Id); used[customer.Id] = true; } } route.Add(0); result.Routes[i] = route; } ApplyTsp(data, result); CalcTotalDist(data, result); return result; }
private void buttonUpload_Click(object sender, EventArgs e) { var dialog = new OpenFileDialog(); if (dialog.ShowDialog() == DialogResult.OK) { var path = dialog.FileName; _vrpData = VrpData.ReadData(path); var minx = 1e30; var maxx = -1e30; var miny = 1e30; var maxy = -1e30; foreach (var point in _vrpData.Customers.Select(c => c.Point)) { minx = Math.Min(minx, point.X); maxx = Math.Max(maxx, point.X); miny = Math.Min(miny, point.Y); maxy = Math.Max(maxy, point.Y); } foreach (var point in _vrpData.Customers.Select(c => c.Point)) { point.X = (point.X - minx) / (maxx - minx) * (m_Width - 60) + 30; point.Y = (point.Y - miny) / (maxy - miny) * (m_Height - 60) + 30; } m_XScale = (maxx - minx) / (m_Width - 60); m_XShift = 30; m_YScale = (maxy - miny) / (m_Height - 60); m_YShift = 30; } GetPath(); RefreshDraw(); }
public override VrpResult Solve(VrpData data) { VrpResult bestResult = null; var timelimit = BaseTimelimit; var stopwatch = Stopwatch.StartNew(); /*var rnd = new Random(); var pr = new double[data.V]; for (int i = 0; i < data.V; i++) { pr[i] = 1D / (data.V - 1); } pr[0] = 0;*/ while (true) { stopwatch.Stop(); if (bestResult != null && (bestResult.Dist < 1400 || stopwatch.ElapsedMilliseconds > timelimit)) { break; } stopwatch.Start(); /*var r = rnd.NextDouble() * pr.Sum(); var sum = 0D; var v = 2; for (int i = 0; i < data.V; i++) { sum += pr[i]; if (sum > r) { v = i + 1; break; } }*/ var v = data.V; var baseClusters = GetKmeanClusters(data, v); var found = UpdateClustersBurn(data, baseClusters, v); if (!found) { //pr[v - 1] /= 2; continue; } var result = new VrpResult(); result.Routes = new List<int>[data.V]; for (int i = 0; i < data.V; i++) { result.Routes[i] = new List<int> { 0 }; } for (int i = 1; i < data.N; i++) { result.Routes[baseClusters.Color[i]].Add(i); } for (int i = 0; i < data.V; i++) { result.Routes[i].Add(0); } ApplyTsp(data, result); CalcTotalDist(data, result); if (bestResult == null || bestResult.Dist > result.Dist) { //pr[v - 1] *= (1 << (data.V - v)); bestResult = result; } } return bestResult; }
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; }
public abstract VrpResult Solve(VrpData data);