我有一个简单的优化问题,我试图优化潜在客户的数量,每个潜在客户都有一定的成本(根据潜在客户的数量而变化,例如 1 个潜在客户可能花费 1 美元,而 2 个潜在客户可能花费每个 1.5 美元)。使用以下函数计算每个潜在客户的成本。这些评论是我为解决不同问题所做的尝试。
# Here x is leads and returns spend
def objective_inverse(x, a, b, c):
if c == 0:
return 0
else:
return np.real(a + (x/c)**(1./b))
这里是变量 reg_feats
,其中列表中的每个元组都是前一个函数中的 (a,b,c)
。
reg_feats = [(0.0, 1.0, 0.0008237661018136143), (0.9999999999999811, 0.8536915943397881, 0.004454688129841911), (0.0, 1.0, 0.0004855869694355375), (0.0, 1.0, 0.00038427101866404334), (8.308985001840891e-10, 1.097417548409198, 0.0009170956872015353), (0.999999999998488, 1.9999999897072056, 1.144122017534284e-07), (0.9999999999825329, 0.8097037523302283, 0.20606857088111075), (0.9999999999999963, 1.1649279015402045, 0.009316713936903972), (0.0, 1.0, 0.0034430519212229715), (0.0, 1.0, 0.0007980573950249244), (0.0, 1.0, 0.0009069008844368589)]
并且还有每个变量的界限的列表。
bounds = [(0, 4), (0, 20), (0, 3), (0, 1), (0, 114), (0, 14), (0, 208), (0, 529), (0, 1), (0, 4), (0, 4)]
这是优化的代码:
m = GEKKO(remote=not bool(i))
m.options.SOLVER=1
# optional solver settings with APOPT
m.solver_options = ['minlp_maximum_iterations 50000', \
# minlp iterations with integer solution
'minlp_max_iter_with_int_sol 100', \
# treat minlp as nlp
'minlp_as_nlp 0', \
# nlp sub-problem max iterations
'nlp_maximum_iterations 500', \
# 1 = depth first, 2 = breadth first
'minlp_branch_method 1', \
# maximum deviation from whole number
'minlp_integer_tol 0.05', \
# covergence tolerance
'minlp_gap_tol 0.01']
这里的 x 是每个广告系列的潜在客户数量。
x = m.Array(m.Var, (len(bounds)),integer=True)
# Here x is the number of leads and is the decision variable
# x variables are nb of leads, not $ to be allocated
for i, xi in enumerate(x):
lb, ub = bounds[i]
xi.lower = lb
xi.upper = ub
xi.value = ub
这个中间变量是获取每个潜在客户的成本。这在下一个约束中使用。
sums = [m.Intermediate(objective_inverse(xi,*y)) for xi,y in zip(x,reg_feats)]
max_budget = 150000
m.Maximize(m.sum(x))
c = m.Const(max_budget, 'Budget')
m.Equation(m.sum(sums) < c)
m.solve(disp=True)
在这里,如果我运行此代码,我会收到一条错误消息,指出没有找到解决方案,Warning: no more possible trial points and no integer solution
此外,如果我删除 max_budget
约束,我会得到一个解决方案,其中花费的总金额低于 max_budget
,这意味着添加约束不应改变解决方案。
我知道我如何定义约束存在问题,但不知道如何修复它。
答案 0 :(得分:1)
问题似乎不在于约束,而在于 x
的起点。当我运行你的代码时,我得到了解决方案(我没有收到任何错误)。但是当我将 max_budget
更改为 100000
时,开始出现相同的错误。我怀疑这是因为 APPT 需要一个很好的初始猜测。由于我没有很好的猜测,我使用 np.random
来生成起点。我尝试了几个不同的 max_budget
并且效果很好(虽然尝试了几次才获得一个好的初始点)。
import numpy as np
from gekko import GEKKO
# Here x is leads and returns spend
def objective_inverse(x, a, b, c):
if c == 0:
return 0
else:
return np.real(a + (x/c)**(1./b))
reg_feats = [(0.0, 1.0, 0.0008237661018136143), (0.9999999999999811, 0.8536915943397881, 0.004454688129841911), (0.0, 1.0, 0.0004855869694355375), (0.0, 1.0, 0.00038427101866404334), (8.308985001840891e-10, 1.097417548409198, 0.0009170956872015353), (0.999999999998488, 1.9999999897072056, 1.144122017534284e-07), (0.9999999999825329, 0.8097037523302283, 0.20606857088111075), (0.9999999999999963, 1.1649279015402045, 0.009316713936903972), (0.0, 1.0, 0.0034430519212229715), (0.0, 1.0, 0.0007980573950249244), (0.0, 1.0, 0.0009069008844368589)]
bounds = [(0, 4), (0, 20), (0, 3), (0, 1), (0, 114), (0, 14), (0, 208), (0, 529), (0, 1), (0, 4), (0, 4)]
m = GEKKO(remote=False)
m.options.SOLVER=1
# optional solver settings with APOPT
m.solver_options = ['minlp_maximum_iterations 50000', \
# minlp iterations with integer solution
'minlp_max_iter_with_int_sol 100', \
# treat minlp as nlp
'minlp_as_nlp 0', \
# nlp sub-problem max iterations
'nlp_maximum_iterations 500', \
# 1 = depth first, 2 = breadth first
'minlp_branch_method 1', \
# maximum deviation from whole number
'minlp_integer_tol 0.05', \
# covergence tolerance
'minlp_gap_tol 0.01']
x = m.Array(m.Var, (len(bounds)),integer=True)
# Here x is the number of leads and is the decision variable
# x variables are nb of leads, not $ to be allocated
for i, xi in enumerate(x):
lb, ub = bounds[i]
xi.lower = lb
xi.upper = ub
xi.value = np.random.randint(lb,ub)
print("Initial Value: ",x)
sums = [m.Intermediate(objective_inverse(xi,*y)) for xi,y in zip(x,reg_feats)]
max_budget = 90000
# max_budget = 100000
# max_budget = 120000
# max_budget = 150000
m.Maximize(m.sum(x))
c = m.Const(max_budget, 'Budget')
m.Equation(m.sum(sums) < c)
m.solve(disp=True)
x_ans =[i[0] for i in x]
print('x : ', x_ans)
print('Constraint: ', np.sum([(objective_inverse(xi,*y)) for xi,y in zip(x_ans,reg_feats)]))
输出:
Initial Value: [2 7 0 0 113 5 205 151 0 3 2]
----------------------------------------------------------------
APMonitor, Version 0.9.2
APMonitor Optimization Suite
----------------------------------------------------------------
--------- APM Model Size ------------
Each time step contains
Objects : 1
Constants : 1
Variables : 24
Intermediates: 11
Connections : 12
Equations : 24
Residuals : 13
Number of state variables: 24
Number of total equations: - 13
Number of slack variables: - 1
---------------------------------------
Degrees of freedom : 10
----------------------------------------------
Steady State Optimization with APOPT Solver
----------------------------------------------
Iter: 1 I: 0 Tm: 0.00 NLPi: 12 Dpth: 0 Lvs: 2 Obj: -8.85E+02 Gap: NaN
Iter: 2 I: 0 Tm: 0.00 NLPi: 3 Dpth: 1 Lvs: 3 Obj: -8.85E+02 Gap: NaN
Iter: 3 I: 0 Tm: 0.00 NLPi: 3 Dpth: 2 Lvs: 4 Obj: -8.85E+02 Gap: NaN
Iter: 4 I: 0 Tm: 0.00 NLPi: 3 Dpth: 3 Lvs: 5 Obj: -8.85E+02 Gap: NaN
Iter: 5 I: 0 Tm: 0.00 NLPi: 3 Dpth: 4 Lvs: 6 Obj: -8.84E+02 Gap: NaN
Iter: 6 I: 0 Tm: 0.00 NLPi: 3 Dpth: 5 Lvs: 7 Obj: -8.84E+02 Gap: NaN
--Integer Solution: -8.84E+02 Lowest Leaf: -8.85E+02 Gap: 8.39E-04
Iter: 7 I: 0 Tm: 0.00 NLPi: 2 Dpth: 6 Lvs: 7 Obj: -8.84E+02 Gap: 8.39E-04
Successful solution
---------------------------------------------------
Solver : APOPT (v1.0)
Solution time : 0.0677 sec
Objective : -884.
Successful solution
---------------------------------------------------
x : [0.0, 18.0, 0.0, 0.0, 114.0, 14.0, 208.0, 529.0, 1.0, 0.0, 0.0]
Constraint: 89187.87455034524
我知道如果没有良好的初始猜测,随机生成起点对于更大的问题可能不可行。但不幸的是,我不知道在这种情况下如何使用 APOT。