我正在做一个项目,使用这个示例代码为核心;使用自定义距离/时间矩阵来解决路由问题。该算法似乎工作完美,但我无法找到一种方式来查看输出的图表。只运行示例代码而不做任何修改,结果是:
2015-07-07 11:56:33,354 [main]警告jsprit.analysis.toolbox.Plotter -无法绘制vrp,因为缺少coord
这个错误是有意义的。没有任何东西可以绘制,因为没有实际指定位置;我们只指定了位置之间的相对距离/时间。我必须使用自定义矩阵,因为我在后期/长期工作,需要点之间的实际道路距离。然而,当我的问题扩大时,对我来说,简单地为每个位置分配它的纬度/长度,并制作一个图来处理这些点,就好像它们是笛卡尔坐标一样,这将是非常有用的。集水区不是很大,所以它仍然可以让我快速看到一个解决方案是否有意义,而无需制作更复杂的情节。所以我的问题是,是否有一个简单的方法,让jsprit来解决使用自定义距离/时间矩阵的问题,但分配坐标的位置为绘图的目的?我好像想不明白,提前谢谢你了。
编辑:我已经花了很长时间在这个工作没有任何效果,即使从斯特凡提出的变化。我找不到一种不改变基本代码的方法,我不希望这对我已经工作的东西造成连锁问题。
创建一个位置是可以的,尽管它与建议的代码略有不同:
Location.Builder.newInstance().setId("0").setCoordinate(Coordinate.newInstance(10.0, 10.0)).build();
问题来了,当我想创建一个服务时,我被当前代码强制定义一个新的位置(位置只接受一个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)",因此它不会显式地使用预定义的位置;它们必须在生成器中定义。如下所示:
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,因此打印的答案仍然是正确的。
您可以直接为您的位置分配lon/lat。如果你自己设置了代价矩阵,算法应该只考虑代价矩阵,即坐标应该对算法没有影响(如果有,请告诉我)。但是,您应该能够绘制它,即将坐标视为笛卡尔坐标。
编辑:位置可以通过位置工厂和生成器来定义。三家工厂之一的工作方式如下:
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:)。这给我带来了另一个解决方案,你总是可以将经纬度投影到你选择的投影,然后将这些投影坐标分配到你的jsprit位置,这可能会使你的情节更有吸引力。
编辑:顺便说一句:如果我是你,我会使用FastVehicleRoutingCostMatrix,这是基于索引而不是id。顾名思义,它只是更快,因为它使用数组而不是映射。