线性规划(二)——两阶段法

两阶段法

单纯形法并未提供初始基向量组的求解方法,因此在该算法中,初始基向量组下标 \pi 是需要额外提供的。幸运的是,两阶段法对于线性规划的标准形提供了一般的初值求解算法。这个算法利用人工变量和基变换,将一个辅助问题的可行基向量组逐步转化为了原问题的可行基向量组。

对于线性规划问题 \mathcal{P}
\mathcal P:\left\{ \begin{matrix} \min~z=c^\mathrm Tx\\[2pt] Ax=b\\[2pt] x\geqslant0 \end{matrix} \right. 其中 A\in\mathbb R^{m\times n},~b\in\mathbb{R}^mb\geqslant0c\in\mathbb R^n,考虑其辅助问题 \mathcal P'
\mathcal P':\left\{ \begin{matrix}\displaystyle \min~w=\sum_{i=1}^my_i\\[12pt] (A~I_m) \begin{pmatrix} x\\y \end{pmatrix} =b\\[8pt] x\geqslant0,~y\geqslant0 \end{matrix} \right. 其中 y=(y_1,\cdots,y_m)^\mathrm Tm 个分量称为人工变量。如果记增广后的矩阵 \widetilde{A}=(A~I_m)\in\mathbb{R}^{m\times (n+m)}, \widetilde{x}= \begin{pmatrix} x\\y \end{pmatrix}\in\mathbb{R}^{n+m},则线性约束约束条件可简写为 \widetilde{A}\widetilde{x}=b
下面来求解 \mathcal{P}'。因为 \displaystyle w=\sum_{i=1}^my_i\geqslant0 恒成立,因此 \mathcal P' 必有最优解 \begin{pmatrix} x^*\\y^* \end{pmatrix},且最小值 w^*\geqslant0


基于 w^* 的正负性,分以下两种情况:

  • w^*>0\mathcal P 的可行域为空,否则 \mathcal P' 中有可行解使 y=0。此时算法直接结束。
  • w^*=0:不妨设 \mathcal P' 的最优解 \widetilde{x}^*=\begin{pmatrix} x^*\\y^* \end{pmatrix} 也是基本解,则 w^*=0\Rightarrow y^*=0。因此 \widetilde{x}^* 的人工变量部分和非基变量部分的值均为 0。这是今后的证明当中会引用到的重要性质。

记最优基本解 \widetilde{x} 所包含的基分量下标集为 \pi\in\mathbb{R}^m,则 B=\widetilde{A}(:,\pi)\in\mathbb{R}^{m\times m}\mathcal P'最优基向量组。与之相对的,记 \pi'\in\mathbb{R}^{n}\widetilde{A} 的非基分量下标集,N=\widetilde{A}(:,\pi')\in\mathbb{R}^{m\times n} 是非基向量组。

我们的目标是要让 B 对应的基变量中不包含人工变量,从而使 B 对应的最优基本解的前 n 个分量构成 \mathcal P 的基本可行解。 用代数的语言来描述,就是 \pi(i)\leqslant n,~~(1\hspace{-1pt}\leqslant \hspace{-1pt}i\hspace{-1pt}\leqslant \hspace{-1pt}m)。为了达到这一目的,只需将 B 中的人工变量替换为非基变量,也就是基变换

\widetilde{x}_B,~\widetilde{x}_N 分别是 \widetilde{x}\pi\pi' 中的分量,则 \widetilde{A}\widetilde{x}=b\Rightarrow B\widetilde{x}_B+N\widetilde{x}_N=b,因此
\widetilde{x}_B=B^{-1}(b-N\widetilde{x}_N) 如果 \widetilde{x}_B 的第 i 个分量(它是基变量)是人工变量,则 \pi(i)>n。记 k=\pi(i)-n,则 y_k 就是上述人工变量。由此可知,\widetilde{x}_B 的第 i 行恰好是 y_k。因此
y_k=a+v^\mathrm T\widetilde{x}_N 其中 v^\mathrm T-B^{-1}N 的第 i 行。由于 \mathcal P' 的最优基本解 \widetilde{x}^* 的人工变量和非基变量部分都是 0,故在 \widetilde{x}^* 处有 y_k=0,~\widetilde{x}_N=0,从而 a=0。上式进一步改写为
y_k=v^\mathrm T\widetilde{x}_Ny_k 可由 n 个非基变量完全线性表示。为了完成关于基变量 y_k 的基变换,需要在非基变量组 \widetilde{x}_N 中选择一个“合适”的非人工变量。因此,选择 1\hspace{-1pt}\leqslant \hspace{-1pt}j\hspace{-1pt}\leqslant \hspace{-1pt}n 使得 v(j)\neq0\pi'(j)\leqslant m。这样的 j 是存在的,否则上式意味着 \{y_j\}_{j=1}^m 是线性相关的,对应于 \mathcal Pm 个方程是线性相关的。这与 \mathrm{rank}~A=m 的条件相矛盾。

最后,令 \pi(i)=\pi'(j) 我们就完成了基替换。记 k=\pi(i)-n,~l=\pi'(j),则原先的基向量 y_k 被替换为了 x_l,相应的,基向量组
B=(P_{\pi(1)},\cdots,P_{\pi(i)},\cdots,P_{\pi(m)}) 变成了向量组
B'=(P_{\pi(1)},\cdots,P_{\pi'(j)},\cdots,P_{\pi(m)})


关于向量组 B',需要证明如下结论:

  • B' 是基向量组。
    相比于单纯形法中的基变换,这一“基向量组”的证明似乎并非显然。回忆一下我们在单纯形法的基变换中是如何证明替换后的向量组 B' 是线性无关的:

存在可逆 Guass-Jordan 矩阵 H,使得 B'=BH

这回我们没有现成的列向量之间的关系加以使用,不过我们可以使用 \widetilde{x} 的分量之间的关系

y_k=v^\mathrm T\widetilde{x}_N

对于向量组 B' 而言,采用与 B 类似的符号:B',N',\widetilde{x}_{B'},\widetilde{x}_{N'}。注意到 v(j)\neq0,故上式可以改写成 x_l 关于 y_k\widetilde{x}_N 的其它分量,也就是 \widetilde{x}_{N'} 的各个分量的线性组合:
x_l=u^\mathrm T\widetilde{x}_{N'} 因为 \widetilde{x} 的各个分量都是 \widetilde{x}_N 的各个分量的线性组合,因此利用 x_l 的表达式进行替换,将得到:\widetilde{x} 的每个分量都是 \widetilde{x}_{N'} 的各个分量的线性组合。因此存在 P\in\mathbb R^{m\times n},~Q\in\mathbb{R}^m,使得
\widetilde{x}_{B'}=P\widetilde{x}_{N'}+Q 对于任何 \widetilde{x}_{N'} 成立。由于 (B'~N') \begin{pmatrix} \widetilde{x}_{B'}\\ \widetilde{x}_{N'} \end{pmatrix}=bB'P+N'=0。因此 (B'~0) 可由 (B'~N') 进行初等列变换得到,而后者的秩恰为 m。故 \mathrm{rank}~B'=m,即 B'm 阶可逆矩阵,命题得证。

  • B' 对应的基本解是 \widetilde{x}^*,因而 B'最优基向量组
    这一结论的证明是容易的,因为 B' 的非基部分 \widetilde{x}_{N'}=0\Rightarrow x_l=0\Rightarrow \widetilde{x}_{N}=0\Rightarrow \widetilde{x}=\widetilde{x}^*。因此 B' 对应的基本解恰好是 \widetilde{x}^*

上述结论推出:每一次基变换都将最优基向量组 B 变成最优基向量组 B',并且最优基本解始终是 \widetilde{x}^*。由于每次变换都使得 B 包含的人工变量数减1,故至多 m 次变换之后将得到不含人工变量的基 B_0,且 B_0\mathcal{P'} 的最优基。因此,B_0\mathcal{P} 的可行基,从而顺利得到了原线性规划问题 \mathcal{P} 的初值。


综合以上的讨论,两阶段法的伪代码如下:

算法(两阶段法):Ax=bx\geqslant0 的条件下,求一个基本可行解。

  • 输入:A\in\mathbb{R}^{m\times n},~b\in\mathbb{R}^{m\times 1}
  • 输出:\pi\in\mathbb{R}^m,即可行基向量组的下标构成的集合

A=(A~I_m) % m*(n+m)
c=(\underbrace{0,\cdots,0}_{n},\underbrace{1,\cdots,1}_m)^\mathrm T % (n+m)*1
\pi=(n+1,\cdots,n+m) % 基分量下标
[\pi,\sim,\omega]=\mathrm{SimplexMethod}(A,b,c,\pi) % 求解辅助问题

  • \omega>0:没有可行解
  • \omega=0
    index=\mathrm{find}(\pi>n) % 人工基变量下标
    \pi'= 非人工变量下标集 \in\mathbb{R}^n
    B=A(:,\pi) % 基向量组,m*m
    N=A(:,\pi') % 非基向量组,m*n

\mathrm{for}~i=index % 遍历人工基向量下标

v=B^{-1}N 的第 i% 1*n
找下标 j 使得 v(j)\neq0\pi'(j)\leqslant n % 找一个非人工变量
交换 \pi(i),\pi'(j)
交换 B(:,i),N(:,j)


返回 \pi

代码实现

最后给出单纯形法和两阶段法的代码实现(MATLAB):

  • 单纯形法:\mathrm{SimplexMethod}
function [ pi,beta,z0 ] = SimplexMethod( A,b,c,pi )
% 初始化
B=A(:,pi); % 基向量组
alpha=B\A;
beta=B\b; % 约化基本解
l=c(pi); % cB
lambda=c-transpose(alpha)*l; % 检验向量
z0=transpose(l)*beta; % 目标函数最小值
% 最优性检验/基变换
while(1)
    k=find(lambda<0,1); % 第一个<0的下标
    if(k) % k存在
        B=alpha(:,k);
        y=find(B>0); % 寻找>0的下标 1...m
        if(y)
            l=beta(y); % beta的子集
            B=B(y); % alpha第k列的子集
            B=l./B; % 寻找其中的最小值
            [~,l]=min(B); % 找到数组最小值下标
            l=y(l); % 找回原来的下标 1..m
            pi(l)=k; % 更换基分量
            y=-alpha(:,k);y(l)=y(l)+1; % 辅助计算
            z0=z0+lambda(k)*beta(l)/alpha(l,k); % 更新z0
            lambda=lambda-lambda(k)*transpose(alpha(l,:))/alpha(l,k); % 更新lambda
            beta=beta+y*beta(l)/alpha(l,k); % 更新beta
            alpha=alpha+y*alpha(l,:)/alpha(l,k); % 更新alpha
        else % 没有正数
            error('单纯形法发生错误:目标函数无界');
        end
    else
        return; % k不存在
    end
end
end
  • 两阶段法:\mathrm{TwoStage}
function [ pi ] = TwoStage( A,b )
[m,n]=size(A); % 矩阵大小
A=[A eye(m)]; % 扩充
i=[zeros(n,1);ones(m,1)];
pi=n+1:n+m; % 基分量下标
[pi,~,w]=SimplexMethod(A,b,i,pi); % 辅助问题
if(w>0) % 返回错误信息
    error('两阶段法发生错误:可行域为空');
else
    index=find(pi>n); % 找到人工变量下标 1...m
    qi=1:n+m;
    qi(pi)=0;
    qi=qi(logical(qi)); % 非基向量下标
    B=A(:,pi); % 基向量组
    N=A(:,qi); % 非基向量组
    for i=index % 遍历人工基向量下标
        j=B\N;
        j=j(i,:); % n*1
        j=(j~=0)&(qi<=n);
        j=find(j,1); % 非基变量下标
        w=pi(i);pi(i)=qi(j);qi(j)=w;
        w=B(:,i);B(:,i)=N(:,j);N(:,j)=w;
    end
    return; % 返回 pi
end
end
  • 线性规划:\mathrm{LinearProgram}
function [ z0,x,pi ] = LinearProgram( A,b,c )
pi=TwoStage(A,b); % 初始基下标
[ pi,b,z0 ]=SimplexMethod(A,b,c,pi); % 求最优解
x=zeros(size(c));
x(pi)=b;
end

例:求解线性规划问题标准形,其中
A= \begin{pmatrix} 0.25 & 0.5 & 1 &&\\ 0.5 & 0.5 & &1 &\\ 0.25 & && &1 \end{pmatrix},~ b=\begin{pmatrix} 120\\ 150 \\50 \end{pmatrix},~ c=\begin{pmatrix} -12\\ -15\\ 0\\ 0\\ 0 \end{pmatrix} 解:执行
[z_0,x,\pi]=\mathrm{LinearProgram}(A,b,c) 可得
z_0=-4140,~x=\begin{pmatrix} 120\\ 180\\ 0\\ 0\\ 20 \end{pmatrix},~\pi=\begin{pmatrix} 5\\2\\1 \end{pmatrix}

参考资料

[1] 清华大学出版社《算法设计与分析(第2版)》

你可能感兴趣的:(线性规划(二)——两阶段法)