python - 如何修复 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)
解决方案
下面是一个应该可以工作的版本,如果你让它解决足够长的时间,尽管解决方案不太可能,因为你有 128*128 = 16384 个二进制变量。有 2^16384 个解,如果整数变量的数量大于几百个,那么像 APOPT 这样的混合整数非线性规划求解器不太可能快速找到解。它可以解决具有数千个变量的连续变量,但混合整数比较困难,因为它必须使用分支定界方法来解决它们。abs
如果您可以使您的问题线性化(用松弛变量代替函数),您可能想尝试像 CPLEX 或 Gurobi 这样的 MILP 求解器。
以下是关于您的模型的一些建议:
- 不要
numpy
用于模型表达式。诸如np.abs
和之类的函数np.sum
不为求解器提供所需的信息。您应该使用m.abs2
(orm.abs3
) andm.sum
来代替。 - 数组
a
和d
可以是一个 numpy 常量数组,而不是 Gekko 参数。 - 您可以将至少一个表达式分解为中间体,以帮助缩短求解时间。
- 目标函数是 的标量结果
a.T x[:,:] d
。您可以使用m.Obj
a[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)
推荐阅读
- bash - Bash 脚本检查具有特定扩展名的文件
- python - 使用 Celery worker 与 SQLAlchemy DB 交互,包括从请求中了解用户
- postgresql - Pgpool 日志错误:主 0 仅拥有 1 个备用数据库中的 0 个备用数据库
- pylint - 如何使 pylint、flake8 或 pycodestyle 自动纠正错误?
- python - 我应该如何使用多种过滤器类型过滤 CSV 的大 (70+MB) 文本文件
- azure - 如何将我的本地 Bash Shell 链接到 Azure 中的文件?
- qt - QZXing如何更换摄像头设备
- oracle-apex - Oracle APEX 中的并发用户
- swift - 遍历 Swift 中的嵌套堆栈
- scala - IntelliJ:Scala Worksheet 控制台删除前导空格