基于optaplanner排程引擎解决枢纽配送路线规划问题

optaplanner根据百度地图计算实际距离规划路线

UserCase:从上海枢纽配送中心前往49个客户(test数据为上海地铁站点),求解最优路线规划

  • 构建求解元数据的地址坐标 (Depot-1 :上海枢纽 Customer-49: 上海49个地铁站点)
 public static Map<Long, Location> initLocations(List<Location> customerLocationList) {
        List<String> locations = new ArrayList<>();
        locations.add("0	121.209207	31.248526	上海枢纽");
        locations.add("55	121.538472	31.311024	翔殷路");
        locations.add("110	121.516066	31.278922	鞍山新村");
        locations.add("165	121.475411	31.259035	中兴路");
        locations.add("220	121.492716	31.217413	陆家浜路");
        locations.add("275	121.50029	31.16671	杨思");
        locations.add("330	121.515133	31.089988	江月路");
        locations.add("385	121.362183	31.248368	丰庄");
        locations.add("440	121.430026	31.236733	隆德路");
        locations.add("495	121.469279	31.241917	自然博物馆");
        locations.add("550	121.488515	31.202606	世博会博物馆");
        locations.add("605	121.492716	31.217413	陆家浜路");
        locations.add("660	121.442314	31.201202	徐家汇");
        locations.add("715	121.375571	31.163862	星中路");
        locations.add("770	121.236257	31.110609	佘山");
        locations.add("825	121.235829	31.006987	醉白池");
        locations.add("880	121.42068	31.148312	锦江乐园");
        locations.add("935	121.45316	31.211335	衡山路");
        locations.add("990	121.474802	31.244699	新闸路");
        locations.add("1045	121.458503	31.285845	上海马戏城");
        locations.add("1100	121.444185	31.345991	呼兰路");
        locations.add("1155 121.307524 31.195432 徐泾东");
        locations.add("1210 121.393672 31.220484 威宁路");
        locations.add("1265 121.465932 31.23413 南京西路");
        locations.add("1320 121.533437 31.234854 世纪大道");
        locations.add("1375 121.608557 31.209932 金科路");
        locations.add("1430 121.535457 31.22605 锦绣路");
        locations.add("1485 121.492645 31.18033 长清路");
        locations.add("1540 121.456628 31.219964 常熟路");
        locations.add("1595 121.428339 31.262583 岚皋路");
        locations.add("1650 121.420161 31.309963 场中路");
        locations.add("1705 121.379313 31.350576 顾村公园");
        locations.add("1760 121.446217 31.414218 江杨北路");
        locations.add("1815 121.499387 31.376563 淞滨路");
        locations.add("1870 121.491636 31.311153 江湾镇");
        locations.add("1925 121.48291 31.257393 宝山路");
        locations.add("1980 121.419507 31.237991 金沙江路");
        locations.add("2035 121.444739 31.182978 漕溪路");
        locations.add("2090 121.51713 31.079655 联航路");
        locations.add("2145 121.487012 31.159351 东方体育中心");
        locations.add("2200 121.496122 31.207672 西藏南路");
        locations.add("2255 121.478011 31.248303 曲阜路");
        locations.add("2310 121.50817 31.280778 四平路");
        locations.add("2365 121.539677 31.301934 黄兴公园");
        locations.add("2420 121.593445 31.353883 外高桥保税区北");
        locations.add("2475 121.595327 31.296804 东靖路");
        locations.add("2530 121.579314 31.256659 云山路");
        locations.add("2585 121.533437 31.234854 世纪大道");
        locations.add("2640 121.516396 31.191286 高科西路");
        locations.add("2695 121.50168 31.154367 灵岩南路");
        Map<Long, Location> locationMap = new LinkedHashMap<>(customerListSize);
        for (int i = 0; i < customerListSize; i++) {
            //地址坐标
            Location location = new RoadLocation();
            String line = locations.get(i);
            String[] lineTokens = StringSplitUtils.splitBySpacesOrTabs(line.trim(), 3, 4);
            location.setId(Long.parseLong(lineTokens[0]));
            location.setLatitude(Double.parseDouble(lineTokens[1]));
            location.setLongitude(Double.parseDouble(lineTokens[2]));
            location.setName(lineTokens[3]);
            customerLocationList.add(location);
            locationMap.put(location.getId(), location);
        }
        return locationMap;
    }
  • 构建矩阵距离(来源:百度地图批量算点服务) 50X50矩阵(计算所有点之间的实际路线距离)
  public static void initMatrixDistance(List<Location> customerLocationList) {
        List<String> matrixDistance = new ArrayList<>();
        matrixDistance.add("0.00 36.5 33.5 28 30.7 35.5 42.6 16 23 27.2 31.5 30.7 26.7 23 17 29.2 28.7 27.3 27.9 29.7 33.2 14.7 20.6 27.1 35.2 44.7 35 34.3 26.5 25 27.5 26.2 36.5 37 33.2 28.8 21.5 28.5 44.2 35.3 31.8 28.1 33 36.3 46.1 40.8 39.3 35.2 35.1 36.6");
        matrixDistance.add("40.1 0.00 8.9 13.9 16.8 22 31.8 25 19.5 15.4 18.9 16.8 21.1 29.5 44.7 52.9 28 19.4 14.7 14 18.6 34.7 23.5 16.5 14.3 15.1 14.3 21.5 18.3 17.3 17.2 24.1 20.3 12.8 9 13.6 19.8 23.6 33.4 24.1 17.8 13.7 9.1 5.2 10.5 7.3 9.6 14.3 18.8 23.7");
        matrixDistance.add("32.8 6.7 0.00 5.8 8.9 14.6 24.3 17.7 11.7 7.6 11 8.9 13.3 21.7 36.8 45 20.1 11.5 6.9 9 16.2 26.8 15.8 8.7 6.9 15.3 6.8 14.1 10.4 10.7 13.7 20.6 19 14.5 6.2 5.6 12.2 15.7 26 16.7 9.9 5.8 2.7 4.8 15.5 8.8 9.9 6.9 11.4 16.3");
        matrixDistance.add("28.3 10.6 6.6 0.00 5 11.5 20.8 12.8 6.6 2.8 6.9 5 9.1 17.1 32.3 40.9 16 7.3 2.4 7.2 14.5 22.2 10.7 4.2 9.3 19 9.2 10.9 6.2 6.4 10.6 17.4 19 16.4 8.1 1.1 7.1 11.6 22.4 13.2 6.1 1.2 6.6 9.8 20.2 13.6 13.4 9.3 9.4 13.1");
        matrixDistance.add("30.6 13.9 9.4 5.1 0.00 6.5 16.3 15.1 8.2 4.5 2.3 0.00 5.6 14.2 29.4 37.2 12.4 4.9 3.9 11.6 18.8 21 11.2 4.5 6.4 14 6.4 6 4.5 11 15.2 22 23.3 20.5 12.2 5.4 9.4 8 17.9 8.7 1.1 3.8 9.9 12.9 22.4 15.7 10.6 6.4 4.5 8.2");
        matrixDistance.add("35.8 20.3 15.2 11.9 6.9 0.00 9.7 20.3 13 10 6.3 6.9 9.9 15 30.2 34.5 11.5 9.6 10.8 18.5 25.7 24.3 15.7 10.1 10 13.3 8.5 2.8 9.4 16.8 20.7 27.6 30.2 27.4 19.1 12.3 14.6 8.6 11.4 2.1 5.9 10.7 16.3 18.5 26.3 19.7 14.5 10 4.3 1.8");
        matrixDistance.add("43.1 29.5 24.6 20.5 15.8 9.6 0.00 28 21.7 18.7 15 15.8 18 20.9 34 34 16.8 18.3 18.8 26.3 33.5 29.6 23.2 18.7 19.3 20.7 17.9 11 18 25.5 29.3 36.2 38.6 35.9 27.6 20.9 22.5 15.9 3.1 8.9 14.9 19.3 25.6 27.9 35.6 29 23.9 19.3 13.6 8.4");
        matrixDistance.add("15.6 21.8 18.8 13.2 15.6 20.4 27.9 0.00 7.9 12.1 16.4 15.6 11.6 11.5 24.9 36.8 14.2 12.2 12.9 14.5 20.4 11.9 5.5 12 20.1 29.6 19.9 19.2 11.5 10.5 12.9 17.8 26.1 24.9 18 13.9 6.4 13.4 29.5 20.3 16.7 13 18.3 21.5 31.4 25.7 24.2 20.1 20 21.5");
        matrixDistance.add("22.7 15.9 12.3 6.9 8.8 13.5 21.8 7.2 0.00 5.6 9.5 8.8 4.9 12.7 27.8 37 12.2 5 6.3 10.7 17.2 17.5 5.7 5.3 13.3 22.8 13.2 12 4.5 5.7 11.1 18 23.3 21.4 13.2 7.4 1.5 7.8 23.4 14.2 9.9 6.5 12.5 15.7 25.5 19.2 17.4 13.3 13.2 14.9");
        matrixDistance.add("27.5 12.3 7.9 2.7 4.4 10.9 18.8 12 5.1 0.00 5.4 4.4 7.2 15.1 30.2 38.9 14 5.4 999 8.5 15.7 20.2 9.2 2.2 9.1 18.4 8.8 9.3 4 7.5 11.4 18.3 20.8 18.1 9.8 3.2 6.3 9.7 20.4 11.1 5.5 1.6 8.3 11.5 21.5 14.8 13.2 9.1 8.9 12.4");
        matrixDistance.add("31.5 16 11.5 7 2.2 6.2 15.6 16 8.8 5.5 0.00 2.2 5.9 12.8 28.5 35.6 10.7 5.6 5.3 13.1 20.4 21.3 11.8 5.6 8.7 13.7 8.1 5.3 5.1 12.3 16.2 23 25.3 22.6 14.4 7.3 10.3 6.4 17.3 8 1.3 5.7 12.1 15.1 24.6 18 12.8 8.7 4.1 7.9");
        matrixDistance.add("30.6 13.9 9.4 5.1 0.00 6.5 16.3 15.1 8.2 4.5 2.3 0.00 5.6 14.2 29.4 37.2 12.4 4.9 3.9 11.6 18.8 21 11.2 4.5 6.4 14 6.4 6 4.5 11 15.2 22 23.3 20.5 12.2 5.4 9.4 8 17.9 8.7 1.1 3.8 9.9 12.9 22.4 15.7 10.6 6.4 4.5 8.2");
        matrixDistance.add("26.9 19.2 14.7 9.9 6.5 10.6 18.1 11.4 5.5 7.3 6.6 6.5 0.00 9.1 24.3 32.9 8 3.4 8.1 15.6 22.3 15.8 6.5 6.7 12.4 20 12.4 9.1 3.8 10.9 16.5 23.3 27.9 25.2 16.9 10.3 6 3.7 19.7 10.5 7.1 8.7 15.2 18.3 27.8 21.7 16.5 12.4 10.5 11.7");
        matrixDistance.add("22.7 26.8 22.4 17.6 14.6 15 20.8 11.2 12.7 14.9 13.3 14.6 9.7 0.00 15.7 26 6.6 11.5 15.7 22.1 28.1 9.3 8.7 14.1 20.5 26.6 20.5 14.7 11.6 17.1 21 26.5 34.8 32.8 24.5 17.9 11.8 8.2 22.5 14.7 14.1 16.3 22.8 26 35.5 29.3 24.6 20.5 17 15.6");
        matrixDistance.add("16.7 41.3 37 32.1 29.1 29.9 33.8 25.2 27.3 29.5 28.1 29.1 24.3 15.8 0.00 12.6 20.8 26 30.3 36.6 42.5 14.7 23.2 28.7 35.1 41.4 35 29.5 26.1 31.6 35.4 39.4 49.3 47.4 39.1 32.4 26.5 23 35.4 28.9 29 30.8 37.4 40.5 50.1 43.9 39.2 35.1 31.9 29.8");
        matrixDistance.add("29 49.5 45 40.2 36.7 34.3 32.8 36.4 36.1 37.6 35.2 36.7 32.1 26.5 12.3 0.00 25.2 33.7 38.4 45.9 52.9 27 34 37.1 42.7 47.5 42.1 34.9 34.1 41.5 46.1 51.7 58.3 55.5 47.2 40.6 36.2 30 31.5 32.8 36 39 45.5 48.6 58.1 52 46.8 42.7 37.8 33.7");
        matrixDistance.add("29.5 24.4 19.9 15 11.5 10.1 16.3 14.9 10.9 12.5 9.9 11.5 7 6.8 22.5 27.1 0.00 8.5 13.3 20.7 27.8 16.1 9.9 11.9 17.5 22.2 16.9 9.8 9 16.4 21.8 28.6 33.1 30.4 22.1 15.4 11.1 4.9 18 9.2 10.7 13.8 20.4 23.4 32.9 26.8 21.7 17.5 12.7 10.2");
        matrixDistance.add("27.4 16.8 12.3 7.5 4.9 9 17.9 11.9 4.8 5 5 4.9 2.1 10.8 25.9 33.6 8.7 0.00 5.8 13.2 20.4 17.4 7.2 4.4 10.4 18.5 10.4 7.5 1.5 9.6 14.6 21.4 25.6 22.9 14.6 7.9 6.2 4.3 19.5 10.3 5.6 6.3 12.9 15.9 25.4 19.2 14.6 10.4 8.9 10.4");
        matrixDistance.add("27.8 11.6 7.2 2.2 3.8 10.3 19.1 12.3 5.4 1.2 5.4 3.8 7.3 15.5 30.6 39.1 14.2 5.6 0.00 8.2 15.4 20.5 9.5 2.5 8 17.8 7.9 9.6 4.4 7.5 11.6 18.4 20.4 17.6 9.4 2.5 6.6 9.8 20.7 11.4 4.9 895 7.6 10.8 20.8 14.1 12.1 8 8.2 12");
        matrixDistance.add("29.5 15.2 11.5 5.4 9.5 16 23.9 14.3 8.8 6 10.6 9.5 12.2 20 35.1 44 19.1 10.4 5.8 0.00 17.2 24.9 12.8 7.4 13.7 23.5 13.6 14.5 9.2 7.9 11.8 18.6 22.4 20.6 12.1 6.4 9.1 14.7 25.6 16.3 10.6 6.4 11.5 14.7 24.8 18.9 17.8 13.7 13.9 17.6");
        matrixDistance.add("33.7 14.4 13.6 10.6 15.5 22 30.4 18.1 14.7 12.5 17.1 15.5 18.6 25.8 40.9 50.4 25.5 16.9 12.3 6.9 0.00 29.4 18.5 13.9 18.9 27.2 18.9 21 15.7 11.1 11.7 18.5 20.3 18.5 10.3 11.3 15.1 21.2 32.1 22.8 16.6 11.8 12.3 14.6 24 20.8 21.8 18.9 19.9 23.7");
        matrixDistance.add("14.5 31.6 28 22.8 22.4 25.7 31.2 12.1 17.6 20.5 22.4 22.4 17.4 11.6 16.3 28.5 17.3 18.5 21.3 25.3 31.3 0.00 12.1 19.7 27.5 35.9 27.4 24.9 18.5 20.7 23.7 26.3 36.3 35 28.8 23.3 16.2 18.8 32.8 25.3 23 21.9 28.2 31.4 41.2 34.9 31.6 27.5 26.3 26.3");
        matrixDistance.add("21.4 20 16.2 10.8 11.1 15 22.5 5.9 5.6 8.9 11.2 11.1 6.2 8.8 23.9 34.3 9.6 7.2 9.5 15 21.3 12.8 0.00 8.1 15.9 24.6 15.7 13.7 6.8 9.8 14.1 20.9 27.5 25.5 17.2 11.3 4.5 8 24.1 14.8 11.7 10.3 16.6 19.8 29.8 23.1 20 15.9 15.1 16.1");
        matrixDistance.add("27.2 13.5 9.2 4.2 4 9.9 18.3 11.7 4.6 1.6 4.9 4 5.2 13.6 28.7 36.9 12.1 3.4 2.5 9.9 17.1 18.7 8.2 0.00 8.7 18 8.5 8.4 2.3 8.3 12.3 19.2 22.3 19.6 11.3 4.6 6 7.7 19.9 10.6 5.1 3 9.5 12.7 22.7 16 12.8 8.7 8.4 11.3");
        matrixDistance.add("34.1 11.4 6.2 7.8 5.9 9.9 19.6 18.6 11.6 7.9 8.1 5.9 10.9 19.3 34.4 42.5 17.6 9 7 13 20.3 25.6 15.2 7.9 0.00 11.5 2.1 9.4 8.1 13.8 17.6 24.4 23.7 19.3 11 7.5 12.9 13.2 21.3 12 6.9 6.9 7.4 9.6 17.3 10.6 5.5 0.00 6.7 11.6");
        matrixDistance.add("44.4 17.8 14.7 18.4 14.1 13.3 21.1 28.9 22 18.3 14 14.1 19.4 25.7 41.4 46.9 22.1 18.7 17.5 23.1 29.9 34.8 25 18.3 10.7 0.00 9.6 13.3 18.3 24.4 27.7 34.5 32 24.8 19.4 18.1 23.2 19.3 22.7 15.4 13 17.2 16.6 14.5 17 11.3 8 10.7 10 14.4");
        matrixDistance.add("35.3 12.5 7.3 9.3 6.5 8.5 18.2 19.8 12.9 9.2 8.7 6.5 11.6 20 35.1 41.6 16.7 9.6 8.3 14.8 22 26.3 15.9 9.2 1.8 9.8 0.00 7.9 9.2 15.3 19.1 26 24.8 20.3 12 9.1 14.1 13.9 19.8 10.6 7.7 8.1 8.5 10.6 18.1 11.4 6.3 1.8 4.7 10.1");
        matrixDistance.add("33.8 19 13.9 10.6 5.6 2.5 11.4 18.3 11 8.1 4.3 5.6 7.9 13.5 29.2 34.7 9.9 7.6 8.9 16.5 23.7 22.9 13.7 8.1 8.7 12.5 7.2 0.00 7.4 14.9 18.8 25.6 28.9 26.1 17.8 11 12.6 7.1 13 3.8 4.6 9.3 15 17.2 25 18.3 13.2 8.7 3 3.9");
        matrixDistance.add("26.6 15.3 11 6 4.9 9.6 18.4 11.1 4.1 3.5 5.5 4.9 2.9 11.3 26.4 34.6 9.7 1.1 4.3 11.8 18.9 17.6 7.2 2.8 9.5 18.9 9.3 8.1 0.00 8.1 13.1 19.9 24.1 21.4 13.1 6.5 5.4 5.3 20.1 10.8 6 4.8 11.4 14.5 24.1 17.9 13.6 9.5 9.3 11");
        matrixDistance.add("23 14.6 11.5 6 9.9 15.2 24 7.8 4.1 6 10.7 9.9 8.2 14.6 29.7 39.9 15 7.5 6.6 7.9 14.2 18.7 7.4 6.1 14.4 23.9 14.3 13.7 6.4 0.00 8.1 15 20.5 19 11.3 6.9 3.9 11 25.6 16.4 11 6.6 11.1 14.3 24.2 19.3 18.5 14.4 14.3 16.6");
        matrixDistance.add("26.7 14.1 12.9 9 13.9 20.4 28.4 11.3 10 9.9 15.1 13.9 14.2 19.1 34.2 44.5 20.7 12.8 10.2 6.5 11.3 22.3 11.9 10.9 18 26.9 17.9 19 11.8 6 0.00 10.8 18 16.6 9.3 9.8 9.8 17 30.1 20.8 15 10.1 12 14.3 23.3 20.5 21.5 18 18.3 21.8");
        matrixDistance.add("26.4 20.5 20.1 16.2 21.1 27.6 35.7 16.4 17.2 17.1 22.3 21.1 21.4 25.9 39.8 50.5 27.9 20.1 17.4 13.7 8.9 26.7 19.2 18.2 25.3 33.9 25.1 26.2 19.1 13.2 8.1 0.00 12.5 12.7 14.9 17.1 17.1 24.2 37.3 28 22.2 17.4 19 20.8 23 27 28.6 25.3 25.5 29");
        matrixDistance.add("36.3 18.5 19.3 18.5 23.5 29.9 39 25.6 23.1 21.1 25.3 23.5 27.2 34 48.9 59 34.1 25.5 20.8 15.9 9.7 35.9 26.9 22.4 24.7 31.9 24.6 29.4 24.3 19.5 16.2 12.8 0.00 8.7 13.3 18.9 23.3 29.7 40.6 31.4 24.5 19.7 18 18.5 18.8 24 26.4 24.7 27.9 31.6");
        matrixDistance.add("37.8 12.3 13.8 15 19.7 26.1 35.5 25.1 20.5 17.6 21.8 19.7 24.1 31.7 46.8 55.8 30.9 22.3 17.3 14 9.4 35.4 24.5 19 19.6 23.7 19.5 25.6 21.2 18.1 15.9 13.8 9.1 0.00 8.2 14.7 20.8 26.5 37.2 27.9 20.7 16.1 12.9 11 11.1 15.8 18.2 19.6 23.6 27.8");
        matrixDistance.add("32.8 7.5 7 7.1 12.1 18.5 27.6 17.3 12.4 9.7 13.9 12.1 15.8 23.4 38.6 47.6 22.7 14.1 9.4 5.9 11.5 28.3 16.5 11 12.3 20.6 12.3 18 12.9 10 9.4 16.2 14.4 10.3 0.00 7.1 12.7 18.3 29.3 20 13.1 8.3 5.6 7.4 17 14 15.2 12.3 16.5 20.2");
        matrixDistance.add("29.2 9.6 5.6 1.4 5.3 11.8 21.3 13.7 7.4 3.7 7.5 5.3 9.7 18.1 33.2 41.4 16.6 7.9 3 7.6 14.8 22.9 11.6 4.8 8.2 17.7 8.1 11.3 6.8 7.4 11.3 18.1 18.7 15.3 7.1 0.00 8 12.2 22.9 13.6 6.4 2 5.6 8.8 19.2 12.5 12.4 8.2 9.7 13.5");
        matrixDistance.add("22.5 15.7 12.6 7.1 10 15.1 23.5 7 2.5 6.5 10.8 10 6.6 12.5 27.6 37.9 13 6.7 7.3 10.6 16.9 17.4 5.5 6.5 14.5 24 14.4 13.6 5.9 5.4 10.9 17.7 23.2 21.2 12.9 8 0.00 9.4 25.1 15.9 11.1 7.5 12.2 15.5 25.3 20.2 18.6 14.5 14.4 16.5");
        matrixDistance.add("28.8 20.7 16.2 11.3 7.9 8.5 15.9 13.3 7.3 8.8 6.5 7.9 3.3 7.7 23.3 30.6 5.7 4.8 9.6 17.1 24.1 17 8.4 8.3 13.9 20 13.8 8.2 5.3 12.8 18.3 25.2 29.4 26.7 18.4 11.8 7.8 0.00 17.6 8.3 7.4 10.2 16.7 19.7 29.2 23.1 18 13.9 10.5 9.6");
        matrixDistance.add("44.2 30.7 25.7 21.7 16.9 10.7 1.3 29.1 22.8 19.8 16.1 16.9 19.1 22.1 35.2 31.9 18 19.5 19.9 27.4 34.6 30.8 24.3 19.8 20.5 21.8 19 12.1 19.1 26.6 30.5 37.3 39.7 37 28.7 22 23.7 17 0.00 10.1 16 20.4 26.7 29 36.8 30.1 25 20.5 14.7 9.5");
        matrixDistance.add("35.7 21.7 16.7 12.7 8 1.8 9.2 20.2 13.9 10.9 7.2 8 10.2 14.4 29.2 33.6 10.5 10.5 11 18.5 25.7 23.7 15.4 10.9 11.5 14.9 10.1 3.2 10.2 17.7 21.5 28.4 30.8 28.1 19.8 13.1 14.7 8.2 10.8 0.00 7.1 11.5 17.8 20.1 27.8 21.2 16.1 11.5 5.8 2.8");
        matrixDistance.add("31.8 15 10.5 6.2 1.2 5.4 15.2 16.3 9.3 5.7 1.2 1.2 6.6 13.7 29.4 36.5 11.6 6.1 5 12.7 19.9 21.9 12.4 5.7 7.6 12.9 7 4.9 5.6 12.2 16.3 23.2 24.5 21.6 13.4 6.5 10.6 7.3 16.8 7.5 0.00 4.9 11 14.1 23.5 16.9 11.7 7.6 3.4 7.1");
        matrixDistance.add("28 10.7 6.3 1.3 3.9 10.3 19.7 12.5 6.1 1.9 5.8 3.9 8 16.3 31.4 39.7 14.8 6.2 1.3 7.8 15.1 21.4 10.2 3.1 8.2 17.8 8.1 9.8 5.1 7.3 11.5 18.3 19.6 16.9 8.7 1.6 6.8 10.5 21.3 12.1 4.9 0.00 6.7 9.9 19.9 13.2 12.3 8.2 8.3 12");
        matrixDistance.add("31.7 5.6 1.8 4.9 8.5 14.9 24.5 16.6 11 7 10.6 8.5 12.9 21.3 36.4 44.6 19.7 11.1 6.3 7.9 15.1 26.3 15.1 8.1 7.2 16.1 7.1 14.4 10 9.6 12.6 19.5 17.9 13.4 5.1 4.6 11.4 15.4 26.1 16.8 9.6 5.3 0.00 4.8 15.2 9.7 10.7 7.2 11.7 16.5");
        matrixDistance.add("36.2 4.2 4.9 9.5 13.1 19 28.8 21.1 15.5 11.6 15.3 13.1 17.5 25.9 41 49.2 24.4 15.7 11 10.5 16.6 30.9 19.6 12.7 11.3 14.8 11.3 18.5 14.6 13.5 14.7 21.5 18.7 11.9 6.5 9.3 15.8 20 30.4 21.2 14.2 9.9 4.7 0.00 11 7.6 9.3 11.3 15.8 20.7");
        matrixDistance.add("46.1 13.3 15.2 19.9 22.4 26.3 36 30.9 25.4 21.7 24.6 22.4 27.5 35.9 51 59.1 34.2 25.5 21 19.9 19 40.9 29.4 22.8 17.6 16.7 18.2 25.8 24.5 23.3 23 23.4 18.5 10.8 15.8 19.6 25.7 29.8 37.7 28.4 23.5 19.9 15 11.1 0.00 7.1 12.5 17.6 22.7 28");
        matrixDistance.add("41 10.3 8.7 13.9 15.5 19.3 29.1 25.5 19.3 15.2 17.6 15.5 20.5 28.9 44 52.1 27.2 18.6 14.5 17 22.5 34.4 23.4 16.3 10.7 10.7 11.2 18.8 18 19.2 20.8 27.6 24.2 16.6 12.6 13.6 19.8 22.8 30.7 21.4 16.5 13.5 10.6 7.2 7.3 0.00 5.6 10.7 15.8 21");
        matrixDistance.add("39.7 12.3 9.9 13.4 11.1 14.9 24.7 24.2 17.2 13.5 13.3 11.1 16.1 24.5 39.7 47.7 22.8 14.2 12.6 18.3 24.6 30.8 20.5 13.5 6.3 7.2 6.8 14.4 13.6 19.4 22.8 29.7 26.3 18.8 14.6 13.1 18.5 18.4 26.3 17.1 12.2 12.5 11.8 8.5 12.1 5.4 0.00 6.3 11.4 16.7");
        matrixDistance.add("34.1 11.4 6.2 7.8 5.9 9.9 19.6 18.6 11.6 7.9 8.1 5.9 10.9 19.3 34.4 42.5 17.6 9 7 13 20.3 25.6 15.2 7.9 0.00 11.5 2.1 9.4 8.1 13.8 17.6 24.4 23.7 19.3 11 7.5 12.9 13.2 21.3 12 6.9 6.9 7.4 9.6 17.3 10.6 5.5 0.00 6.7 11.6");
        matrixDistance.add("35.1 17.1 11.9 9.6 4.5 4.1 13.9 19.6 12.7 9 4.5 4.5 9.9 16.2 31.9 37.4 12.5 9.5 8.4 16.1 23.3 25.3 15.7 9.1 6.4 10 4.8 3.8 9 15.6 19.7 26.5 27.8 24.5 16.2 9.9 13.9 9.8 15.5 6.2 3.5 8.3 13.1 15.2 22.7 16.1 10.9 6.4 0.00 5.8");
        matrixDistance.add("37 22.1 17 13.8 8.7 1.9 8.4 21.5 14.1 11.2 7.4 8.7 11 14.5 29.3 33.7 10.6 10.7 12.1 19.6 26.8 23.8 16.5 11.2 11.8 14.7 10.3 4 10.5 18 21.9 28.7 32 29.2 21 14.1 15.8 9.4 10 2.3 7.7 12.5 18.1 20.4 28.1 21.5 16.3 11.8 6.1 0.00");

        for (int i = 0; i < customerListSize; i++) {
            //距离矩阵
            String line = matrixDistance.get(i);
            String[] lineTokens = StringSplitUtils.splitBySpacesOrTabs(line.trim(), customerListSize);
            RoadLocation location = (RoadLocation) customerLocationList.get(i);
            Map<RoadLocation, Double> travelDistanceMap = new LinkedHashMap<>(customerListSize);
            for (int j = 0; j < customerListSize; j++) {
                double travelDistance = Double.parseDouble(lineTokens[j]);
                if (i == j) {
                    if (travelDistance != 0.0) {
                        throw new IllegalStateException("The travelDistance (" + travelDistance
                                + ") should be zero.");
                    }
                } else {
                    RoadLocation otherLocation = (RoadLocation) customerLocationList.get(j);
                    travelDistanceMap.put(otherLocation, travelDistance);
                }
            }
            location.setTravelDistanceMap(travelDistanceMap);
        }
    }
  • 构建个客户网点货量需求 (目前DEMO仅演示 capacity参数值 可根据业务需求 设置各网点客户volume和weight参数值)
    (0 0) 上海枢纽id :配送货物需求0
    (55 15) 翔殷路 :配送货物需求15
 public static void initDepotAndCustomerList(VehicleRoutingSolution solution, Map<Long, Location> locationMap) {
        //枢纽
        List<Depot> depotList = new ArrayList<>(customerListSize);
        //客户
        List<Customer> customerList = new ArrayList<>(customerListSize);
        List<String> demandList = new ArrayList<>();
        demandList.add("0 0");
        demandList.add("55 15");
        demandList.add("110 16");
        demandList.add("165 31");
        demandList.add("220 14");
        demandList.add("275 33");
        demandList.add("330 7");
        demandList.add("385 9");
        demandList.add("440 17");
        demandList.add("495 33");
        demandList.add("550 26");
        demandList.add("605 18");
        demandList.add("660 10");
        demandList.add("715 32");
        demandList.add("770 26");
        demandList.add("825 14");
        demandList.add("880 32");
        demandList.add("935 33");
        demandList.add("990 30");
        demandList.add("1045 25");
        demandList.add("1100 18");
        demandList.add("1155 26");
        demandList.add("1210 2");
        demandList.add("1265 25");
        demandList.add("1320 10");
        demandList.add("1375 3");
        demandList.add("1430 28");
        demandList.add("1485 9");
        demandList.add("1540 21");
        demandList.add("1595 7");
        demandList.add("1650 24");
        demandList.add("1705 1");
        demandList.add("1760 5");
        demandList.add("1815 19");
        demandList.add("1870 4");
        demandList.add("1925 9");
        demandList.add("1980 7");
        demandList.add("2035 16");
        demandList.add("2090 27");
        demandList.add("2145 15");
        demandList.add("2200 17");
        demandList.add("2255 20");
        demandList.add("2310 27");
        demandList.add("2365 33");
        demandList.add("2420 18");
        demandList.add("2475 31");
        demandList.add("2530 19");
        demandList.add("2585 24");
        demandList.add("2640 16");
        demandList.add("2695 32");
        for (int i = 0; i < customerListSize; i++) {
            String line = demandList.get(i);
            Boolean timewindowed = false;
            String[] lineTokens = StringSplitUtils.splitBySpacesOrTabs(line.trim(), timewindowed ? 5 : 2);
            long id = Long.parseLong(lineTokens[0]);
            int demand = Integer.parseInt(lineTokens[1]);
            if (demand == 0) {
                Depot depot = timewindowed ? new TimeWindowedDepot() : new Depot();
                depot.setId(id);
                Location location = locationMap.get(id);
                if (location == null) {
                    throw new IllegalArgumentException("此枢纽 (" + id
                            + ")尚未录入坐标 (" + location + ").");
                }
                depot.setLocation(location);
                depotList.add(depot);
            } else {
                Customer customer = timewindowed ? new TimeWindowedCustomer() : new Customer();
                customer.setId(id);
                Location location = locationMap.get(id);
                if (location == null) {
                    throw new IllegalArgumentException("此枢纽 (" + id
                            + ") 尚未录入坐标 (" + location + ").");
                }
                customer.setLocation(location);
                customer.setDemand(demand);
                // Notice that we leave the PlanningVariable properties on null
                customerList.add(customer);
            }
        }

        solution.setCustomerList(customerList);
        solution.setDepotList(depotList);
    }

  • 构建配送车辆
    目前自定10辆同规格配送车 capacity统一为125
  public static void initVehicleList(VehicleRoutingSolution solution, List<Depot> depotList) {
        Integer vehicleListSize = 10;
        Integer capacity = 125;
        List<Vehicle> vehicleList = new ArrayList<>(vehicleListSize);
        long id = 0;
        for (int i = 0; i < vehicleListSize; i++) {
            Vehicle vehicle = new Vehicle();
            vehicle.setId(id);
            id++;
            vehicle.setCapacity(capacity);
            // Round robin the vehicles to a depot if there are multiple depots 1 2 多枢纽车辆均分
            vehicle.setDepot(depotList.get(i % depotList.size()));
            vehicleList.add(vehicle);
        }
        solution.setVehicleList(vehicleList);
    }
 public static void main(String[] args) {
        Integer customerListSize = 50;
        List<Location> customerLocationList = new ArrayList<>(customerListSize);
        Map<Long, Location> locationMap = InitSolution3Data.initLocations(customerLocationList);
        InitSolution3Data.initMatrixDistance(customerLocationList);
        System.out.println(locationMap);
    }
  • 构建求解引擎 —>>>问题求解结果输出
  /**
     * 初始化引擎
     *
     * @return
     */
    public void init() {
        //初始化求解问题
        VehicleRoutingSolution solution = InitSolutionData.initBaseInfo();
        //初始化求解器---公共变量 public
        SolverFactory<VehicleRoutingSolution> solverFactory = SolverFactory.createFromXmlResource(SOLVER_CONFIG);
        Solver<VehicleRoutingSolution> solver = solverFactory.buildSolver();
        ScoreDirectorFactory<VehicleRoutingSolution> scoreDirectorFactory = solver.getScoreDirectorFactory();
        ScoreDirector<VehicleRoutingSolution> scoreDirector = scoreDirectorFactory.buildScoreDirector();
        //初始化求解器---局部变量 private
        SolutionBusiness<VehicleRoutingSolution> solutionBusiness = new SolutionBusiness<VehicleRoutingSolution>();
        solutionBusiness.setSolver(solver);
        solutionBusiness.setScoreDirector(scoreDirector);
        solutionBusiness.setSolution(solution);
        //开始求解
        VehicleRoutingSolution solveResult = solutionBusiness.solve(solution);
        getSolutionView(solveResult);
    }
  • 多种算法组合计算结果对比(算法通过)
    通过配置文件变更各阶段算法和终止条件 通过测试对比最优的算法配置
<?xml version="1.0" encoding="UTF-8"?>
<solver>
  <!--<environmentMode>FULL_ASSERT</environmentMode>--><!-- To slowly prove there are no bugs in this code -->
  <!--<moveThreadCount>AUTO</moveThreadCount>--><!-- To solve faster by saturating multiple CPU cores -->

  <solutionClass>com.dag.schedule.vehicleRouting.domain.VehicleRoutingSolution</solutionClass>
  <entityClass>com.dag.schedule.vehicleRouting.domain.Standstill</entityClass>
  <entityClass>com.dag.schedule.vehicleRouting.domain.Customer</entityClass>
  <entityClass>com.dag.schedule.vehicleRouting.domain.timewindowed.TimeWindowedCustomer</entityClass>

  <scoreDirectorFactory>
    <!--<easyScoreCalculatorClass>org.optaplanner.examples.vehicleRouting.solver.score.VehicleRoutingEasyScoreCalculator</easyScoreCalculatorClass>-->
    <incrementalScoreCalculatorClass>com.dag.schedule.vehicleRouting.solver.score.VehicleRoutingIncrementalScoreCalculator</incrementalScoreCalculatorClass>
    <!--<scoreDrl>org/optaplanner/examples/vehicleRouting/solver/vehicleRoutingScoreRules.drl</scoreDrl>-->
    <!--<assertionScoreDirectorFactory>-->
    <!--<easyScoreCalculatorClass>org.optaplanner.examples.vehicleRouting.solver.score.VehicleRoutingEasyScoreCalculator</easyScoreCalculatorClass>-->
    <!--</assertionScoreDirectorFactory>-->
    <initializingScoreTrend>ONLY_DOWN</initializingScoreTrend>
  </scoreDirectorFactory>

  <termination>
     **配置计算终止条件如果得分连续30秒没有优化自动结束任务**
    <unimprovedSecondsSpentLimit>30</unimprovedSecondsSpentLimit>
  </termination>
  
**以下是算法配置**
  <constructionHeuristic>
    <constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
  </constructionHeuristic>
  <localSearch>
    <unionMoveSelector>
      <changeMoveSelector>
        <entitySelector id="entitySelector1"/>
        <valueSelector>
          <nearbySelection>
            <originEntitySelector mimicSelectorRef="entitySelector1"/>
            <nearbyDistanceMeterClass>com.dag.schedule.vehicleRouting.domain.solver.nearby.CustomerNearbyDistanceMeter</nearbyDistanceMeterClass>
            <parabolicDistributionSizeMaximum>1000</parabolicDistributionSizeMaximum>
          </nearbySelection>
        </valueSelector>
      </changeMoveSelector>
      <swapMoveSelector>
        <entitySelector id="entitySelector2"/>
        <secondaryEntitySelector>
          <nearbySelection>
            <originEntitySelector mimicSelectorRef="entitySelector2"/>
            <nearbyDistanceMeterClass>com.dag.schedule.vehicleRouting.domain.solver.nearby.CustomerNearbyDistanceMeter</nearbyDistanceMeterClass>
            <parabolicDistributionSizeMaximum>1000</parabolicDistributionSizeMaximum>
          </nearbySelection>
        </secondaryEntitySelector>
      </swapMoveSelector>
      <tailChainSwapMoveSelector>
        <entitySelector id="entitySelector3"/>
        <valueSelector>
          <nearbySelection>
            <originEntitySelector mimicSelectorRef="entitySelector3"/>
            <nearbyDistanceMeterClass>com.dag.schedule.vehicleRouting.domain.solver.nearby.CustomerNearbyDistanceMeter</nearbyDistanceMeterClass>
            <parabolicDistributionSizeMaximum>1000</parabolicDistributionSizeMaximum>
          </nearbySelection>
        </valueSelector>
      </tailChainSwapMoveSelector>
    </unionMoveSelector>

    <!--<acceptor>-->
      <!--<entityTabuSize>9</entityTabuSize>-->
    <!--</acceptor>-->
    <!--<forager>-->
      <!--<acceptedCountLimit>2000</acceptedCountLimit>-->
    <!--</forager>-->

    <acceptor>
      <lateAcceptanceSize>200</lateAcceptanceSize>
    </acceptor>
    <forager>
      <acceptedCountLimit>1</acceptedCountLimit>
    </forager>

  </localSearch>
</solver>


 1. 官方demo问题求解结果

[vehicle--0  (125)]配送线路:【START】BRUSSEL--->SOMZEE(20)--->MONT_NAM.(7)--->AVE-ET-AUFFE(16)--->POUPEHAN(9)--->SELANGE(15)--->VAUX(18)--->TAILLES(27)--->EVELETTE(10)--->【END】完成配送:122 单量:8
[vehicle--1  (125)]配送线路:【START】BRUSSEL--->BAVIKHOVE(31)--->KOMEN(2)--->ELVERDINGE(18)--->RENINGE(7)--->BULSKAMP(9)--->LISSEWEGE(3)--->DAMME(33)--->WETTEREN(16)--->【END】完成配送:119 单量:8
[vehicle--2  (125)]配送线路:【START】BRUSSEL--->GELINDEN(26)--->VILLERS(31)--->BLERET(33)--->WARNANT(24)--->【END】完成配送:114 单量:4
[vehicle--3  (125)]配送线路:【START】BRUSSEL--->SAINT(27)--->ORET(19)--->BOURLERS(7)--->BERSILLIES-L'ABBAYE(14)--->DONSTIENNES(26)--->FONTAINE-L'EVEQUE(32)--->【END】完成配送:125 单量:6
[vehicle--5  (125)]配送线路:【START】BRUSSEL--->SINT(17)--->GONDREGNIES(14)--->JURBISE(26)--->NAAST(24)--->HEPPIGNIES(30)--->LES_BONS_VILLERS(10)--->【END】完成配送:121 单量:6
[vehicle--7  (125)]配送线路:【START】BRUSSEL--->PEPINGEN(4)--->OLLIGNIES(5)--->MAFFLE(28)--->CHIEVRES(17)--->MAULDE(9)--->GUIGNIES(32)--->LANDEGEM(25)--->【END】完成配送:120 单量:7
[vehicle--8  (125)]配送线路:【START】BRUSSEL--->NIEUWKERKEN(1)--->MERKSPLAS(21)--->ROSMEER(16)--->XHENDELESSE(32)--->TILFF(33)--->ANTHISNES(15)--->【END】完成配送:118 单量:6
[vehicle--9  (125)]配送线路:【START】BRUSSEL--->VOSSEM(19)--->HOFSTADE_BT.(25)--->HUMBEEK(18)--->HAREN_BRUSSEL(33)--->【END】完成配送:95 单量:4

 2. tabusearch 算法

TS     best score (0hard/-668700soft), score calculation speed (300446/sec), phase total (2), environment mode (REPRODUCIBLE).
[vehicle--0  (125)]配送线路:【START】上海枢纽--->世纪大道(10)--->世纪大道(24)--->锦绣路(28)--->陆家浜路(18)--->西藏南路(17)--->世博会博物馆(26)--->【END】完成配送:123 单量:6
[vehicle--2  (125)]配送线路:【START】上海枢纽--->常熟路(21)--->衡山路(33)--->徐家汇(10)--->漕溪路(16)--->锦江乐园(32)--->【END】完成配送:112 单量:5
[vehicle--3  (125)]配送线路:【START】上海枢纽--->长清路(9)--->杨思(33)--->灵岩南路(32)--->江月路(7)--->联航路(27)--->东方体育中心(15)--->威宁路(2)--->【END】完成配送:125 单量:7
[vehicle--4  (125)]配送线路:【START】上海枢纽--->丰庄(9)--->隆德路(17)--->自然博物馆(33)--->新闸路(30)--->南京西路(25)--->金沙江路(7)--->【END】完成配送:121 单量:6
[vehicle--5  (125)]配送线路:【START】上海枢纽--->陆家浜路(14)--->高科西路(16)--->金科路(3)--->云山路(19)--->东靖路(31)--->外高桥保税区北(18)--->淞滨路(19)--->江杨北路(5)--->【END】完成配送:125 单量:8
[vehicle--6  (125)]配送线路:【START】上海枢纽--->徐泾东(26)--->星中路(32)--->醉白池(14)--->佘山(26)--->【END】完成配送:98 单量:4
[vehicle--7  (125)]配送线路:【START】上海枢纽--->岚皋路(7)--->鞍山新村(16)--->四平路(27)--->黄兴公园(33)--->翔殷路(15)--->江湾镇(4)--->呼兰路(18)--->顾村公园(1)--->【END】完成配送:121 单量:8
[vehicle--8  (125)]配送线路:【START】上海枢纽--->曲阜路(20)--->宝山路(9)--->中兴路(31)--->上海马戏城(25)--->场中路(24)--->【END】完成配送:109 单量:5

3. tabusearch + nearby 算法
TS+NEARBY  best score (0hard/-676600soft), score calculation speed (349799/sec)
[vehicle--0  (125)]配送线路:【START】上海枢纽--->世纪大道(10)--->世纪大道(24)--->锦绣路(28)--->金科路(3)--->云山路(19)--->宝山路(9)--->中兴路(31)--->【END】完成配送:124 单量:7
[vehicle--1  (125)]配送线路:【START】上海枢纽--->四平路(27)--->鞍山新村(16)--->黄兴公园(33)--->翔殷路(15)--->江湾镇(4)--->场中路(24)--->顾村公园(1)--->【END】完成配送:120 单量:7
[vehicle--3  (125)]配送线路:【START】上海枢纽--->徐家汇(10)--->长清路(9)--->灵岩南路(32)--->江月路(7)--->联航路(27)--->醉白池(14)--->佘山(26)--->【END】完成配送:125 单量:7
[vehicle--4  (125)]配送线路:【START】上海枢纽--->丰庄(9)--->隆德路(17)--->新闸路(30)--->曲阜路(20)--->自然博物馆(33)--->金沙江路(7)--->【END】完成配送:116 单量:6
[vehicle--5  (125)]配送线路:【START】上海枢纽--->岚皋路(7)--->上海马戏城(25)--->呼兰路(18)--->江杨北路(5)--->淞滨路(19)--->外高桥保税区北(18)--->东靖路(31)--->【END】完成配送:123 单量:7
[vehicle--6  (125)]配送线路:【START】上海枢纽--->世博会博物馆(26)--->西藏南路(17)--->高科西路(16)--->杨思(33)--->东方体育中心(15)--->漕溪路(16)--->威宁路(2)--->【END】完成配送:125 单量:7
[vehicle--7  (125)]配送线路:【START】上海枢纽--->徐泾东(26)--->星中路(32)--->锦江乐园(32)--->【END】完成配送:90 单量:3
[vehicle--9  (125)]配送线路:【START】上海枢纽--->衡山路(33)--->常熟路(21)--->陆家浜路(14)--->陆家浜路(18)--->南京西路(25)--->【END】完成配送:111 单量:5

4. lateacceptance+ nearby 算法
LA+NEARBY  best score (0hard/-669000soft), score calculation speed (256233/sec), phase total (2), environment mode (REPRODUCIBLE).
[vehicle--0  (125)]配送线路:【START】上海枢纽--->东方体育中心(15)--->灵岩南路(32)--->江月路(7)--->联航路(27)--->醉白池(14)--->佘山(26)--->【END】完成配送:121 单量:6
[vehicle--1  (125)]配送线路:【START】上海枢纽--->陆家浜路(14)--->高科西路(16)--->金科路(3)--->云山路(19)--->东靖路(31)--->外高桥保税区北(18)--->淞滨路(19)--->江杨北路(5)--->【END】完成配送:125 单量:8
[vehicle--2  (125)]配送线路:【START】上海枢纽--->世纪大道(10)--->世纪大道(24)--->锦绣路(28)--->长清路(9)--->杨思(33)--->漕溪路(16)--->威宁路(2)--->【END】完成配送:122 单量:7
[vehicle--4  (125)]配送线路:【START】上海枢纽--->鞍山新村(16)--->四平路(27)--->黄兴公园(33)--->翔殷路(15)--->江湾镇(4)--->场中路(24)--->【END】完成配送:119 单量:6
[vehicle--6  (125)]配送线路:【START】上海枢纽--->丰庄(9)--->隆德路(17)--->南京西路(25)--->自然博物馆(33)--->新闸路(30)--->金沙江路(7)--->【END】完成配送:121 单量:6
[vehicle--7  (125)]配送线路:【START】上海枢纽--->岚皋路(7)--->宝山路(9)--->曲阜路(20)--->中兴路(31)--->上海马戏城(25)--->呼兰路(18)--->顾村公园(1)--->【END】完成配送:111 单量:7
[vehicle--8  (125)]配送线路:【START】上海枢纽--->徐泾东(26)--->星中路(32)--->锦江乐园(32)--->【END】完成配送:90 单量:3
[vehicle--9  (125)]配送线路:【START】上海枢纽--->徐家汇(10)--->陆家浜路(18)--->西藏南路(17)--->世博会博物馆(26)--->衡山路(33)--->常熟路(21)--->【END】完成配送:125 单量:6

猜你喜欢

转载自blog.csdn.net/sinat_41359797/article/details/85042569
今日推荐