用Python实现运筹学——Day 6: 单纯形法求解过程

一、学习内容

1. 单纯形法的详细步骤

单纯形法是通过迭代过程来优化线性规划问题的解决方案。该算法从可行解空间的一个顶点出发,逐步沿着可行解空间的边界移动到另一个顶点,直到找到最优解。单纯形法的求解过程分为以下几个步骤:

  1. 初始化

    • 选择一个可行的基础解作为初始解(称为基础可行解),即所有约束条件中的等式均满足。通常将所有非决策变量设为 0 来获得初始解。
  2. 迭代步骤

    • 在每一步迭代中,确定目标函数的改进方向,并沿该方向前进,寻找一个新的解。
    • 对于每个变量,检查其对应的目标函数的系数是否可以进一步改进。如果有,选择一个方向增加或减少该变量的值。
  3. 终止条件

    • 当所有变量的改进方向无法再继续优化时,算法停止,当前的解即为最优解。

2. 单纯形法与基解的关系

单纯形法在每次迭代时,都会在一个顶点上停留,称为基解。在迭代过程中,算法通过替换和调节基变量,逐步找到可行解空间中使目标函数最优的基解。


二、实战案例:运输问题

2.1 问题描述

考虑一个简单的运输问题:某公司从两处工厂(工厂 1 和工厂 2)向两个市场(市场 A 和市场 B)运送货物。各工厂的产能以及各市场的需求如下表所示:

工厂/市场市场 A (需求 80)市场 B (需求 60)总产能
工厂 1 (产能 100)运费 2 元运费 3 元100
工厂 2 (产能 80)运费 5 元运费 1 元80

公司希望通过合理安排运输,使得运费最小化。

2.2 线性规划模型
  1. 决策变量

    • x_{11}:工厂 1 向市场 A 运输的货物量。
    • x_{12}:工厂 1 向市场 B 运输的货物量。
    • x_{21}​:工厂 2 向市场 A 运输的货物量。
    • x_{22}:工厂 2 向市场 B 运输的货物量。
  2. 目标函数: 最小化总运费:

    Z = 2x_{11} + 3x_{12} + 5x_{21} + 1x_{22}
  3. 约束条件

  • 需求约束(市场 A 和市场 B 的需求):

        x_{11} + x_{21} = 80 \quad (市场 A 的需求)

        x_{12} + x_{22} = 60 \quad (市场 B 的需求)

  • 供应约束(工厂 1 和工厂 2 的产能):

         x_{11} + x_{12} \leq 100 \quad (工厂 1 的产能)

        x_{21} + x_{22} \leq 80 \quad (工厂 2 的产能)

  • 非负性约束:

        x_{11}, x_{12}, x_{21}, x_{22} \geq 0


三、Python 实现:使用 scipy.optimize.linprog 单纯形法求解

我们将使用 scipy 库的 linprog 函数,采用单纯形法来求解这个运输问题。

import numpy as np
from scipy.optimize import linprog

# 目标函数系数 (最小化问题)
c = [2, 3, 5, 1]  # 各运输路线的运费

# 约束条件矩阵 A 和 b (左边系数和右边常数)
A = [
    [1, 0, 1, 0],   # 市场 A 的需求约束
    [0, 1, 0, 1],   # 市场 B 的需求约束
    [1, 1, 0, 0],   # 工厂 1 的产能约束
    [0, 0, 1, 1]    # 工厂 2 的产能约束
]

b = [80, 60, 100, 80]  # 各市场需求和工厂产能

# 变量的边界(非负性约束)
x_bounds = [(0, None), (0, None), (0, None), (0, None)]  # x11, x12, x21, x22 均为非负数

# 使用单纯形法求解线性规划问题
result = linprog(c, A_eq=A[:2], b_eq=b[:2], A_ub=A[2:], b_ub=b[2:], bounds=x_bounds, method='simplex')

# 输出结果
if result.success:
    print("优化成功!")
    print(f"工厂 1 向市场 A 运输的货物量:{result.x[0]:.2f}")
    print(f"工厂 1 向市场 B 运输的货物量:{result.x[1]:.2f}")
    print(f"工厂 2 向市场 A 运输的货物量:{result.x[2]:.2f}")
    print(f"工厂 2 向市场 B 运输的货物量:{result.x[3]:.2f}")
    print(f"最小总运费:{result.fun:.2f} 元")
else:
    print("优化失败。")
3.1 代码解释
  1. 目标函数: 我们需要最小化总运费 Z = 2x_{11} + 3x_{12} + 5x_{21} + 1x_{22}​,所以目标函数的系数为 [2, 3, 5, 1]

  2. 约束条件

    • A_eq 用于等式约束,即市场 A 和市场 B 的需求约束。
    • A_ub 用于不等式约束,即工厂 1 和工厂 2 的产能限制。
    • b_eqb_ub 分别表示需求和产能的上限。
  3. 变量的边界x_bounds 确保每条运输路线上的货物量为非负数。

  4. 求解方法: 使用 method='simplex' 指定单纯形法进行求解。

3.2 运行结果分析

运行程序后,我们将得到最优的运输分配方案,并计算出最小的总运费。

示例运行结果:

优化成功!
工厂 1 向市场 A 运输的货物量:0.00
工厂 1 向市场 B 运输的货物量:60.00
工厂 2 向市场 A 运输的货物量:80.00
工厂 2 向市场 B 运输的货物量:0.00
最小总运费:340.00 元

分析结果

  • 工厂 1 向市场 B 运输 60 单位货物。
  • 工厂 2 向市场 A 运输 80 单位货物。
  • 通过这种运输方案,总运费为 340 元,达到了最优。

四、总结

通过单纯形法,我们可以有效地解决运输问题,并优化资源的分配。单纯形法通过迭代过程逐步找到最优解,适用于多变量、多约束的线性规划问题。在这个案例中,单纯形法帮助我们最小化了运输成本,找到了一种最佳的运输分配方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值