Arindam
Arindam

Reputation: 326

Constrained Optimization Problem : Python

I am sure , there must be a simple solution that keeps evading me. I have a function

f=ax+by+c*z

and a constraint

lx+my+n*z=B

Need to find the (x,y,z), that maximizes f subject to the constraint. I also need

x,y,z>=0

I remember having seen a solution like this. This example uses

a,b,c=2,4,10 and l,m,n=1,2,4 and B=5

Ideally, this should give me x=1,y=0 , z=1, such that f=12

import numpy as np
from scipy.optimize import minimize
def objective(x, sign=-1.0):
    x1 = x[0]
    x2 = x[1]
    x3 = x[2]
    return sign*((2*x1) + (4*x2)+(10*x3))
def constraint1(x, sign=1.0):
    return sign*(1*x[0] +2*x[1]+4*x[2]- 5)

x0=[0,0,0]

b1 = (0,None)
b2 = (0,None)
b3=(0,None)
bnds= (b1,b2,b3)
con1 = {'type': 'ineq', 'fun': constraint1}

cons = [con1]
sol = minimize (objective,x0,method='SLSQP',bounds=bnds,constraints=cons)

print(sol)

This is generating bizarre solution. What am I missing ?

Upvotes: 2

Views: 1721

Answers (3)

chthonicdaemon
chthonicdaemon

Reputation: 19820

The problem as you stated originally without integer constraints can be solved simply and efficiently by linprog:

import scipy.optimize

c = [-2, -4, -10]
A_eq = [[1, 2, 4]]
b_eq = 5

# bounds are for non-negative values by default

scipy.optimize.linprog(c, A_eq=A_eq, b_eq=b_eq)

I would recommend against using more general purpose solvers to solve narrow problems like this as you will often encounter worse performance and sometimes unexpected results.

Upvotes: 1

Ladi Oyeleye
Ladi Oyeleye

Reputation: 154

Like Jeff said, scipy.optimize only works with linear programming problems.

You can try using PuLP instead for Integer Optimization problems:

from pulp import *

prob = LpProblem("F Problem", LpMaximize)

# a,b,c=2,4,10 and l,m,n=1,2,4 and B=5
a,b,c=2,4,10
l,m,n=1,2,4
B=5

# x,y,z>=0
x = LpVariable("x",0,None,LpInteger)
y = LpVariable("y",0,None,LpInteger)
z = LpVariable("z",0,None,LpInteger)

# f=ax+by+c*z
prob += a*x + b*y + c*z, "Objective Function f"

# lx+my+n*z=B
prob += l*x + m*y + n*z == B, "Constraint B"

# solve
prob.solve()

print("Status:", LpStatus[prob.status])

for v in prob.variables():
  print(v.name, "=", v.varValue)

Documentation is here: enter link description here

Upvotes: 0

AirSquid
AirSquid

Reputation: 11938

You need to change your constraint to an 'equality constraint'. Also, your problem didn't specify that integer answers were required, so there is a better non-integer answer to this knapsack problem. (I don't have much experience with scipy.optimize and I'm not sure if it can work integer LP problems.)

In [13]: con1 = {'type': 'eq', 'fun': constraint1}                                               

In [14]: cons = [con1,]                                                                          

In [15]: sol = minimize (objective,x0,method='SLSQP',bounds=bnds,constraints=cons)               

In [16]: print(sol)                                                                              
     fun: -12.5
     jac: array([ -2.,  -4., -10.])
 message: 'Optimization terminated successfully.'
    nfev: 10
     nit: 2
    njev: 2
  status: 0
 success: True
       x: array([0.  , 0.  , 1.25])

Upvotes: 0

Related Questions