最优化方法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)。
写博不易,敬请支持:

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

相关推荐
网易独家音乐人Mike Zhou2 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
安静读书2 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
小二·3 小时前
java基础面试题笔记(基础篇)
java·笔记·python
小喵要摸鱼5 小时前
Python 神经网络项目常用语法
python
一念之坤6 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
wxl7812277 小时前
如何使用本地大模型做数据分析
python·数据挖掘·数据分析·代码解释器
NoneCoder7 小时前
Python入门(12)--数据处理
开发语言·python
LKID体7 小时前
Python操作neo4j库py2neo使用(一)
python·oracle·neo4j
小尤笔记8 小时前
利用Python编写简单登录系统
开发语言·python·数据分析·python基础
FreedomLeo18 小时前
Python数据分析NumPy和pandas(四十、Python 中的建模库statsmodels 和 scikit-learn)
python·机器学习·数据分析·scikit-learn·statsmodels·numpy和pandas