用Java从Google DistanceMatrix响应计算2d距离矩阵

用Java从Google DistanceMatrix响应计算2d距离矩阵,java,google-distancematrix-api,distance-matrix,Java,Google Distancematrix Api,Distance Matrix,我试图用谷歌或工具库解决旅行推销员问题和车辆路径问题,在教程中发现,他们使用了一个距离矩阵,其I,j条目是从位置I到位置j的距离(以英里为单位),位置顺序如下: 纽约1。洛杉矶2。芝加哥3。明尼阿波利斯4号。丹佛5号。达拉斯6号。西雅图7。波士顿8。旧金山9。圣路易斯10号。休斯顿11。凤凰12号。盐湖城 它们的矩阵距离如下所示: public final long[][] distanceMatrix = { {0, 2451, 713, 1018, 1631, 1374, 2

我试图用谷歌或工具库解决旅行推销员问题和车辆路径问题,在教程中发现,他们使用了一个距离矩阵
,其I,j
条目是从位置I到位置j的距离(以英里为单位),位置顺序如下:

  • 纽约1。洛杉矶2。芝加哥3。明尼阿波利斯4号。丹佛5号。达拉斯6号。西雅图7。波士顿8。旧金山9。圣路易斯10号。休斯顿11。凤凰12号。盐湖城
  • 它们的矩阵距离如下所示:

      public final long[][] distanceMatrix = {
          {0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145, 1972},
          {2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357, 579},
          {713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453, 1260},
          {1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280, 987},
          {1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371},
          {1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887, 999},
          {2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114, 701},
          {213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300, 2099},
          {2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653, 600},
          {875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272, 1162},
          {1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017, 1200},
          {2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0, 504},
          {1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504, 0},
      };
    
    
    它们进一步提供了一个关于如何动态创建距离矩阵的方法,除了在
    Python
    中,我在这方面不是很好,我正在使用
    Java

    在我的Java
    实现中
    我使用的是
    Java客户机
    ,我的代码如下

    private static long[][] buildDistanceMatrix(int matrixSize, DistanceMatrix distanceMatrix) {
            long[][] matrix = new long[matrixSize][matrixSize];
            for (int i = 0; i < distanceMatrix.rows.length; i++) {
                DistanceMatrixElement[] elements = distanceMatrix.rows[i].elements;
                for (int j = 0; j < elements.length; j++) {
                        matrix[i][j] = elements[j].distance.inMeters;
                }
            }
            return matrix;
        }
    
    
        public static void getDistanceMatrix(List<LatLng> origins, List<LatLng> destinations){
            GeoApiContext context = new GeoApiContext.Builder()
                    .apiKey(GOOGLE_MAPS_API_KEY)
                    .build();
            DistanceMatrixApiRequest distanceMatrixApiRequest = DistanceMatrixApi.newRequest(context)
                    .mode(TravelMode.DRIVING)
                    .trafficModel(TrafficModel.BEST_GUESS)
                    .departureTime(Instant.now().atZone(ZoneOffset.UTC).toInstant())
                    .destinations(destinations.toArray(new LatLng[destinations.size()]))
                    .origins(origins.toArray(new LatLng[origins.size()]));
    
    
            distanceMatrixApiRequest.setCallback(new PendingResult.Callback<DistanceMatrix>() {
                @Override
                public void onResult(DistanceMatrix distanceMatrix) {
    
                    long[][] matrix = buildDistanceMatrix(destinations.size(), distanceMatrix);
                    System.out.println(Arrays.deepToString(matrix));
    
                }
    
                @Override
                public void onFailure(Throwable throwable) {
                    throwable.printStackTrace();
    
                }
            });
        }
    
    "destinationAddresses": [
        "Central St, Lusaka, Zambia",
        "Unnamed Road, Lusaka, Zambia",
        "Jacaranda Rd, Lusaka, Zambia"
    ],
    "originAddresses": [
        "1940 - 3 Munthaka Cl, Lusaka, Zambia"
    ],
    "rows": [
        {
            "elements": [
                {
                    "distance": {
                        "humanReadable": "10.2 km",
                        "inMeters": 10193
                    },
                    "duration": {
                        "humanReadable": "23 mins",
                        "inSeconds": 1352
                    },
                    "durationInTraffic": {
                        "humanReadable": "26 mins",
                        "inSeconds": 1549
                    },
                    "status": "OK"
                },
                {
                    "distance": {
                        "humanReadable": "6.6 km",
                        "inMeters": 6647
                    },
                    "duration": {
                        "humanReadable": "13 mins",
                        "inSeconds": 779
                    },
                    "durationInTraffic": {
                        "humanReadable": "14 mins",
                        "inSeconds": 839
                    },
                    "status": "OK"
                },
                {
                    "distance": {
                        "humanReadable": "4.9 km",
                        "inMeters": 4881
                    },
                    "duration": {
                        "humanReadable": "9 mins",
                        "inSeconds": 516
                    },
                    "durationInTraffic": {
                        "humanReadable": "9 mins",
                        "inSeconds": 538
                    },
                    "status": "OK"
                }
            ]
        }
    ]
    
    }```
    
    public static Assignment findWithVehicleRoutingProblem(List<LatLng> destinations, int numOfVehicles) {
        long[][] distanceMatrix = RoutUtils.computeEuclideanDistanceMatrix(RoutUtils.scaleCoordinatesForEuclidean(destinations));
        RoutingIndexManager manager = new RoutingIndexManager(distanceMatrix.length, numOfVehicles, 0);
    
        RoutingModel routing = new RoutingModel(manager);
        final int transitCallbackIndex = routing.registerTransitCallback((long fromIndex, long toIndex) -> {
            int fromNode = manager.indexToNode(fromIndex);
            int toNode = manager.indexToNode(toIndex);
            return distanceMatrix[fromNode][toNode];
        });
    
        routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
    
        routing.addDimension(transitCallbackIndex, 0, 3000,
                true, 
                "Distance");
        RoutingDimension distanceDimension = routing.getMutableDimension("Distance");
        distanceDimension.setGlobalSpanCostCoefficient(100);
    
        RoutingSearchParameters searchParameters = main.defaultRoutingSearchParameters()
                .toBuilder()
                .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
                .build();
    
        return routing.solveWithParameters(searchParameters);
    }
    

    我确实解决了这个问题。我用
    欧几里德距离公式
    得到了一个距离矩阵

    /// @brief Compute Euclidean distance matrix from locations array.
    /// @details It uses an array of locations and computes
    /// the Euclidean distance between any two locations.
    private static long[][] computeEuclideanDistanceMatrix(long[][] locations) {
        // Calculate distance matrix using Euclidean distance.
        long[][] distanceMatrix = new long[locations.length][locations.length];
        for (int fromNode = 0; fromNode < locations.length; ++fromNode) {
            for (int toNode = 0; toNode < locations.length; ++toNode) {
                if (fromNode == toNode) {
                    distanceMatrix[fromNode][toNode] = 0;
                } else {
                    distanceMatrix[fromNode][toNode] =
                            (long) Math.hypot(locations[toNode][0] - locations[fromNode][0],
                                    locations[toNode][1] - locations[fromNode][1]);
                }
            }
        }
        return distanceMatrix;
    }
    
    以及
    scalecoordinationsforeuclidean
    方法

    private static final long DISTANCE_MATRIX_SCALE_FACTOR = 100000000000L;
       private static long[][] scaleCoordinatesForEuclidean(List<LatLng> destinations) {
        long[][] locations = new long[destinations.size()][destinations.size()];
        for (int i = 0; i < destinations.size(); i++) {
            long[] coordinate = {(long) (destinations.get(i).lat * DISTANCE_MATRIX_SCALE_FACTOR), (long) (destinations.get(i).lng * DISTANCE_MATRIX_SCALE_FACTOR)};
            locations[i] = coordinate;
        }
        return locations;
    }
    
    专用静态最终长距离矩阵比例系数=1000000000L;
    专用静态长[][]ScaleCoordinationsForeClidean(列出目的地){
    long[][]位置=新的long[destinations.size()][destinations.size()];
    对于(int i=0;i
    @Anbry Lungu找到了任何解决方案,请告诉我。@RajKumar是的,我找到了。检查我的答案,如果你需要进一步的帮助,请不要犹豫。你能帮我找出这个方法需要的参数吗?计算uclideandstancematrix(..)@astonio这些参数非常简单,因此在地图上给定两个位置,每个位置都由其坐标标识,坐标包括纬度和经度。所以位置数组只是一个多维的位置数组,在我最初的问题中,这就是纽约1号的坐标。洛杉矶2。芝加哥3。明尼阿波利斯4号。丹佛5号。达拉斯6号。西雅图7。波士顿8。旧金山9。圣路易斯10号。休斯顿11。凤凰12号。盐湖城你的意思是我们需要准备一个带有经纬度的数组?这里经纬度是双精度的,但我们需要将变量作为长数组传递,如果我们将双精度转换为长数组,那么结果将是2位数字,比如22.272504,96.607590到22,96,可以吗?
    private static final long DISTANCE_MATRIX_SCALE_FACTOR = 100000000000L;
       private static long[][] scaleCoordinatesForEuclidean(List<LatLng> destinations) {
        long[][] locations = new long[destinations.size()][destinations.size()];
        for (int i = 0; i < destinations.size(); i++) {
            long[] coordinate = {(long) (destinations.get(i).lat * DISTANCE_MATRIX_SCALE_FACTOR), (long) (destinations.get(i).lng * DISTANCE_MATRIX_SCALE_FACTOR)};
            locations[i] = coordinate;
        }
        return locations;
    }