MPL allows you to concisely express multitudes of vectors, data, and constraints, with intuitive and flexible expression formats. In Session 2, you were introduced to plain variables, the objective function and plain constraints. In this session, we introduce several new model elements that are necessary for constructing models for larger problems.
The model you were using in Session 2 was small, involving only two variables. Real world models have hundreds or thousands of variables and constraints, and sometimes extend to millions of variables. MPL allows the user to set up a model using Indexes, Data Vectors, Vector Variables and Vector Constraints to define the problem in a concise, easy-to-read, way.
Indexes define the domains of the model, encapsulate the problem dimensions, and make it easy to quickly adjust the problem size. Once you have defined the indexes for a model, you can then use them to define data, variable, and constraint vectors.
The realm of subscripted variables and constraints is where a modeling language, such as MPL, can allow dramatic productivity, since it allows the model developer to formulate the model in a concise, easy to read manner, using indexes and vectors. Examples of indexes include:
Vectors are basically aggregations of elements in the model that share common characteristics and purpose. Once you have defined the indexes in a model, you can use them to define vectors that contain the data, variables and constraints for the model. This allows you to work in a more condensed way, as you don't have to type every element each time you need it.
Data Vectors are used when the coefficients or statistics from the problem come in lists or tables of numerical data. When an index is defined there is one value for each value of the index and the data vectors allow you to group collections of data together in the model. This data can either be specified as lists of numbers in the model file, or retrieved from an external file, which will be covered in the next session. Examples of data vectors, in a production model with a 'product' index, include:
Variable Vectors can be defined in a similar way as data vectors, to form a collection of variables defined over a certain index. Examples of variable vectors include:
Constraint Vectors are defined over indexes, which MPL expands to a collection of simple constraints when generating the model. A vector constraint can be defined in this way, over a number of indexes, such as periods and products. Examples of constraint vectors include:
Data Constants are used in the model to aid readability, and make the model easier to maintain. They are assigned a specific value, but not defined over a specific index.
One of the operations usually done on vectors is to sum or add all the values for each element of the vector. This is done in MPL by using the keyword SUM surrounding the vector expression to be added together. The expression is prefixed by a list of indexes, over which the sum hinges. The sum expression contains a single variable vector per term, possibly multiplied by one or more data vectors.
SUM(product: Price * Sales); SUM(product, month: ProdCost * Produce);
You are now going to create a model formulation to see how indexes and vectors are used in MPL. We formulated a small product-mix model for a bakery that contained two products and three constraints. In this example, you are going to do a similar model, but this one will include three products, which will be called A1, A2, and A3. For these three products you are going to create an index, and then create a variable vector that represents how much of each of these products need to be produced.
Given the definitions of these new terms, indexes and vectors, we are going to apply them to a sample model. The product-mix model is a question of how to distribute production capacity between products, and to determine the production level, given the demand.
The selling price for each product is fixed: $120.00 for A1, $100.00, for A2, and $115.00 for A3. There is also a limit on the maximum demand for each product: 4300 for A1, 4500 for A2, and 5400 for A3.
The production rate is measured by how many items of each product are produced for each day. In this problem, you have a total of 22 production days available. The production cost is different for each product. The production rate and production cost for each product is given in the table below:
Production | A1 | A2 | A3 |
---|---|---|---|
Production Cost | $73.30 | $52.90 | $65.40 |
Production Rate | 500 | 450 | 550 |
The next step is to take the problem described in the previous section, and formulate it into an MPL model. To see an overview of the Planning3 model to be created, a full listing of the model formulation is shown here below.
TITLE Production_Planning3; INDEX product := (A1, A2, A3); DATA Price[product] := (120.00, 100.00, 115.00); Demand[product] := (4300, 4500, 5400); ProdCost[product] := (73.30, 52.90, 65.40); ProdRate[product] := (500, 450, 550); ProdDaysAvail := 22; VARIABLES Produce[product] -> Prod; MACROS TotalRevenue := SUM(product: Price * Produce); TotalCost := SUM(product: ProdCost * Produce); MODEL MAX Profit = TotalRevenue - TotalCost; SUBJECT TO ProdCapacity -> PCap: SUM(product: Produce / ProdRate) < ProdDaysAvail; BOUNDS Produce < Demand; END
You will now go through entering a simple model, step by step, to allow you to understand model formulation as you set it up.
Start the MPL application.
Choose New from the File menu to create a new empty model file.
Choose Save As from the File menu and save the model file as Planning3.mpl.
The title is optional, but a convenient place to name the model. The title will be used in the solution file to identify the model. You should now have an empty editor window where you can enter your MPL formulation. To enter the title for the Planning3 model, type in the following text in the model editor:
TITLE Production_Planning3;
The first section in an MPL model is usually the INDEX section where you define the indexes for the model. In this example, you have three products, A1, A2, and A3 for which you are creating an index called product. In the model editor, directly below the title, add an INDEX section with a definition for the product index as follows:
INDEX product := (A1, A2, A3);
The next section in MPL is usually the DATA section where you define the Data Vectors and Data Constants for the model. The first data vector you will enter, contains the prices for each product, which were given in the problem description.
In the model editor, directly below the index definition, add a DATA section with a definition for the data vector Price followed by the index [product] inside brackets:
DATA Price[product] := (120.00, 100.00, 115.00);
Following the declaration, you enter an assignment symbol ':=' and then a list of numbers containing the prices for each product. Surround the list with parentheses and separate each number by either a space, comma or both. There should be a semicolon after each data vector definition to separate it from the other definitions in the model.
The problem description also listed data for the demand, production cost and production rate. There is a certain demand for each product, an amount it costs to produce, and an upper limit on how many of each product you can produce per day. To enter this data into MPL, add the following definitions to the DATA section directly below the Price data vector:
Demand[product] := (4300, 4500, 5400); ProdCost[product] := (73.30, 52.90, 65.40); ProdRate[product] := (500, 450, 550);
The problem description also listed how many production days there are available. Add the following data constant definition for the production days available directly below the ProdRate data vector:
ProdDaysAvail := 22;
Usually, the next section will be the VARIABLES section where you define the variables for the model. In the problem description, you were asked to use the model to determine how much to produce of each product. To do this you need to define a vector variable named Produce over the index product. In the model editor, directly below the data definitions add the VARIABLES section with a definition for the Produce vector variable as follows:
VARIABLES Produce[product] -> Prod;
The name that appears after the '->' (read becomes) sign is an optional abbreviation of the vector name used to offset the name size limitations of most LP solvers. This allows you to use long and descriptive names for variables in your model.
In the problem description, you were asked to maximize the profit for the company, which is represented as Total revenue - Total cost . The total revenue is calculated by multiplying the price for each product by how much of that product was produced. In the same fashion, the total cost is calculated by multiplying the production cost for each product by the amount produced of that product. These summations will be used to define the objective function for the model.
When entering summations for the objective function it is useful to define them separately as macros, to make the model easier to read. By using macros you can then, in the model, refer to these summations using the macro names. In the model editor, directly below the variable definition, enter the following macro definitions in the MACROS section.
MACROS TotalRevenue := SUM(product: Price * Produce); TotalCost := SUM(product: ProdCost * Produce);
The model part in MPL is where you define the actual objective function and the constraints for the model. You will be using the macros, defined above, to create the objective function by referring to the macro names where you need to use the summations. Since you are maximizing the profit in this model, the name of this objective function will be Profit. In the model editor, enter the keyword MODEL to note the start of the model part, followed by the definition for the objective function:
MODEL MAX Profit = TotalRevenue - TotalCost;
The formula for the objective function is quite simple, as we are using macros to contain to actual summations. This results in the objective function determining how to maximize profit by computing the difference between the revenues and the total cost.
Following the objective function you need to define the constraints for the model in the SUBJECT TO section. In the problem description, you were given the production rate defined as how many items of each product you can produce each day. As well as how many production days are available. Since this limits how many items you can produce you will need to create a production capacity constraint called ProdCapacity, for each product.
In the model editor, add the SUBJECT TO heading, followed by the constraint definition:
SUBJECT TO ProdCapacity -> PCap: SUM(product: Produce / ProdRate) <= ProdDaysAvail;
In the summation, you divide the number of items produced by the production rate to receive the total number of days used to produce each product. The total production days used must be less than the days available for production.
The BOUNDS section is used to define the upper and lower bounds on the variables in the model. Bounds are similar to constraints but are limited to only one variable per bound. In the problem description, we specified that the total number of items produced must be less than the demand. Therefore, enter the following upper bound on the Produce variable in the BOUNDS section.
BOUNDS Produce < Demand; END
Please note that in most linear programming models all variables have an implied lower bound of zero. These lower bounds are handled automatically by MPL and do not have to be specified unless they are nonzero.
At the end of the model enter the keyword END to note the end of the model. After you have finished entering the model, you should save it by choosing Save from the File menu.
The next step is to solve the Planning3 model. Solving the model involves several tasks done automatically by MPL including checking the syntax, parse the model into memory, transfer the model to the solver, solve the model and then retrieving the solution from the solver and create the solution file. All these tasks are done transparently to the user when he chooses the solve command from the menues. To solve the model take the following steps:
Choose Solve CPLEX from the Run menu or press the Run Solve button in the Toolbar.
While solving the model the Status Window appears providing you with information about the solution progress.
The Status Window for the Planning3 model
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 detailed earlier in this session.
After solving the model MPL automatically creates a standard solution file containing various elements of the model solution. This includes, among other things, the optimal value of the objective function, the activity and reduced costs for the variables, and slack and shadow prices for the constraints. This solution file is created with the same name as the model file, but with the extension '.sol' instead. In our case the solution file is named 'Planning3.sol'.
After you have solved the model you can display the solution file in a view window by pressing the View button at the bottom of the Status Window. This will display the view window shown below.
View Window with the Planning3.sol Solution File
The View Window stores the solution file in memory, allowing you to quickly browse through the solution using the scroll bars. A full listing of the solution file for the Planning3 model is shown here below:
MPL Modeling System - Copyright (c) 1988-1999, Maximal Software, Inc. -------------------------------------------------------------------------------- MODEL STATISTICS Problem name: Producton_Planning3 Filename: Planning3.mpl1 Date: April 18, 1998 Time: 09:59 Parsing time: 0.57 sec Solver: CPLEX Objective value: 544566.636364 Iterations: 3 Solution time: 0.12 sec Constraints: 1 Variables: 3 Nonzeros: 3 Density: 100 % SOLUTION RESULT Optimal solution found MAX Profit = 544566.6364 MACROS Macro Name Values ----------------------------------------------- TotalRevenue 1298181.8182 TotalCost 753615.1818 ----------------------------------------------- DECISION VARIABLES VARIABLE Produce[product] : product Activity Reduced Cost --------------------------------------------- A1 4300.0000 4.3100 A2 1611.8182 0.0000 A3 5400.0000 11.0636 --------------------------------------------- CONSTRAINTS PLAIN CONSTRAINTS Constraint Name Slack Shadow Price ------------------------------------------------------ ProdCapacity 0.0000 -21195.0000 ------------------------------------------------------ END
The first part of the solution file contains various statistics for the model such as the filename, date and time the model was solved, which solver was used, the value of the objective function, and the size of the model.
The next part of the solution file contains the solution results. Here you can see if the solution that was found was optimal or if it was unbounded or infeasible. It also shows you the name and the optimal value of the objective function.
In the MACROS section of the solution file you get a list of all of the macros defined in the model along with the solution values for them. For example, in our Planning3 model, the total revenue is $1.298 million and the total cost is $754,000. This corresponds with the profit of $545,000, which is the value of the objective function.
In the DECISION VARIABLE section you get a list of all the variables in the model, both vector variables and plain variables. In our case, we have a single vector variable Produce defined over the index product. You will see that for product A1 and A3 the solution suggests that you produce 4300 and 5400 units respectively. This is the same amount as the demand for those products. On the other hand, product A2 is suggested to produce 1612 units which is less than the demand. Clearly we did not have the capacity to produce enough to fulfill the demand for all of the products and the model chose products A1 and A3 to fulfill the demand for.
By the way, you might have noticed that the value for A2 in the solution output is actually 1611.8182 units instead of 1612. This results from the fact that all variables in Linear Programming models are by default continuous. In this model it does not matter very much and we can just round it up to the nearest number 1612, but if it did, you could have restricted the variable to take only integer values by specifying it as an integer variable in the model. Please see the MPL User Manual for more details on how to formulate models in MPL with integer variables.
In the CONSTRAINTS section the solution file lists all of the constraints for the model, again both plain and vector constraints. In our model, we had a single plain constraint called ProdCapacity. Since the slack for the constraint is 0.0 this means that we are running at full capacity. The shadow price tells you what the marginal cost would be if you needed to reduce the limit of the constraint by one unit. Since the production capacity constraint has production days as the unit, reducing the days available by one day, the profit would decrease by $21,195.