且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Gekko找不到小问题的解决方案

更新时间:2023-11-15 20:45:52

有时候,求解器需要更好的初始猜测或选择范围的帮助,以避开有问题的解决方案.只需一个求解器调用,即可帮助解决问题.

Sometimes solvers need help with a better initial guess or selective bounds to stay away from problematic solutions. Here is something that helps solve the problem with only one solver call.

lower = [0,0,4,0,0]
for i in range(ni):
    for j in range(nj):
        x[i][j].value = 5
        x[i][j].lower = lower[j]
        x[i][j].upper = 20

如果将所有发电单元的下限都设置为零,我总是会收到infeasible solution消息.求解器似乎卡在全零的试用解或全部低于某个阈值时.在这种情况下,我必须将中间单元的边界设置为4以上才能获得成功的解决方案,而其他单元为零.这是完整的代码:

I always get an infeasible solution message if I set the lower bound to zero for all generation units. The solver appears to get stuck at a trial solution of all zeros or when all are below a certain threshold. In this case, I had to bound the middle unit to be above 4 to get a successful solution while the others are at zero. Here is the complete code:

from gekko import GEKKO

P = [[3.0,3.55,5.18,7.9,5.98],
    [1.56,1.56,2.48,3.15,2.38],
    [1.49,4.96,6.4,9.4,6.5]]

M = [[1,2,3,4,5],
     [6,7,8,9,10],
     [11,12,13,14,15]]

mm = M
pp = P
c1 = [300,200,150,250,180]
qtde = [10,10,10]
flex = [0.2,0.2,0.2]

m = GEKKO(remote=False)
ni = 3
nj = 5
x = [[m.Var(integer=True) for j in range(nj)] for i in range(ni)]

# Fix x at values to check the feasibility of the initial guess
#x = [[m.Param() for j in range(nj)] for i in range(ni)]

lower = [0,0,4,0,0]
for i in range(ni):
    for j in range(nj):
        x[i][j].value = 5
        x[i][j].lower = lower[j]
        x[i][j].upper = 20

s = 0
expr = []
for i in range(ni):
    for j in range(nj):
        s += x[i][j]*pp[i][j]
    expr.append(s)
    s = 0

for i in range(ni):
    for j in range(nj):
        if mm[i][j] == 0:
            m.Equation(x[i][j] == 0)


for i in range(len(flex)):
    if flex[i] == 0:
        m.Equation(sum([x[i][j] for j in range(nj)]) >= qtde[i])
    else:
        m.Equation(sum([x[i][j] for j in range(nj)]) >= qtde[i])
        m.Equation(sum([x[i][j] for j in range(nj)]) <= (1+flex[i])*qtde[i])


b = m.Array(m.Var,nj,value=0.5,integer=True,lb=0,ub=1)
iv = [None]*nj



for j in range(nj):
   iv[j] = m.sum([pp[i][j]*x[i][j] for i in range(ni)])
   m.Equation(iv[j] >= b[j]*c1[j])


m.Obj(m.sum(expr))

for j in range(nj):
    m.Equation((1 - b[j])*iv[j] <= 1e-5)

print('Initial guess: ' + str(x))

# solve as NLP first to see iterations
#m.solver_options = ['minlp_as_nlp 1']
#m.options.SOLVER = 1
#m.solve(debug=0)



# solve as MINLP
m.options.SOLVER=1 # switch to APOPT
m.solver_options = ['minlp_gap_tol 1.0e-2',\
                    'minlp_maximum_iterations 50000',\
                    'minlp_max_iter_with_int_sol 50000',\
                    'minlp_branch_method 1',\
                    'minlp_integer_leaves 2']

m.options.SOLVER=1
m.solve(disp=False)

print('Final solution: ' + str(x))

有了一个完美的求解器,就不需要进行初步猜测,并且可以将范围从0设置为infinity.有些问题较难解决,例如混合整数变量的问题以及使用互补条件时的问题.您的问题同时存在,因此对于没有最初的猜测或适当的边界的求解器,我感到惊讶.

With a perfect solver, an initial guess would not be needed and bounds could be set from 0 to infinity. Some problems are harder to solve, such as problems with mixed integer variables and when using complementarity conditions. Your problem has both so I'm not surprised that the solver struggles without the initial guess or appropriate bounds.