@jie31best, i am really sorry to bother you again, but i am really stuck. I am really trying. Thanks for you time.

It seems that there is something wrong with my implementation. I have been trying and trying but something is not right.

My distanceCost and timeCost both have a value of 1. When i run my work without any penalties, i get the following results:

After that i set a penalty on job 4 with a value of 10, the results changes to this:

First, you can see that the total cost is not aligned with the total costs for each route (19 + 15 != 44).

Second, the end time in the first route is penalized, while in my code i have ignored penalizing it.

Third, the pickup arrival time for job 3 is more than its delivery arrival.

Fourth, in the second route, the arrival of the endtime is completely wrong.

I also tried setting penalty on job1 and job4 each with an amount of 4 and 10 respectively. I got the following results:

First, you can see that the arrival time for job3 is 23 and then its delivery is 22, i am not sure how could this happen.

Second, the penalization of job4 is not correct.

Third, the end time for the first route is not correct also.

I am really not sure where did my implementation went wrong.

I have implemented a SoftActivtyConstraint, here is my code:

```
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct,TourActivity nextAct,double prevActDepTime) {
// Get and check job order time
double orderTime = iFacts.getJob().getOrderTime();
if (orderTime == 0) {
return 0;
}
double totalCost = 0;
if (newAct instanceof DeliverShipment) {
double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocation(),
newAct.getLocation(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double endTimeAtNewAct = Math.max(arrTimeAtNewAct, newAct.getTheoreticalEarliestOperationStartTime())
+ newAct.getOperationTime();
newAct.setArrTime(arrTimeAtNewAct);
newAct.setEndTime(endTimeAtNewAct);
totalCost = rewardAndPenatlies(newAct, arrTimeAtNewAct);
// Update arrival times & penalties for downstream activities
boolean start = false;
for (TourActivity tourActivity : iFacts.getRoute().getActivities()) {
if (!start && !tourActivity.equals(nextAct))
continue;
start = true;
// Memorize values
prevAct = newAct;
newAct = tourActivity;
prevActDepTime = endTimeAtNewAct;
// Get arrival & end time
arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocation(),newAct.getLocation(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
endTimeAtNewAct = Math.max(arrTimeAtNewAct, newAct.getTheoreticalEarliestOperationStartTime())+ newAct.getOperationTime();
// Set new calculated times
newAct.setArrTime(arrTimeAtNewAct);
newAct.setEndTime(endTimeAtNewAct);
// Set cost
if (tourActivity instanceof DeliverShipment)
totalCost += rewardAndPenatlies(tourActivity, arrTimeAtNewAct);
}
}
//Check end activity
if(nextAct instanceof End){
double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocation(),
newAct.getLocation(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double endTimeAtNewAct = Math.max(arrTimeAtNewAct, newAct.getTheoreticalEarliestOperationStartTime())
+ newAct.getOperationTime();
double arrTimeAtNextAct = endTimeAtNewAct + routingCosts.getTransportTime(newAct.getLocation(),
nextAct.getLocation(), endTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double endTimeAtNextAct = Math.max(endTimeAtNewAct, nextAct.getTheoreticalEarliestOperationStartTime())
+ nextAct.getOperationTime();
nextAct.setArrTime(arrTimeAtNextAct);
nextAct.setEndTime(endTimeAtNextAct);
}
return totalCost;
}
public static double rewardAndPenatlies(TourActivity tourActivity, double arrivalTime) {
if (tourActivity instanceof DeliverShipment) {
// If order time is not used
AbstractJob job = (AbstractJob) ((DeliverShipment) tourActivity).getJob();
double allowedOrderTime = job.getAllowedOrderTime();
double orderTime = job.getOrderTime();
if (orderTime == 0 || allowedOrderTime == 0) {
return 0;
}
// Get delivery duration from order time
double deliveryOrderTime = Math.max(0, arrivalTime - orderTime);
// Check if delivery duration time exceeds the allowed time
if (deliveryOrderTime <= allowedOrderTime)
return 0; // Reward
else
return job.getPenaltyOrderTime(); // Penalty
}
return 0;
}`
```

Also i have implemented an ActivtyCost, here is my code:

```
public double getActivityCost(TourActivity tourAct, double arrivalTime, Driver driver, Vehicle vehicle) {
if (arrivalTime == Time.TOURSTART || arrivalTime == Time.UNDEFINED) {
return 0;
}
double waiting = vehicle.getType().getVehicleCostParams().perWaitingTimeUnit
* Math.max(0., tourAct.getTheoreticalEarliestOperationStartTime() - arrivalTime);
double servicing = vehicle.getType().getVehicleCostParams().perServiceTimeUnit
* getActivityDuration(tourAct, arrivalTime, driver, vehicle);
// Custom constraints
// OrderTime
double orderTimePenalty;
if(tourAct instanceof End)
orderTimePenalty = 0;
else
orderTimePenalty = OrderTimeConstraint.rewardAndPenatlies(tourAct, arrivalTime);
return waiting + servicing + orderTimePenalty;
}
```

Finally the ObjectiveFunction, here is my code:

```
SolutionCostCalculator costCalculator = new SolutionCostCalculator() {
@Override
public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.;
for(VehicleRoute route : solution.getRoutes()){
costs+=route.getVehicle().getType().getVehicleCostParams().fix;
costs+=stateManager.getRouteState(route, InternalStates.COSTS, Double.class);
for(TourActivity tourActivity : route.getActivities())
costs+=OrderTimeConstraint.rewardAndPenatlies(tourActivity, tourActivity.getArrTime());
}
return costs;
}
};
```

Thank you again and sorry for the trouble.