Skip to content

Commit

Permalink
Small fix on the initial fleet-size bound and repair operator
Browse files Browse the repository at this point in the history
The XML set, recently proposed [HERE](https://openreview.net/pdf?id=yHiMXKN6nTl) has provided us with 10,000 small scales instances of 100 customers.
Runs on these instances permitted to detect a few edge cases which prevented the algorithm from producing feasible solutions, though feasibility on the CVRP is generally easy to achieve (no limit on fleet size).
- The number of vehicles used to initialize the data structures (2+20% more than the Bin Packing linear-relaxation bound) was too small. This did not allow to find a feasible solution on 3 instances out of 10,000. This number has been raised to 3+30%.
- There was a small bug in the local search which, in theory, could permit to exit the LS immediately after the first loop. This behavior only happens if no move is found in the entire neighborhood. In the current implementation, moves that lead to the creation of new routes are only explored on the second loop and onward, as a consequence, the LS could miss moves that are important to repair the solution. This rare behavior did not allow to find a feasible solution in 1 out of 10,000 instances. A condition has been added to ensure that the LS always does at least two loops, therefore fixing this weakness.
- This commit fixes these two weaknesses, and also relax a bit the range of allowed penalty parameter values to be more permissive in the future.
  • Loading branch information
vidalt committed Mar 25, 2022
1 parent 6c1f09b commit 35b32d8
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 4 deletions.
3 changes: 2 additions & 1 deletion Program/LocalSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ void LocalSearch::run(Individual * indiv, double penaltyCapacityLS, double penal
searchCompleted = false;
for (loopID = 0; !searchCompleted; loopID++)
{
searchCompleted = true;
if (loopID > 1) // Allows at least two loops since some moves involving empty routes are not checked at the first loop
searchCompleted = true;

/* CLASSICAL ROUTE IMPROVEMENT (RI) MOVES SUBJECT TO A PROXIMITY RESTRICTION */
for (int posU = 0; posU < params->nbClients; posU++)
Expand Down
2 changes: 1 addition & 1 deletion Program/Params.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Params::Params(std::string pathToInstance, int nbVeh, int seedRNG) : nbVehicles(
// Default initialization if the number of vehicles has not been provided by the user
if (nbVehicles == INT_MAX)
{
nbVehicles = std::ceil(1.2*totalDemand/vehicleCapacity) + 2; // Safety margin: 20% + 2 more vehicles than the trivial bin packing LB
nbVehicles = std::ceil(1.3*totalDemand/vehicleCapacity) + 3; // Safety margin: 30% + 3 more vehicles than the trivial bin packing LB
std::cout << "----- FLEET SIZE WAS NOT SPECIFIED: DEFAULT INITIALIZATION TO " << nbVehicles << " VEHICLES" << std::endl;
}
else
Expand Down
4 changes: 2 additions & 2 deletions Program/Population.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,12 @@ void Population::managePenalties()
{
// Setting some bounds [0.1,1000] to the penalty values for safety
double fractionFeasibleLoad = (double)std::count(listFeasibilityLoad.begin(), listFeasibilityLoad.end(), true) / (double)listFeasibilityLoad.size();
if (fractionFeasibleLoad < params->targetFeasible - 0.05 && params->penaltyCapacity < 1000) params->penaltyCapacity = std::min<double>(params->penaltyCapacity * 1.2,1000.);
if (fractionFeasibleLoad < params->targetFeasible - 0.05 && params->penaltyCapacity < 100000.) params->penaltyCapacity = std::min<double>(params->penaltyCapacity * 1.2,100000.);
else if (fractionFeasibleLoad > params->targetFeasible + 0.05 && params->penaltyCapacity > 0.1) params->penaltyCapacity = std::max<double>(params->penaltyCapacity * 0.85, 0.1);

// Setting some bounds [0.1,1000] to the penalty values for safety
double fractionFeasibleDuration = (double)std::count(listFeasibilityDuration.begin(), listFeasibilityDuration.end(), true) / (double)listFeasibilityDuration.size();
if (fractionFeasibleDuration < params->targetFeasible - 0.05 && params->penaltyDuration < 1000) params->penaltyDuration = std::min<double>(params->penaltyDuration * 1.2,1000.);
if (fractionFeasibleDuration < params->targetFeasible - 0.05 && params->penaltyDuration < 100000.) params->penaltyDuration = std::min<double>(params->penaltyDuration * 1.2,100000.);
else if (fractionFeasibleDuration > params->targetFeasible + 0.05 && params->penaltyDuration > 0.1) params->penaltyDuration = std::max<double>(params->penaltyDuration * 0.85, 0.1);

// Update the evaluations
Expand Down

0 comments on commit 35b32d8

Please sign in to comment.