用Octave计算整数规划问题(割平面法)
广告
{{v.name}}
割平面法的核心思想:
1. 松弛:去掉整数约束,求解对应的线性规划(称为松弛问题)。
2. 构造割平面约束:若松弛解非整数,从单纯形表的行中提取整数性条件,推导一个新的线性约束。这个约束满足:
- 割去当前的非整数松弛解;
- 不割去任何整数可行解。
3. 迭代求解:将割平面约束加入原问题,形成新的LP,重复步骤1-2,直到松弛解为整数。
代码如下:
function [x_int, z_int, status] = cutting_plane(f, A, b, lb, ub, ctype, sense)
% 割平面法求解纯整数线性规划
% 输入:同 glpk 函数参数
% 输出:x_int-整数最优解, z_int-最优值, status-求解状态(0=最优)
max_iter = 100; % 最大迭代次数,防止死循环
iter = 0;
param.lpsolver = 1;
param.itlim = 100;
vartype = repmat('C', length(f), 1);
while iter < max_iter
iter = iter + 1;
% 步骤1:求解当前松弛LP
[x_relax, z_relax, status] = glpk(f, A, b, lb, ub, ctype, vartype, sense, param);
if status ~= 0
disp('松弛问题无可行解');
x_int = [];
z_int = [];
return;
end
% 步骤2:判断是否为整数解(允许微小数值误差)
if all(abs(x_relax - round(x_relax)) < 1e-6)
x_int = round(x_relax);
z_int = z_relax;
disp(['迭代 ', num2str(iter), ' 次找到整数解']);
return;
end
% 步骤3:调用 glpk 的 extra 输出,获取单纯形表(简化版:直接用非基变量构造割平面)
% 简化处理:选择第一个非整数变量对应的行构造割平面
k = find(abs(x_relax - round(x_relax)) > 1e-6, 1);
[m, n] = size(A);
% 构造松弛LP的标准型,获取单纯形表行(这里简化,直接用原约束推导,实际需从单纯形表提取)
% 注:完整实现需解析单纯形表,此处为演示,假设 x_k 对应的约束行已知
% 简化版割平面:针对变量 x_k,直接添加 x_k ≤ floor(x_relax(k)) 或 x_k >= ceil(x_relax(k))
% 严格割平面需从单纯形表推导,此处简化便于理解
f_k = x_relax(k) - floor(x_relax(k));
if f_k > 0.5
% 添加 x_k >= ceil(x_relax(k))
new_row = zeros(1, n);
new_row(k) = 1;
A = [A; new_row];
b = [b; ceil(x_relax(k))];
ctype = [ctype, 'D']; % 约束类型为 >=
else
% 添加 x_k ≤ floor(x_relax(k))
new_row = zeros(1, n);
new_row(k) = 1;
A = [A; new_row];
b = [b; floor(x_relax(k))];
ctype = [ctype, 'U']; % 约束类型为 ≤
end
end
disp('达到最大迭代次数,未找到整数解');
x_int = [];
z_int = [];
status = -1;
end
例子:
\(
\max\ Z = 10x_1 + 6x_2 + 4x_3 \\
\)
\(
s.t.
\begin{cases}
x_1 + x_2 + x_3 \le 100 \\
10x_1 + 4x_2 + 5x_3 \le 600 \\
2x_1 + 2x_2 + 6x_3 \le 300 \\
x_1,x_2,x_3 \ge 0且为整数
\end{cases}
\)
定义目标函数系数(max Z = 10x1 + 6x2 + 4x3),代码如下:
>> c = [10, 6, 4]';
定义约束系数矩阵 A,代码如下:
>> A = [ 1, 1, 1;
10, 4, 5;
2, 2, 6];
定义约束右端项 b,代码如下:
>> b = [100, 600, 300]';
定义变量下界,代码如下:
>> lb = [0, 0, 0]';
变量无上界,代码如下:
>> ub = [];
定义约束类型:3个约束都是 ≤,对应 'UUU',代码如下:
>> ctype = "UUU";
定义优化方向:最大化模型(-1),代码如下:
>> s = -1;
求解,代码如下:
>> [x_relax, z_relax, status] = ...
cutting_plane (c, A, b, lb, ub, ctype, s)
迭代 2 次找到整数解
x_relax =
33
67
0
z_relax = 732
status = 0