C++内点法求解大规模线性规划问题——对标MATLAB中linprog函数


项目资源链接如下https://download.csdn.net/download/weixin_46584887/86406561


1. 项目场景

对于如下大规模线性规划问题:

min ⁡    c 1 x 1 + c 2 x 2 + ⋯ + c n x n s.t.   a 11 x 1 + a 12 x 2 + ⋯ + a 1 n x n = b 1 a 21 x 1 + a 22 x 2 + ⋯ + a 2 n x n = b 2 … a m 1 x 1 + a m 2 x 2 + ⋯ + a m n x n = b m x 1 , x 2 , … , x n ≥ 0 \begin{array}{rl} \min\ \ &c_1x_1+c_2x_2+\dots+c_nx_n\\ \textrm{s.t.}\ \ &a_{11}x_1+a_{12}x_2+\dots+a_{1n}x_n=b_1\\ &a_{21}x_1+a_{22}x_2+\dots+a_{2n}x_n=b_2\\ &\dots\\ &a_{m1}x_1+a_{m2}x_2+\dots+a_{mn}x_n=b_m\\ &x_1,x_2,\dots,x_n\ge0 \end{array} min  s.t.  c1x1+c2x2++cnxna11x1+a12x2++a1nxn=b1a21x1+a22x2++a2nxn=b2am1x1+am2x2++amnxn=bmx1,x2,,xn0

或者写成如下形式:

min ⁡   c x   s.t.  { A x = b x ≽ 0 \min\ \bf{cx}\ \ \textrm{s.t.}\ \left\{\begin{array}{l}\bf Ax=b\\ \bf x\succcurlyeq 0\\ \end{array}\right. min cx  s.t. {Ax=bx0

并且 A ∈ R m × n , x ∈ R n × 1 , b ∈ R m × 1 \bf{A}\in R_{m\times n},x\in R_{n\times 1},b\in R_{m\times 1} ARm×n,xRn×1,bRm×1.


2. 约束的规范化

  • 对于缺乏非负约束的变量 x i x_i xi,我们做出如下转化 :

    • x i = x i 1 − x i 2 x_i=x_{i1}-x_{i2} xi=xi1xi2

    • x i 1 ≥ 0 , x i 2 ≥ 0 x_{i1}\ge0,x_{i2}\ge0 xi10,xi20

  • 对于不等式约束,我们也需要将其松弛为等式约束:

    • ∑ j = 0 n a i j x j ≤ b i \sum_{j=0}^{n}a_{ij}x_{j}\le b_i j=0naijxjbi 或者 ∑ j = 0 n a i j x j ≥ b i \sum_{j=0}^{n}a_{ij}x_{j}\ge b_i j=0naijxjbi

    • x n + i ± ∑ j = 0 n a i j x j = b i , x n + i ≥ 0 x_{n+i}\pm\sum_{j=0}^{n}a_{ij}x_{j}=b_i, x_{n+i}\ge 0 xn+i±j=0naijxj=bi,xn+i0


3. 输入格式

代码从文本文件中读取数据(data.txt):

  • 该文本文件的第一行包含两个整数, m and n, 分别代表约束个数与变量个数
  • 第二行的 n 个元素代表目标函数中变量前的系数 c i c_i ci
  • 接下来 m 行每行包括 n + 1 个元素, 每行的前 n 个元素代表变量前的系数 a i j a_{ij} aij,,最后一个元素代表 b i b_i bi

举个例子,对于如下线性规划问题:

max ⁡ 5 x 1 + 10 x 2 s.t. 8 x 1 + 8 x 2 ≤ 160 4 x 1 + 12 x 2 ≤ 180 x 1 ≤ 15 x 1 , x 2 ≥ 0 \begin{array}{rl} \max&5x_1+10x_2\\ \textrm{s.t.}&8x_1+8x_2\le 160\\ &4x_1+12x_2\le180\\ &x_1\le15\\ &x_1,x_2\ge0 \end{array} maxs.t.5x1+10x28x1+8x21604x1+12x2180x115x1,x20

我们首先要将其转换为如下形式:

min ⁡ − 5 x 1 − 10 x 2 s.t. 8 x 1 + 8 x 2 + x 3 = 160 4 x 1 + 12 x 2 + x 4 = 180 x 1 + x 5 = 15 x 1 , x 2 , x 3 , x 4 , x 5 ≥ 0 \begin{array}{rl} \min&-5x_1-10x_2\\ \textrm{s.t.}&8x_1+8x_2+x_3= 160\\ &4x_1+12x_2+x_4=180\\ &x_1+x_5=15\\ &x_1,x_2,x_3,x_4,x_5\ge0 \end{array} mins.t.5x110x28x1+8x2+x3=1604x1+12x2+x4=180x1+x5=15x1,x2,x3,x4,x50

接着输入文件 data.txt 中的内容应如下:

3 5
-5 -10 0 0 0
8 8 1 0 0 160
4 12 0 1 0 180
1 0 0 0 1 15

应注意的是,在上述情况下获得的求解结果不是特别精确。对于小规模模型的求解,我们可以尝试使用一些整数规划解算器,例如 Google 的 OR-Tools,或者使用单纯形法来求解。

对于大规模线性规划问题(包括整数和浮点数),代码的求解精度是不错的。


4. 如何构建模型

确保你的电脑中有这些编译工具,以 Ubuntu 为例:

sudo apt install build-essential cmake make

接着进入项目目录,执行如下命令:

cd LinprogSolver4C && cmake CMakeLists.txt

可以看见目录中生成了 Makefile 文件,你可以使用 make 工具获得可执行文件:

make

5. 如何使用

在目录中构建出可执行文件之后,其用法如下:

./linprog data.txt # any data paths

在终端中可以得到如下输出:

1

LP problem:
 Iter  Residual        Mu    Alphax    Alphas
    0  2.70e-01  1.54e+00       ---       ---
    1  1.24e-03  6.01e-02  1.00e+00  1.00e+00
    2  7.97e-08  3.86e-06  1.00e+00  1.00e+00
    3  3.99e-12  1.93e-10  1.00e+00  1.00e+00
    4  2.06e-16  9.66e-15  1.00e+00  1.00e+00

----------------------------

Optx:
    1       7.5
    2        12
    3   2.4e-14
    4   2.6e-14
    5       7.5

----------------------------

linprog Terminated. Status : 0
[Iters: 4] [Time: 2.82e-03s]

第一行输出的整数含义如下:

0 - optimal

1 - terminated by maxIter

2 - infeasible


GitHub地址:https://github.com/ZhiQiangFeng

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐