运筹学运输问题

点击查看原课程

产销平衡

运输问题模型

在运输问题中,我们有m个工厂生产物品, n个目的地(商店,企业)需要这些物品。

这些物品需要从出发地运输到目的地,这有相关的成本。

目标是使运输总成本最小化。

在这里插入图片描述

表上作业法求解

求解步骤:

步骤一:求初始基本可行解(西北角法、最小元素法、伏格尔法)
步骤二:求检验数并判断(闭回路法、位势法)
步骤三:调整运量(闭回路法)
步骤四:重复步骤二、三,直到求得最优解

在这里插入图片描述

在这里插入图片描述
西北角法(可能导致运费偏大)

在这里插入图片描述

Python求解


#运输问题初始解的构造方式有两种:最小元素法、沃格尔法
#'----------------------------------------最小元素法------------------------------------' \

import numpy as np
import copy

supplyNum = 3  # 供应商数量
demandNum = 4  # 需求商数量
A = np.array([16, 10, 22])  # 产量
B = np.array([8, 14, 12, 14])  # 销量
C = np.array([[4, 12, 4, 11], [2, 10, 3, 9], [8, 5, 11, 6]])  # 成本
X = np.zeros((supplyNum, demandNum))  # 初始解
c = copy.deepcopy(C)
maxNumber = 10000  # 极大数

def pivot(A, B, c, X):
    index = np.where(c == np.min(c))  # 寻找最小值的索引
    minIndex = (index[0][0], index[1][0])  # 确定最小值的索引
    # 确定应该优先分配的量,并且改变价格
    if A[index[0][0]] > B[index[1][0]]:
        X[minIndex] = B[index[1][0]]
        c[:, index[1][0]] = maxNumber  # 改变价格
        A[index[0][0]] = A[index[0][0]] - B[index[1][0]]
        B[index[1][0]] = 0  # 改变销量
    else:
        X[minIndex] = A[index[0][0]]
        c[index[0][0], :] = maxNumber
        B[index[1][0]] = B[index[1][0]] - A[index[0][0]]
        A[index[0][0]] = 0
    return A, B, c, X

def minimumElementMethod(A, B, c, X):# 最小元素法
    while (c < maxNumber).any():
        A, B, c, X = pivot(A, B, c, X)
    return X

solutionMin = minimumElementMethod(A, B, c, X)
print('最小元素法得到的初始解为:')
print(solutionMin)
print('最小元素法得到的总运费为:', ((solutionMin * C).sum()))

'-----------------------------------Vogel法---------------------------------'
supplyNum = 3  # 供应商数量
demandNum = 4  # 需求商数量
A = np.array([16, 10, 22])  # 产量
B = np.array([8, 14, 12, 14])  # 销量
C = np.array([[4, 12, 4, 11], [2, 10, 3, 9], [8, 5, 11, 6]])  # 成本
X = np.zeros((supplyNum, demandNum))  # 初始解
c = copy.deepcopy(C)
numPunish = [0] * (supplyNum + demandNum)  # 整体罚数


def pivot(X, A, B, C):
    # 求解罚数,其中列罚数排在行罚数后面
    for i in range(supplyNum):
        sortList = np.sort(C[i, :])
        numPunish[i] = sortList[1] - sortList[0]
    for i in range(demandNum):
        sortList = np.sort(C[:, i])
        numPunish[i + supplyNum] = sortList[1] - sortList[0]
    maxIndex = np.argmax(numPunish)  # 寻找最大罚数的索引

    if maxIndex < supplyNum: #若最大的罚数属于行罚数
        minIndex = np.argmin(C[maxIndex, :])
        index = (maxIndex, minIndex)  #得到最大罚数的一行中最小的运价

        if A[maxIndex] > B[minIndex]: # 若产量大于销量
            X[index] = B[minIndex]  #更新解
            C[:, minIndex] = maxNumber  #将已经满足的一列中的运价增大替代删除操作
            A[maxIndex] -= B[minIndex]  # 更新剩余产量
            B[minIndex] = 0  # 更新已经满足的销量
        else:# 若销量大于产量
            X[index] = A[maxIndex]
            C[maxIndex, :] = maxNumber
            B[minIndex] -= A[maxIndex]  # 更新销量
            A[maxIndex] = 0

    else:# 若最大的罚数为列罚数
        minIndex = np.argmin(C[:, maxIndex - supplyNum])  # 这时maxIndex-supplyNum是罚数最大的列
        index = (minIndex, maxIndex - supplyNum)
        if A[minIndex] > B[maxIndex - supplyNum]:  # 这里是产量大于销量,因此有限满足销量
            X[index] = B[maxIndex - supplyNum]
            C[:, maxIndex - supplyNum] = maxNumber
            A[minIndex] -= B[maxIndex - supplyNum]
            B[maxIndex - supplyNum] = 0
        else:
            X[index] = A[minIndex]
            C[minIndex, :] = maxNumber
            B[maxIndex - supplyNum] -= A[minIndex]
            A[minIndex] = 0
    return X, A, B, C

# 沃格尔法得到初始解
def Vogel(A, B, C):
    X = np.zeros((supplyNum, demandNum))  # 初始解
    numPunish = [0] * (supplyNum + demandNum)  # 整体罚数
    # 迭代,直到所有的产量和销量全部满足
    while (A != 0).any() and (B != 0).any():
        X, A, B, C = pivot(X, A, B, C)
    return X

# 上面对于条件的判断,还需要对销量和需求量进行改变
# solutionVogel = Vogel(A, B, c)
# print('Vogel法得到的初始解为:')
# print(solutionVogel)
# print('Vogel法得到的总运费为:', (C * solutionVogel).sum())

产销不平衡

转化为产销平衡问题,然后使用表上作业法进行求解。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值