用python实现线性规划中的单纯形法
例题如下(已是标准形式):
m a x z = 1500 x 1 + 1000 x 2 max z=1500x_1+1000x_2 maxz=1500x1+1000x2
{ 3 x 1 + 2 x 2 + x 3 = 65 2 x 1 + x 2 + x 4 = 40 3 x 2 + x 5 = 75 x 1 , x 2 , x 3 , x 4 , x 5 ≥ 0 \left\{ \begin{array}{c} 3x_1+2x_2+x_3=65 \\ 2x_1+x_2+x_4=40 \\ 3x_2+x_5=75\\ x_1,x_2,x_3,x_4,x_5\geq0 \end{array} \right. ⎩⎪⎪⎨⎪⎪⎧3x1+2x2+x3=652x1+x2+x4=403x2+x5=75x1,x2,x3,x4,x5≥0
代码如下:
#输入变量的数量
arg_num = int(input())
#输入目标函数
max_z = list(map(int,input().split(' ')))
z = 0
x = {}
class pure_chat():
def __init__(self):
self.c_b = []
self.b = []
self.opt = []
self.no_base_args = []
self.ex_num_list = max_z[:]
#输入约束条件
def input_chat(self):
for i in range(len(max_z)):
if max_z[i] != 0:
self.no_base_args.append(i)
while True:
exper = list(map(int, input().split(' ')))
if exper.count(0) == arg_num + 1:
break
self.opt.append(exper)
for i in range(arg_num - len(self.opt) + 1):
self.b.append(arg_num - len(self.opt) + i)
self.c_b.append(max_z[arg_num - len(self.opt) + i])
def get_max(self):
m_i = 0
max = -10000
for i in self.no_base_args:
if self.ex_num_list[i] > max:
max = self.ex_num_list[i]
m_i = i
return m_i
#判断非基变量的检验数是否都为小于0
def examine(self):
for i in self.no_base_args:
if self.ex_num_list[i] > 0:
return False
return True
#确定出基变量
def out_base(self):
min = 100000
i = self.get_max()
if self.ex_num_list[i] > 0:
for j in range(len(self.opt)):
if self.opt[j][i] == 0:
continue
t = self.opt[j][arg_num] / self.opt[j][i]
if t < min:
min = t
out_i = i
out_j = j
return out_i, out_j
#将基变量矩阵化为单位矩阵
def to_e(self,b_i, b_j):
s = self.opt[b_i][b_j]
for i in range(len(self.opt[b_i])):
self.opt[b_i][i] = self.opt[b_i][i] / s
for j in range(len(self.opt)):
if j != b_i:
t = self.opt[j][b_j]
for k in range(len(self.opt[j])):
self.opt[j][k] = self.opt[j][k] - t * self.opt[b_i][k]
#出基与进基
def change_base_args(self,b_i, b_j):
t = self.no_base_args.index(b_j)
self.no_base_args[t] = self.b[b_i]
self.b[b_i] = b_j
#更新基变量的系数矩阵
def update_c_b(self):
for i in range(len(self.b)):
self.c_b[i] = max_z[self.b[i]]
#计算检验数
def compute_ex_num(self,b_i, b_j):
self.ex_num_list[b_j] = 0
for i in self.no_base_args:
s = max_z[i]
count = 0
for j in self.b:
s = s - max_z[j] * self.opt[count][i]
count += 1
self.ex_num_list[i] = s
#计算目标函数值
def compute_z(self):
s = 0
for i in range(len(self.opt)):
s = s + self.c_b[i] * self.opt[i][arg_num]
return s
#计算最优解
def compute_x(self):
for i in range(len(self.opt)):
x[self.b[i]] = self.opt[i][arg_num]
for i in range(arg_num):
if i not in self.b:
x[i] = 0
chat = pure_chat()
chat.input_chat()
#循环迭代
while True:
if chat.examine():
chat.compute_x()
x = sorted(x.items(), key=lambda x: x[0])
z = chat.compute_z()
break
j,i = chat.out_base()
chat.change_base_args(i,j)
chat.update_c_b()
chat.to_e(i,j)
chat.compute_ex_num(i,j)
print(x)
print(z)
'''
测试数据:
5
1500 1000 0 0 0
3 2 1 0 0 65
2 1 0 1 0 40
0 3 0 0 1 75
0 0 0 0 0 0
输出的结果:
[(0, 15.0), (1, 10.0), (2, 0), (3, 0), (4, 45.0)]
32500.0
'''
输入的数据格式为:
5
1500 1000 0 0 0
3 2 1 0 0 65
2 1 0 1 0 40
0 3 0 0 1 75
0 0 0 0 0 0
第一行的5为变量的个数,第二行为目标函数中的对应系数,其余行为约束条件的对应系数,最后输入全0表示结束输入
输出的结果为:
[(0, 15.0), (1, 10.0), (2, 0), (3, 0), (4, 45.0)]
32500.0
第一行的列表表示最优解,为 x 1 = 15 , x 2 = 10 , x 3 = 0 , x 4 = 0 , x 5 = 45 x_1=15,x_2=10,x_3=0,x_4=0,x_5=45 x1=15,x2=10,x3=0,x4=0,x5=45;第二行为最优解对应的最优目标函数值,为32500.
ps:个人github地址:https://github.com/zhouyanb
github地址