约束在使用 Scipy 的优化中不起作用
Constraints not working in Optimization using Scipy
我正在尝试解决利润最大化问题。公司有一些促销计划运行。我制作了一个 objective 函数,用于在某些限制条件下实现利润最大化。我想做一个限制,说公司不能 运行 并行超过 2 个促销计划。然而这个条件不起作用
这是我的代码:
from scipy.optimize import minimize
from math import floor
#Objective function
def objective(x):
return -((-14.12*x[0]+1*floor(x[1])+2*floor(x[2])+4*floor(x[3]))*x[0] \ #total revenue (qty*price)
-(-14.12*x[0]+1*floor(x[1])+2*floor(x[2])+4*floor(x[3]))*10000*0.05\ #Gold price cost
-(-14.12*x[0]+1*floor(x[1])+2*floor(x[2])+4*floor(x[3]))*x[0]*0.1\ #Rebate cost
-(-14.12*x[0]+1*floor(x[1])+2*floor(x[2])+4*floor(x[3])/15000*100000))
#Points constraint
#Constraints
def PriceConstraint(x):
return x[0]-3000
def GoldCoinConstraint(x):
return floor(x[1])-1
def PointsConstraint(x):
return floor(x[2])-1
def ProgressiveRebateConstraint(x):
return floor(x[3])-1
def CombinationConstraint(x):
return 2-floor(x[1])+floor(x[2])+floor(x[3])
#Initial guesses
n=5
x0=np.zeros(5)
x0[0]=1
x0[1]=2
x0[2]=2
x0[3]=1
x0[4]=3
# show initial objective
print('Initial Objective: ' + str(objective(x0)))
# optimize
b = (0.0,1.0)
pricebound = (1,3000)
bnds = (pricebound, b, b, b,b)
con1= {'type':'ineq','fun':PriceConstraint}
con2= {'type':'ineq','fun':GoldCoinConstraint}
con3= {'type':'ineq','fun':PointsConstraint}
con4= {'type':'ineq','fun':ProgressiveRebateConstraint}
con5= {'type':'ineq','fun':CombinationConstraint}
cons = ([con1, con2, con3, con4, con5])
solution = minimize(objective,x0,method='SLSQP',\
bounds=bnds,constraints=cons)
x = solution.x
# show final objective
print('Final Objective: ' + str(objective(x)))
# print solution
print('Solution')
print('x1 = ' + str(x[0]))
print('x2 = ' + str(x[1]))
print('x3 = ' + str(x[2]))
print('x4 = ' + str(x[3]))
如您所见,我使用 combinationconstrain 函数限制了营销方案的数量不应超过 2 个。不知何故它似乎没有工作? x[1]、x[2] 和 x[3] 的输出为 1。
谁能帮我看看为什么这不起作用?
另一种思路是非线性优化中有影子价格之类的东西。我知道它存在于线性规划中,但不确定非线性?
2-floor(x[1])+floor(x[2])+floor(x[3])
应该可以阅读
2-(floor(x[1])+floor(x[2])+floor(x[3]))
这并不能真正帮助你。当你 运行 它时,你可能会得到类似的东西:
fun: -976376.097853337
jac: array([567.265625, 0. , 0. , 0. , 0. ])
message: 'Positive directional derivative for linesearch'
nfev: 32
nit: 7
njev: 3
status: 8
success: False
x: array([300.9, 1. , 1. , 1. , 1. ])
您的 floor
函数导致问题 non-differentiable。 SLSQP 只喜欢平滑的问题(即可微)。
我认为你的问题实际上是一个 Mixed-Integer 二次规划问题。所以我建议 而不是 使用连续 NLP 求解器而不是 MIQP 求解器来解决这个问题。这样你就不需要 floor
函数了。不幸的是 scipy 不包含 MIQP 求解器。
问:非线性优化中有影子价格之类的东西吗?
A:是的,对于连续性问题,大多数 NLP 求解器可以提供对偶或影子价格(scipy 求解器不这样做 afaik)。对偶不适用于离散问题。
我正在尝试解决利润最大化问题。公司有一些促销计划运行。我制作了一个 objective 函数,用于在某些限制条件下实现利润最大化。我想做一个限制,说公司不能 运行 并行超过 2 个促销计划。然而这个条件不起作用
这是我的代码:
from scipy.optimize import minimize
from math import floor
#Objective function
def objective(x):
return -((-14.12*x[0]+1*floor(x[1])+2*floor(x[2])+4*floor(x[3]))*x[0] \ #total revenue (qty*price)
-(-14.12*x[0]+1*floor(x[1])+2*floor(x[2])+4*floor(x[3]))*10000*0.05\ #Gold price cost
-(-14.12*x[0]+1*floor(x[1])+2*floor(x[2])+4*floor(x[3]))*x[0]*0.1\ #Rebate cost
-(-14.12*x[0]+1*floor(x[1])+2*floor(x[2])+4*floor(x[3])/15000*100000))
#Points constraint
#Constraints
def PriceConstraint(x):
return x[0]-3000
def GoldCoinConstraint(x):
return floor(x[1])-1
def PointsConstraint(x):
return floor(x[2])-1
def ProgressiveRebateConstraint(x):
return floor(x[3])-1
def CombinationConstraint(x):
return 2-floor(x[1])+floor(x[2])+floor(x[3])
#Initial guesses
n=5
x0=np.zeros(5)
x0[0]=1
x0[1]=2
x0[2]=2
x0[3]=1
x0[4]=3
# show initial objective
print('Initial Objective: ' + str(objective(x0)))
# optimize
b = (0.0,1.0)
pricebound = (1,3000)
bnds = (pricebound, b, b, b,b)
con1= {'type':'ineq','fun':PriceConstraint}
con2= {'type':'ineq','fun':GoldCoinConstraint}
con3= {'type':'ineq','fun':PointsConstraint}
con4= {'type':'ineq','fun':ProgressiveRebateConstraint}
con5= {'type':'ineq','fun':CombinationConstraint}
cons = ([con1, con2, con3, con4, con5])
solution = minimize(objective,x0,method='SLSQP',\
bounds=bnds,constraints=cons)
x = solution.x
# show final objective
print('Final Objective: ' + str(objective(x)))
# print solution
print('Solution')
print('x1 = ' + str(x[0]))
print('x2 = ' + str(x[1]))
print('x3 = ' + str(x[2]))
print('x4 = ' + str(x[3]))
如您所见,我使用 combinationconstrain 函数限制了营销方案的数量不应超过 2 个。不知何故它似乎没有工作? x[1]、x[2] 和 x[3] 的输出为 1。
谁能帮我看看为什么这不起作用?
另一种思路是非线性优化中有影子价格之类的东西。我知道它存在于线性规划中,但不确定非线性?
2-floor(x[1])+floor(x[2])+floor(x[3])
应该可以阅读
2-(floor(x[1])+floor(x[2])+floor(x[3]))
这并不能真正帮助你。当你 运行 它时,你可能会得到类似的东西:
fun: -976376.097853337
jac: array([567.265625, 0. , 0. , 0. , 0. ])
message: 'Positive directional derivative for linesearch'
nfev: 32
nit: 7
njev: 3
status: 8
success: False
x: array([300.9, 1. , 1. , 1. , 1. ])
您的 floor
函数导致问题 non-differentiable。 SLSQP 只喜欢平滑的问题(即可微)。
我认为你的问题实际上是一个 Mixed-Integer 二次规划问题。所以我建议 而不是 使用连续 NLP 求解器而不是 MIQP 求解器来解决这个问题。这样你就不需要 floor
函数了。不幸的是 scipy 不包含 MIQP 求解器。
问:非线性优化中有影子价格之类的东西吗?
A:是的,对于连续性问题,大多数 NLP 求解器可以提供对偶或影子价格(scipy 求解器不这样做 afaik)。对偶不适用于离散问题。