IBM ILOG Solver User's Manual > More on Solving > Controlling the Search: Locating Warehouses > Model

Once you have written a description of your problem, you can use Concert Technology classes to model it.

Step 2   -  

Open the example file

Open the example file YourSolverHome/examples/src/tutorial/storesbs_partial.cpp in your development environment.

First, you represent the warehouse locations using C++ enumerations to associate meaningful names with values. This code is provided for you:

const char* Suppliers[] = {"Bonn", "Bordeaux", "London", "Paris", "Rome"};

As usual, you declare an environment and a model. You declare i and j for use in loops. This code is provided for you:

int main(int argc, char** argv){
  IloEnv env;
  try {
    IloModel model(env);
    IloInt i, j;

In this lesson, you will input data from the file YourSolverHome/examples/data/store.dat. The following code is provided for you:

    const char* fileName;
    if ( argc != 2 ) {
      env.warning() << "usage: " << argv[0] << " <filename>" << endl;
      env.warning() << "Using default file" << endl;
      fileName = "../../../examples/data/store.dat";
    } else
      fileName = argv[1];

    ifstream file(fileName);
    if ( !file )
      throw FileError();

Here is the data from the file YourSolverHome/examples/data/store.dat:

30
[[20, 24, 11, 25, 30],
 [28, 27, 82, 83, 74],
 [74, 97, 71, 96, 70],
 [2,  55, 73, 69, 61],
 [46, 96, 59, 83, 4],
 [42, 22, 29, 67, 59],
 [1,  5,  73, 59, 56],
 [10, 73, 13, 43, 96],
 [93, 35, 63, 85, 46],
 [47, 65, 55, 71, 95]]
[1, 4, 2, 1, 3]

The first line of data, 30, is the cost associated with building a warehouse. The second part of the data is a matrix representing the relative cost of supplying each existing store from each of the potential warehouse sites. This is the information presented in Table 13.1. The last line of data is the capacity of each potential supplier warehouse: Bonn 1, Bordeaux 4, London 2, Paris 1, and Rome 3.

You model the cost associated with building a supplier warehouse as an integer buildingCost. You model the matrix of relative supply costs as an instance of IloIntArray2, an array of arrays. You model the capacities of the potential warehouses as an instance of IloIntArray.

Step 3   -  

Model the data

Add the following code after the comment //Model the data

    IloInt       buildingCost;
    IloIntArray2 costMatrix(env);
    IloIntArray  capacity(env);


Now, you input the data. The overloaded C++ operator >> directs input to an input stream.

Step 4   -  

Input the data

Add the following code after the comment //Input the data

    file >> buildingCost >> costMatrix >> capacity;

You create variables to represent the number of stores, nStores, and the number of supplier warehouses, nSuppliers. The number of stores can be deduced from the size of the costMatrix array of arrays. The number of supplier warehouses can be deduced from the size of the capacity array. This allows you to easily extend the example by using another data file. This code is provided for you:

    IloInt nStores    = costMatrix.getSize();
    IloInt nSuppliers = capacity.getSize();

Now you declare the decision variables. The first array of decision variables represents the unknown information in this problem--which supplier warehouse should supply each store. To represent this information, you declare an array of variables supplier. The array supplier represents the supplier warehouse selected for each store. This array has nStores elements or, in this example, 10. The possible values for these variables represent the supplier warehouses. In this example, a value of 0 represents Bonn, a value of 1 represents Bordeaux, a value of 2 represents London, a value of 3 represents Paris, and a value of 4 represents Rome. The array of decision variables supplier will contain the solution to the problem, once it is solved.

Step 5   -  

Declare the supplier decision variables

Add the following code after the comment
//Declare the supplier decision variables

    IloIntVarArray supplier(env, nStores, 0, nSuppliers-1);

You also declare three other arrays of decision variables that will be used in creating the constraints. The array of variables cost represents the relative cost of supplying each existing store from each of the potential warehouse site. It has nStores elements or, in this example, 10.

Step 6   -  

Declare the cost decision variables

Add the following code after the comment //Declare the cost decision variables

    IloIntVarArray cost(env, nStores, 0, 99999);

The array of decision variables open represents whether a potential supplier warehouse site is open or not--whether the warehouse should be built. It has nSuppliers elements or, in this example, 5. There are two possible values for each variable. The value is 1 if the warehouse is open and 0 if the warehouse is not open.

Step 7   -  

Declare the warehouse open decision variables

Add the following code after the comment
//Declare the warehouse open decision variables

    IloIntVarArray open(env, nSuppliers, 0,1);

You create a decision variable to represent the total cost in the problem. This total cost is defined as a constraint later in this section. It reflects a balance between finding the lowest relative supply costs for each store and the cost of building more warehouses.

Step 8   -  

Declare the totalCost decision variable

Add the following code after the comment
//Declare the totalCost decision variable

    IloIntVar totalCost(env, 0, 999999);

Now, you add the constraints. The first constraint states that the cost associated with each store is equal to the relative cost given in the matrix for this store and the supplier that has been selected for it. Using a "for" loop, this constraint is added for each store. For example, if store 0 is supplied by the Rome warehouse, then cost[0] is equal to the value in costMatrix represented by store 0 and the supplier for store 0. The element [i] denotes the row and the element (supplier[i]) denotes the column. In this case, the value at [0]-- or row 0--and supplier[0]--or Rome, column 4--is 30. See Table 13.1.

Step 9   -  

Add the constraints on relative cost

Add the following code after the comment
//Add the constraints on relative cost

    for (i = 0; i < nStores; i++){
      model.add(cost[i] == costMatrix[i](supplier[i]));

Next, you add the constraint that states that the supplier warehouse used in the previous constraint must be open--in other words, the warehouse must be built if a store is going to be supplied by it. For example, if store 0 is supplied by the Rome warehouse, this constraint states that the value of the open variable associated with the Rome warehouse must be equal to 1. The Rome warehouse must be built.

Step 10   -  

Add the constraints on open warehouses

Add the following code after the comment
//Add the constraint on open warehouses

      model.add(open(supplier[i])==1 );
    }

Next, you add the constraints relating to supplier warehouse capacity. To do this, you need to find a way to add the number of stores being supplied by a warehouse and make sure that this number does not exceed the capacity of the warehouse. You can use the Concert Technology function IloSum to do this. This function returns a numeric value representing the sum of the variables in an array. Here is a constructor for IloSum:

IloExpr IloSum(const IloNumVarArray vars);

To add the constraints on warehouse capacity, you use two "for" loops. For each supplier warehouse j, you create a temporary array, temp, representing whether a store is supplied by that supplier. The array temp has nStores elements or 10 in this example. For each store k, add a constraint that if the supplier of that store equals j, then temp [k] equals 1. If the store is not supplied by supplier j, then temp[k] equals 0. Then, use the function IloSum to sum up the variables in the array temp. This sum will equal the number of stores supplied by the supplier warehouse j. This sum is constrained to be less than or equal to the capacity of supplier warehouse j. You add these constraints for all the supplier warehouses, 5 in this example.

Step 11   -  

Add the constraints on warehouse capacity

Add the following code after the comment
//Add the constraints on warehouse capacity

    for (j = 0; j < nSuppliers; j++ ) {
      IloIntVarArray temp(env, nStores, 0, 1);
      for (IloInt k = 0; k < nStores; k++)
        model.add(temp[k] == (supplier[k] == j));
      model.add(IloSum(temp) <= capacity[j]);
    }

Finally, you use the function IloSum to add the constraints on total cost to the model. There are two cost issues in this problem. First, you want to supply each store with the warehouse that is the most cost-efficient. However, you also want to minimize the number of open warehouses since it costs a certain amount, 30 in this example, to open an warehouse. Therefore, the total cost is constrained to be equal to the sum of the relative costs of supplying each store from its supplier warehouse plus the number of open warehouses multiplied by the cost to build each warehouse. No explicit objective is added to the model in the problem, since total cost is minimized during search using a search selector. For more information on using search selectors, see "Solve".

Step 12   -  

Add the constraint on total cost

Add the following code after the comment //Add the constraint on total cost

    model.add(totalCost == IloSum(cost) + IloSum(open) * buildingCost);