using System; using System.Collections.Generic; using System.IO; using System.Linq; using HeuristicLab.Problems.FacilityLocation; using HeuristicLab.Problems.VehicleRouting; namespace HeuristicLab.Networks.IntegratedOptimization.LocationRouting { public static class LrpUtils { public enum DistanceType { Unknown = int.MinValue, CEIL_2D = 0, EUC_2D = 1, } public static readonly Dictionary> DistanceFuncs; static LrpUtils() { DistanceFuncs = new Dictionary>(); DistanceFuncs.Add(DistanceType.EUC_2D, (d, i, c, j) => Math.Sqrt(Math.Pow(d[i, 0] - c[j, 0], 2.0) + Math.Pow(d[i, 1] - c[j, 1], 2.0))); DistanceFuncs.Add(DistanceType.CEIL_2D, (d, i, c, j) => Math.Ceiling(DistanceFuncs[DistanceType.EUC_2D](d, i, c, j)) * 100); } public static void Import(string filePath, out int nrOfDepots, out int nrOfCustomers, out double[,] depotCoordinates, out double[,] customerCoordinates, out DistanceType distanceType, out double[] depotCapacities, out double[] customerDemands, out double[] depotCosts, out double vehicleCapacity, out double vehicleCost) { nrOfDepots = 0; nrOfCustomers = 0; depotCoordinates = new double[0, 0]; customerCoordinates = new double[0, 0]; distanceType = DistanceType.Unknown; depotCapacities = new double[0]; customerDemands = new double[0]; depotCosts = new double[0]; vehicleCapacity = 0.0; vehicleCost = 0.0; int dataIndex = 0; using (var fs = new FileStream(filePath, FileMode.Open)) using (var sr = new StreamReader(fs)) { string input; while ((input = sr.ReadLine()) != null) { int commentCol = input.IndexOf("//"); input = input.Substring(0, commentCol >= 0 ? commentCol : input.Length); if (string.IsNullOrEmpty(input)) continue; switch (dataIndex) { case 0: int.TryParse(input, out nrOfCustomers); customerCoordinates = new double[nrOfCustomers, 2]; customerDemands = new double[nrOfCustomers]; ++dataIndex; break; case 1: int.TryParse(input, out nrOfDepots); depotCoordinates = new double[nrOfDepots, 2]; depotCapacities = new double[nrOfDepots]; depotCosts = new double[nrOfDepots]; ++dataIndex; break; case 2: for (int i = 0; i < nrOfDepots; i++) { string[] coords = input.Split('\t'); double x; double.TryParse(coords[0], out x); double y; double.TryParse(coords[1], out y); depotCoordinates[i, 0] = x; depotCoordinates[i, 1] = y; if (i < nrOfDepots - 1) input = sr.ReadLine(); } ++dataIndex; break; case 3: for (int i = 0; i < nrOfCustomers; i++) { string[] coords = input.Split('\t'); double x; double.TryParse(coords[0], out x); double y; double.TryParse(coords[1], out y); customerCoordinates[i, 0] = x; customerCoordinates[i, 1] = y; if (i < nrOfCustomers - 1) input = sr.ReadLine(); } ++dataIndex; break; case 4: double.TryParse(input, out vehicleCapacity); ++dataIndex; break; case 5: for (int i = 0; i < nrOfDepots; i++) { double capacity; double.TryParse(input, out capacity); depotCapacities[i] = capacity; if (i < nrOfDepots - 1) input = sr.ReadLine(); } ++dataIndex; break; case 6: for (int i = 0; i < nrOfCustomers; i++) { double demand; double.TryParse(input, out demand); customerDemands[i] = demand; if (i < nrOfCustomers - 1) input = sr.ReadLine(); } ++dataIndex; break; case 7: for (int i = 0; i < nrOfDepots; i++) { double cost; double.TryParse(input, out cost); depotCosts[i] = cost; if (i < nrOfDepots - 1) input = sr.ReadLine(); } ++dataIndex; break; case 8: double.TryParse(input, out vehicleCost); ++dataIndex; break; case 9: Enum.TryParse(input, out distanceType); break; } } } } public static double[,] GetFlpDeliveryCosts(double[,] depotCoordinates, double[,] customerCoordinates, DistanceType distanceType) { int nrOfDepots = depotCoordinates.GetLength(0), nrOfCustomers = customerCoordinates.GetLength(0); var deliveryCosts = new double[nrOfDepots, nrOfCustomers]; for (int i = 0; i < nrOfDepots; i++) for (int j = 0; j < nrOfCustomers; j++) deliveryCosts[i, j] = DistanceFuncs[distanceType](depotCoordinates, i, customerCoordinates, j); return deliveryCosts; } public static double[,] GetVrpCoordinates(double[,] depotCoordinates, double[,] customerCoordinates, int depotIdx, int[] customers) { var coordinates = new double[customers.Length + 1, 2]; coordinates[0, 0] = depotCoordinates[depotIdx, 0]; coordinates[0, 1] = depotCoordinates[depotIdx, 1]; for (int i = 0; i < customers.Length; i++) { coordinates[i + 1, 0] = customerCoordinates[customers[i], 0]; coordinates[i + 1, 1] = customerCoordinates[customers[i], 1]; } return coordinates; } public static double[,] GetVrpDistances(double[,] depotCoordinates, double[,] customerCoordinates, int depotIdx, int[] customers, DistanceType distanceType) { var coordinates = GetVrpCoordinates(depotCoordinates, customerCoordinates, depotIdx, customers); return GetVrpDistances(coordinates, distanceType); } public static double[,] GetVrpDistances(double[,] coordinates, DistanceType distanceType) { int nrOfNodes = coordinates.GetLength(0); var distances = new double[nrOfNodes, nrOfNodes]; for (int i = 1; i < nrOfNodes; i++) for (int j = 0; j < i; j++) distances[i, j] = distances[j, i] = DistanceFuncs[distanceType](coordinates, i, coordinates, j); return distances; } public static double Evaluate(FacilityLocationSolution flpSolution, VRPSolution[] vrpSolutions) { return flpSolution.TotalOpeningCostsParameter.Value.Value + vrpSolutions.Sum(x => x.Quality.Value); } } }