You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Gekko中使用sos1与Lookup表求解优化最大值时遇局部最优问题

问题描述

优化器需要从离散选项(0-5)中选择合适值以最大化目标函数,选项与对应值通过Lookup表关联。以下是简化示例:

数据

x_data = np.array([0, 1, 2, 3, 4, 5])
y_data = np.array([1000,2000,9000,4500,5000,900])
z_data = np.array([15,13,12,17,11,10])

我尝试用cspline函数建立离散选择变量x(定义为sos1类型)与因变量y、z的关系,代码如下:

from gekko import GEKKO
import numpy as np

# 定义数据点
x_data = np.array([0, 1, 2, 3, 4, 5])
y_data = np.array([1000,2000,9000,4500,5000,900])
z_data = np.array([15,13,12,17,11,10])

# 创建模型与变量
m = GEKKO()
x = m.sos1(x_data)
y,z = m.Array(m.Var,2)
m.cspline(x, y, x_data, y_data)
m.cspline(x, z, x_data, z_data)

# 定义目标函数并求解
m.Maximize(y*z)
m.options.SOLVER = 1
m.solve(disp=True)

# 打印结果
print(f'x: {x.value[0]}, y: {y.value[0]}, z: {z.value[0]}')
print('Objective:', y.value[0]*z.value[0])
print(y_data*z_data)

但求解得到了错误结果(疑似局部最优):

x: 0.0, y: 1000.0, z: 15.0
Objective: 15000.0

推测是三次样条导致的局部最优问题,请问有什么方法可以找到该合成函数的全局最大值?


解决方案

针对这个离散选择优化问题,三次样条插值反而会引入不必要的连续插值区域,增加局部最优的概率。以下是几种更直接有效的解决方法:

方法1:直接映射离散值(推荐)

既然x是离散选项,直接用二进制变量建立x与y、z的映射关系,完全避免插值带来的问题:

from gekko import GEKKO
import numpy as np

x_data = np.array([0, 1, 2, 3, 4, 5])
y_data = np.array([1000,2000,9000,4500,5000,900])
z_data = np.array([15,13,12,17,11,10])

m = GEKKO()
# 定义6个二进制选择变量,每个变量对应一个x选项
b = m.Array(m.Var, 6, lb=0, ub=1, integer=True)
m.Equation(sum(b) == 1)  # 约束:仅选择一个选项

# 通过二进制变量映射得到选中的x、y、z值
x = m.sum([b[i] * x_data[i] for i in range(6)])
y = m.sum([b[i] * y_data[i] for i in range(6)])
z = m.sum([b[i] * z_data[i] for i in range(6)])

# 最大化目标函数
m.Maximize(y * z)
m.options.SOLVER = 1  # 使用APOPT整数规划求解器
m.solve(disp=True)

# 输出最优结果
selected_idx = np.argmax([bi.value[0] for bi in b])
print(f'x: {x_data[selected_idx]}, y: {y_data[selected_idx]}, z: {z_data[selected_idx]}')
print('Objective:', y_data[selected_idx] * z_data[selected_idx])

这种方法直接针对离散选项建模,求解结果准确,不会出现局部最优问题。

方法2:启用全局优化模式

如果坚持使用样条插值,可以通过配置APOPT求解器的全局优化选项来提升找到全局最优的概率:

# 在原代码基础上修改求解器设置
m.options.SOLVER = 1
# 配置APOPT全局优化参数
m.solver_options = ['minlp_gap_tol 1.0e-5',
                    'minlp_maximum_iterations 1000',
                    'minlp_max_iter_with_int_sol 100',
                    'minlp_branch_method 1',
                    'minlp_integer_tol 1.0e-5']

不过这种方法仍受插值函数形状影响,可靠性不如直接映射。

方法3:枚举所有离散选项

由于选项仅6个,最简单高效的方式是直接遍历所有可能的x值,计算对应目标值后取最大值:

# 计算所有选项的目标值
objective_values = y_data * z_data
# 找到最大值对应的索引
max_idx = np.argmax(objective_values)
# 输出结果
print(f'最优x: {x_data[max_idx]}, 目标值: {objective_values[max_idx]}')

这种方法适用于选项数量少的场景,结果绝对准确,无需调用优化求解器。


内容的提问来源于Stack Exchange,提问作者TexasEngineer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 14:07:08