首页 > 解决方案 > 如何修复 Python Gekko Max Equation Length 错误

问题描述

我的代码适用于小变量。但是当我在 128*128 变量数组中执行时,出现以下错误:

APM 模型错误:字符串 > 15000 个字符 考虑将行分解为多个等式 这也可能是由于仅使用换行符 CR 而不是 CR LF(对于 Windows)或 LF(对于 MacOS/Linux) 要解决此问题,请保存 APM带有适当换行符的文件

我不知道如何解决这个错误。

假设是 gekko 不能像那样运行大数组变量。

我把代码放在下面。

from gekko import GEKKO
import numpy as np

m = GEKKO()
m.options.SOLVER=1
# optional solver settings with APOPT
m.solver_options = ['minlp_maximum_iterations max', \
                    # minlp iterations with integer solution
                    'minlp_max_iter_with_int_sol max', \
                    # treat minlp as nlp
                    'minlp_as_nlp min', \
                    # nlp sub-problem max iterations
                    'nlp_maximum_iterations 5000', \
                    # 1 = depth first, 2 = breadth first
                    'minlp_branch_method 1', \
                    # maximum deviation from whole number
                    'minlp_integer_tol 0.0005', \
                    # covergence tolerance
                    'minlp_gap_tol 0.0001' ,\
                    'max_cpu_time 10min']

n = 128 
p = 8 
q = 16 


x = m.Array(m.Var,(n,n),integer=True)

for i in range(n):
    for j in range(n):
        x[i,j].value = 1
        x[i,j].lower = 0
        x[i,j].upper = 1


s = 60

a = m.Array(m.Param,(x.shape[0],))
a_ = [172,282,10, 264, 287, 442, 393, 428, 484, 444, 344, 250, 293,  34, 473, 110, 338,  62,
 250, 205,  81, 336, 249, 199, 328, 447, 408,  82, 357, 334, 181, 133, 378,  79, 292, 103,
 494, 382,  10, 477, 237, 267, 337, 313, 395, 110, 114, 381,  52, 232, 457,  69, 167, 344,
 363, 284, 136 ,240, 258, 449, 119, 317, 370, 404, 197, 102, 428, 238, 321, 103, 282,  37,
  41,  86, 496  ,31, 148, 245,  78, 219,  37, 115, 378, 129,  37, 448, 415, 368, 238, 406,
 408, 100, 112 ,289 ,205, 329, 338, 396, 494, 145, 355,  45,   5, 220, 411, 167,  85, 369,
 426, 442, 406 ,217,  57, 176,  12, 368, 444, 227, 337,  63, 267, 216, 227, 182, 408, 116,
 385, 140]
for i in range(len(a)):
    a[i] = a_[i]


O1 = np.array(range(n))
O_= np.transpose(np.nonzero(O1+1))

O = np.zeros((x.shape[0],x.shape[1]),dtype=int)
for i in range(n):
    for j in range(n):
        O[i,O_[i]] = 1


d = m.Array(m.Param,(p,q))
for i in range(p):
    for j in range(q):
        d[i,j] = (round(p/2)-int(i/2))*4-(j%4)

#condition
m.Equation(m.sum(abs(x[:,:]-O[:,:]))<=2*s)

for i in range(n):
    m.Equation(m.sum(x[:,i])==1)

for i in range(n):
    m.Equation(m.sum(x[i,:])==1)

#Objective
m.Obj(np.sum(a.T*np.sum(x*d.reshape(1,n),axis=1)))

#Set global options
m.options.IMODE = 3

#Solve simulation
m.solve(disp=False,debug=True)

标签: pythongekko

解决方案


下面是一个应该可以工作的版本,如果你让它解决足够长的时间,尽管解决方案不太可能,因为你有 128*128 = 16384 个二进制变量。有 2^16384 个解,如果整数变量的数量大于几百个,那么像 APOPT 这样的混合整数非线性规划求解器不太可能快速找到解。它可以解决具有数千个变量的连续变量,但混合整数比较困难,因为它必须使用分支定界方法来解决它们。abs如果您可以使您的问题线性化(用松弛变量代替函数),您可能想尝试像 CPLEX 或 Gurobi 这样的 MILP 求解器。

以下是关于您的模型的一些建议:

  • 不要numpy用于模型表达式。诸如np.abs和之类的函数np.sum不为求解器提供所需的信息。您应该使用m.abs2(or m.abs3) andm.sum来代替。
  • 数组ad可以是一个 numpy 常量数组,而不是 Gekko 参数。
  • 您可以将至少一个表达式分解为中间体,以帮助缩短求解时间。
  • 目标函数是 的标量结果a.T x[:,:] d。您可以使用m.Obja[i] x[i,j] d[j] 中的多个函数,而不是使用矩阵乘法产生的一个大型表达式。
  • 我建议您从较小的问题开始,然后在您对模型和解决方案充满信心时扩大到较大的问题。
from gekko import GEKKO
import numpy as np

m = GEKKO()
m.options.SOLVER=1
# optional solver settings with APOPT
m.solver_options = ['minlp_maximum_iterations 1000', \
                    # minlp iterations with integer solution
                    'minlp_max_iter_with_int_sol 100', \
                    # treat minlp as nlp
                    'minlp_as_nlp 1', \
                    # nlp sub-problem max iterations
                    'nlp_maximum_iterations 5000', \
                    # 1 = depth first, 2 = breadth first
                    'minlp_branch_method 1', \
                    # maximum deviation from whole number
                    'minlp_integer_tol 0.0005', \
                    # covergence tolerance
                    'minlp_gap_tol 0.0001']

n = 128 
p = 8 
q = 16 

x = m.Array(m.Var,(n,n),integer=True)

for i in range(n):
    for j in range(n):
        x[i,j].value = 1
        x[i,j].lower = 0
        x[i,j].upper = 1


s = 60

# don't need a gekko array here, constants are okay
#a = m.Array(m.Param,(x.shape[0],))
a = np.array([172,282,10, 264, 287, 442, 393, 428, 484, 444, 344, 250, 293,  34, 473, 110, 338,  62,
 250, 205,  81, 336, 249, 199, 328, 447, 408,  82, 357, 334, 181, 133, 378,  79, 292, 103,
 494, 382,  10, 477, 237, 267, 337, 313, 395, 110, 114, 381,  52, 232, 457,  69, 167, 344,
 363, 284, 136 ,240, 258, 449, 119, 317, 370, 404, 197, 102, 428, 238, 321, 103, 282,  37,
  41,  86, 496  ,31, 148, 245,  78, 219,  37, 115, 378, 129,  37, 448, 415, 368, 238, 406,
 408, 100, 112 ,289 ,205, 329, 338, 396, 494, 145, 355,  45,   5, 220, 411, 167,  85, 369,
 426, 442, 406 ,217,  57, 176,  12, 368, 444, 227, 337,  63, 267, 216, 227, 182, 408, 116,
 385, 140])

# use .value to assign a value instead of over-writing the gekko variable
#   with a floating point number
#for i in range(len(a)):
#    a[i].value = a_[i]

O1 = np.array(range(n))
O_= np.transpose(np.nonzero(O1+1))

O = np.zeros((x.shape[0],x.shape[1]),dtype=int)
for i in range(n):
    for j in range(n):
        O[i,O_[i]] = 1

d = np.empty((p,q)) # doesn't need to be a gekko array
for i in range(p):
    for j in range(q):
        d[i,j] = (round(p/2)-int(i/2))*4-(j%4)

#condition - use m.abs2 or m.abs3 for versions of ABS that
# have continuous first and second derivatives
xabs = [[m.Intermediate(m.abs3(x[i,j]-O[i,j])) for j in range(n)] for i in range(n)]
# matrix summation
msum = m.sum([m.sum([xabs[i][j] for i in range(n)]) for j in range(n)])
m.Equation(msum<=2*s)

for i in range(n):
    m.Equation(m.sum(x[:,i])==1)

for i in range(n):
    m.Equation(m.sum(x[i,:])==1)

#Objective - can add multiple objectives
e = d.reshape(n)
for i in range(n):
    for j in range(n):
        m.Obj(a[i]*x[i,j]*e[j])
#m.Obj(m.sum(a.T*m.sum(x*d.reshape(1,n))))

#Set global options
m.options.IMODE = 3

#Solve simulation
m.solve(disp=True,debug=True)

推荐阅读