编写背景
对偶单纯形法的算法原理在各个版本的《运筹学》教材中已经被阐述得很详细了,但是手工计算不仅繁琐,而且容易出错。编写程序时笔者尚未接触Lingo,故使用Python对算法进行实现。
程序
import re
import pandas as pd
from fractions import Fraction
data = pd.read_csv("data2.csv", header=0, index_col=0)
print("=======The Original Table=======")
print(data)
def do_it(data):
in_base_index = data.loc["sigma", :][data.loc['sigma', :] < 0].index
rec = {}
res_val = []
for i in in_base_index:
out_base_index = data.loc[:, i][data.loc[:, i] < 0].index.drop("sigma")
for j in out_base_index:
res = Fraction(data.loc["sigma", i], data.loc[j, i])
res_val.append(res)
rec[str(j) + "," + str(i)] = res
def get_key(dic, value):
return [k for k, v in dic.items() if v == value]
s = get_key(rec, min(res_val))
s = re.split(r"\,", s[0])
# 这里是将本身变成1
param1 = Fraction(1, data.loc[s[0], s[1]])
data.loc[s[0], :] = data.loc[s[0], :] * param1
# 将其他变为0
for row in data.index.drop(s[0]):
target = data.loc[row, s[1]]
param2 = Fraction(-target, 1)
data.loc[row, :] = data.loc[s[0], :] * param2 + data.loc[row, :]
data = data.rename(index={s[0]: s[1]})
print("================================")
print(data)
if (data["b"].drop("sigma") < 0).any():
print("Need More Action!")
do_it(data)
else:
print("Can't Do Any More.")
return data
# 如何b中的任何一个数小于零,都需要进一步操作
if (data["b"].drop("sigma") < 0).any():
print("Need More Action!")
do_it(data)
else:
print("Can't Do Any More.")
输出
程序会输出计算过程中每一次迭代的单纯形表,并给出是否需要再一次迭代的提示,最后一张表就是输入题目的结果。
说明
该程序需要用户自行将题目调整成标准形式,并将初始单纯形表以csv文件的格式读入程序。如下图所示:
csv文件的存放位置及读入可以参考其他博主的文章,或者自行查阅Pandas的参考文档,在此不进行赘述。
缺点
该程序的缺点也很明显——只能拿来做题,而且是明知道有最优解的题目,否则会陷入死循环。因此此程序仅作为练手参考使用,请不要轻易将其用于解题!!!