GEKKO(Python)提供了不正确的解决方案。

huangapple go评论68阅读模式
英文:

GEKKO (Python) giving incorrect solution

问题

  1. 为什么 results.json 文件与提示中显示的内容不匹配?

    这个问题可能是由于GEKKO求解器的设置或代码中的某些问题导致的。要解决这个问题,你可以检查以下几个方面:

    • 检查GEKKO模型的设置,包括求解器、参数和约束条件是否正确设置。确保模型的目标函数和约束条件与你的预期一致。

    • 检查代码中的随机数生成部分,确保随机数生成的方式和范围是正确的。np.random.randintnp.random.random 的使用应该是符合你的需求的。

    • 检查结果文件 results.json 是否包含了正确的输出数据。如果结果文件不正确,可能是代码中输出结果的部分存在问题。

  2. 为什么我得到了错误的解决方案?

    得到错误的解决方案可能是由于以下原因之一引起的:

    • 模型的约束条件可能不正确或不完整,导致求解器找到了一个满足约束条件的局部最优解,但这个解并不是全局最优解。你应该仔细检查模型的约束条件,确保它们涵盖了问题的所有限制。

    • 求解器选择和参数设置可能会影响结果。你可以尝试不同的求解器、不同的求解器选项或参数来寻找更好的解决方案。

    • 模型的目标函数可能不正确。确保你的目标函数正确地描述了问题的优化目标。

    • 代码中的数据生成部分可能存在问题,导致输入数据不符合预期。

要解决这个问题,你可以逐步调试代码,检查模型设置、约束条件和目标函数是否正确,以及检查输入数据是否合理。还可以尝试不同的求解器和参数设置来查找更好的解决方案。

英文:

Consider the following GEKKO code:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

import numpy as np
from gekko import GEKKO
import matplotlib.pyplot as plt

# Build model

#initialize GEKKO model
m = GEKKO()
m.options.solver = 1

# Seed
np.random.seed(0)

max_r = 5
min_r = 2

b = 2
b_r = {}

for i in range(b):
    b_r[i] = np.random.randint(low=min_r,high=max_r)


u = 2

br = np.random.random((b,u))

lv = m.Array(m.Var,(b, u),lb=0,ub=1, integer=True)

av = {}
for i in range(b):
    av[i] = m.Array(m.Var,(b_r[i], u),lb=0,ub=1, integer=True)


## Constraints
    
for i in range(u):
    lv_sum = m.Const(value=0, name=&#39;Link Sum &#39; + str(i))
    for j in range(b):
        lv_sum += lv[j][i]
    m.Equation(lv_sum &lt;= 1)


for i in range(b):
    for j in range(b_r[i]):
        av_sum = m.Const(value=0, name=&#39;Alloc Sum &#39; + str((i,j)))
        for k in range(u):
            av_sum += av[i][j][k]
        m.Equation(av_sum &lt;= 1)


# Objective function
obj_u = m.Const(value=0, name=&#39;Final Objective&#39;)
for i in range(u):
    obj_b = m.Const(value=0, name=&#39;Objective &#39;+str(i))
    for j in range(b):
        for k in range(b_r[j]):
            obj_b += lv[j][i]*av[j][k][i]*br[j][i]
    obj_u += m.log(1+obj_b)



# Maximize/Minimize objective
m.Maximize(obj_u)

#Set global options
m.options.IMODE = 3 #steady state optimization

# m.options.IMODE = 6 #Dynamic optimization

print(m.path)
#Solve simulation
m.solve()

<!-- end snippet -->

Quite obviously the solution to this piece of code will always be non-negative as we are maximizing log(1+x) where 0 &lt;= x. Yet somehow GEKKO gives the following output:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

/tmp/tmpw15jz3zhgk_model0
apm 203.192.204.172_gk_model0 &lt;br&gt;&lt;pre&gt; ----------------------------------------------------------------
 APMonitor, Version 1.0.1
 APMonitor Optimization Suite
 ----------------------------------------------------------------
 
 
 Warning: there is insufficient data in CSV file 203.192.204.172_gk_model0.csv
 
 --------- APM Model Size ------------
 Each time step contains
   Objects      :            0
   Constants    :           10
   Variables    :           21
   Intermediates:            0
   Connections  :            0
   Equations    :            8
   Residuals    :            8
 
 Number of state variables:             21
 Number of total equations: -            7
 Number of slack variables: -            7
 ---------------------------------------
 Degrees of freedom       :              7
 
 ----------------------------------------------
 Steady State Optimization with APOPT Solver
 ----------------------------------------------
Iter:     1 I:  0 Tm:      0.00 NLPi:    7 Dpth:    0 Lvs:    0 Obj: -2.26E+00 Gap:  0.00E+00
 Successful solution
 
 ---------------------------------------------------
 Solver         :  APOPT (v1.0)
 Solution time  :   1.460000000952277E-002 sec
 Objective      :   -2.26374259105544     
 Successful solution
 ---------------------------------------------------

<!-- end snippet -->

The model file is as follows:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

Model
Constants
	link_sum_0 = 0
	link_sum_1 = 0
	alloc_sum_0_0_ = 0
	alloc_sum_0_1_ = 0
	alloc_sum_1_0_ = 0
	alloc_sum_1_1_ = 0
	alloc_sum_1_2_ = 0
	final_objective = 0
	objective_0 = 0
	objective_1 = 0
End Constants
Variables
	int_v1 = 0, &lt;= 1, &gt;= 0
	int_v2 = 0, &lt;= 1, &gt;= 0
	int_v3 = 0, &lt;= 1, &gt;= 0
	int_v4 = 0, &lt;= 1, &gt;= 0
	int_v5 = 0, &lt;= 1, &gt;= 0
	int_v6 = 0, &lt;= 1, &gt;= 0
	int_v7 = 0, &lt;= 1, &gt;= 0
	int_v8 = 0, &lt;= 1, &gt;= 0
	int_v9 = 0, &lt;= 1, &gt;= 0
	int_v10 = 0, &lt;= 1, &gt;= 0
	int_v11 = 0, &lt;= 1, &gt;= 0
	int_v12 = 0, &lt;= 1, &gt;= 0
	int_v13 = 0, &lt;= 1, &gt;= 0
	int_v14 = 0, &lt;= 1, &gt;= 0
End Variables
Equations
	((link_sum_0+int_v1)+int_v3)&lt;=1
	((link_sum_1+int_v2)+int_v4)&lt;=1
	((alloc_sum_0_0_+int_v5)+int_v6)&lt;=1
	((alloc_sum_0_1_+int_v7)+int_v8)&lt;=1
	((alloc_sum_1_0_+int_v9)+int_v10)&lt;=1
	((alloc_sum_1_1_+int_v11)+int_v12)&lt;=1
	((alloc_sum_1_2_+int_v13)+int_v14)&lt;=1
	maximize ((final_objective+log((1+(((((objective_0+((((int_v1)*(int_v5)))*(0.8442657485810173)))+((((int_v1)*(int_v7)))*(0.8442657485810173)))+((((int_v3)*(int_v9)))*(0.8472517387841254)))+((((int_v3)*(int_v11)))*(0.8472517387841254)))+((((int_v3)*(int_v13)))*(0.8472517387841254))))))+log((1+(((((objective_1+((((int_v2)*(int_v6)))*(0.8579456176227568)))+((((int_v2)*(int_v8)))*(0.8579456176227568)))+((((int_v4)*(int_v10)))*(0.6235636967859723)))+((((int_v4)*(int_v12)))*(0.6235636967859723)))+((((int_v4)*(int_v14)))*(0.6235636967859723))))))
End Equations

End Model

<!-- end snippet -->

And the results.json file is as follows:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

{
  &quot;time&quot; : [0.00],
  &quot;link_sum_0&quot; : [ 0.00              ],
  &quot;link_sum_1&quot; : [ 0.00              ],
  &quot;alloc_sum_0_0_&quot; : [ 0.00              ],
  &quot;alloc_sum_0_1_&quot; : [ 0.00              ],
  &quot;alloc_sum_1_0_&quot; : [ 0.00              ],
  &quot;alloc_sum_1_1_&quot; : [ 0.00              ],
  &quot;alloc_sum_1_2_&quot; : [ 0.00              ],
  &quot;final_objective&quot; : [ 0.00              ],
  &quot;objective_0&quot; : [ 0.00              ],
  &quot;objective_1&quot; : [ 0.00              ],
  &quot;int_v1&quot; : [ 0.00              ],
  &quot;int_v2&quot; : [   1.0000000000E+00],
  &quot;int_v3&quot; : [   1.0000000000E+00],
  &quot;int_v4&quot; : [ 0.00              ],
  &quot;int_v5&quot; : [ 0.00              ],
  &quot;int_v6&quot; : [   1.0000000000E+00],
  &quot;int_v7&quot; : [ 0.00              ],
  &quot;int_v8&quot; : [   1.0000000000E+00],
  &quot;int_v9&quot; : [   1.0000000000E+00],
  &quot;int_v10&quot; : [ 0.00              ],
  &quot;int_v11&quot; : [   1.0000000000E+00],
  &quot;int_v12&quot; : [ 0.00              ],
  &quot;int_v13&quot; : [   1.0000000000E+00],
  &quot;int_v14&quot; : [ 0.00              ],
  &quot;slk_1&quot; : [ 0.00              ],
  &quot;slk_2&quot; : [ 0.00              ],
  &quot;slk_3&quot; : [ 0.00              ],
  &quot;slk_4&quot; : [ 0.00              ],
  &quot;slk_5&quot; : [ 0.00              ],
  &quot;slk_6&quot; : [ 0.00              ],
  &quot;slk_7&quot; : [ 0.00              ]
}

<!-- end snippet -->

I am confused of the folllowing:

  1. Why does the results.json not match with what is being displayed in the prompt?
  2. More importantly why am I getting an incorrect solution?

答案1

得分: 1

m.Const() 是一个常数声明,而不是一个约束。然后,像以下的循环会重新定义这个常数:

for i in range(u):
    lv_sum = m.Const(value=0, name='Link Sum ' + str(i))
    for j in range(b):
        lv_sum += lv[j][i]
    m.Equation(lv_sum <= 1)

相反,可以这样定义 lv_sum 和约束:

for i in range(u):
    lv_sum = m.Var(value=0, ub=1, name='Link Sum ' + str(i))
    m.Equation(lv_sum == sum(lv[1:b][i]))

使用 m.Var() 定义变量,使用 m.Equation() 定义方程,或者使用 m.Equations() 一次性定义多个方程。不要使用 +=,因为它会重新定义 gekko 变量。不要使用循环,可以尝试使用列表推导、矩阵操作和向量求和。这里有示例(参见 test_arrays.pytest_matrix.pytest_summations.py)。一旦修复了问题定义,它应该会给你一个正确的问题陈述,然后求解器可以解决。

英文:

The m.Const() is a constant declaration, not a constraint. Loops such as the following then redefine the constant:

for i in range(u):
    lv_sum = m.Const(value=0, name=&#39;Link Sum &#39; + str(i))
    for j in range(b):
        lv_sum += lv[j][i]
    m.Equation(lv_sum &lt;= 1)

Instead, define lv_sum and the constraint this way:

for i in range(u):
    lv_sum = m.Var(value=0, ub=1, name=&#39;Link Sum &#39; + str(i))
    m.Equation(lv_sum = sum(lv[1:b][i]))

Use m.Var() to define the variable and m.Equation() to define the equation or m.Equations() to define multiple equations at once. Don't use += because it redefines the gekko variable. Instead of loops, try list comprehensions, matrix operations, and vector summations. Here are examples (see test_arrays.py, test_matrix.py, test_summations.py). Once you fix the problem definition, it should give you a correct problem statement that the solver can then solve.

huangapple
  • 本文由 发表于 2023年6月29日 19:27:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76580596.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定