IBM ILOG Dispatcher User's Manual > The Basics > Adding Visit Disjunctions > Model > Define the createVisits function

Now you create the visits. In this problem, since each visit can be performed at either of two alternative sites, the visits are created in pairs. These pairs are themselves each a neighborhood, since they represent alternative moves that can be taken in a search for a solution--they can be swapped or exchanged with each other. The array of neighborhoods _swapArray is created using the constructor IloNHoodArray. This constructor creates an array of neighborhoods associated with environment _env. The size of the array is the value returned by csvVisitReader.getNbOfItems divided by 2. There are half as many neighborhood pairs as there are visits.

Step 3   -  

Create the visit swap array

Add the following code after the comment //Create the visit swap array

void RoutingModel::createVisits( const char* visitsFileName) {
  IloCsvReader csvVisitReader(_env, visitsFileName);
  _swapArray = IloNHoodArray (_env, csvVisitReader.getNumberOfItems()/2);
  IloInt i=0;
  IloCsvReader::LineIterator  it(csvVisitReader);
  while(it.ok()){

Now the pairs of visits are created. Each visit of a pair is created in the same way. You use csv reader functionality to input visit data from a csv file. A visit must be associated to a node, its location. A visit also has a quantity--the amount of goods delivered to the location. A visit can have a minimum time and a maximum time during which it can be performed--a time window. Additionally, visits have a drop time--the amount time required to perform the visit. These side constraints are modeling using the dimensions _time and _weight and the delay, transit, and cumulative variables associated with the visit.

You use the member function IloVisit::setPenaltyCost to set the cost of not performing visit1 to 20 units. This allows the visit to not be performed, since only one visit of each pair will be performed.

Step 4   -  

Create the first visit of the pair

Add the following code after the comment // Create the first visit of the pair

    IloCsvLine line1 = *it;
    //read visit data from files
    char * visitName1 = line1.getStringByHeader("name");
    char * nodeName1 = line1.getStringByHeader("node");
    IloNum quantity1 = line1.getFloatByHeader("quantity");
    IloNum minTime1 = line1.getFloatByHeader("minTime");
    IloNum maxTime1 = line1.getFloatByHeader("maxTime");
    IloNode node1 = IloNode::Find(_env, nodeName1);
    IloVisit visit1(node1, visitName1);
    _mdl.add(visit1.getTransitVar(_weight) == quantity1);
    visit1.setPenaltyCost(20);
    _mdl.add(minTime1 <= visit1.getCumulVar(_time) <= maxTime1);
    _mdl.add(visit1);
    ++it;

The second visit of the pair is created in the same way as the first, except that it has a different penalty cost. You use the member function IloVisit::setPenaltyCost to set the cost of not performing visit2 to 10 units. This means that the solution will be more likely to include the visit1 of each pair, rather than the visit2 of each pair, since the penalty for not performing visit1 of each pair is higher than the penalty for not performing visit2. The following code is provided for you:

    IloCsvLine line2 = *it;
    char * visitName2 = line2.getStringByHeader("name");
    char * nodeName2 = line2.getStringByHeader("node");
    IloNum quantity2 = line2.getFloatByHeader("quantity");
    IloNum minTime2 = line2.getFloatByHeader("minTime");
    IloNum maxTime2 = line2.getFloatByHeader("maxTime");
    IloNode node2 = IloNode::Find(_env, nodeName2);
    IloVisit visit2(node2, visitName2);
    _mdl.add(visit2.getTransitVar(_weight) == quantity2);
    visit2.setPenaltyCost(10);
    _mdl.add(minTime2 <= visit2.getCumulVar(_time) <= maxTime2);
    _mdl.add(visit2);
    ++it;
 

Once both visits are created, you post a constraint that ensures that only one of the two visits is performed. You use the member function IloVisit::unperformed to add this constraint.

Step 5   -  

Add the visit disjunction constraint

Add the following code after the comment
//Add the visit disjunction constraint

    _mdl.add(visit1.unperformed() + visit2.unperformed() == 1);

You then create an array of visits that includes visit1 and visit2. You create a neighborhood using the function IloSwapPerform that will modify the solution by exchanging the performed visit of the pair with the unperformed visit of the pair. This is used in the solution improvement phase.

Step 6   -  

Create the swap neighborhood

Add the following code after the comment //Create the swap neighborhood

    IloVisitArray visits(_env, 2);
    visits[0] = visit1; visits[1] = visit2;
    _swapArray[i] = IloSwapPerform(_env, visits);
    ++i;
  }
  csvVisitReader.end();
}