簡體   English   中英

帶有自定義 function 的 Gekko 優化約束

[英]Gekko optimization constraint with self-defined function

我目前正在嘗試使用 Gekko 解決混合 Integer 非線性問題,使用它的 Branch&Bound 實現加上它的熱啟動方法來加速和改進與 vanilla branch&bound 相比的收斂過程。 該算法會在很短的時間內找到解決方案。 然而,它傷害了我可能錯誤定義的約束:我有一個 gekko 數組變量 X,需要另一個 gekko 數組變量“indices_open”來保存 x == 1 的 x 的每個索引。這個“indices_open”進入另一個自定義 function 期望“indices_open”作為 numpy 數組,並且不接受 gekko 中間變量的列表或 gekko 數組。 自定義function返回一個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

有一個未定義的 function _, 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 中的 function 進行回調。 相反,二進制變量應該用於在優化問題中打開或關閉某些東西。 這可以是一個方程,例如二進制變量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 文檔中有一個關於if3()函數的教程,它也可能很有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM