我们以该题为例,来讲解单纯型法及其python实现:
0. 第一步:用矩阵的方式把上述等式,不等式的系数表示出来
import numpy as np
c=np.array([-2,-3]) #min z=-2x1-3x2
b=np.array([[8],[16],[12]])
Info=np.array([[1,2],[4,0],[0,4]]) #代表限制条件
basic=np.eye(Info.shape[0]) #产生基变量
s=np.append(Info,basic,axis=1)
A=np.append(s,b,axis=1)
c1=np.append(c,np.zeros(Info.shape[0]))
print(c1)
print(A)
1.第二步:求初始解
Cost=np.array(np.zeros(A.shape[1]))
Cost[0:c.shape[0]]=c
BV=np.array(range(c.shape[0],A.shape[1]-1)) #BV的用法后续会说
temp=np.array([Cost[y] for y in BV]).reshape(1,3)
zjcj=Cost-np.dot(temp,A)
zjcj
3.经过上述两步,我们获得了三个矩阵,他们分别对应了单纯型表的相应部分(见下图)
4.开始循环
4.1 最优解的判断
当单纯型表的最后一行没有负数的时候,即意味着找到了最优解。
因此我写了一个函数is_bigger_zero,当返回值为True时,找到最优解:
def is_bigger_zero(zjcj):
for z in zjcj:
if z<0:
return False
return True
4.2 找出进基变量和离基变量
我写了一个index函数,返回的是数组中值最小的数对应的下标:
def index(table):
min=table[0]
index2=0
for i,t in enumerate(table):
if table[i]<min:
min=table[i]
index2=i
return index2
所以,进基变量的下标通过调用index即可求:
enter=index(zjcj[0][:zjcj[0].shape[0]-1]) #zjcj[0]是因为zjcj本身是二维的
离基变量:
这里我们用到了BV,这个数组是一开始就定义了的。
在一开始BV=[2,3,4],单位矩阵由x3,x4,x5构成。
所以,BV即是对应的下标。之所以不是[3,4,5],是因为这里是从0开始计数的。
对应代码如下:
for i in range(0 ,A.shape[0]):
if A[i][enter]>0:
ans[i]=A[i][A.shape[1]-1]/A[i][enter]
else:
ans[i]=inf
leave=BV[index(ans)]
4.3 高斯消元
代码不是很复杂,
for i in range(0,A.shape[0]):
if i!=index(ans):
A[i]=A[i][:]-A[i][enter]*A[index(ans)]
else:
A[i]=A[index (ans)]
其中,这行代码可能难理解
A[i]=A[i][:]-A[i][enter]*A[index(ans)]
所以,我们举个例子:
5.运行结果
我这个代码可能写的不是很好,在使用之前必须化成标准型,还是比较麻烦的,有很多地方可以优化,如果大家发现bug的话,请务必告诉我!!
6.获取完整代码
如果对你有帮助的话,欢迎给个star!!
三克油!
代码