最优化方法Python计算:线性规划辅助问题最优解的预后处理

对标准型线性规划
{ minimize c ⊤ x s.t. A x = b x ≥ o ( 1 ) \begin{cases} \text{minimize}\quad\boldsymbol{c}^\top\boldsymbol{x}\\ \text{s.t.}\quad\quad\boldsymbol{Ax}=\boldsymbol{b}\\ \quad\quad\quad\quad\boldsymbol{x}\geq\boldsymbol{o} \end{cases}\quad\quad(1) ⎩ ⎨ ⎧minimizec⊤xs.t.Ax=bx≥o(1)

添加人工变量 x a \boldsymbol{x}_a xa后,得到辅助线性规划问题
{ minimize e ⊤ x a s.t. A ′ ( x x a ) = A x + E x a = b x , x a ≥ o ( 2 ) \begin{cases} \text{minimize}\quad\quad\boldsymbol{e}^\top\boldsymbol{x}_a\\ \text{s.t.\ \ \ \ }\quad\quad\quad\boldsymbol{A}'\begin{pmatrix}\boldsymbol{x}\\\boldsymbol{x}_a\end{pmatrix} =\boldsymbol{Ax}+\boldsymbol{Ex}_a =\boldsymbol{b}\\ \quad\quad\quad\quad\quad\quad\boldsymbol{x},\boldsymbol{x}_a\geq\boldsymbol{o} \end{cases}\quad\quad(2) ⎩ ⎨ ⎧minimizee⊤xas.t. A′(xxa)=Ax+Exa=bx,xa≥o(2)

其中, e ∈ R n \boldsymbol{e}\in\text{R}^n e∈Rn,所有元素均为1。 E \boldsymbol{E} E是单位阵的一部分,与 A \boldsymbol{A} A中若干列构成单位阵 I \boldsymbol{I} I,作为问题(2)的初始基矩阵,运用单纯形算法可算得辅助问题(2)最优解, x ∗ = ( x x a ) \boldsymbol{x}^{*}=\begin{pmatrix}\boldsymbol{x}\\\boldsymbol{x}_a\end{pmatrix} x∗=(xxa),求解过程称为第一阶段 。若 x a = o \boldsymbol{x}_a=\boldsymbol{o} xa=o则原问题(1)可行。并且,若 x ∗ \boldsymbol{x}^{*} x∗中的原问题决策变量部分 x \boldsymbol{x} x恰巧是是(1)的基本可行解,即第一阶段计算所得的辅助问题的基矩阵 B ∗ \boldsymbol{B}^{*} B∗恰包含在原问题(1)的系数矩阵 A \boldsymbol{A} A中,则以此为起点,可运用单纯形算法求解问题(1),这一过程称为第二阶段

然而,第一阶段计算所得的辅助问题的基矩阵 B ∗ \boldsymbol{B}^{*} B∗未必包含在原问题(1)的系数矩阵 A \boldsymbol{A} A中。
例1 对线性规划
{ minimize x 1 − x 2 s.t. − x 1 + 2 x 2 + x 3 + x 4 = 2 − 4 x 1 + 4 x 2 − x 3 = 4 x 1 − x 3 = 0 x 1 , x 2 , x 3 , x 4 ≥ 0 . \begin{cases} \text{minimize}\quad\quad x_1-x_2\\ \text{s.t.\ \ \ \ \ }\quad\quad -x_1+2x_2+x_3+x_4=2\\ \quad\quad\quad\quad\quad -4x_1+4x_2-x_3=4\\ \quad\quad\quad\quad\quad x_1-x_3=0\\ \quad\quad\quad\quad\quad x_1,x_2,x_3,x_4\geq0 \end{cases}. ⎩ ⎨ ⎧minimizex1−x2s.t. −x1+2x2+x3+x4=2−4x1+4x2−x3=4x1−x3=0x1,x2,x3,x4≥0.

用下列代码进行第一阶段计算。

python 复制代码
import numpy as np
from fractions import Fraction as F
np.set_printoptions(formatter={'all':lambda x:
                               str(F(x).limit_denominator())})
A=np.array([[-1, 2, 1, 1],
            [-4, 4, -1, 0],
            [1, 0, -1, 0]])
b = np.array([2, 4, 0])
c = np.array([1, -1, 0, 0])
E, pos = prepro(A)
A1 = np.hstack((A, E))
Bind = pos
Nind = np.setdiff1d(np.arange(4+E.shape[1]),Bind)
c1 = np.concatenate((np.zeros(4), np.ones(E.shape[1])), axis = 0)
Bindst = simplex(A1, b, c1, Bind, Nind)
Bst = A1[:, Bindst]#当前基矩阵
Bst1 = np.linalg.inv(Bst)#逆阵
xBst = np.matmul(Bst1,b.reshape(3, 1)).flatten()#对应基矩阵最优解部分
x = np.zeros(4+E.shape[1])
x[Bindst] = xBst#最优解
print('辅助问题最优解x=%s'%x)
print('辅助问题最优解对应的基矩阵向量下标:%s'%Bindst)

程序的7~9行设置线性规划数据。第10行调用博文《最优化方法Python计算:标准型线性规划的辅助问题》中定义的第一阶段预前处理函数prepro,根据本题等式约束系数矩阵A计算需添加的人工变量系数矩阵E和第一阶段需要的基矩阵下标集pos。第11~14行根据E和pos构造辅助问题数据A1,c1,b。第15行调用博文《最优化方法Python计算:标准型线性规划的单纯形算法》定义的simplex计算辅助问题最优解,完成第一阶段任务。运行程序,输出

python 复制代码
辅助问题最优解x=[0 1 0 0 0 0]
辅助问题最优解对应的基矩阵向量下标:[1 4 5]

尽管辅助问题最优接种对应人工变量的 x 5 = x 6 = 0 x_5=x_6=0 x5=x6=0,即本问题可行,但是最优解对应基矩阵由A1中第2、5、6列构成,包含了E中两列,故不能直接进入第二阶段计算。而需要根据方程组 B ∗ − 1 ( A x + E x a ) = B ∗ − 1 b \boldsymbol{B}^{*-1}(\boldsymbol{Ax}+\boldsymbol{Ex}_a )=\boldsymbol{B}^{*-1}\boldsymbol{b} B∗−1(Ax+Exa)=B∗−1b的结构,或将 B ∗ \boldsymbol{B}^{*} B∗中对应人工变量的向量"驱赶"出去,以重构 B ∗ \boldsymbol{B}^{*} B∗。或删掉方程中线性相关的方程,以重构 A \boldsymbol{A} A、 B ∗ \boldsymbol{B}^{*} B∗和 b \boldsymbol{b} b,使得 B ∗ \boldsymbol{B}^{*} B∗含于 A \boldsymbol{A} A中。下列定义的Python函数prognostic,完成第一阶段的预后处理。

python 复制代码
import numpy as np									#导入numpy
def prognostic(A, E, Bind, b):
    n = A.shape[1]									#原问题决策变量数
    n1 = n + E.shape[1]								#辅助问题决策变量数
    Nind = np.setdiff1d(np.arange(n1), Bind)		#非基矩阵向量下标
    A1 = np.hstack((A, E))
    B = A1[:, Bind]									#基矩阵B
    B1 = np.linalg.inv(B)							#B的逆阵
    A1 = np.matmul(B1, np.hstack((A, E)))
    index = np.where(Bind >= n)[0]					#对应人工变量的向量位置
    for l in index:									#对每一个对应人工变量的向量
        i = np.where(A1[:, Bind[l]] == 1)[0][0]		#对应行
        beta = np.where((Nind < n) &				#第i行中非基非零系数位置
        		(abs(A1[i, Nind]) > 1e-10))[0]
        if beta.size == 0:							#无非基非零系数,删除该行
            A = np.delete(A, i, axis = 0)
            b = np.delete(b, i, axis = 0)
            Bind = np.delete(Bind, l, axis = 0)
        else:										#存在非基非零系数,驱逐对应基向量
            e = beta[0]
            Bind[l], Nind[e] = Nind[e], Bind[l]
    return A, Bind, b

程序的第2~22行定义的函数prognostic实现第一阶段预后处理过程Prognostic。该函数的参数A,E分别表示标准线性规划(1)等式约束系数矩阵 A \boldsymbol{A} A和预前过程算得的辅助问题中人工变量的系数矩阵 E \boldsymbol{E} E。参数Bind表示第一阶段算得的辅助问题(2)的最优解对应的基矩阵 B ∗ \boldsymbol{B}^{*} B∗的列向量下标集。参数b表示问题(1)的等式约束的常数向量 b \boldsymbol{b} b。函数体内,第6行计算 ( A , E ) (\boldsymbol{A},\boldsymbol{E}) (A,E)赋予A1。第7~8行计算 B ∗ − 1 \boldsymbol{B}^{*-1} B∗−1赋予B1。第9行计算 A ′ = B ∗ − 1 ( A , E ) \boldsymbol{A}'=\boldsymbol{B}^{*-1}(\boldsymbol{A},\boldsymbol{E}) A′=B∗−1(A,E)重置A1。第10行计算B中对应人工变量的列向量下标赋予index。第11~21行的for 循环考察index指引的 B ∗ \boldsymbol{B}^{*} B∗的每一个对应人工变量的向量 α l ′ \boldsymbol{\alpha}'_l αl′,根据其唯一非零且等于1的元素对应 A ′ \boldsymbol{A}' A′中的第 i i i行结构决定是用"删除"法(第16~18行的操作)还是"驱赶"法(第20~21行的操作)重构基矩阵 A \boldsymbol{A} A, b \boldsymbol{b} b和 B ∗ \boldsymbol{B}^{*} B∗,使得 B ∗ \boldsymbol{B}^{*} B∗为 A \boldsymbol{A} A的一个基矩阵。第22行返回经改造的A,Bind和b。
例2 下列代码用prognostic函数预后处理例1中第一阶段的计算。

python 复制代码
............
A, Bind, b=prognostic(A, E, Bindst, b)
print(A, Bind, b)

代码中第1行的省略号代表例1中的程序代码,在气候添加上列两行:第2行对例1中得到的A,E,Bintst和b调用预后处理函数prognostic,算得的结果为赋予A,Bind和b。运行程序输出

python 复制代码
............
[[-1 2 1 1]
 [-4 4 -1 0]
[1 0 -1 0]] [1 0 2] [2 4 0]

省略号代表例1中代码的输出信息。检查余下的输出数据可见系数矩阵A和常数向量b没有发生变化,但是基矩阵下标集由[1, 4, 5]变成了[1, 0, 2]即用非基向量 α 1 \boldsymbol{\alpha}_1 α1驱赶了 α 5 \boldsymbol{\alpha}_5 α5,非基向量 α 3 \boldsymbol{\alpha}_3 α3驱赶了 α 6 \boldsymbol{\alpha}_6 α6。得到原问题的初始基矩阵 B = ( α 2 , α 1 , α 3 ) \boldsymbol{B}=(\boldsymbol{\alpha}_2,\boldsymbol{\alpha}_1,\boldsymbol{\alpha}_3) B=(α2,α1,α3)。
写博不易,敬请支持:

如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

相关推荐
databook10 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar11 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户83562907805111 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_11 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机18 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机19 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机19 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机19 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i19 小时前
drf初步梳理
python·django
每日AI新事件19 小时前
python的异步函数
python