Linear programming in Python (2)

Here’s an example of a transportation problem, with information given as a table:

Demands
300 360 280 340 220
750 100 150 200 140 35
Supplies  400 50 70 80 65 80
350 40 90 100 150 130

This is an example of a balanced, non-degenerate transportation problem. It is balanced since the sum of supplies equals the sum of demands, and it is non-degenerate as there is no proper subset of supplies whose sum is equal to that of a proper subset of demands. That is, there are no balanced “sub-problems”.

In such a problem, the array values may be considered to be the costs of transporting one object from a supplier to a demand. (In the version of the problem I pose to my students it’s cars between distributors and car-yards; in another version it’s tubs of ice-cream between dairies and supermarkets.) The idea of course is to move all objects from supplies to demands while minimizing the total cost.

This is a standard linear optimization problem, and it can be solved by any method used to solve such problems, although generally specialized methods are used.

But the intention here is to show how easily this problem can be managed using myMathProg (and with numpy, for the simple use of printing an array):

import pymprog as py
import numpy as np
py.begin('transport')
M = range(3)  # number of rows and columns
N = range(5)
A = py.iprod(M,N) # Cartesian product
x = py.var('x', A, kind=int) # all the decision variables are integers
costs = [[100,150,200,140,35],[50,70,80,65,80],[40,90,100,150,130]]
supplies = [750,400,350]
demands = [300,360,280,340,220]
py.minimize(sum(costs[i][j]*x[i,j] for i,j in A))
# the total sum in each row must equal the supplies
for k in M:
    sum(x[k,j] for j in N)==supplies[k]
# the total sum in each column must equal the demands
for k in N:
    sum(x[i,k] for i in M)==demands[k]
py.solve()
print('\nMinimum cost: ',py.vobj())
A = np.array([[x[i,j].primal for j in N] for i in M])
print('\n')
print(A)
print('\n')
#py.sensitivity()
py.end()

with solution:

GLPK Simplex Optimizer, v4.65
n8 rows, 15 columns, 30 non-zeros
      0: obj =   0.000000000e+00 inf =   3.000e+03 (8)
      7: obj =   1.789500000e+05 inf =   0.000e+00 (0)
*    12: obj =   1.311000000e+05 inf =   0.000e+00 (0)
OPTIMAL LP SOLUTION FOUND
GLPK Integer Optimizer, v4.65
8 rows, 15 columns, 30 non-zeros
15 integer variables, none of which are binary
Integer optimization begins...
Long-step dual simplex will be used
+    12: mip =     not found yet >=              -inf        (1; 0)
+    12: >>>>>   1.311000000e+05 >=   1.311000000e+05   0.0% (1; 0)
+    12: mip =   1.311000000e+05 >=     tree is empty   0.0% (0; 1)
INTEGER OPTIMAL SOLUTION FOUND

Minimum cost:  131100.0

[[  0. 190.   0. 340. 220.]
 [  0. 120. 280.   0.   0.]
 [300.  50.   0.   0.   0.]]

As you see, the definition of the problem in Python is very straightforward.

 
comments powered by Disqus