使用自定义距离/时间矩阵时绘制解决方案

时间:2015-07-07 11:29:43

标签: jsprit

我正在开发一个以this示例代码为核心的项目;使用自定义距离/时间矩阵来解决路由问题。算法似乎工作得很好,但我找不到在图表中查看输出的方法。只运行示例代码而不进行任何修改会导致:

2015-07-07 11:56:33,354 [main] WARN jsprit.analysis.toolbox.Plotter - 无法绘制vrp,因为coord缺失

此错误有意义。没有任何东西可以绘制,因为实际上没有指定位置;我们只指定了位置之间的相对距离/时间。我必须使用自定义矩阵,因为我在lat / long工作并且需要点之间的实际道路距离。然而,随着我的问题扩展,我只需要为每个位置分配其纬度/经度并生成一个图形来处理这些点,就好像它们是笛卡尔坐标一样。集水区域不是很大,所以它仍然可以让我快速查看解决方案是否有意义,而无需做更详细的情节。所以我的问题是,是否有一种简单的方法可以让jsprit使用自定义距离/时间矩阵来解决问题,但是为了绘图而为这些位置分配坐标?我提前感谢,我似乎无法弄明白。

编辑:我花了很长时间在这方面工作无济于事,即使是Stefan提议的更改。我没有办法在不改变基本代码的情况下做到这一点,我不希望这会导致我已经工作的连锁问题。

建立一个位置很好,虽然它与建议的代码略有不同:

Location.Builder.newInstance().setId("0").setCoordinate(Coordinate.newInstance(10.0, 10.0)).build();

然后出现问题,当我想创建一个服务时,我被当前代码强制定义一个新位置(Location只接受newInstance):

Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(Location.newInstance(6.0, 1.0)).build();

我找不到现有的方法来简单地说服务位于预先定义的位置。

接下来,我考虑将位置直接添加到VehicleRoutingProblem.Builder中。请注意,向构建器添加位置需要将其定义为" addLocation(String LocationID,Coordinate coordinate),因此它不会明确地采用预定义的位置;它们必须在Builder中定义。这看起来如下:

    VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 5).setCostPerDistance(1).setCostPerTime(2).build();
    VehicleImpl vehicle = VehicleImpl.Builder.newInstance("vehicle")
            .setStartLocation(Location.newInstance("0")).setType(type).build();

    Service s1 = Service.Builder.newInstance("1").addSizeDimension(0, 1).setLocation(Location.newInstance("1")).build();
    Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocation(Location.newInstance("2")).build();
    Service s3 = Service.Builder.newInstance("3").addSizeDimension(0, 1).setLocation(Location.newInstance("3")).build();        

    //define a matrix-builder building an asymmetric matrix
    VehicleRoutingTransportCostsMatrix.Builder costMatrixBuilder = VehicleRoutingTransportCostsMatrix.Builder.newInstance(true);
    costMatrixBuilder.addTransportDistance("0", "1", 19.13);
    costMatrixBuilder.addTransportDistance("0", "2", 18.56);
    costMatrixBuilder.addTransportDistance("0", "3", 21.68);
    costMatrixBuilder.addTransportDistance("1", "0", 15.91);
    costMatrixBuilder.addTransportDistance("1", "2", 15.01);
    costMatrixBuilder.addTransportDistance("1", "3", 11.45);
    costMatrixBuilder.addTransportDistance("2", "0", 19.42);
    costMatrixBuilder.addTransportDistance("2", "1", 12.54);
    costMatrixBuilder.addTransportDistance("2", "3", 11.13);
    costMatrixBuilder.addTransportDistance("3", "0", 25.75);
    costMatrixBuilder.addTransportDistance("3", "1", 9.94);
    costMatrixBuilder.addTransportDistance("3", "2", 11.24);

    costMatrixBuilder.addTransportTime("0", "1", 12);
    costMatrixBuilder.addTransportTime("0", "2", 11);
    costMatrixBuilder.addTransportTime("0", "3", 15);
    costMatrixBuilder.addTransportTime("1", "0", 10);
    costMatrixBuilder.addTransportTime("1", "2", 10);
    costMatrixBuilder.addTransportTime("1", "3", 10);
    costMatrixBuilder.addTransportTime("2", "0", 15);
    costMatrixBuilder.addTransportTime("2", "1", 9);
    costMatrixBuilder.addTransportTime("2", "3", 10);
    costMatrixBuilder.addTransportTime("3", "0", 17);
    costMatrixBuilder.addTransportTime("3", "1", 13);
    costMatrixBuilder.addTransportTime("3", "2", 10);

    VehicleRoutingTransportCosts costMatrix = costMatrixBuilder.build();

    VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().setFleetSize(FleetSize.FINITE).setRoutingCost(costMatrix)
            .addVehicle(vehicle).addJob(s1).addJob(s2).addJob(s3)
            .addLocation("0", Coordinate.newInstance(1.0, 1.0)).addLocation("1", Coordinate.newInstance(9.0, 2.0))
            .addLocation("2", Coordinate.newInstance(5.0, 4.0)).addLocation("3", Coordinate.newInstance(4.0, 8.0))
            .addLocation("4", Coordinate.newInstance(3.0, 7.0)).build();`

运行正常。但是,它仍然不会绘制,因为它不会使位置索引与绘制它们的能力之间建立关联。但是,我可以确认(按照要求)解算器仅使用预定义的costMatrix,因此打印的答案仍然正确。

1 个答案:

答案 0 :(得分:1)

您只需将lon / lat指定给您的位置即可。如果您设置自己的成本矩阵,算法应该只考虑成本矩阵,即坐标应该对算法没有影响(如果有,请告诉我)。但是,您应该能够绘制它,即将坐标视为笛卡尔坐标。

编辑:可以使用位置工厂和构建器定义位置。 3家工厂中的一家如下:

Location location = Location.newInstance(10,12);

构建器更灵活但不如工厂方便,并且工作方式如下:

Location location = Location.Builder.newInstance().setId("1").setIndex(1).setCoordinate(Coordinate.newInstance(10,12).build();

您可以通过以下方式创建地点,并始终可以将这些地点分配给此类车辆和服务:

Service service = Service.Builder.newInstance("s1").setLocation(location).build();

和类似的车辆。如果您需要成本矩阵的位置ID和绘图坐标,请指定具有id和坐标的位置(请参见上文)...并且不要手动将位置添加到问题构建器。请注意,您需要为您的车辆和服务进行此操作。

你还可以做的是扩展绘图仪,使它可以将lon / lat投影到任何首选投影,并将你的扩展贡献给jsprit :)。这让我想到了另一个解决方案,你可以随时将lon / lat投影到你选择的投影上,然后将这些投影坐标分配给你的jsprit位置,这可能会使你的情节更具吸引力。

编辑: 顺便说一句:如果我是你,我会使用基于indeces而不是id的FastVehicleRoutingCostMatrix。顾名思义,它只是更快,因为它使用数组而不是地图。