![](/img/trans.png)
[英]Formulate a nonlinear optimization problem in Python (gekko) and with m.Equations
[英]Python GEKKO: optimizing performance of nonlinear optimization
我正在使用GEKKO
解决非线性规划问题。 我的目标是将GEKKO
的性能与替代产品进行比较,因此我想确保我从GEKKO
那里得到它所能提供的最好的。
有n个二进制变量,每个变量都分配了一个权重,每个权重都是区间[0, 1]中的一个数(即满足0<= w <= 1的有理数w )。 每个约束都是线性的。 目标 function 是非线性的:它是非零变量权重的乘积,目标是使乘积最大化。
我首先将目标 function 指定为
m.Obj(-np.prod([1 - variables[i] + weights[i] * variables[i] for i in range(len(variables))]))
但后来我会碰到APM model error: string > 15000 characters
。 所以我使用if3
function 切换到辅助变量
aux_variables = [m.if3(variables[i], weights[i], 1) for i in range(len(variables))]
m.Obj(-np.prod(aux_variables))
我手动设置的唯一全局参数在以下代码中。
# initialize model
m = GEKKO(remote=False)
# set global variables
m.options.SOLVER = 1 # APOPT solver
# "APOPT is an MINLP solver"
# "APOPT is also the only solver that handles Mixed Integer problems."
m.options.IMODE = 3 # steady state optimization
m.solver_options = ['minlp_maximum_iterations 500', \
# minlp iterations with integer solution
'minlp_max_iter_with_int_sol 10', \
# treat minlp as nlp
'minlp_as_nlp 0', \
# nlp sub-problem max iterations
'nlp_maximum_iterations 50', \
# 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']
# initialize variables
variables = m.Array(m.Var, (number_of_vars), lb=0, ub=1, integer=True)
# set initial values
for var in variables:
var.value = 1
问题:
就全局参数和目标 function 的制定而言,我还能做些什么来优化GEKKO
针对这个特定问题的性能?
同时,我希望GEKKO
能取得不错的成绩。
重新制定问题以提高速度的一种方法是使用中间变量。
原始(0.0325 秒,# Var=5)
m.Obj(-np.prod([1 - variables[i] + weights[i] * variables[i] \
for i in range(len(variables))]))
修改(0.0156 秒,# Var=5)
ival = [m.Intermediate(1 - variables[i] + weights[i] * variables[i]) \
for i in range(len(variables))]
m.Obj(-np.prod(ival))
这也应该可以帮助您避免字符串长度的问题,除非您的number_of_vars
非常大。 似乎最优解总是variables[i]=1
当weights[i]=1
和variables[i]=0
当weights[i]=0
时。 使用np.prod
这意味着整个目标 function 为零是任何一个乘积项为零。 将单个产品值设置为1
而不是使用目标 function 来查找值是否有帮助? 帮助 APPT 找到正确解决方案的一件事是在中间声明中使用类似1.1
的东西,而不是1.0
。 因此,当您最大化时,它会尝试避免0.1
值,以寻找给出1.1
的解决方案。
from gekko import GEKKO
import numpy as np
m = GEKKO(remote=False)
number_of_vars = 5
weights = [0,1,0,1,0]
m.options.IMODE = 3
variables = m.Array(m.Var, (number_of_vars), lb=0, ub=1, integer=True)
for var in variables:
var.value = 1
ival = [m.Intermediate(1.1 - variables[i] + weights[i] * variables[i]) \
for i in range(len(variables))]
# objective function
m.Obj(-np.prod(ival))
# integer solution with APOPT
m.options.SOLVER = 1
m.solver_options = ['minlp_maximum_iterations 500', \
# minlp iterations with integer solution
'minlp_max_iter_with_int_sol 10', \
# treat minlp as nlp
'minlp_as_nlp 0', \
# nlp sub-problem max iterations
'nlp_maximum_iterations 50', \
# 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']
m.solve()
print(variables)
求解器也更容易找到求和的解决方案,例如m.sum()
并且它提供与np.prod()
选项相同的variables
解决方案。
# objective function
m.Obj(-m.sum(ival))
您可以添加一条后处理线来恢复产品目标 function ,该目标将为0
或1
。
if3
function 不是您应用的好选择,因为开关条件为 0,轻微的数值变化会导致结果不可靠。 根据选项minlp_integer_tol=0.05
,求解器将0
到0.05
和0.95
到1
视为 integer 解。 当 integer 值足够接近时,此选项允许接受 integer 解决方案。 如果variables[i]
值为0.01
,则if3
function 将选择True
选项,而 select 将选择False
选项。 如果您在诸如m.if3(variables[i]-0.5, weights[i], 1)
之类的二进制值之间进行了切换点,您仍然可以使用if3
function 。 但是,有比使用if3
function 更简单的方法来解决您的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.