简体   繁体   English

带有自定义 function 的 Gekko 优化约束

[英]Gekko optimization constraint with self-defined function

I am currently trying to solve a Mixed Integer Non Linear Problem with Gekko using its Branch&Bound implementation coupled with its warm-start method to speed up and improve the convergence process compared to vanilla branch& bound.我目前正在尝试使用 Gekko 解决混合 Integer 非线性问题,使用它的 Branch&Bound 实现加上它的热启动方法来加速和改进与 vanilla branch&bound 相比的收敛过程。 The algorithm finds a solution after a short amount of time.该算法会在很短的时间内找到解决方案。 Nevertheless, it hurts the constraint, which I might have defined wrongly: I have a gekko array-variable X and need another gekko array-variable "indices_open" that saves every index of x where x == 1. This "indices_open" goes into another self-defined function which is expecting "indices_open" as an numpy array and does not accept a list or gekko-array of gekko-intermediate variables.然而,它伤害了我可能错误定义的约束:我有一个 gekko 数组变量 X,需要另一个 gekko 数组变量“indices_open”来保存 x == 1 的 x 的每个索引。这个“indices_open”进入另一个自定义 function 期望“indices_open”作为 numpy 数组,并且不接受 gekko 中间变量的列表或 gekko 数组。 The self-defined function returns a numpy array.自定义function返回一个numpy数组。 This final array shall be used in m.Equations and I therefore cast it to a gekko variable array.这个最终数组将在 m.Equations 中使用,因此我将它转换为一个 gekko 变量数组。 Needless to say, something went wrong and the current solution hurts the inequality constraint, while the equality constraint is met.不用说,出了点问题,当前的解决方案损害了不等式约束,同时满足了等式约束。 While analyzing the result, I came to the conclusion that "indices_open" seems not to have updated in each iteration.在分析结果时,我得出的结论是“indices_open”似乎在每次迭代中都没有更新。

In the following my try so far:以下是我迄今为止的尝试:

m = GEKKO()
m.options.SOLVER = 1  # APOPT is an MINLP solver
# optional solver settings with APOPT
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']

#Declare x
x = m.Array(m.Var,(65),lb=0,ub=1,integer=True)
for i, xi in enumerate(x[0:65]):
    xi.value = np.random.choice(np.arange(0, 2), 1, p=[0.4, 0.6])[0]
#constr
m = ineq_constraint_new(x, m)
m = eq_constraint_new(x, m)

#target
m = objective(x,m)

#STArt
start_time = time.time()
#m.solve(disp=False)
m.solve()
print('Objective: ' + x)
print('Objective: ' + str(m.options.objfcnval))

# save x
m.x = [x[j].value[0] for j in range(65)]


def eq_constraint_new(x, m):

    mask = np.isin(list_unique, specific_value)
    indices_fixed = np.nonzero(mask)[0]
    m.Equations([x[j] == 1 for j in indices_fixed])

    return m

def ineq_constraint_new(x, m):

    indices_open = [j for j in range(65) if x[j].value == 1]
    # DOes not work
    #indices_open_banks = [m.Intermediate(j) for j in range(65) if x[j].value == 1]
    array_perc, _, _,_ = self_defined_f(indices_open, some_value)

    #convert to gekko variables
    gekko_vec_perc_upper_bound = m.Array(m.Var, (65))
    for i, xi in enumerate(gekko_vec_perc_upper_bound[0:65]):
        xi.value = some_array[i]

    gekko_arr_perc = m.Array(m.Var, (65))
    for i, xi in enumerate(gekko_arr_perc[0:65]):
        xi.value = arr_perc[i]

    diff = gekko_vec_perc_upper_bound - gekko_arr_perc

    m.Equations([diff[j] >= 0 for j in range(65)])
    
    return m

def objective(x,m):

    
    indices_open = [j for j in range(65) if x[j].value == 1]

    
    _, arr_2, arr_3, arr_4 = self_defined_f(indices_open,some_value )

    # intermediates for objective
    res_dist = [None] * self.ds.n_banks
    res_wand = [None] * self.ds.n_banks
    res_wand_er = [None] * self.ds.n_banks
    
    x_closed = np.array([1]*len(x)) - x

    for j in range(self.ds.n_banks):
        res_dist[j] = m.Intermediate(arr_2[j] * some_factor  )
        res_wand[j] = m.Intermediate(arr_3[j] * some_factor)
        res_wand_er[j] = m.Intermediate(arr_4[j] * some_factor)

    res_sach = some_factor * (some_vector * x_closed)

    # Will be added together
    m.Minimize(sum(res_dist))
    m.Minimize(sum(res_wand))
    m.Minimize(sum(res_wand_er))
    m.Maximize(sum(res_sach))

    return m

There is an undefined function _, arr_2, arr_3, arr_4 = self_defined_f(indices_open,some_value ) that prevents the code from running.有一个未定义的 function _, arr_2, arr_3, arr_4 = self_defined_f(indices_open,some_value )阻止代码运行。 From a quick scan of the code, an expression like:通过快速扫描代码,可以看到如下表达式:

indices_open = [j for j in range(65) if x[j].value == 1]

is not allowed because gekko requires that the equations are all defined before the m.solve() command.不允许,因为 gekko 要求所有方程都在m.solve()命令之前定义。 A callback to a function in Python is not allowed.不允许对 Python 中的 function 进行回调。 Instead, binary variables should be used to turn something On or Off in the optimization problem.相反,二进制变量应该用于在优化问题中打开或关闭某些东西。 This can be an equation such as binary variable b :这可以是一个方程,例如二进制变量b

b = m.Var(lb=0,ub=1,integer=True)
m.Equation(x*(1-b)<=0)
m.Equation(x*b>=0)

This makes the value of b equal to 0 if x is less than zero and b equal to 1 if x if greater than zero.这使得如果x小于零,则b的值等于 0,如果x大于零,则b等于 1。 There is a tutorial on if3() functions in theAPMonitor documentation that may also be useful. APMonitor 文档中有一个关于if3()函数的教程,它也可能很有用。

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

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