Menu

[r118]: / Doc / tutorial.rst  Maximize  Restore  History

Download this file

245 lines (184 with data), 8.4 kB

A Dive-in Tutorial on PyMathProg

A dive-in example

Let's start with a simple problem. Suppose you are given an easy linear program, which has 3 variables and 3 constraints. The data is given as a 3x3 matrix for the constraints, and 2 vectors of length 3 for the objective function and the right-hand-side of the constraints. You need to solve the problem and report the optimal solution. Very basic. Here is how to get it done with PyMathProg:

I suppose the code above is not very hard to understand if you know a little bit about programming. Basically, there are three logical building blocks: it starts with a data block, followed by a modelling block, and ends with a solution report block.

Data block ( lines 3-8 ): the matrix and the vectors are defined in it (of course, you can also read data from some external database, as Python can do that easily). Also, in line 3 the index for variables 'xid' and the index for constraints 'rid' are defined to be integers in the range from 0 to 3: [0, 3). These index sets are used later in defining the model. Indices can be almost anything: strings, numbers (yes, numbers, not just integers!), etc. In Python terminology, they can be any immutable objects (so that they have a well-defined hash).

Modelling block: ( lines 10-18 ): It all starts by a function:

that declare the beginning of a problem with the given name. This basically creates a problem instance and put in a hidden place, which you can only access through other functions provided by PyMathProg, as the rest of this example illustrates. However, if you prefer explicitly handling the problem directly, PyMathProg also provides that for you, and we will come to that later.

Line 11 turns on the verbosity option, which enables the PyMathProg to output the actually model you are defining (the actual output will be provided later).

Line 12 defines the variable: you simply provide the index set and the name of the variable. The name is optional, and PyMathProg can supply default names. It is usually a good habbit to explicitly specify the name of variables.

Lines 13-15 define the objective: maximize the summation of the terms b[i]*x[i], where i goes from 0 to 3.

Line 16-18 define the constraints. the function st(...) adds the provided constraints to the current model, the returned constraints are kept in the variable 'r'.

OK, we are done with model definition, and we can actually do it with three calls in three lines for three components: the variables, the objective, and the constraints.

Solution and Report ( lines 19-39 ):

Line 19 issues a call solve() to solve the model. This function can take an optional argument, indicating what kind of program to deal with:

Since GLPK provides different methods to solve a problem, PyMathProg provides solver options to choose which method you would use. Use global function solvopt(...) to set your options. For example:

>>> solvopt(method='exact', integer='advanced')

will enable you to access the exact arithmetic provided by GLPK to solve the LP problem first, then use the advanced branch and bound method for the integer problem. For LP problems, you can choose from 'simplex' (default), 'exact', 'interior'; for integer problems, 'plain' (default) or 'advanced'.

Line 20 reports the solution status.

Line 21 printss the optimal objective function value. You can also check the status of the solver by call the status() function.

Line 23-25 reports the actual solution. Notice how the solutions are conveniently accessed by x[i].primal and x[i].name. You can also access the dual values by x[i].dual. Similar syntax holds for constraints as returned from the st(...) function call.

Line 31 reports the KKT optimality condition. For more details you may refer to PYGLPK and GLPK documentation. You can also access the environment to set some environment variables for the solver ( line 32 ), which is documented in PYGLPK.

Line 37 evaluates an expression containing variables, which yields the same result as Line 38. The function evaluate(.) saves you from typing '.primal's after the variables.

Finally, line 39 calls the function endModel() to do away with the problem.

And we are finished! Here is the output (with the verbosity turned on):

MAX 'myobj': 10 X[0]+ 6 X[1]+ 4 X[2]
s.t. R0[0]: X[0]+ X[1]+ X[2] <= 100.0
s.t. R0[1]: 10 X[0]+ 4 X[1]+ 5 X[2] <= 600.0
s.t. R0[2]: 2 X[0]+ 2 X[1]+ 6 X[2] <= 300.0
Solver status: opt
Z = 733.333;
X[0] = 33.3333 {dual: 0};
X[1] = 66.6667 {dual: 0};
X[2] = 0 {dual: -2.66667}
R0[0] = 100 {dual: 3.33333};
R0[1] = 600 {dual: 0.666667};
R0[2] = 200 {dual: 0}

Karush-Kuhn-Tucker optimality conditions:
=========================================

1) Error in Primal Solutions:
-----------------------------
Largest absolute error: 0.000000 (row id: 1)
Largest relative error: 0.000000 (row id: 1)
Quality of primal solution: H

2) Error in Satisfying Primal Bounds:
-------------------------------------
Largest absolute error: 0.000000 (var id: 0)
Largest relative error: 0.000000 (var id: 0)
Quality of primal feasibility: H

3) Error in Dual Solutions:
-----------------------------
Largest absolute error: 0.000000 (col id: 0)
Largest relative error: 0.000000 (col id: 2)
Quality of dual solution: H

4) Error in Satisfying Dual Bounds:
-------------------------------------
Largest absolute error: 0.000000 (var id: 0)
Largest relative error: 0.000000 (var id: 0)
Quality of dual feasibility: H

Environment: <glpk.Environment object at 0xb7cf66bc>

A parallel example

In the above example, we use global function calls to create and manipulate a hidden model -- we did not directly handle it. PyMathProg also provides another set of means to allow you direct handling of the model. We now take a look at an equivalent example with direct model handling:

Zero-sum Two-player Game

Here this example intends to show the use of the 'primal' and 'dual' properties. A zero-sum two-player game is a game between two players, where the gain of one player is the loss of the other, hence their pay-offs always sums up to zero. The pay-off of player one under his own strategy i and player two's strategy j is given as a(i,j), which gives the pay-off matrix when all strategy combinations are taken into consideration.

Here is an LP formulation to find the equilibrium mixed strategies and the value of the game.

And the output is as follows:

game_value=7.000000
Player 1's mixed Strategy:
A1: 0.333333333333 A2: 0.666666666667
Player 2's mixed strategy:
{1: prob[1]=0.500000, 2: prob[2]=0.500000}

Customized algorithms

It is possible to write your customized algorithms using row/column generation and warm start your simplex method(that is, start the simplex method with the optimal basis from your last invocation, which is often used when employing row/column generation -- just remember not to turn on the 'presolve' option). If your row/column generation algorithm is computation intensive and you need to write them in C and invoke from Python, you can consider EXPY (http://expy.sf.net), ctypes, SWIG (Sip for C++), and Boost.Python.

It is also possible to have a callback hooked into the Branch & Bound method of GLPK, by passing a callback function object as an option to the solver. For how to manipulate options, please refer to the other documents of pymathprog.