[英]Can you help me with my Clarke and Wright algorithm implementation?
I am trying to implement the Clarke and Wright algorithm to construct an initial VRP solution.我正在尝试实施克拉克和赖特算法来构建初始 VRP 解决方案。 It seems to run properly but for some reason the solution's quality I get is not the expected one.
它似乎运行正常,但由于某种原因,我得到的解决方案的质量不是预期的。 For a description of the algorithm see here
有关算法的描述,请参见 此处
Here's my code to compute the savings element:这是我计算储蓄元素的代码:
private void computeSavingsElements() {
for(int i = 0; i<vrp.getDimension(); i++) {
for(int j = 0; j < i; j++) {
double savingValue = vrp.distance(i, 0) + vrp.distance(0, j) - lamda * vrp.distance(i, j);
SavingsElement savingElement = new SavingsElement (i,j, savingValue);
savingsElements.add(savingElement);
}
}
Collections.sort(savingsElements); // sort in ascending order
Collections.reverse(savingsElements); // but we need descending order
}
The method to construct the solution:构造解的方法:
private void constructSolution() {
List<VRPNode> nodes = this.vrp.getNodesList();
VRPNode depot = this.vrp.getDepot();
double vehicleCapacity = this.vrp.getVehicleCapacity();
VRPSolution solution = new VRPSolution(vehicleCapacity, depot);
/*
* In the initial solution, each vehicle serves exactly one customer
*/
for (VRPNode customer:nodes) {
if (customer.getId()!=0) { // if not depot
VRPRoute route = new VRPRoute(vehicleCapacity, depot);
route.addCustomer(customer);
solution.addRoute(route);
route = null; // eliminate obsolete reference to free resources
}
}
//System.out.println("INITIAL SOLUTION: \n"+solution.toString());
int mergesCounter=0;
for (SavingsElement savingElement : this.savingsElements) {
if (savingElement.getSavingValue() > 0) { // If serving customers consecutively in a route is profitable
VRPNode i = this.vrp.getNode(savingElement.getNodeId1());
VRPNode j = this.vrp.getNode(savingElement.getNodeId2());
VRPRoute route1 = solution.routeWhereTheCustomerIsTheLastOne(i);
VRPRoute route2 = solution.routeWhereTheCustomerIsTheFirstOne(j);
if ((route1!=null) & (route2!=null)) {
if (route1.getDemand() + route2.getDemand() <= this.vrp.getVehicleCapacity()) { // if merge is feasible
/*
* Merge the two routes
*/
solution.mergeRoutes(route1, route2);
mergesCounter++;
}
}
}
}
//System.out.println("\n\nAfter "+mergesCounter+" Merges"+"\n"+solution.toString());
this.solutionConstructed = solution;
}
And for the route merges:对于路线合并:
public void mergeRoutes(VRPRoute a, VRPRoute b) {
/*
* Provided that feasibility check has already been performed
*/
List<VRPNode> customersFromRouteA = new LinkedList<VRPNode>(a.getCustomersInRoute());
List<VRPNode> customersFromRouteB = new LinkedList<VRPNode>(b.getCustomersInRoute());
/*
* Remove the old routes
*/
solutionRoutes.remove(a);
solutionRoutes.remove(b);
/*
* Construct a new merged route
*/
VRPRoute mergedRoute = new VRPRoute(vehicleCapacity,depot);
/*
* The new route has to serve all the customers
* both from route a and b
*/
for (VRPNode customerFromA: customersFromRouteA) {
mergedRoute.addCustomer(customerFromA);
}
for (VRPNode customerFromB: customersFromRouteB) {
mergedRoute.addCustomer(customerFromB);
}
addRoute(mergedRoute);
evaluateSolutionCost();
}
It seems to compute the savings correctly and to merge the route as it should.它似乎正确计算了节省并按应有的方式合并了路线。 But the constructed solution's cost is too much.
但是构建的解决方案的成本太高了。 For example in a given instance i get 1220 while it should be 820.
例如,在给定的实例中,我得到 1220,而它应该是 820。
One apparent issue is that your code only considers joining route j after route i when j < i .一个明显的问题是您的代码仅在j < i时考虑在路由i之后加入路由j 。 You should also consider joining them the other way around - in other words, in the inner loop in computeSavingsElements j should go up to the number of customer nodes (
vrp.getDimension()
).您还应该考虑以相反的方式加入它们 - 换句话说,在 computeSavingsElements 的内部循环中, j应该达到客户节点的数量 (
vrp.getDimension()
)。
Of course it's hard to tell if there are bugs in the parts of the code you are not showing, eg is the array routeWhereTheCustomerIsTheLastOne
properly updated?当然,很难判断您未显示的代码部分是否存在错误,例如数组
routeWhereTheCustomerIsTheLastOne
是否已正确更新?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.