IBM ILOG Dispatcher User's Manual > Developing Dispatcher Applications > Developing Your Own First Solution Heuristics > Using the Dispatcher First Solution Framework > Creating the decision class

First, you create your decision class PDPDecision. This is a subclass of IloPairDecisionI, an abstract class that is a subclass of IloSingleVehicleFSDecisionI, involving one vehicle, and a pair of pickup and delivery visits. This class is dedicated to PDP heuristics.

The abstract class IloSingleVehicleFSDecisionI handles decisions concerning one vehicle. To simplify the decision comparison process, a cost is associated to decisions, computed by a new virtual member function called evaluate. Subclassing from this class requires you to define an evaluate member function. In addition, you will also define the following member functions: make, calcFeasibility, and display.

class PDPDecision : public IloPairDecisionI {

public:
  PDPDecision(IloVehicle vehicle,
              IloVisit pickup, IloVisit delivery);

  virtual void make(IloFSDecisionMakerI * dm);
  virtual IloNum evaluate(IloFSDecisionMakerI* dm) const;
  virtual IloBool calcFeasibility(IloFSDecisionMakerI* dm) const ;
  virtual void display(ostream& os) const;
};

The constructor for PDPDecision takes three parameters: a vehicle, a pickup visit, and a delivery visit.

PDPDecision
::PDPDecision(IloVehicle vehicle, IloVisit pickup, IloVisit delivery)
  : IloPairDecisionI(vehicle, pickup, delivery) {}


The function make performs the decision. It is called after a decision has been selected and checked for feasibility.

void PDPDecision::make(IloFSDecisionMakerI* dm) {
  IloDispatcher dispatcher = dm->getDispatcher();
  IloVisit up = getOutChainEnd(dispatcher);
  IloVisit down = getInChainStart(dispatcher);

  dispatcher.setNext( up, getPickup());
  dispatcher.setNext( getDelivery(), down);
}


The evaluate member function computes a cost that is used to select a best decision to execute. Decisions with the lowest cost are preferred.

IloNum PDPDecision::evaluate(IloFSDecisionMakerI* dm) const {
  IloDispatcher dispatcher = dm->getDispatcher();
  IloVisit up = getOutChainEnd(dispatcher);
  IloVisit down = getInChainStart(dispatcher);
  IloVehicle vehicle(getVehicle());

  IloNum cost = 0;

  cost += dispatcher.getCost(up, getPickup(), vehicle);
  cost += dispatcher.getCost(getDelivery(), down, vehicle);
  return cost;
}


The calcFeasibility member function is used to filter infeasible decisions before calling solver.solve to save CPU time.

IloBool PDPDecision::calcFeasibility(IloFSDecisionMakerI * dm) const {
  IloBool ok = IloPairDecisionI::calcFeasibility(dm);
  IloDispatcher dispatcher = dm->getDispatcher();
  IloVisit up = getOutChainEnd(dispatcher);
  IloVisit down = getInChainStart(dispatcher);
  if ( ok ) {
    ok = IsArcLinkable(dispatcher, up, getPickup())
      && IsArcLinkable(dispatcher, getPickup(), getDelivery())
      && IsArcLinkable(dispatcher, getDelivery(), down)
      ;
  }
  if ( ok ) {
    IloDimension2 time = IloDimension2::Find(dispatcher.getEnv(), "Time");
    ok = canInsertPairOnDimension
      (dispatcher, time, getVehicle(), up, down, getPickup(), getDelivery());
  }
  return ok;
}



The display member function displays the decision object.

void PDPDecision::display(ostream& os) const {
  os << "[<-" << getPickup().getName()
     << ".(" << getVehicle().getName() << ")."
     << getDelivery().getName() << "->]"
    ;
}