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

如何借助Casadi的Bonmin求解器获取解的迭代过程

问题描述

使用Casadi调用Bonmin求解MINLP问题时,无法通过opti.callback()获取迭代过程,但切换为IPOPT求解器时该代码可以正常运行并输出迭代信息。以下是可复现的代码:

import casadi as ca

opti = ca.Opti()

x1 = opti.variable()
x2 = opti.variable()

opti.set_initial(x1, 1)
opti.set_initial(x2, 10)

obj = x1**2 + x2**2
opti.minimize(obj)

opti.subject_to( x1*x2 >= 1 )

p_opts = {}
s_opts = {'print_level': 4}
opti.solver('ipopt', p_opts, s_opts)

opti.callback(lambda i: print(i, opti.debug.value(x1)))

sol = opti.solve()

将求解器改为'bonmin'后,回调函数不再输出任何内容,请问如何通过Bonmin获取解的迭代过程?

解决方案

Bonmin是基于分支定界框架的MINLP求解器,底层会调用IPOPT这类NLP求解器处理子问题,但Casadi的opti.callback()仅对直接调用的NLP求解器(如IPOPT)生效,无法直接捕获Bonmin的分支定界迭代或子问题求解过程。要获取Bonmin的迭代信息,可以通过以下两种方式:

1. 开启Bonmin的详细日志输出

通过设置Bonmin的求解器选项,让其输出分支定界过程、子问题求解的详细日志,替代回调函数的功能:

import casadi as ca

opti = ca.Opti()

x1 = opti.variable()
x2 = opti.variable()

opti.set_initial(x1, 1)
opti.set_initial(x2, 10)

obj = x1**2 + x2**2
opti.minimize(obj)

opti.subject_to( x1*x2 >= 1 )

# 设置Bonmin的选项,开启详细日志
p_opts = {}
s_opts = {
    'print_level': 6,  # 更高的打印级别,输出分支定界细节
    'bonmin.print_level': 6,
    'ipopt.print_level': 4  # 同时输出子问题IPOPT的迭代信息
}
opti.solver('bonmin', p_opts, s_opts)

sol = opti.solve()

调整print_level的值(通常1-6,数值越高输出越详细),可以得到分支定界的迭代次数、当前上下界、子问题的求解状态等信息。

2. 自定义Bonmin的回调函数(进阶)

如果需要程序化地捕获迭代数据,可以通过Casadi的Function创建Bonmin的回调函数,并通过求解器选项注册:

import casadi as ca

# 定义回调函数,参数需符合Bonmin的要求
def bonmin_callback(iter_num, obj_val, primal_vars, dual_vars, stats):
    print(f"Bonmin迭代 {iter_num}: 目标值={obj_val}, x1={primal_vars[0]}")
    return True  # 返回True表示继续求解

# 将Python函数包装为Casadi Function
callback_fun = ca.Function('bonmin_callback', 
                           [ca.MX.sym('iter'), ca.MX.sym('obj'), ca.MX.sym('x', 2), ca.MX.sym('lam'), ca.MX.sym('stats')],
                           [ca.MX(True)],
                           ['iter', 'obj', 'x', 'lam', 'stats'],
                           ['continue'])

opti = ca.Opti()

x1 = opti.variable()
x2 = opti.variable()

opti.set_initial(x1, 1)
opti.set_initial(x2, 10)

obj = x1**2 + x2**2
opti.minimize(obj)

opti.subject_to( x1*x2 >= 1 )

p_opts = {
    'bonmin.callback': callback_fun  # 注册回调函数
}
s_opts = {'print_level': 4}
opti.solver('bonmin', p_opts, s_opts)

sol = opti.solve()

注意:Bonmin的回调函数参数格式需要严格匹配,这种方式可以更灵活地处理迭代过程中的数据。

内容的提问来源于stack exchange,提问作者tempname

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 17:25:19