news 2026/10/23 2:15:46

HiGHS 线性规划求解器实战:从 20 行建模代码到生产级性能调优

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HiGHS 线性规划求解器实战:从 20 行建模代码到生产级性能调优

HiGHS 线性规划求解器实战:从 20 行建模代码到生产级性能调优

【免费下载链接】HiGHSLinear optimization software项目地址: https://gitcode.com/GitHub_Trending/hi/HiGHS

HiGHS 线性规划求解器是一个 MIT 协议的开源 C++ 求解器,同时覆盖线性规划(LP)、凸二次规划(QP)和混合整数规划(MIP),内置 presolve(求解前自动削减问题规模的过程)、单纯形法、内点法和分支定界框架,不依赖任何第三方库。本文以 Python 接口为主线,从跑通第一个模型讲起,把建模、求解器选型、性能调优和生产环境中的模型交换逐一过一遍,源码结构见highs/主目录,示例代码集中在examples/目录。

一条产线、两种产品、三台瓶颈设备

先说清楚要解决的问题:你负责产线排产,产品 A 每件利润 30 元、产品 B 每件 25 元;每单位 A 耗 1 单位原料、每单位 B 耗 2 单位,原料每天只有 80 单位;A 的日产能上限是 150 件。排产计划每周重排一次,而 Excel 试凑法每次要花大半天,还不敢保证全局最优。

这就是最典型的 LP 场景,也是 HiGHS 的主场。它的优势不在于"功能全",而在于默认配置下就能给出最优解,且 presolve、单纯形、内点法、MIP 四条技术路线在同一个引擎里切换,不需要换工具。

装完highspy后,你可以直接跳到下一节跑通第一个实例;如果暂时只想了解它内部有哪些求解器,仓库文档docs/src/solvers.md有一份完整清单。

HiGHS Python 安装后,5 分钟跑通第一个模型

HiGHS 的 Python 包是highspy,一条 pip 命令即可:

pip install highspy

之后就是建模的三步曲:声明变量、加约束、求解取解。下面这个例子对应开篇的排产问题,注意显式给出下界为 0——HiGHS 变量的默认下界是负无穷,不写的话求解器会认为"产量"可以是负数:

import highspy h = highspy.Highs() inf = highspy.kHighsInf # 默认下界是 -inf,排产量不可能为负,所以要显式钉住下界 h.addVars(2, lb=[0.0, 0.0], ub=[100.0, 150.0]) # 目标系数:A 每件 30 元,B 每件 25 元 h.changeColsCost(2, [0, 1], [30.0, 25.0]) # 原料约束 1*x1 + 2*x2 <= 80,右端写成上界 80 h.addRow(0.0, 80.0, 2, [0, 1], [1.0, 2.0]) h.run() info = h.getInfo() print("状态:", h.modelStatusToString(h.getModelStatus())) print("最优目标值:", info.objective_function_value) sol = h.getSolution() print("产量:", list(sol.col_value))

输出大致是:

状态: HighsModelStatus.kOptimal 最优目标值: 2000 产量: [40.0, 20.0]

run()背后发生的事:presolve 先尝试削减问题,然后调用默认求解器(LP 默认是单纯形法),最后把 primal 解写回getSolution()。getInfo()返回的objective_function_value是最优目标值,simplex_iteration_count是迭代次数,这两个字段后面调优时都会反复用到。

这个接口对 LP、QP、MIP 是同一套,区别只在建模时用什么变量类型。下面看命名建模语法,以及把 MIP 也跑起来。

从 LP 到 MIP:HiGHS 混合整数规划建模教程

对熟悉PuLP或scipy.optimize的人来说,highspy最省适应成本的地方是它的表达式建模语法——变量可以直接参与+、<=运算。仓库自带的家具厂经典例子(完整版在examples/chip.py)精简后长这样:

import highspy h = highspy.Highs() h.silent() # 关掉求解日志,只要结果 # 命名变量 + 目标系数一次声明,后面可以直接用 x['Tables'] 引用 x = h.addVariables(['Tables', 'SetsOfChairs'], obj=[10.0, 25.0]) h.addConstrs(x['Tables'] + 2*x['SetsOfChairs'] <= 80, # 装配工时 x['Tables'] + 4*x['SetsOfChairs'] <= 120, # 涂装工时) h.setMaximize() h.solve() print([h.variableValue(v) for v in x]) # 最优产量 print([h.variableDual(v) for v in x]) # 变量对偶(简化成本) print([h.constrValue(c) for c in h.getConstrs()]) # 约束取到的值

解完 LP 顺手能拿到对偶值(影子价格),这对"原料涨价多少还值不值得外购"这类决策问题直接可用。

如果决策是"选或不选",就换成整数变量。highspy提供了addBinaries快捷方法,0-1 背包问题十几行就能写完:

import highspy h = highspy.Highs() h.silent() # 演示 setSolution 热启动时,presolve 会改变问题规模、使传入的解对不上号, # 所以这个例子里先关掉 h.setOptionValue("presolve", "off") x = h.addBinaries(5) # 5 个 0-1 变量 h.addConstr((x * [4, 3, 1, 5, 4]).sum() <= 11) # 背包重量 h.maximize((x * [8, 5, 3, 11, 7]).sum()) # 物品价值 h.run() print("背包总价值:", h.getInfo().objective_function_value) # 22 # 分支定界支持热启动:喂回一个已有解,让搜索从它出发 h.clearSolver() # 清空求解状态,保留模型 h.setSolution(h.getSolution()) h.run()

setSolution在 MIP 求解器里并不常见,它的价值在于:业务系统里已有的启发式解可以作为初始可行解传入,搜索不用从零开始。热启动之外,MIP 子问题用什么求解器,是下一个章节的选型问题。

3 种求解策略怎么选

LP 部分,highspy默认走单纯形法(solver = "choose"时 LP 的默认就是它)。想换路线,直接改solver选项即可:"simplex"、"ipm"(HiPO 内点法)、"ipx"、"hipo"。内点法在小问题上不一定占优,但仓库文档里明确:问题规模一大,HiPO 的优势可以拉开一个数量级以上,所以大规模稀疏 LP 值得试一次切换:

h.setOptionValue("solver", "ipm") # 切到内点法(HiPO) h.setOptionValue("parallel", "on") # 启用并行 h.setOptionValue("threads", 4) # 限制最多 4 个线程

MIP 部分有一个专门的旋钮:mip_lp_solver控制分支定界树中 LP 子问题的求解器("simplex"/"ipm"/"hipo"),根节点没有基信息时它尤其有用。

这些选项的完整说明见仓库文档docs/src/options/definitions.md,每一项都带取值范围和默认值。参数怎么落到生产环境的配置文件里,下面接着说。

让求解更快的四个参数旋钮

调优的顺序建议是:默认配置跑一遍拿基线 → 一次只改一个参数 → 对比model_status、目标值和迭代/节点数的变化。乱改一堆参数只会让你分不清是谁起了作用。

最常见的三种场景和对应旋钮:

问题特征建议旋钮原因
大规模稀疏 LP,单纯形迭代数很高solver = "ipm"内点法迭代次数不随规模线性膨胀
大 MIP,且有时间限制presolve = "on"+mip_lp_solver = "ipm"根节点和深节点松弛用内点法求解更快
LP 反复报数值病态、容差超标微调kkt_tolerance控制可行性/最优性(KKT)判定阈值

生产环境里参数通常放在选项文件中,一次性生效。HiGHS 选项文件支持#注释、空行和--命令行风格的行:

# highs_options.txt # HiGHS 选项文件:每行一个选项,# 开头为注释 presolve = on time_limit = 3600 # 最多跑 1 小时,超时返回当前最优解 threads = 4 # 并行时最多用 4 个线程 solver = choose # 让 HiGHS 按问题类型自选(LP 默认单纯形) ranging = off # 需要敏感性报告时再打开

加载它只需一行:

h.passOptionsFile("highs_options.txt")

参数调不动的时候,多半是模型结构的问题——比如满是不参与任何约束的变量、约束右端项量级相差十亿倍。这种情况改参数没有用,应该回到建模层面,把冗余变量清掉、把量级对齐。

参数和配置文件解决了"怎么跑得快",还有两件生产上绕不开的事:模型怎么在系统之间传递,以及解出来之后怎么利用对偶信息。

模型读写、敏感性分析与多目标

HiGHS 原生读 MPS 和 CPLEX 风格 LP 文件,求解后也能把模型写回磁盘,适合在"建模脚本 → 求解服务 → 结果归档"的链路里做模型快照:

# 读入已有模型并求解 h2 = highspy.Highs() h2.readModel("model.lp") h2.run() # 求解后把模型归档,便于事后复盘"当时到底解的是什么" h2.writeModel("model_archive.mps")

对 LP 的决策者来说,比最优解本身更值钱的是"解有多稳健"。打开ranging选项后,HiGHS 会一次算出目标系数、变量边界、约束右端项各自允许变化多少而不改变当前最优基:

# highs_options.txt(在上一节的基础上追加) ranging = on

多目标优化 HiGHS 也能接:多个目标按权重加权成单目标求解,权重变化时重新求解即可对比方案。到这里,建模、求解、调优、交换的闭环就完整了。

从哪里继续

仓库里的check/目录有一整套测试用例和实例文件(LP、MPS 混合,含issue-*.mps这类回归用例),examples/里还有网络流、多目标、回调(callback)等更多完整脚本,可以直接拿来当模板改。如果你下一步的计划是处理含整数变量的排产或选址问题,建议从 MIP 建模的完整案例读起;需要嵌入自有 C++ 服务时,C 接口头文件在highs/interfaces/highs_c_api.h,示例程序见examples/call_highs_from_c.c。

【免费下载链接】HiGHSLinear optimization software项目地址: https://gitcode.com/GitHub_Trending/hi/HiGHS

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/23 2:15:45

OE_市场调研_工业清扫机器人01

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/23 2:14:25

玩转Minecraft启动器全攻略:从新手到大神的秒会指南

玩转Minecraft启动器全攻略&#xff1a;从新手到大神的秒会指南 Plain Craft Launcher 2&#xff08;PCL2&#xff09;是一款功能强大的Minecraft启动器&#xff0c;支持多账号管理、模组一键安装和游戏环境智能配置&#xff0c;让你轻松驾驭Minecraft的无限可能。 30秒快速上…

作者头像 李华
网站建设 2026/10/23 2:12:12

Python+Django 14天工单系统实战:权限、状态流转与部署

很多 Python 学习者都会卡在同一个位置&#xff1a;Django 教程能跟着敲完&#xff0c;models、views、urls、templates 都认识&#xff0c;但真要做一套能交给别人用的系统&#xff0c;就发现缺的并不是语法&#xff0c;而是把权限、状态流转、部署、排错这几件事串起来的能力…

作者头像 李华
网站建设 2026/10/23 2:11:25

10分钟跑通OpenDLSS-NR:Windows编译构建与运行完整教程

【免费下载链接】OpenDLSS-NR A Vulkan reimplementation of NVIDIAs DLSS 5 Neural Rendering network, bit-exact against the original. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/op/OpenDLSS-NR 点击查看 免费下载 OpenDLSS-NR 是一个基于 Vulkan 对 NVIDIA …

作者头像 李华