简体   繁体   中英

Constrained Optimization Problem : Python

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

f=a x+b y+c*z

and a constraint

l x+m y+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 ?

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.

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])

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM