Gekko约束中的最大方程长度限制

时间:2020-06-14 12:25:27

标签: python numpy gekko

我正在努力优化约束条件下的一长串方程。目标函数可以拆分为多个目标函数,但是我无法以我能找到的任何方式拆分约束函数。在过去的一个月中,我尝试使用sympy和scipy.optimize以几种不同的方式解决此问题,但都需要花一些时间才能运行。在此示例中,我将长度限制为发生错误的最短长度之一,但是我希望能够通过增加约束月份,nummonthstodo并添加到db1permonth来尽可能扩展此长度。我如何解决长度限制错误:

Exception:  @error: Max Equation Length
 Error with line number:           67
 (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
 [...lots of numbers here..]
 0/(1.0+(2.718281828459045^(-(((v14-476.0))/(120)))))))))+((-2.02635827)*((200.0
 /(1.0+(2.718281

 APM model error: string >       15000  characters
 Consider breaking up the line into multiple equations

 The may also be due to only using newline character CR
   instead of CR LF (for Windows) or LF (for MacOS/Linux)
 To fix this problem, save APM file with appropriate newline characters

 STOPPING...

在此代码中:

import numpy as np
from gekko import GEKKO    
from math import e


m = GEKKO()

nummonthstodo = 20
constraintmonth = 15
markets=3
fudgefactor = 1.18
constraint = -100000
ig = np.tile([1169.00,476.00,191.00],(nummonthstodo))
dynamic_scale = np.tile(np.array([100,120,80]),nummonthstodo)
turning_point =np.tile( np.array([1169.00,476.00,191.00]),nummonthstodo)
eo14_scale = np.tile(np.array([72.00,200.00,500.00]),nummonthstodo)
db1life = np.tile(np.array([2131.64415,  927.62553,  376.79813]),nummonthstodo)

db1permonth = np.array([-7.69469125e+01, -8.27515903e+01, -8.23699131e+01,  4.45215469e+02,
        3.69705278e+02,  1.58977477e+02, -3.88706011e+00, -3.02636074e+00,
       -2.79420475e+00, -7.67567831e-01, -3.03178864e+00, -2.79921627e+00,
        6.82114433e+01,  5.11866268e+01,  7.41661986e+01, -3.22847133e+00,
       -2.28929507e+00, -1.28846317e+00, -7.10922109e-01, -2.29483815e+00,
       -1.29158293e+00,  5.33895986e+01,  3.53279803e+01,  4.70884129e+01,
       -2.98307479e+00, -2.02448766e+00, -8.09906719e-01, -8.69398271e-01,
       -2.02635827e+00, -8.10655068e-01,  4.40599327e+01,  2.74298296e+01,
        3.40114832e+01, -2.83729295e+00, -1.90180770e+00, -5.82931770e-01,
       -4.06643364e+01, -2.85105835e+01, -8.73890925e+00,  2.05687539e+02,
        1.15368035e+02,  2.54844135e+01, -1.93419651e+00, -1.17779492e+00,
       -4.36383453e-01, -3.54686842e-01, -1.17891974e+00, -4.36800210e-01,
        3.28820412e+01,  1.73557733e+01,  2.03414999e+01, -1.85294103e+00,
       -1.09751072e+00, -3.47833721e-01, -4.44622167e-01, -1.09856091e+00,
       -3.48166558e-01,  2.90051018e+01,  1.46659871e+01,  1.69382174e+01])



x = m.Array(m.Var,(len(ig)))

# lower bounds
for i,xi in enumerate(x):
    xi.value = ig[i]
    xi.lower = 0
    xi.upper = 1500


def eo14(a,b):
    return np.divide(np.tile(eo14_scale[0:3],int((b-a)/3)),(np.ones(b-a)+e**(-np.divide((x[a:b]-np.tile(turning_point[0:3],int((b-a)/3))),np.tile(dynamic_scale[0:3],int((b-a)/3))))))
def db1(a,b):
    return db1permonth[a:b]
def cac(a,b):
    return x[a:b]

eo14s = [eo14(i*markets,(i+1)*markets) for i in range(nummonthstodo)]
db1s = [db1(i*markets,(i+1)*markets) for i in range(nummonthstodo)]
cacs = [cac(i*markets,(i+1)*markets) for i in range(nummonthstodo)]

db1month = 0

for i in range(constraintmonth):
    for j in range(constraintmonth-i):
        db1month = db1month + np.multiply(db1s[j],eo14s[i])

spend = 0

for i in range(constraintmonth):
        spend = spend + np.multiply(cacs[i],eo14s[i])

alleo14 = eo14(0,len(ig))

m.Equation(m.sum(db1month - spend) >= constraint)

for i in range(len(ig)):
   m.Obj(-(np.multiply(db1life-x,alleo14))[i])

m.solve()

print(x)

预先感谢您提供的任何帮助,作为一名数据科学的学生和初学者,这确实让我头疼了一段时间。

1 个答案:

答案 0 :(得分:2)

通过将产品声明为列表,然后使用m.sum(),可以克服最大方程长度。否则,它将构建一个非常大的表达式,每个表达式超过15,000个字符的限制。您也可以使用m.Intermediate()变量来减小表达式的大小。这是您的程序成功解决的新版本。

import numpy as np
from gekko import GEKKO    
from math import e

m = GEKKO(remote=False)

nummonthstodo = 20
constraintmonth = 15
markets=3
fudgefactor = 1.18
constraint = -100000
ig = np.tile([1169.00,476.00,191.00],(nummonthstodo))
dynamic_scale = np.tile(np.array([100,120,80]),nummonthstodo)
turning_point =np.tile( np.array([1169.00,476.00,191.00]),nummonthstodo)
eo14_scale = np.tile(np.array([72.00,200.00,500.00]),nummonthstodo)
db1life = np.tile(np.array([2131.64415,  927.62553,  376.79813]),nummonthstodo)

db1permonth = np.array([-7.69469125e+01, -8.27515903e+01, -8.23699131e+01,  4.45215469e+02,
        3.69705278e+02,  1.58977477e+02, -3.88706011e+00, -3.02636074e+00,
       -2.79420475e+00, -7.67567831e-01, -3.03178864e+00, -2.79921627e+00,
        6.82114433e+01,  5.11866268e+01,  7.41661986e+01, -3.22847133e+00,
       -2.28929507e+00, -1.28846317e+00, -7.10922109e-01, -2.29483815e+00,
       -1.29158293e+00,  5.33895986e+01,  3.53279803e+01,  4.70884129e+01,
       -2.98307479e+00, -2.02448766e+00, -8.09906719e-01, -8.69398271e-01,
       -2.02635827e+00, -8.10655068e-01,  4.40599327e+01,  2.74298296e+01,
        3.40114832e+01, -2.83729295e+00, -1.90180770e+00, -5.82931770e-01,
       -4.06643364e+01, -2.85105835e+01, -8.73890925e+00,  2.05687539e+02,
        1.15368035e+02,  2.54844135e+01, -1.93419651e+00, -1.17779492e+00,
       -4.36383453e-01, -3.54686842e-01, -1.17891974e+00, -4.36800210e-01,
        3.28820412e+01,  1.73557733e+01,  2.03414999e+01, -1.85294103e+00,
       -1.09751072e+00, -3.47833721e-01, -4.44622167e-01, -1.09856091e+00,
       -3.48166558e-01,  2.90051018e+01,  1.46659871e+01,  1.69382174e+01])

x = m.Array(m.Var,len(ig),lb=0,ub=1500)
for i,xi in enumerate(x):
    xi.value = ig[i]

def eo14(a,b):
    return np.divide(np.tile(eo14_scale[0:3],int((b-a)/3)),\
                     (np.ones(b-a)+e**(-np.divide((x[a:b]\
                        -np.tile(turning_point[0:3],int((b-a)/3))),\
                            np.tile(dynamic_scale[0:3],int((b-a)/3))))))
def db1(a,b):
    return db1permonth[a:b]
def cac(a,b):
    return x[a:b]

eo14s = [eo14(i*markets,(i+1)*markets) for i in range(nummonthstodo)]
db1s = [db1(i*markets,(i+1)*markets) for i in range(nummonthstodo)]
cacs = [cac(i*markets,(i+1)*markets) for i in range(nummonthstodo)]

prod1 = [db1s[j]*eo14s[i] for j in range(constraintmonth-i) \
                         for i in range(constraintmonth)]
db1month = m.sum(prod1)

prod2 = [cacs[i]*eo14s[i] for i in range(constraintmonth)]
spend = m.sum(prod2)

alleo14 = eo14(0,len(ig))

m.Equation(db1month - spend >= constraint)

for i in range(len(ig)):
   m.Maximize((np.multiply(db1life-x,alleo14))[i])

m.solve()

print(x)

这将提供求解器输出:

Number of Iterations....: 9

                                   (scaled)                 (unscaled)
Objective...............: -1.7974777841412724e+003  -2.8845129361943263e+006
Dual infeasibility......:  1.3421365394256974e-009   2.1538014234551661e-006
Constraint violation....:  0.0000000000000000e+000   0.0000000000000000e+000
Complementarity.........:  2.1861799117816599e-010   3.5082849379387629e-007
Overall NLP error.......:  1.3421365394256974e-009   2.1538014234551661e-006


Number of objective function evaluations             = 10
Number of objective gradient evaluations             = 10
Number of equality constraint evaluations            = 10
Number of inequality constraint evaluations          = 0
Number of equality constraint Jacobian evaluations   = 10
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations             = 9
Total CPU secs in IPOPT (w/o function evaluations)   =      0.066
Total CPU secs in NLP function evaluations           =      0.001

EXIT: Optimal Solution Found.

 The solution was found.

 The final value of the objective function is  -2884512.9361943263

 ---------------------------------------------------
 Solver         :  IPOPT (v3.12)
 Solution time  :  0.127 sec
 Objective      :  -2884512.9361943263
 Successful solution
 ---------------------------------------------------

解决方法:

[[1359.5263445] [561.97176237] [203.39330742] [1359.5263445]
 [561.97176237] [203.39330742] [1359.5263445] [561.97176237]
 [203.39330742] [1359.5263445] [561.97176237] [203.39330742]
 [1359.5263445] [561.97176237] [203.39330742] [1359.5263445]
 [561.97176237] [203.39330742] [1359.5263445] [561.97176237]
 [203.39330742] [1359.5263445] [561.97176237] [203.39330742]
 [1359.5263445] [561.97176237] [203.39330742] [1359.5263445]
 [561.97176237] [203.39330742] [1359.5263445] [561.97176237]
 [203.39330742] [1359.5263445] [561.97176237] [203.39330742]
 [1359.5263445] [561.97176237] [203.39330742] [1359.5263445]
 [561.97176237] [203.39330742] [1359.5263445] [561.97176237]
 [203.39330742] [1359.5263445] [561.97176237] [203.39330742]
 [1359.5263445] [561.97176237] [203.39330742] [1359.5263445]
 [561.97176237] [203.39330742] [1359.5263445] [561.97176237]
 [203.39330742] [1359.5263445] [561.97176237] [203.39330742]]