Session 5: A Production Planning Model with Multiple Plants

When formulating a model for larger companies, you frequently encounter models that are not limited to a single plant in order to produce the product. Therefore, in this session, you will create a production planning model that includes multiple plants. You will take the model from the previous session and upgrade it to include another index, plants, which will represent all of the plants that are available in order to produce the products. You will then go through the model, step by step, and update all the variable vectors and constraints to account for the new index.


New Concepts in This Session

Plants and other Location Indexes

Location indexes are quite common when formulating production planning models. One example of a location index, would be to represent the plants where the company produces the products for the company. Other examples would include warehouses, factories, distribution centers, etc.

It is common, when working with models that include location indexes, that shipping is allowed between the locations. These models are often called transportation or distribution models and will be covered in later sessions.

External Data Files

When formulating small simple models it is reasonable to leave the data definitions inside the model. As soon as you start working with multi-dimensional models, this becomes difficult to manage, and it is necessary to move the data into separate data files. Keeping the data separate from the model, enhances the readability of the model and make the data easier to maintain.

The model you are creating in this session has multiple indexes, product, month, and plant, and data vectors such as Demand, that are two-dimensional and could be moved into a separate data file. In the model, instead of listing all the data elements for the data vector, you can use the keyword DATAFILE and then the name of the data file as shown here below:

     demand[product, month]   :=  DATAFILE("Demand.dat");
    

Problem Description: A Production Planning Model with Multiple Plants

In this session, you will create a new model formulation for the production planning model to include multiple plants, as well as the multiple periods that were introduced in Session 4. What you want to decide is how much to produce of each product, for each month, in each plant, as well as how much to sell and store in inventory, for each month, in each plant.

In this new problem you are going to have four different plants p1, p2, p3, and p4. Any of these plants can produce all three of the products. Create an index called plants that contains the four different plants, and then update the model accordingly by adding the index to the applicable vectors.

As in the previous session, the selling price stays the same for each product $120.00, $100.00, and $150.00, respectively. The product demands also remain the same as in the previos session. Refer to the demand table in Session 3 for the necessary data.

Now that you have multiple plants the production cost for each product is different for each plant. This data is in the table below.

Production Cost A1 A2 A3
plant 1 $73.30 $52.90 $65.40
plant 2 $79.00 $52.00 $66.80
plant 3 $75.80 $52.10 $50.90
plant 4 $82.70 $63.30 $53.80

The production rate for each product is also different for each plant as shown in the table below:

Production Rate A1 A2 A3
plant 1 500 450 450
plant 2 550 450 300
plant 3 450 350 300
plant 4 550 400 350

Formulation of the Model in MPL

Listed below is the entire model formulation for Planning5. The additions to the model are highlighted in boldface in order to make it easy for you to see the changes from the model in Session 4.

     TITLE
        Production_Planning5;

     INDEX
        product := (A1, A2, A3);
        month   := (Jan, Feb, Mar, Apr);
        plant   := (p1, p2, p3, p4);

     DATA
        Price[product]            :=  (120.00, 100.00, 115.00);
        Demand[product, month]    :=  DATAFILE("Demand.dat");
        ProdCost[plant, product]  :=  DATAFILE("ProdCost.dat");
        ProdRate[plant, product]  :=  DATAFILE("ProdRate.dat");

        ProdDaysAvail[month]      :=  (23, 20, 23, 22);
        InvtCost[product]         :=  (3.50, 4.00, 3.00);
        InvtCapacity              :=  800;

     VARIABLES
        Produce[plant, product, month]  -> Prod;
        Inventory[product, month]       -> Invt;
        Sales[product, month]           -> Sale;

     MACROS
        TotalRevenue   := SUM(product, month: Price * Sales);
        TotalProdCost  := SUM(plant, product, month: ProdCost * Produce);
        TotalInvtCost  := SUM(product, month: InvtCost * Inventory);
        TotalCost      := TotalProdCost + TotalInvtCost;

     MODEL

        MAX  Profit  =  TotalRevenue - TotalCost;

     SUBJECT TO
        ProdCapacity[plant, month] -> PCap:
           SUM(product: Produce / ProdRate)  <=  ProdDaysAvail;

        InvtBal[product, month] -> IBal:
           SUM(plant: Produce) + Inventory[month-1]  =  Sales + Inventory;

        MaxInventory[month] -> MaxI:
           SUM(product: Inventory)   <=  InvtCapacity;

     BOUNDS
        Sales   <=  Demand;

     END
    

Enter New Elements to the Model Step-by-Step

Step 1: Start MPL and Create a New Model

  1. Start the MPL application.

  2. Choose File | Open and open the model from the previous session Planning4.mpl.

  3. Choose File | Save As to save it as a new model file Planning5.mpl.

Step 2: Change the Title for the Model

Change the title for the model to reflect that you are working with the Planning5 model:

     TITLE
        Production_Planning5;
    

Step 3: Add the Location Index 'plant' to the Model

In this example, you have four different plant locations. Create a new index which you will call plant. This index will have four elements p1, p2, p3, and p4 to represent each period of the four month planning period. Add the following definition for the plant index to the INDEX section:

     INDEX
        product :=  (A1, A2, A3);
        month   :=  (Jan, Feb, Mar, Apr);
        plant   :=  (p1, p2, p3, p4);
    

Step 4: Change the definition of the 'Demand' Data Vector to Read Data from an External Data File

In this session, you are going move the data values for the two-dimensional data vectors to external data files. When working with data vectors that have two dimensions or higher, it is often a good idea to move the data values to an external data file instead of listing all of the numbers directly in the model file. This keeps the data separate from the model, enhances the readability of the model, and makes the data easier to maintain.

The first data vector you want to move to an external data file is the Demand data vector. In the DATA section, use the Cut command from the Edit menu to remove the list of numbers for the Demand vector and then enter the keyword DATAFILE and the filename Demand.dat in its place as follows:

     DATA
        Price[product]          :=  (120.00, 100.00, 115.00);
        Demand[product, month]  :=  DATAFILE("Demand.dat");
    

Step 5: Create the Data File 'Demand.dat'

The next step is to create the data file Demand.dat. First, open a new model editor window by choosing New in the File menu. If you used the Edit | Cut command in the previous Step 4 to remove the data values, they are now in the Clipboard and you can use the Edit | Paste command to place the data back into the data file. Otherwise, you can use the demand data table from the problem description in Session 3 to enter the data values into the data file as follows:

     !  Demand.dat  -  Demand per month for each product
     !
     !  Demand[product,month]:
     !
     !          Jan    Feb    Mar    Apr
     !        ----------------------------
               4300,  4200,  6400,  5300,
               4500,  5400,  6500,  7200,
               5400,  6700,  7800,  8200
    

The lines that start with exclamation marks are comments used to enhance the readability. The numbers in the data file can be separated by comma or space or both. After you have entered all of the data save the file as Demand.dat in the Tutorial folder.

Step 6: Upgrade the 'ProdCost' and 'ProdRate' Data Vectors to Include the 'plant' Index

Two of the data vectors, ProdCost and ProdRate, need to be upgraded to include the plant index. The ProdCost data vector is now defined over two domain indexes, plant and product and will given data values from an external data file. The ProdRate data vector will also be given values from a data file. In the model editor, add the index, plant, to the declaration of both the ProdCost and the ProdRate data vectors, and follow it with the data filenames ProdCost.dat and ProdRate.dat respectively as follows:

        ProdCost[plant, product]  :=  DATAFILE("ProdCost.dat");
        ProdRate[plant, product]  :=  DATAFILE("ProdRate.dat");
        ProdDaysAvail[month]      :=  (23, 20, 23, 22);
        InvtCost[product]         :=  (3.50, 4.00 3.00);
        InvtCapacity              :=  800;
    

Step 7: Create the Data Files for the 'ProdCost' and 'ProdRate' Data Vectors

Now open a new editor window by selecting File | New in the menu to enter the data file. Type in the data from the Production Cost table in the problem description as follows:

     !
     !  ProdCost.dat  -  Cost per item produced
     !
     !  ProdCost[plant, product]:
     !
     !           A1      A2      A3
     !        -----------------------
               73.30,  52.90,  65.40,
               79.00,  52.00,  66.80,
               75.80,  52.10,  50.90,
               82.70,  63.30,  53.80
    

Again, the lines that start with exclamation marks are comments used to enhance the readability. After you have entered all of the data save the file using the name ProdCost.dat.

For the production rate create a new data file called ProdRate.dat using the values from the table in the problem description.

     !
     !  ProdRate.dat  -  Items produced per day
     !
     !  ProdRate[plant, product]:
     !
     !          A1    A2    A3
     !        ------------------
               500,  450,  450,
               550,  450,  300,
               450,  350,  300,
               550,  400,  350
    

Step 8: Update the 'Produce' Variable to Include the 'plant' Index

In order to determine how much you want to produce of each product, for each plant, you need to add the plant index to the vector definition of the Produce variable as follows:

     VARIABLES
        Produce[plant, product, month] -> Prod;
        Inventory[product, month]      -> Invt;
        Sales[product, month]          -> Sale;
     

Step 9: Add the 'plant' Index to the 'TotalProdCost' Summation

Since the Produce vector variable now includes the new index, plant, the calculation of the total production cost in the MACROS section needs also to be updated to include the plant index:

     MACROS
        TotalRevenue   := SUM(product, month: Price * Sales);
        TotalProdCost  := SUM(plant, product, month: ProdCost * Produce) ;
        TotalInvtCost  := SUM(product, month: InvtCost * Inventory);
        TotalCost      := TotalProdCost + TotalInvtCost;
    

The objective function itself does not change as you are using the same macros as in the previous session.

Step 10: Add the 'plant' Index to the 'ProdCapacity' Constraint

The change for the production capacity constraint is very simple. Add the index plant to the production capacity declaration and the rest of the constraint remains the same.

     SUBJECT TO
        ProdCapacity[plant, month] -> PCap:
           SUM(product: Produce / ProdRate)   <=  ProdDaysAvail;
    

Step 11: Add Summation of the 'Produce' Variable Over the 'plant' Index to the Inventory Balance Constraint

You can now produce the products in any of the four plants, therefore, you need to update the inventory balance constraint to include a summation, over all of the plants, of the Produce variable vector.

     InvtBal[product, month] -> IBal:
        SUM(plant: Produce) + Inventory[month-1]  =  Sales + Inventory;
    

After you have finished entering the model, you should save it by choosing Save from the File menu.


Solve the Model and Analyze the Solution

Since we have added more indexes to the model, the number of variables have increased considerably. Typically, when working with larger models, the model developer wants to include only some of the values in the solution. In our case, to reduce the output, we want to include only the variables that have nonzero solution values. MPL has number of options dialog boxes in the Options menu where you can change the default behavior of the program. One of the dialog boxes is the Solution File Options dialog where you can adjust what is included in the solution file. To change the default to include nonzero values only in the solution file do the following:

  1. From the Options menu choose Solution File to open the Options Dialog Box shown here below:

  2. The Solution File Options Dialog Box

  3. Turn the Nonzero Values Only check box On by clicking on it.

  4. Close the dialog box by pressing the OK button.

After changing the Nonzero Values Only option, the next step is to solve the model by choosing Solve CPLEX from the Run menu. If everything goes well MPL will display the message "Optimal Solution Found". If there is an error message window with a syntax error please check the formulation you entered with the model listing detailed earlier in this session.

As the models you are working with become bigger you tend to look at only certain parts of the solution instead of the whole solution file. This time, instead of listing the whole solution file, we are going to use the model definitions tree window to view only the parts of the solution we are interested in.

The model definitions window allows you to see all of the defined items from the model formulation in a hierarchical tree where each branch corresponds to a section in the model. While in MPL it is normally a good idea to leave the tree window open at all times. MPL will then automatically update its contents every time you solve your model. To look at the model definitions for the Planning5 model choose Model Definitions from the View menu.

The Model Definitions Window for the Planning5 model

From the tree window you can select any of the defined items in the model to look at the actual values for that item. For example, to look at the values for the Produce variable, either double-click on the Produce item in the tree, or select it and then press the View button. This will display a window containing only the values for the Produce variable.

     VARIABLE Produce[plant,product,month] :

       plant  product  month           Activity     Reduced Cost
      -----------------------------------------------------------
       p1     A1       Jan           4300.0000           0.0000
       p1     A1       Feb           4200.0000           0.0000
       p1     A1       Mar           6400.0000           0.0000
       p1     A1       Apr           5300.0000           0.0000
       p2     A2       Jan           4500.0000           0.0000
       p2     A2       Feb           5400.0000           0.0000
       p2     A2       Mar           6500.0000           0.0000
       p2     A2       Apr           7200.0000           0.0000
       p3     A3       Jan           5400.0000           0.0000
       p3     A3       Feb           6000.0000           0.0000
       p3     A3       Mar           6900.0000           0.0000
       p3     A3       Apr           6600.0000           0.0000
       p4     A3       Feb            700.0000           0.0000
       p4     A3       Mar            900.0000           0.0000
       p4     A3       Apr           1600.0000           0.0000
       -----------------------------------------------------------
      

If you look at the activity values for the Produce variable you will see that this time we are fulfilling the demand for all the products since we now have enough capacity. The model decides which plants are used for which products. For example, plant p1 is used to produce product A1, plant p2 is used for product A2, and plants p3 and p4 are used for product A3.

If you go to the tree window again and open a window for the ProdCapacity constraint you will get the following solution values.

     CONSTRAINT ProdCapacity[plant,month] :

       plant  month              Slack     Shadow Price
      --------------------------------------------------
       p1     Jan             14.4000           0.0000
       p1     Feb             11.6000           0.0000
       p1     Mar             10.2000           0.0000
       p1     Apr             11.4000           0.0000
       p2     Feb              8.0000           0.0000
       p2     Mar              8.5556           0.0000
       p2     Apr              6.0000           0.0000
       p3     Jan              5.0000           0.0000
       p4     Jan             23.0000           0.0000
       p4     Feb             18.0000           0.0000
       p4     Mar             20.4286           0.0000
       p4     Apr             17.4286           0.0000
      --------------------------------------------------
    

There is a great deal of slack for each plant and month in the production capacity constraint. This can be interpreted to mean that we could produce a lot more of the products, but it is not necessary as we are already fulfilling the demand. Since the production capacity constraint uses production days as the unit of measure, the slack values represent how many days per month each plant is idle.


Back To Top | Maximal Home Page | Overview | Previous Page | Next Page