离散优化(SOS1约束) – GEKKO.

我想用Python中的GEKKO定义一个优化问题,我想使用一些带有预定义选择列表的设计变量。同时,每个选择都有一个相关的成本,约束条件是总成本应该在一个指定的限制之下。

下面是一个常见的gekko例子(找到的) 此处),但需修改为 x1x2sos1. 同时用索引的选择值 x1x2我从另一个列表中找到它们的相关成本,它们的总和应该小于某个值(约束)。

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 函数的初始值作为 x1x2 似乎是零。

这段代码不工作,我得到以下错误。

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

我不知道是什么原因导致这个错误。我应该如何重新计算我的模型,以获得理想的结果?

编辑:这个例子代码只是我尝试重新创建错误。我的实际应用是设计一个工程系统。例如,假设系统有2个组件–电池和灯泡。我对电池有两个选择,电池A重10kg,其可靠性为0.97,电池B重6kg,其可靠性为0.75。同样,灯泡也有不同的选择。我需要选择电池和灯泡,使系统的总可靠性尽可能高(目标),总重量小于’x’kg(约束)。在上面的代码中,请考虑 x1x2 值作为组件的选择,我找到它们的指数以获得它们的相关重量成本(如果电池A和灯泡B被选中,我获得它们的重量以检查总重量是否小于允许的限制)。现在我的实际系统有 n 组成部分和 m 每个组件的选择。而每个选择都有相关的重量、成本、可靠性等。我想在系统重量、成本等约束条件下,找到最佳组合,使系统可靠性最大化。

解决方案:

我根据你的例子描述建立了一个简单的模型。

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)

给TA打赏
共{{data.count}}人
人已打赏
未分类

警告:遇到一个非数字值的问题。遇到一个非数字值的问题

2022-9-8 11:11:38

未分类

让python调度脚本在Windows上运行

2022-9-8 11:22:18

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索