1

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

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

这个错误是有道理的。由于没有实际指定位置,因此无法绘制任何内容;我们只指定了位置之间的相对距离/时间。我必须使用自定义矩阵,因为我在纬度/经度中工作并且需要点之间的真实道路距离。但是,随着我的问题不断扩大,只需为每个位置分配其纬度/经度并生成将这些点视为笛卡尔坐标的图形,这对我来说将非常有用。集水区并不大,所以它仍然可以让我快速查看解决方案是否有意义,而无需进行更精细的绘图。所以我的问题是,是否有一种简单的方法可以让 jsprit 使用自定义距离/时间矩阵来解决问题,但为了绘图而将坐标分配给位置?好像想不通

编辑:即使 Stefan 提出了更改,我也花了很长时间来解决这个问题。如果不更改基本代码,我无法找到一种方法来做到这一点,我不希望这对我已经工作的内容造成连锁问题。

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

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

然后问题来了,当我希望创建一个服务时,我被当前代码强制定义一个新位置(位置只接受一个新实例):

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

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

继续前进,我考虑将位置直接添加到 VehicleRoutingProblem.Builder 中。请注意,向构建器添加位置需要将其定义为“addLocation(String LocationID, Coordinate coordinate),因此它不会显式采用预定义的位置;它们必须在构建器中定义。如下所示:

    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,因此打印的答案仍然正确。

4

1 回答 1

1

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

编辑:可以使用位置工厂和构建器定义位置。三个工厂之一的工作如下:

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

builder 更灵活,但不如 factory 方便,工作方式如下:

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 位置,这可能会使您的绘图更具吸引力。

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

于 2015-07-07T13:24:31.580 回答