IBM ILOG Solver User's Manual > Local Search > Minimizing Talent Wait Cost Using LNS > Problem representation: Model

The next step is to create a Concert Technology model of the problem from the data that have been read. The following code is provided for you.

      // Create the decision variables, cost, and the model
      IloInt numScenes = sceneDuration.getSize();
      IloInt numActors = actorPay.getSize();
      IloIntVarArray scene(env, numScenes, 0, numScenes - 1);
      IloIntVar idleCost(env, 0, IloIntMax);
      IloModel model = BuildModel(
        scene, idleCost, actorPay, sceneDuration, actorInScene
      );

This code creates the main decision variables of the problem scene. Element i of this array will specify which scene is to be filmed in slot i. The code also creates the cost variable idleCost. Then a call to the function BuildModel is made which creates the model which calculates the idle cost of a particular filming order, given actor pay and scene involvement, as well as the scene filming durations.

Now you create the model of the talent scheduling problem. Go to the function BuildModel in your file. The head of the function is provided for you. It simply creates the Concert Technology model object and retrieves the number of actors and scenes to film.

// Build the talent scheduling model
IloModel BuildModel(IloIntVarArray scene,
                    IloIntVar idleCost,
                    IloIntArray actorCost,
                    IloIntArray sceneDuration,
                    IloArray<IloIntSet> actorInScene) {
  IloEnv env = scene.getEnv();
  IloInt numScenes = scene.getSize();
  IloInt numActors = actorCost.getSize();
  IloModel model(env);

The decision variables of the problem are, for each time slot, which scene to film in that particular time slot, and indeed this model is the most intuitive one for most people. However, it turns out that the model is easier to specify if a secondary model is used. Instead of having one variable per time slot, indicating the scene, the dual model has one variable per scene, indicating in which time slot that scene is filmed.

Here, you will create this secondary model. The two models are connected together using the inverse constraint which ensures that for two arrays of constrained variables x and y of equal size, for any index i, y[x[i]] = x[y[i]] = i.

This constraint also has the virtue of ensuring that all variables in x must take on different values, as must all those in y; if this were not the case, the inversion would not be possible.

You will now create the secondary model.

Step 1   -  

Create the secondary model

Add the following code after the comment
// Make the slot-based secondary model

  IloIntVarArray slot(env, numScenes, 0, numScenes - 1);
  model.add(IloInverse(env, scene, slot));

You will now build the cost function which is the sum of the waiting cost of each actor. The basic loop is already provided for you:

  // Expression representing the global cost
  IloIntExpr cost(env);

  // Loop over all actors, building cost
  for (IloInt a = 0; a < numActors; a++) {
    // Expression for the waiting time for this actor
    IloIntExpr actorWait(env);


    // Calculate the first and last slots where this actor plays


    // If an actor is not in a scene,
    // he waits if he is on set when the scene is filmed


    // Accumulate the cost of waiting time for this actor
    cost += actorCost[a] * actorWait;
  }

  model.add(idleCost == cost);
  return model;

}

You will write the code which will calculate the expression actorWait for each actor. There are three points to note here:

First of all, you will work out when an actor is on set by creating variables which represent the first and last time slots where the actor is needed. To do this, you first create an array of variables which contains all the slots where the actor plays.

Step 2   -  

Create the slots in which the actor plays

Insert the following code after the comment
// Calculate the first and last slots where this actor plays

    IloIntVarArray position(env);
    for (IloIntSet::Iterator it(actorInScene[a]); it.ok(); ++it)
      position.add(slot[*it]);
    IloIntExpr firstSlot = IloMin(position);
    IloIntExpr lastSlot = IloMax(position);

This code iterates over all scenes which the current actor plays in, and adds the appropriate slot variables for those scenes to an array of variables position. Then, two expressions are built: the first slot that the actor plays in is the minimum of these slot variables and the last slot that he plays in is their maximum.

firstSlot and lastSlot define when the actor is on set; he will be present for every scene filmed between firstSlot and lastSlot inclusively.

You are now ready to build the part of the model which will evaluate the waiting time of the current actor a in the loop.

Step 3   -  

Create the waiting time for an actor

Insert the following code after the comment // If an actor is not in a scene,

// he waits if he is on set when the scene is filmed

    for (IloInt s = 0; s < numScenes; s++) {
      if (!actorInScene[a].contains(s)) { // not in scene
        IloIntExpr wait = (firstSlot <= slot[s] && slot[s] <= lastSlot);
        actorWait += sceneDuration[s] * wait;
      }
    }

Here, you loop over all scenes. For any scene in which the actor does not appear, you add a waiting time if and only if the slot in which the scene is filmed is a slot for which the actor is on set (in other words, a slot between the arrival and departure of the actor). This is done by creating a 0-1 expression from the Boolean condition of being on set. This 0-1 expression is then multiplied by the filming duration of the scene in question to arrive at the correct waiting time for that scene. Notice that the waiting time for the scene is either 0 or the filming duration.

The remainder of the code of the BuildModel function which is provided for you works out the waiting cost of the actor to be his waiting time multiplied by his pay rate, and accumulates this cost. Then the total waiting cost is constrained to be equal to the cost variable passed as parameter, and the model is returned.