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

如何在CVXPY中为Mosek传递回调函数提前终止ILP求解

问题描述

我用CVXPY构建了一个整数线性规划(ILP)模型,目标是寻找可行解。直接将其作为可行性问题求解时往往得不到结果,因此我改成了优化问题并设置超时,求解后再检查解是否满足约束。但即便可行解很早就被找到,求解过程通常仍会耗尽全部超时时间。我希望添加一个回调函数,在求解过程中检查可行性,一旦找到目标值≥10的可行解便终止求解。我找到了Mosek官方关于回调的文档,但不清楚如何在CVXPY中实现。我的疑问是:

  1. 如何将stop_criterion函数加入mosek_params?
  2. stop_criterion函数应接收哪些输入,输出什么?

示例代码:

import cvxpy as cvx
import mosek
import numpy as np

m,n = 320,160
np.random.seed(0)
A = np.random.randint(10, size = (m,n))
b = np.random.randint(10, size = m) + 100
c = np.random.randint(10, size = n)

def stop_criterion(data):
  if data.sum() >= 10: break

x = cvx.Variable(n, integer = True)
prob = cvx.Problem(cvx.Maximize(c @ x), [A @ x <= b, x >= 0])
prob.solve(solver = cvx.MOSEK, mosek_params={mosek.dparam.optimizer_max_time: 10}, verbose = True)

解决方案

1. 回调函数的注册方式

在CVXPY中调用Mosek求解时,需要通过mosek_params里的mosek.iparam.callback参数注册回调函数,直接将定义好的回调函数赋值给该参数即可。

2. 回调函数的输入与输出要求

Mosek的回调函数必须遵循固定的参数格式,接收以下4个输入:

  • callbackcode:回调事件类型(比如找到新整数解、内点法迭代等)
  • din:双精度数组,存储当前求解的相关数值(比如当前目标值)
  • intin:整数数组,存储求解过程中的整数状态信息
  • strin:字符串数组,存储求解过程中的文本信息

回调函数需要返回一个mosek.rescode类型的结果:

  • 返回mosek.rescode.ok:告诉求解器继续运行
  • 返回mosek.rescode.err_user_stop:触发求解器立即终止

我们需要关注mosek.callbackcode.mio_new_int_sol事件——这是MIP求解过程中找到新整数可行解的触发点,在此事件下检查目标值是否满足条件。

修改后的完整代码

import cvxpy as cvx
import mosek
import numpy as np

m,n = 320,160
np.random.seed(0)
A = np.random.randint(10, size = (m,n))
b = np.random.randint(10, size = m) + 100
c = np.random.randint(10, size = n)

# 符合Mosek规范的回调函数
def stop_criterion(callbackcode, din, intin, strin):
    # 当找到新的整数可行解时检查目标值
    if callbackcode == mosek.callbackcode.mio_new_int_sol:
        # din[0]存储当前找到的整数解的目标值
        current_obj = din[0]
        if current_obj >= 10:
            # 返回终止信号
            return mosek.rescode.err_user_stop
    # 其他情况继续求解
    return mosek.rescode.ok

x = cvx.Variable(n, integer = True)
prob = cvx.Problem(cvx.Maximize(c @ x), [A @ x <= b, x >= 0])

# 注册回调并求解
prob.solve(
    solver=cvx.MOSEK,
    mosek_params={
        mosek.dparam.optimizer_max_time: 10,
        mosek.iparam.callback: stop_criterion
    },
    verbose=True
)

# 检查求解结果
if prob.status in [cvx.OPTIMAL, cvx.USER_LIMIT]:
    print(f"找到符合条件的可行解,目标值: {prob.value:.2f}")
else:
    print("未找到满足目标值要求的可行解")

关键说明

  • 回调函数必须严格匹配Mosek的参数格式,否则会触发求解器报错
  • 终止后CVXPY的问题状态会变为USER_LIMIT,需要手动确认解的有效性
  • 如果需要更细致的求解状态监控,可以扩展回调函数处理其他callbackcode事件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 02:23:13