【问题标题】:Gekko optimization constraint with self-defined function具有自定义函数的 Gekko 优化约束
【发布时间】:2021-07-29 03:17:34
【问题描述】:

我目前正在尝试使用 Gekko 解决混合整数非线性问题,使用它的 Branch&Bound 实现加上它的热启动方法,以加快和改进与 vanilla branch&bound 相比的收敛过程。 该算法会在很短的时间内找到解决方案。然而,它伤害了我可能错误定义的约束:我有一个 gekko 数组变量 X,需要另一个 gekko 数组变量“indices_open”来保存 x == 1 的 x 的每个索引。这个“indices_open”进入另一个自定义函数,它期望“indices_open”作为一个 numpy 数组并且不接受 gekko 中间变量的列表或 gekko 数组。自定义函数返回一个numpy数组。这个最终数组将在 m.Equations 中使用,因此我将它转换为一个 gekko 变量数组。 不用说,出了点问题,当前的解决方案损害了不等式约束,同时满足了等式约束。在分析结果时,我得出的结论是“indices_open”似乎在每次迭代中都没有更新。

到目前为止我的尝试如下:

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

【问题讨论】:

    标签: python python-3.x optimization gekko


    【解决方案1】:

    有一个未定义的函数_, arr_2, arr_3, arr_4 = self_defined_f(indices_open,some_value ) 阻止代码运行。快速扫描代码,如下表达式:

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

    是不允许的,因为 gekko 要求所有方程都在 m.solve() 命令之前定义。不允许在 Python 中回调函数。相反,二进制变量应该用于在优化问题中打开或关闭某些东西。这可以是等式,例如二进制变量b:

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

    如果x 小于零,则b 的值等于0,如果x 大于零,则b 等于1。 APMonitor documentation 中有一个关于 if3() 函数的教程,可能也有用。

    【讨论】:

    • 谢谢。我已经通读了文档并看到了 if2 和 if3 功能,但发现很难将它们与我当前的问题联系起来:我基本上需要 x(gekko 数组)等于 1 的索引。我尝试了几个 gekko 数组的东西就像其他 numpy 操作(如 np.diag 和 np.inner)似乎可以与 gekko 一起使用,但代码“indices_open = np.where(x == 1)”似乎无法正常工作。之后,这个新数组将不得不进入“self_defined_f(indices_open, some_value)”,这不起作用。
    • 很棒的观察。您是正确的,某些函数可以工作,因为结果是不变的(不随值变化)与变体(符号输​​出随值变化)。在这种情况下,np.where 输出会根据 x 的值而变化,因此不允许这样做。
    猜你喜欢
    • 1970-01-01
    • 2018-05-03
    • 2017-11-10
    • 2015-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    相关资源
    最近更新 更多