跳转至

运筹学

饮料企业多工厂生产与补货优化

本文基于某饮料企业的工厂、仓库与商品相关的历史信息,结合随机模拟的售价与成本数据,构建了多工厂、多仓库的生产与补货优化模型。

数值试验表明,本文构建的优化后的生产与补货模型能够比基线模型(简单基于历史销量而固定生产量)多获得约 500 万元的利润,且在补货行为上更具优势。对工厂和仓库容量的灵敏度分析表明,工厂 2 和 DC4、5、7、14 多具有当前容量较小、运输成本低、历史销量高等特点,对它们进行扩容能够取得显著的回报增益。对整托约束的松弛表明,整托运输虽以节省运输成本为目的,但实际却可能造成运输资源的浪费,而考虑适当放松整托约束有潜力能够提高约 100 万元的利润。

问题目标示意图

Dijkstra 算法求解最短路径问题

本文使用 Python 实现了 Dijkstra 算法求解最短路径问题。在算法实现中,使用数组存储网络中各结点之间的距离,使用二叉堆存储 T 集合,并尽量使用向量化计算加快运行速度。

最终在三种网络结构下的运行时间为:

输入文件 grid_150_150 random_20000_40000 dense_1000
运行时间 302.93ms 292.14ms 135.29ms

但在最开始实现 Dijkstra 算法时,我的程序需要花 5 秒才能完成计算。经过逐步优化,运行时间可以降为 3 秒甚至 0.13 秒。把算法效率优化到极致的过程是非常有收获的,既加深了对算法本身的理解,又学习了许多优化算法的经验。

优化算法的经验

  1. 多考虑用向量化计算,尽量避免使用 for 循环。
  2. 想清楚算法的终止条件是什么。例如,在 One-to-all 问题中,可以把“遍历完T集合中的所有元素,直到 T 集合为空集”作为终止条件,也可以把“ P 集合中的元素个数等于网络中的结点个数”作为终止条件。虽然两者都能得到正确的结果,但当 P 集合中的元素个数等于网络中的结点个数时,T 集合中的元素是不需要再更新的,所以后者比前者所需要的运算次数少得多。
  3. 熟悉 NumPy 等科学计算库的实现细节。例如,在 NumPy 中,np.onesnp.empty 都可以用来创建指定形状的数组,其中 np.ones 会创建一个填充 1 的数组,而 np.empty 会在一块内存上创建一个未初始化的数组。由于 np.empty 不会进行初始化,因此生成速度要比 np.ones 更快。
  4. 使用合适的数据类型。例如,若问题中的变量可以肯定为整数,则可以考虑用 dtype=np.int32 或者 dtype=np.int16,节约内存空间。不同整数数据类型所能表示的整数范围如下:
Type Capacity
Int16 (-32,768 to +32,767)
Int32 (-2,147,483,648 to +2,147,483,647)
Int64 (-9,223,372,036,854,775,808 to +9,223,372,036,854,775,807)

Gurobi 求解线性规划问题

本文针对钢铁企业对供应商的选择问题,构建线性规划模型,并使用 Gurobi 求解器进行求解。

题目背景

考虑一家小型的钢铁企业,该企业炼钢时使用的主要原材料是炼焦煤,每年的需求量在 100 到 150 万吨。现在需要帮助该公司安排明年的生产,选择原料的供应商。目前他们收到了 8 家供应商的报价,如下表。表格中的信息包括了每家供应商的最大供应量、是否为工会的公司、运输的方式、炼焦煤的可燃率、单位价格。

1 2 3 4 5 6 7 8
供应量 (千吨/年) 300 600 510 655 575 680 450 490
工会U/ 非工会 N U U N U N U N N
卡车T/ 铁路 R R T R T T T R R
可燃率(%) 15 16 18 20 21 22 23 25
价格 (¥/吨) 49.5 50.0 61.0 63.5 66.5 71.0 72.5 80.0

单纯形法求解线性规划问题

线性规划的一般形式

在线性约束条件下,寻找目标函数 \(z\) 的最大值:

\[ \max \ z = x_1 + x_2 \]
\[ s.t \begin{cases} 2x_1 + x_2 \leq 12 \\ x_1 + 2x_2 \leq 9 \\ x_1, x_2 \geq 0 \end{cases} \]

线性规划的可行域

满足线性规划问题约束条件的所有点组成的集合就是线性规划的可行域。若可行域有界(以下主要考虑有界可行域),线性规划问题的目标函数最优解必然在可行域的顶点上达到最优。

单纯形法就是通过设置不同的基向量,经过矩阵的线性变换,求得基可行解(可行域顶点),并判断该解是否最优,否则继续设置另一组基向量,重复执行以上步骤,直到找到最优解。所以,单纯形法的求解过程是一个循环迭代的过程。

kexingyu

图 1 可行域