Linear Programming in Python

07 Dec 2018

interesting stuff!! have not used my Excel Solver sinceā€¦ forever. LOL


Check out Pulp for intuitive linear programming:

https://github.com/coin-or/pulp


from pulp import LpVariable, LpProblem, LpMinimize, value

x = LpVariable("x", 0, 3)
y = LpVariable("y", 0, 1)

# create problem
prob = LpProblem("myProblem", LpMinimize)
# add constraint
prob += x + y <= 2
# define objective
prob += -4*x + y
# solve
status = prob.solve()

# print results
print(f'x = {value(x)}, y = {value(y)}')


Check out scipy for Constrained minimization of multivariate scalar functions. Matrix multiplication is back to haunt me lol - was never very good at them.

https://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html


import numpy as np
from scipy.optimize import Bounds, LinearConstraint, NonlinearConstraint, minimize, rosen, rosen_der, rosen_hess

bounds = Bounds([0, -0.5], [1.0, 2.0])
linear_constraint = LinearConstraint([[1, 2], [2, 1]], [-np.inf, 1], [1, 1])

def cons_f(x):
    return [x[0]**2 + x[1], x[0]**2 - x[1]]
def cons_J(x):
    return [[2*x[0], 1], [2*x[0], -1]]
def cons_H(x, v):
    return v[0]*np.array([[2, 0], [0, 0]]) + v[1]*np.array([[2, 0], [0, 0]])

nonlinear_constraint = NonlinearConstraint(cons_f, -np.inf, 1, jac=cons_J, hess=cons_H)

x0 = np.array([0.5, 0])

res = minimize(rosen, x0, method='trust-constr', jac=rosen_der, hess=rosen_hess,
               constraints=[linear_constraint, nonlinear_constraint],
               options={'verbose': 1}, bounds=bounds)

print(res.x)


oh my - for beginners, check THIS out instead for scipy optimise if you need to solve for vectors: https://www.youtube.com/watch?v=cXHvC_FGx24

helped me immensely in my very beginner try to code some optimisation down below:


from pulp import LpVariable, LpProblem, LpMinimize, value

exp1sec = LpVariable("exp1sec", 0, 1000)
exp1unsec = LpVariable("exp1unsec", 0, 1000)
exp2sec = LpVariable("exp2sec", 0, 1000)
exp2unsec = LpVariable("exp2unsec", 0, 1000)

# create problem
prob = LpProblem("myProblem", LpMinimize)
# add constraint
prob += exp1sec + exp1unsec == 160 # exp1 must add up
prob += exp2sec + exp2unsec == 90 # exp2 must add up
prob += exp1sec + exp2sec == 150 # sec must add up
prob += exp1unsec + exp2unsec == 100 # unsec must add up

# define objective
sec_weight = 0.1
unsec_weight = 1
prob += (sec_weight*exp1sec + unsec_weight*exp1unsec) + (sec_weight*exp2sec + unsec_weight*exp2unsec)
# solve
status = prob.solve()

# print results
print(f"""exp1sec = {value(exp1sec)}, exp1unsec = {value(exp1unsec)}, 
      exp2sec = {value(exp2sec)}, exp2unsec = {value(exp2unsec)}""")


if you have a variable number of variables (oh my) you can use vectors instead. In the example below, I have 4 variables to solve (the length of the array x is 4).

import numpy as np
from scipy.optimize import minimize

def obj(x):
    """The objective function"""
    weight_for_sec = np.array([0.1, 0.1, 0.1, 0.1])
    weight_for_unsec = np.array([1, 1, 1, 1])
    exposure_sec = x
    exposure_unsec = np.array([160, 90, 150, 100]) - exposure_sec
    return np.sum(weight_for_sec * exposure_sec + weight_for_unsec * exposure_unsec)

def sec_total_contraint(x):
    """Sec must all add up"""
    return np.sum(x) - 300

con1 = {'type':'eq', 'fun': sec_total_contraint}
cons = [con1]

bnds = ((0, 160), (0, 90), (0, 150), (0, 100))

x0 = np.array([1, 1, 1, 1]) #initial guess

sol = minimize(obj, x0, method='SLSQP', 
               bounds=bnds, constraints=cons)

print(sol.x)


one more level up - if you want x to be a matrix, check out my repo hoho: https://github.com/yinglinglow/proj_linearprog

bonus - there is an excel sheet in the repo that helped me tremendously to figure things out. check it out!

also in other news: happy 2019!!