【运筹学】学习笔记--单纯形法Python实现

1 利用Python单纯形法

1.1 创建单纯形表

import numpy as np
# 本例中需要采用标准型LP问题(添加人工变量、目标函数最小值、变量取值非负)
# 单纯形表前m行n列为系数表,m+1行为目标函数系数,n+1行为约束值,-(m+1,n+1)为目标函数值;
# 注:此案例中默认添加的人工变量系数矩阵为初始基矩阵;目前没有出基变量的索引(相当于没有解的索引);
def crate_tableau(A,b,c):
    # np.hstack水平组合向量或矩阵;array.reshape(-1,1)将b转化为n行1列的矩阵;
    tableau=np.hstack((A, b.reshape(-1,1) ))
    # 需要增加判断,是求最小值还是最大值;
    c_row=np.hstack((c, np.zeros(1)))
    tableau=np.vstack((tableau,c_row))
    print('Iteration 0:\n',tableau)
    return tableau

1.2 定义换基过程

# 首先判断目标函数系数向量中非基变量的值是否非负,若全是非负数,则达到最优;若存在负数,则取最小值对应的变量作为入基变量;
# 原理是利用目标函数系数向量*变化量向量(改进方向/非基变量列),观察是否减小;
# 由于目标函数系数向量跟着变化(单纯形字典),用非基变量表示目标函数,而换基时是固定一个非基变量,变化一个非基变量,因此可以只看目标函数系数即可
def pivot(tableau):
    entering_vari_col=np.argmin(tableau[-1,:-1]) #取系数行中最小的值
    if (tableau[-1,entering_vari_col]>=0):
        print('当前解为最优解') 
        return False
    else:
        print(f'入基变量为x{entering_vari_col+1};',end='')
        #最小比值法确定步长和出基变量;存在疑问:基变量的变化量会为0吗?如果变化为0,则约束没变
        ratios=tableau[:-1,-1]/tableau[:-1,entering_vari_col] # b列是基变量的取值,始终非负
        ratios=np.where(ratios<0,np.inf,ratios)
        leaving_vari_row=np.argmin(ratios) #需要取非负最小值的索引
        if ratios[leaving_vari_row]<0:
            print('此LP问题无界')
            return False
        else:
            print(f'出基变量为x{leaving_vari_row+3};')
            tableau[leaving_vari_row,:]/=tableau[leaving_vari_row,entering_vari_col]
            for i in range(len(tableau)):
                if i!=leaving_vari_row:
                    tableau[i,:]-=tableau[i,entering_vari_col]*tableau[leaving_vari_row,:]
            print(tableau)
            return True

1.3 提取最优解和解的情况

def optimal(tableau,num_variable):
    optimal_value = -tableau[-1, -1]  # tableau[-1, -1]是目标函数最小值的负数
    optimal_x=np.zeros(num_variable)
    for i in range(len(A)):
        array=np.where(tableau[i,:num_variable]==1)
        if len(array) == 1:
            optimal_x[array[0]]=tableau[i,-1]
    return optimal_value,optimal_x

2 输入参数等

num_variable=2
c = np.array([-12, -9, 0, 0, 0, 0])  # 目标函数的系数
A = np.array([[1, 0, 1, 0, 0, 0],
              [0, 1, 0, 1, 0, 0],
              [1, 1, 0, 0, 1, 0],
              [4, 2, 0, 0, 0, 1]])  # 约束矩阵
b = np.array([10, 15, 17.5, 48])  # 约束的右端项
tableau=crate_tableau(A,b,c)
iteration=1
while True:
    print(f"\nIteration {iteration}:",end='')
    iteration+=1
    if pivot(tableau)==False:
        break

opt_value,solution=optimal(tableau,num_variable)
print("\n最优解:")
print("目标函数最小值:", opt_value)
for i,val in enumerate(solution):
    print(f'x{i}={val}',end='; ')

 3 问题实例及运行结果

4 关于问题 

        本文旨在记录作者学习运筹学过程中复现经典算法的一步步过程,可能存在算法流程不完善、表述不清楚的情况,请不吝您的宝贵意见,作者会持续学习和完善!

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值