当前位置: 首页 > 知识库问答 >
问题:

离散优化(SOS1约束)-GEKKO

长孙雅志
2023-03-14

我试图用Python中的GEKKO定义一个优化问题,我想使用一些带有预定义选择列表的设计变量。此外,每个选择都有一个相关的成本,约束条件是总成本应低于指定的限制。

下面是一个常见的壁虎示例(在这里找到),修改后的x1和x2是sos1。此外,利用所选值x1和x2的索引,我从另一个列表中找到了它们的相关成本,它们的总和应该小于某个值(约束)。

from gekko import GEKKO
def test(x1,x2,x3,x4):
    res = x1*x4*(x1+x2+x3)+x3
    return res

def check(x1,x2):
    tt = [1,2,3,4,5]
    cost = [10,10,10,2,1]
    if x1.value in tt:
        y1 = tt.index(x1.value)
        y2 = tt.index(x2.value)
        C = cost[y1]+cost[y2]
        return C
    return 10

m = GEKKO() # Initialize gekko
m.options.SOLVER=1  # APOPT is an MINLP solver

# optional solver settings with APOPT
m.solver_options = ['minlp_maximum_iterations 500', \
                    # minlp iterations with integer solution
                    'minlp_max_iter_with_int_sol 10', \
                    # treat minlp as nlp
                    'minlp_as_nlp 0', \
                    # nlp sub-problem max iterations
                    'nlp_maximum_iterations 50', \
                    # 1 = depth first, 2 = breadth first
                    'minlp_branch_method 1', \
                    # maximum deviation from whole number
                    'minlp_integer_tol 0.05', \
                    # covergence tolerance
                    'minlp_gap_tol 0.01']

# Integer constraints for x3 and x4
x3 = m.Var(value=1,lb=1,ub=5,integer=True)
x4 = m.Var(value=2,lb=1,ub=5,integer=True)
x1 = m.sos1([1,2,3,4,5])
x2 = m.sos1([1,2,3,4,5])

# Equations
m.Equation(x1*x2*x3*x4>=25)
m.Equation(x1**2+x2**2+x3**2+x4**2==40)
m.Equation(check(x1,x2)<=5)
m.Obj(test(x1,x2,x3,x4)) # Objective

m.solve(disp=False) # Solve
print('Results')
print('x1: ' + str(x1.value))
print('x2: ' + str(x2.value))
print('x3: ' + str(x3.value))
print('x4: ' + str(x4.value))
print('Objective: ' + str(m.options.objfcnval))

注意:我必须在check函数中添加一个if块作为x1的初始值,而x2似乎为零。

这段代码不起作用,我得到了以下错误。

> Exception has occurred: Exception
 @error: Equation Definition
 Equation without an equality (=) or inequality (>,<)
 true
 STOPPING...

我不知道是什么导致了这个错误。我应该如何重新制定我的模型以获得所需的结果?

编辑:这个示例代码只是我试图重新创建错误。我的实际应用是设计一个工程系统。例如,假设系统有两个组件——电池和灯泡。电池我有两个选项,电池A重10公斤,可靠性为0.97,电池B重6公斤,可靠性为0.75。同样,灯泡也有不同的选项。我需要为电池和灯泡选择一个选项,使总系统可靠性尽可能高(客观),总重量小于“x”公斤(约束)。在上面的代码中,将x1x2值视为组件的选定选项,我找到它们的索引以获得它们相关的重量/成本(如果选择了电池A和灯泡B,我得到它们的权重以检查总重量是否小于允许的限制)。现在我的实际系统有n组件和每个组件的m选项。每个选择都有相关的权重、成本、可靠性等。我试图找到最佳组合,以最大限度地提高系统可靠性,同时限制系统重量、成本等

共有2个答案

马华茂
2023-03-14

除了user7440787给出的很好的答案之外,您还需要从一组预定义的离散设计变量中查找多个值。您可以使用如下内容将一个二进制决策变量数组与多个相关性或变量联系起来,而不是使用预定义的m. SOS1()函数。

from gekko import GEKKO
m = GEKKO(remote=False)
# design variable
y = m.Var(lb=1,ub=5)
# options
n = 4
# weight
weight=[19.05-y, 25.0-0.1*y**2, 29.3-0.02*y**3, 30.2]
# cost
cost = [3.2+y,2.4+0.01*y**2,1.6+y+0.001*y**3,5.2]
# SOS1 with binary variables
b = m.Array(m.Var,n,lb=0,ub=1,integer=True)
m.Equation(m.sum(b)==1) # only select one
# cost x weight
cxw = m.sum([b[i]*cost[i]*weight[i] for i in range(4)])
# minimize cost x weight
m.Minimize(cxw)
# change to APOPT solver
m.options.SOLVER = 1
m.solve(disp=False)
print('Design Variable: ' + str(y.value[0]))
print('Option: ' + str(b))

在本例中,您有一个设计变量y,以及基于设计变量的成本和重量的不同方程。总体目标是在调整y时最小化成本和重量的乘积。

林玮
2023-03-14

我根据您的示例描述构建了一个简单的模型。

from gekko import GEKKO
import numpy as np

m = GEKKO() # Initialize gekko
m.options.SOLVER=1  # APOPT is an MINLP solver

# optional solver settings with APOPT
m.solver_options = ['minlp_maximum_iterations 500', \
                    # minlp iterations with integer solution
                    'minlp_max_iter_with_int_sol 10', \
                    # treat minlp as nlp
                    'minlp_as_nlp 0', \
                    # nlp sub-problem max iterations
                    'nlp_maximum_iterations 50', \
                    # 1 = depth first, 2 = breadth first
                    'minlp_branch_method 1', \
                    # maximum deviation from whole number
                    'minlp_integer_tol 0.05', \
                    # covergence tolerance
                    'minlp_gap_tol 0.01']


x1 = m.Array(m.Var, 5, **{'value':0,'lb':0,'ub':1, 'integer': True}) # battery options
print(f'x1_initial: {x1}')
x2 = m.Array(m.Var, 5, **{'value':0,'lb':0,'ub':1, 'integer': True}) # bulb options
print(f'x2_initial: {x2}')
bat_cost = np.array([ 10, 2, 3, 4, 5])  # battery costs
bat_weigh = np.array([ 1, 25, 20, 19, 20])  # battery weighs
bulb_cost = np.array([ 2, 5, 33, 24, 5])  # bulb costs
bulb_weigh = np.array([ 6, 10, 2, 10, 20])  # bulb weighs
m.Equation( sum(bat_weigh * x1) + sum(bulb_weigh * x2) <= 25)  # limit total weigh 
m.Equation(m.sum(x1) == 1)  # restrict choice to a single battery 
m.Equation(m.sum(x2) == 1)  # restrict choice to a single bulb
m.Obj( sum(bat_cost * x1) + sum(bulb_cost * x2) ) # Objective

m.solve(disp=False) # Solve
print('Results:')
print(f'x1: {x1}')
print(f'x2: {x2}')
print(f'battery cost: {sum(np.array([i[0] for i in x1]) * bat_cost)}')
print(f'battery weigh: {sum(np.array([i[0] for i in x1]) * bat_weigh)}')
print(f'bulb cost: {sum(np.array([i[0] for i in x2]) * bulb_cost)}')
print(f'bulb weigh: {sum(np.array([i[0] for i in x2]) * bulb_weigh)}')
print('Objective value: ' + str(m.options.objfcnval))

结果如下:

x1_initial: [0 0 0 0 0]
x2_initial: [0 0 0 0 0]
Results:
x1: [[0.0] [0.0] [0.0] [1.0] [0.0]]
x2: [[1.0] [0.0] [0.0] [0.0] [0.0]]
battery cost: 4.0
battery weigh: 19.0
bulb cost: 2.0
bulb weigh: 6.0
Objective value: 6.0

这是一个非常简单的示例,展示了如何表示电池和灯泡信息。它可以变得更复杂,但我需要更多的细节,并理解为什么你有多项式方程,它们代表什么。

重申一下,你遇到的错误与线路有关:

m.Equation(check(x1,x2)<=5)
 类似资料:
  • 这是一个非常特殊的绘图请求,但我有数据要以非常特殊的方式查看。情况如下: 1) 我拥有的数据分为25个数据箱,每个数据箱包含不同数量的数据点。仓位值越大,粗略地说,仓位中的数据点数量就越少(这只是数据处理的结果)。 2)我可以访问bin值。 我可以在matplotlib中轻松生成“errorbar”类型的绘图(y轴从半径缩放到以下度数): 但是,对于我想研究的内容来说,这并不是特别有见地。我真的很

  • 我目前正试图用Gekko的分支来解决一个混合整数非线性问题 以下是我迄今为止的尝试:

  • 离散流或者DStreams是Spark Streaming提供的基本的抽象,它代表一个连续的数据流。它要么是从源中获取的输入流,要么是输入流通过转换算子生成的处理后的数据流。在内部,DStreams由一系列连续的 RDD组成。DStreams中的每个RDD都包含确定时间间隔内的数据,如下图所示: 任何对DStreams的操作都转换成了对DStreams隐含的RDD的操作。在前面的例子中,flatM

  • 我试图用双积分动力学的形式来解决一个简单的最短时间最优控制问题, GEKKO优化框架如下: 我想做的是用梯形积分形成一个等式约束系统,然后用GEKKO求解这个系统的最优控制输入。但是,使用函数定义, 结合平等制约制度, 给了我以下的错误, 我在上面的代码片段中添加了两行注释代码,这将允许程序正确运行,但我希望避免将每个方程分开,因为我想将其扩展到处理更复杂的系统动力学的问题,并使用更复杂的配置方法

  • 文件有两个驱动程序:(运行时间为~3秒)和(运行时间为~83秒),当使用d专门化用-O3编译时。 其核心是:对于测试,加法代码被专用于s等上的向量,而对于则使用通用向量代码。在第10行,您可以看到GHC编写了的专用版本,而不是第167行的通用版本。专门化的规则在第225行。我相信这条规则应该会在270号线上开火。(调用,因此是应该专门化的地方。) 我的目标是通过专门化使与一样快。我找到了两种方法:

  • 目前,我已将数字按特定顺序排列。我怎么能把这个随机化呢?例如,每次单击按钮时,我希望每个按钮都更改按钮的所有位置。问题是GridPane可以将节点堆叠在一个地方,使得按钮相互隐藏。有没有办法设置节点不能堆栈? 另一方面,我从一个帖子中找到了一个方法,有人想要切换两个按钮的位置。代码如下所示: 我尝试创建一个包含节点的arraylist,然后使用Math.random从arraylist中获取一个随