简体   繁体   English

Python GEKKO:非线性优化的优化性能

[英]Python GEKKO: optimizing performance of nonlinear optimization

I'm using GEKKO for solving a nonlinear programming problem.我正在使用GEKKO解决非线性规划问题。 My goal is to compare the GEKKO performance with an alternative, and so I want to make sure that I'm getting from GEKKO the best it can offer.我的目标是将GEKKO的性能与替代产品进行比较,因此我想确保我从GEKKO那里得到它所能提供的最好的。

There are n binary variables, each of them is assigned a weight, each of the weights is a number from the interval [0, 1] (ie, a rational number w satisfying 0<= w <= 1 ).n个二进制变量,每个变量都分配了一个权重,每个权重都是区间[0, 1]中的一个数(即满足0<= w <= 1的有理数w )。 Each of the constraints is linear.每个约束都是线性的。 The objective function is non-linear: it is the product of weights of the non-zero variables, and the goal is to maximize the product.目标 function 是非线性的:它是非零变量权重的乘积,目标是使乘积最大化。

I started with specifying the objective function as我首先将目标 function 指定为

m.Obj(-np.prod([1 - variables[i] + weights[i] * variables[i] for i in range(len(variables))]))

but then I would bump into APM model error: string > 15000 characters .但后来我会碰到APM model error: string > 15000 characters So I switched to auxiliary variables using the if3 function as所以我使用if3 function 切换到辅助变量

aux_variables = [m.if3(variables[i], weights[i], 1) for i in range(len(variables))]
m.Obj(-np.prod(aux_variables))

The only global parameters that I'm setting manually are in the following code.我手动设置的唯一全局参数在以下代码中。

# 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

Question:问题:

what more, if anything, can I do, in terms of global parameters and formulation of the objective function, to optimize the GEKKO 's performance for this particular problem?就全局参数和目标 function 的制定而言,我还能做些什么来优化GEKKO针对这个特定问题的性能?

At the same time, I would love GEKKO to produce decent results.同时,我希望GEKKO能取得不错的成绩。

One way to reformulate your problem for increased speed is to use Intermediate variables.重新制定问题以提高速度的一种方法是使用中间变量。

Original (0.0325 sec with # Var=5)原始(0.0325 秒,# Var=5)

m.Obj(-np.prod([1 - variables[i] + weights[i] * variables[i] \
      for i in range(len(variables))]))

Modified (0.0156 sec with # Var=5)修改(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))

This should also help you avoid the problem with string length, unless you have number_of_vars that is very large.这也应该可以帮助您避免字符串长度的问题,除非您的number_of_vars非常大。 It seems that the optimal solution will always be variables[i]=1 when weights[i]=1 and variables[i]=0 when weights[i]=0 .似乎最优解总是variables[i]=1weights[i]=1variables[i]=0weights[i]=0时。 With np.prod this means that the entire objective function is zero is any one of the product terms are zero.使用np.prod这意味着整个目标 function 为零是任何一个乘积项为零。 Would it help to set the individual product values equal to 1 instead of using the objective function to find the values?将单个产品值设置为1而不是使用目标 function 来查找值是否有帮助? One thing that helps APOPT find a correct solution is to use something like 1.1 in your intermediate declaration instead of 1.0 .帮助 APPT 找到正确解决方案的一件事是在中间声明中使用类似1.1的东西,而不是1.0 So that when you are maximizing, it tries to avoid 0.1 values in favor of finding a solution that gives 1.1 .因此,当您最大化时,它会尝试避免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)

It is also much easier for a solver to find a solution to a summation such as m.sum() and it gives the same variables solution as the np.prod() option.求解器也更容易找到求和的解决方案,例如m.sum()并且它提供与np.prod()选项相同的variables解决方案。

# objective function
m.Obj(-m.sum(ival))

You could add a post-process line to recover product objective function that will be either 0 or 1 .您可以添加一条后处理线来恢复产品目标 function ,该目标将为01

The if3 function isn't a good option for your application because the switching condition is at 0 and slight numerical variations will cause unreliable results. if3 function 不是您应用的好选择,因为开关条件为 0,轻微的数值变化会导致结果不可靠。 The solver considers 0 to 0.05 and 0.95 to 1 to be integer solutions according to the option minlp_integer_tol=0.05 .根据选项minlp_integer_tol=0.05 ,求解器将00.050.951视为 integer 解。 This is an option that allows integer solutions to be accepted when they are close enough to an integer value.当 integer 值足够接近时,此选项允许接受 integer 解决方案。 If the variables[i] value is 0.01 then the if3 function will chose the True option when it should select the False option.如果variables[i]值为0.01 ,则if3 function 将选择True选项,而 select 将选择False选项。 You could still use the if3 function if you made the switch point between the binary values such as m.if3(variables[i]-0.5, weights[i], 1) .如果您在诸如m.if3(variables[i]-0.5, weights[i], 1)之类的二进制值之间进行了切换点,您仍然可以使用if3 function 。 However, there are easier ways to solve your problem than using the if3 function.但是,有比使用if3 function 更简单的方法来解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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