IBM ILOG Dispatcher User's Manual > The Basics > Minimizing the Number of Vehicles > Solve > Define the reduceActiveVehicles function

To reduce the number of active vehicles, you first use the function getShortestRoute to find the vehicle with the smallest number of visits. You make a copy of the solution and use an IloRoutingSolution::RouteIterator to move through the route of the selected vehicle. You add a vehicle incompatibility constraint on each visit associated with the vehicle, stating that the visit should not be assigned to the vehicle you are trying to empty.

Step 11   -  

Empty the vehicle

Add the following code after the comment //Empty the vehicle

void RoutingSolver::reduceActiveVehicles () {
  IloVehicle vehicle = getShortestRoute();
  IloRoutingSolution solCopy(_env);
  IloBool vehicleClosed = IloTrue;
  IloGoal sync = IloRestoreSolution(_env, _solution)
              && IloStoreSolution(_env, _solution);
  while (vehicleClosed && vehicle.getImpl()) {
    solCopy.copy(_solution);
    _solver.out() << "Emptying " << vehicle.getName() << " ..." << endl;
    IloAnd andCt(_env);
    _mdl.add(andCt);
    for (IloRoutingSolution::RouteIterator iter(solCopy, vehicle);
         iter.ok();
         ++iter) {
      IloVisit visit = *iter;
      if (!visit.isFirstVisit() && !visit.isLastVisit()) {
        andCt.add(vehicle != visit.getVehicleVar());

You then remove the visit from the solution, which sets the state of the visit to unperformed in the solution. You use the function IloInsertVisit to insert the unperformed visit back into the routing plan. This goal always succeeds because the visit has a finite penalty cost, which allows it be unperformed.

Step 12   -  

Insert the unperformed visits into the routing plan

Add the following code after the comment
//Insert the unperformed visits into the routing plan

        _solution.remove(visit);
        _solver.solve(sync);
        IloGoal insert = IloInsertVisit(_env, visit, _solution);
        _solver.solve(insert);
        _solution.add(visit);
        _solution.store(_solver);
      }
    }

Then you improve the solution, using the neighborhoods IloMakePerformed, IloMakeUnperformed, and IloSwapPerform to try to perform the visits belonging to the emptied vehicle. If, after improvement, the number of unperformed visits is 0 (zero) and the vehicle is still empty, then this vehicle is closed by constraining the next-variable of the first visit to be set equal to the last visit of the vehicle. You then search for the next vehicle to empty, that is the one whose route size is now shortest. When you cannot empty any more vehicles and still perform all the visits, the loop breaks and the last vehicle that was unsuccessfully emptied is added back to the routing solution.

Step 13   -  

Improve the solution

Add the following code after the comment //Improve the solution

    improveWithNhood();
    if (_solution.getNumberOfUnperformedVisits() == 0
        && _solution.getRouteSize(vehicle) == 0) {
      _mdl.add(vehicle.getFirstVisit().getNextVar()
              == vehicle.getLastVisit());
      vehicle = getShortestRoute();
    }
    else {
      _mdl.remove(andCt);
      _solution.copy(solCopy);
      vehicleClosed = IloFalse;
    }
  }

Finally, you restore the last solution found, which is the solution that uses the smallest number of vehicles.

Step 14   -  

Restore the solution

Add the following code after the comment //Restore the solution

  _solver.solve(_restoreSolution);
}