The Primal & Dual Linear Programming Problems: Canonical Form

*James D. Gaboardi*


*Florida State University*     |     *Department of Geography*



Adapted from:

Daskin, M. S. 1995. Network and Discrete Location: Models, Algorithms, and Applications. Hoboken, NJ, USA: John Wiley & Sons, Inc.


0. Imports and Data Creation


In [2]:
# Imports
import numpy as np
import gurobipy as gbp
import datetime as dt

#  Constants
Aij = np.random.randint(5, 50, 25)
Aij = Aij.reshape(5,5)
AijSum = np.sum(Aij)
Cj = np.random.randint(10, 20, 5)
CjSum = np.sum(Cj)
Bi = np.random.randint(10, 20, 5)
BiSum = np.sum(Bi)

# Matrix Shape
rows = range(len(Aij))
cols = range(len(Aij[0]))

1. Primal


In [3]:
# Instantiate Model
mPrimal_Canonical_GUROBI = gbp.Model(' -- Canonical Primal Linear Programming Problem -- ')

# Set Focus to Optimality
gbp.setParam('MIPFocus', 2)

# Decision Variables
desc_var = []
for dest in cols:
    desc_var.append([])
    desc_var[dest].append(mPrimal_Canonical_GUROBI.addVar(vtype=gbp.GRB.CONTINUOUS, 
                                    name='y'+str(dest+1)))
# Update Model
mPrimal_Canonical_GUROBI.update()

#Objective Function
mPrimal_Canonical_GUROBI.setObjective(gbp.quicksum(Cj[dest]*desc_var[dest][0] 
                        for dest in cols), 
                        gbp.GRB.MINIMIZE)
# Constraints
for orig in rows:
    mPrimal_Canonical_GUROBI.addConstr(gbp.quicksum(Aij[orig][dest]*desc_var[dest][0] 
                        for dest in cols) - Bi[orig] >= 0)
# Optimize
mPrimal_Canonical_GUROBI.optimize()
# Write LP file
mPrimal_Canonical_GUROBI.write('LP.lp')
print '\n*************************************************************************'
print '    |   Decision Variables'
for v in mPrimal_Canonical_GUROBI.getVars():
    print '    |  ', v.VarName, '=', v.x
print '*************************************************************************'
val = mPrimal_Canonical_GUROBI.objVal
print '    |   Objective Value ------------------ ', val
print '    |   Aij Sum -------------------------- ', AijSum
print '    |   Cj Sum --------------------------- ', CjSum
print '    |   Bi Sum --------------------------- ', BiSum
print '    |   Matrix Dimensions ---------------- ', Aij.shape
print '    |   Date/Time ------------------------ ', dt.datetime.now()
print '*************************************************************************'
print '-- Gurobi Canonical Primal Linear Programming Problem --'
print '\nJames Gaboardi, 2015'


Changed value of parameter MIPFocus to 2
   Prev: 0   Min: 0   Max: 3   Default: 0
Optimize a model with 5 rows, 5 columns and 25 nonzeros
Coefficient statistics:
  Matrix range    [5e+00, 5e+01]
  Objective range [1e+01, 2e+01]
  Bounds range    [0e+00, 0e+00]
  RHS range       [2e+01, 2e+01]
Presolve time: 0.00s
Presolved: 5 rows, 5 columns, 25 nonzeros

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    0.0000000e+00   1.421875e+00   0.000000e+00      0s
       2    8.6978673e+00   0.000000e+00   0.000000e+00      0s

Solved in 2 iterations and 0.01 seconds
Optimal objective  8.697867299e+00

*************************************************************************
    |   Decision Variables
    |   y1 = 0.0
    |   y2 = 0.387440758294
    |   y3 = 0.244075829384
    |   y4 = 0.0
    |   y5 = 0.0
*************************************************************************
    |   Objective Value ------------------  8.69786729858
    |   Aij Sum --------------------------  646
    |   Cj Sum ---------------------------  68
    |   Bi Sum ---------------------------  91
    |   Matrix Dimensions ----------------  (5, 5)
    |   Date/Time ------------------------  2015-08-20 15:57:33.917082
*************************************************************************
-- Gurobi Canonical Primal Linear Programming Problem --

James Gaboardi, 2015

2. Dual


In [4]:
# Instantiate Model
mDual_Canonical_GUROBI = gbp.Model(' -- Canonical Dual Linear Programming Problem -- ')

# Set Focus to Optimality
gbp.setParam('MIPFocus', 2)

# Decision Variables
desc_var = []
for dest in cols:
    desc_var.append([])
    desc_var[dest].append(mDual_Canonical_GUROBI.addVar(vtype=gbp.GRB.CONTINUOUS, 
                                    name='u'+str(dest+1)))
# Update Model
mDual_Canonical_GUROBI.update()

#Objective Function
mDual_Canonical_GUROBI.setObjective(gbp.quicksum(Bi[orig]*desc_var[orig][0] 
                        for orig in rows), 
                        gbp.GRB.MAXIMIZE)
# Constraints
for dest in cols:
    mDual_Canonical_GUROBI.addConstr(gbp.quicksum(Aij[orig][dest]*desc_var[dest][0] 
                        for orig in rows) - Cj[dest] <= 0)
# Optimize
mDual_Canonical_GUROBI.optimize()
# Write LP file
mDual_Canonical_GUROBI.write('LP.lp')
print '\n*************************************************************************'
print '    |   Decision Variables'
for v in mDual_Canonical_GUROBI.getVars():
    print '    |  ', v.VarName, '=', v.x
print '*************************************************************************'
val = mDual_Canonical_GUROBI.objVal
print '    |   Objective Value ------------------ ', val
print '    |   Aij Sum -------------------------- ', AijSum
print '    |   Cj Sum --------------------------- ', CjSum
print '    |   Bi Sum --------------------------- ', BiSum
print '    |   Matrix Dimensions ---------------- ', Aij.shape
print '    |   Date/Time ------------------------ ', dt.datetime.now()
print '*************************************************************************'
print '-- Gurobi Canonical Dual Linear Programming Problem --'
print '\nJames Gaboardi, 2015'


Parameter MIPFocus unchanged
   Value: 2   Min: 0   Max: 3   Default: 0
Optimize a model with 5 rows, 5 columns and 5 nonzeros
Coefficient statistics:
  Matrix range    [7e+01, 2e+02]
  Objective range [2e+01, 2e+01]
  Bounds range    [0e+00, 0e+00]
  RHS range       [1e+01, 2e+01]
Presolve removed 5 rows and 5 columns
Presolve time: 0.01s
Presolve: All rows and columns removed
Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    1.0189809e+01   0.000000e+00   0.000000e+00      0s

Solved in 0 iterations and 0.01 seconds
Optimal objective  1.018980898e+01

*************************************************************************
    |   Decision Variables
    |   u1 = 0.095652173913
    |   u2 = 0.0722222222222
    |   u3 = 0.110294117647
    |   u4 = 0.12676056338
    |   u5 = 0.150684931507
*************************************************************************
    |   Objective Value ------------------  10.189808983
    |   Aij Sum --------------------------  646
    |   Cj Sum ---------------------------  68
    |   Bi Sum ---------------------------  91
    |   Matrix Dimensions ----------------  (5, 5)
    |   Date/Time ------------------------  2015-08-20 15:57:37.578770
*************************************************************************
-- Gurobi Canonical Dual Linear Programming Problem --

James Gaboardi, 2015