动态规划是运筹学的一个分支,主要用于求解多阶段决策过程的优化问题。1950年代初,R.E. Bellman提出了最优性原理,将复杂的多阶段问题分解为一系列单阶段问题逐步求解,开创了动态规划这一方法。1957年,他出版了《Dynamic Programming》,成为该领域的经典著作。动态规划自问世以来,在经济管理、生产调度、工程技术及最优控制等领域得到广泛应用,如最短路径、库存管理、资源分配等问题。虽然动态规划主要用于动态过程的优化,但一些静态问题(如线性规划)也可通过引入时间因素来求解。动态规划作为一种解决问题的方法,没有固定的算法或规则,需要针对具体问题进行灵活建模与求解。
一、多阶段决策问题
动态规划是一种求解多阶段决策问题的数学方法。通过将复杂的问题分解为多个相互关联的子问题,并利用其递归结构,动态规划能够有效求解最优化问题。该方法的核心思想是将每个阶段的最优决策作为后续阶段的基础,避免重复计算。
例1:一艘货轮在 A 港装货后驶往 F 港,中途须靠港加油和加淡水 3 次,从 A 港到 F港全部可能的航行路线及两港之间的距离如图所示,F 港有 3 个码头,试求最合理的停靠的码头及航线,使总路程最短。
最短路问题 | 多阶段决策 |
---|---|
问题是求 A 港到 F 港最短路程,但从 A 港到 F 港不能直接到达,中途须靠港加油和加淡水 3 次,即必须经过 B1、B2,C1、C2、C3,D1、D2 中的一个港口加油和加淡水。这样的问题可看成一个多阶段决策问题,第一阶段考虑货轮到 B1 港还是到 B2 港;第二阶段考虑货轮到 C1 港、C2 港还是到 C3 港?第三阶段考虑货轮到 D1 港还是到 D2港;第四阶段考虑货轮到 F1 港、F2 港还是到 F3 港;依此类推,最后获得货轮从 A 港到 F 港的一条路径。显然这样的路径有很多,问题是选择一条最优路径,使得总的路程最短,这是一个典型的动态规划问题。
例2:资源分配问题。设有6万元资金用于4个工厂的扩建,已知每个工厂的投资收益(万吨)同投资额的大小有关。应如何确定对这4个工厂的投资额,使总投资收益最大?
工厂投资额(i) | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
1 | 0 | 20 | 42 | 60 | 75 | 85 | 90 |
2 | 0 | 25 | 45 | 57 | 65 | 70 | 73 |
3 | 0 | 18 | 39 | 61 | 78 | 90 | 95 |
4 | 0 | 28 | 47 | 65 | 74 | 80 | 85 |
可以把对4个工厂的投资依次看成4个阶段的决策过程,对第i个工厂的投资额看成第i个阶段的决策,i = 1, 2, 3, 4。第一个阶段开始时拥有的资金为6万元,即考虑工厂1投资决策时的资金额是6万元,投资工厂1的资金额为\(u_1\),所以在考虑工厂2投资时剩余的资金额为\(6 - u_1\),依此类推,第4阶段的决策是将剩余资金都投入建厂,这样第5阶段的投资额为0,即\(s_5 = 0\)。
一般地,\(n\)阶段的动态规划问题可以描述为下图所示的模式,其中:
- 状态\(s_k\) 表示第\(k\)个阶段开始时的已知决策条件;
- \(u_k\)表示在这种决策环境下第k个阶段所采取的决策;
- 选择这个方案获得的收益为\(v(u_k)\);
- 该决策也决定了第$ k+1\(个阶段的状态\)s_{k+1}$;
- 状态\(s_{k+1}\)的确定依赖于状态之间的关系方程\(T_k\),其中¥k = 1, 2, \cdots, n$。
这种描述模式概括了动态规划问题的基本结构,其中每个阶段的决策依赖于当前状态,并影响下一个阶段的状态和可能的收益。
\(n\)阶段动态规划 | 动态规划的子过程 |
---|---|
二、动态规划的基本概念和数学模型
动态规划是一种用于解决多阶段决策问题的数学方法,特别适合处理具有重叠子问题和最优子结构特性的复杂优化问题。其核心思想是将问题分解为多个相互关联的子问题,通过逐步解决每个子问题,从而得到全局最优解。
2.1 基本概念
- 阶段 (Stage)
阶段是动态规划中将问题解决过程进行自然划分的一个概念。通常基于时间或空间的顺序,在每个阶段,决策者都需要做出一个决策。阶段变量通常用 $ k $ 表示,$ k = 1, 2, \dots, n $,其中 $ n $ 代表问题的总阶段数。 - 状态 (State)
状态是动态规划中用于描述每个阶段开始时系统所处的状况的概念。状态变量通常用 $ x_k $ 表示,其中 $ k $ 是阶段的编号。
-决策 (Decision)
在动态规划的每个阶段,系统处于某个状态,决策者需要根据当前的状态来选择一个最优的决策。决策变量描述了系统在每个阶段的选择,通常记作 $ u_k(x_k) $。 - 策略 (Policy)
策略是动态规划中由一系列决策组成的一个完整序列。完整的策略可以记作 $ p_1^n(x_1) $,其中 $ p_1^n(x_1) $ 是从初始状态 $ x_1 $ 开始经过 $ n $ 个阶段的所有决策序列。 - 状态转移方程 (State Transition Equation)
状态转移方程是描述系统如何从一个阶段的状态转换到下一个阶段状态的关系式。形式通常为:$$ x_{k+1} = f(x_k, u_k(x_k))$$ - 指标函数与最优值函数 (Objective Function & Optimal Value Function)
指标函数用来衡量决策过程的优劣,通常以收益或成本作为标准。最优值函数 $ V_k(x_k) $ 表示从第 $ k $ 阶段的状态 $ x_k $ 开始到过程结束时的最优总收益或最小总成本。
例3:假设有一个背包,能够承受的最大重量是 $ W $,现有若干物品,每个物品有一个重量 $ w_i $ 和价值 $ v_i $。目标是选择一组物品放入背包,使得背包中的物品总价值最大。
- 阶段:每一个物品对应一个阶段,$ k $ 阶段表示当前是否考虑第 $ k $ 个物品。
- 状态:$ x_k $ 表示在第 $ k $ 阶段时,当前背包中的剩余承重量。
- 决策:$ u_k(x_k) $ 表示在第 $ k $ 阶段是否选择放入物品 $ k $,决策变量是 0 或 1。
- 状态转移方程:如果选择了物品 $ k $,下一个状态就是当前承重量减去物品 $ k $ 的重量 $ w_k $,即 $ x_{k+1} = x_k - w_k $。
- 指标函数:指标函数是所有被选中物品的总价值,目标是最大化背包的总价值。
通过递归求解上述问题,可以找到使得背包总价值最大化的最优策略,即哪些物品应该被放入背包。
2.2 数学模型
最优化原理:作为整个过程的最优策略具有这样的性质:无论过去的状态和决策如何,相对于前面的决策所形成的状态而言,余下的决策序列必然构成最优子策略。也就是说,一个最优策略的子策略也是最优的。
动态规划方法建模的关键在于正确地写出基本的递推关系式和恰当的边界条件(简称基本方程)。要做到这一点,就必须将问题的过程分成几个相互联系的阶段,恰当的选取状态变量和决策变量及定义最优值函数,从而把一个大问题转化成一组同类型的子问题,然后逐个求解。即从边界条件开始,逐段递推寻优,在每一个子问题的求解中,均利用了它前面的子问题的最优化结果,依次进行,最后一个子问题所得的最优解,就是整个问题的最优解。在多阶段决策过程中,动态规划方法是既把当前一段和未来一段分开,又把当前效益和未来效益结合起来考虑的一种最优化方法。因此,每段决策的选取是从全局来考虑的,与该段的最优选择答案一般是不同的。通常需要按照以下步骤建立模型:
- 划分阶段
划分阶段是动态规划求解的第一步。阶段的划分通常基于时间或空间顺序。每个阶段代表决策过程中的一个步骤。例如,在路径规划问题中,每个阶段可以表示在地图上走到某一位置的时刻;在投资规划中,每个阶段可以表示某一年。
对于静态问题,也可以人为地引入时间概念来划分阶段。将过程分成多个阶段的目的是逐步求解每个子问题,确保递推关系的建立。 - 选择状态变量
状态变量用于描述每个阶段系统所处的状态。状态变量应能全面反映当前阶段的系统情况,并且需要满足无后效性,即当前的状态不依赖于之前的路径。状态变量通常以 $ x_k $ 表示,表示第 $ k $ 阶段的状态。允许状态的集合称为允许状态集合,记作 $ X_k $。
例如,在背包问题中,状态变量可以选择当前背包的剩余承重量和已经装入背包物品的总价值。 - 确定决策变量及允许决策集合
决策变量是每个阶段需要做出的选择,它直接影响系统从当前状态向下一阶段状态的演变。决策变量 $ u_k(x_k) $ 表示在第 $ k $ 阶段,处于状态 $ x_k $ 时的决策选择。
决策变量的取值范围称为允许决策集合,记作 $ U_k(x_k) $。它包含所有在当前状态下可行的决策。例如,在路径规划问题中,决策变量可能表示从当前地点出发,向哪个方向行进。 - 建立状态转移方程
状态转移方程描述系统从当前阶段的状态演变到下一阶段的规则。给定当前阶段的状态和决策,系统会演变到下一阶段的状态,状态转移方程通常表示为:$$ x_{k+1} = f(x_k, u_k(x_k)) $$
状态转移方程的形式因问题而异。例如,在背包问题中,若决定选择某个物品放入背包,那么下一个阶段的状态就是当前的剩余承重量减去该物品的重量。 - 确定阶段指标函数和最优值函数,建立动态规划基本方程
阶段指标函数用来衡量当前阶段的收益或成本,通常记作 $ g_k(x_k, u_k(x_k)) $,它表示在状态 $ x_k $ 下,做出决策 $ u_k(x_k) $ 所获得的收益或成本。
最优值函数 $ V_k(x_k) $ 表示从第 $ k $ 阶段状态 $ x_k $ 开始,系统演变到终止状态所能获得的最大收益或最小成本。根据阶段的递推关系,可以写出动态规划的基本方程:
该方程表示在每个阶段,最优决策是通过比较当前阶段收益与下一阶段的最优值来递归求解的。递推过程自最后阶段向前进行,从而逐步找到整个问题的最优解。
例4:假设有一个城市网络,网络中的城市通过道路连接,每条道路有一个正数权重,表示两座城市之间的距离。目标是从起点城市(比如 A)到终点城市(比如 E),找到经过的总距离最短的路径。这个问题可以用动态规划来求解。
- 阶段:阶段是指每一次从一个城市到达另一个城市的过程。在这个问题中,阶段的划分可以基于城市的访问顺序。第 \(k\) 阶段表示正在访问网络中的第 \(k\) 个城市。例如,从起点城市 A 开始,经过第一个城市到达第二个城市,直到到达终点 E,每个阶段对应城市的访问顺序。
- 状态:状态描述每个阶段所处的城市。状态变量 \(x_k\) 表示在第 \(k\) 阶段所处的城市。每个城市对应一个状态,状态的集合就是所有可能访问的城市集合。例如,若 A、B、C、D、E 为五个城市,则状态集合 \(X_k = \{A, B, C, D, E\}\)。其中 \(x_k\) 表示在第 \(k\) 阶段处于哪个城市,例如 \(x_3 = C\) 表示第 3 阶段处于城市 C。
- 决策:在每个阶段,给定当前所在城市,决策变量是指下一步选择前往哪个城市。决策变量 \(u_k(x_k)\) 表示当前状态 \(x_k\) 下的决策,即从当前城市前往的下一个城市。允许决策集合是当前城市可以前往的所有邻接城市的集合。例如,如果从城市 A 出发可以前往 B、C,那么决策变量 \(u_k(A)\) 可以是 B 或 C。
- 状态转移方程:状态转移方程描述了从当前城市(状态)前往下一城市的演变规则。在这个问题中,状态转移方程表示从当前城市 \(x_k\),通过选择决策 \(u_k(x_k)\),到达下一个城市 \(x_{k+1}\)。假设从城市 \(x_k\) 到城市 \(x_{k+1}\) 的距离为 \(d(x_k, x_{k+1})\),那么状态转移方程可以表示为:$$x_{k+1} = u_k(x_k)$$,也就是说,给定当前状态(城市)和决策(选择的下一城市),系统将转移到下一个状态(下一个城市)。
- 阶段指标函数和最优值函数
阶段指标函数 \(g_k(x_k, u_k(x_k))\) 表示从当前城市 \(x_k\) 出发,通过选择决策 \(u_k(x_k)\) 后到达下一城市所消耗的距离。在最短路径问题中,阶段指标函数就是两座城市之间的距离。最优值函数 \(V_k(x_k)\) 表示从城市 \(x_k\) 开始,到达终点城市所能走的最短距离。根据递推关系,动态规划的基本方程可以写为:$$V_k(x_k) = \min_{u_k(x_k)} { g_k(x_k, u_k(x_k)) + V_{k+1}(x_{k+1}) }$$,其中,\(g_k(x_k, u_k(x_k))\) 表示当前阶段的距离,而 \(V_{k+1}(x_{k+1})\) 表示从下一城市到终点的最短路径。
三、动态规划的Python求解
3.1 案例
例5:一家公司有1000辆运输卡车,要求在未来5年制定一个分配方案,以在高负荷(每天行驶500km)和低负荷(每天行驶300km)运输之间平衡卡车的分配,从而最大化公司的利润。高负荷与低负荷运输条件下的年利润和年损坏率不同,应用动态规划来解决这个多阶段决策问题。
动态规划数学模型
- 阶段划分
问题分为5个阶段,每个阶段代表一年。每年公司可以决定有多少辆车进行高负荷运输,剩下的车则进行低负荷运输。 - 状态变量
状态变量 $ x_k $ 表示在第 $ k $ 年剩余的完好卡车数量。初始状态为 $ x_0 = 1000 $,表示公司开始时有1000辆完好的卡车。 - 决策变量
决策变量 $ u_k $ 表示在第 $ k $ 年选择进行高负荷运输的卡车数量,剩余的 $ x_k - u_k $ 辆车将进行低负荷运输。 - 状态转移方程
卡车在一年中的损坏率不同,状态转移方程为:$$ x_{k+1} = x_k - 0.3 \cdot u_k - 0.1 \cdot (x_k - u_k)$$,表示在第 $ k $ 年结束时剩下的完好卡车数量。 - 收益函数
每年的总利润为高负荷和低负荷运输的总收益之和:$$ R_k(u_k) = 25 \cdot u_k + 16 \cdot (x_k - u_k)$$ - 数学模型
- \(f(k, x_k)\)表示从第\(k\)年开始,剩余\(x_k\)辆完好卡车时的最大利润。
- 递推关系:
3.2 Python程序
from mip import Model, xsum, maximize, INTEGER
def optModel(m, n, g, h, a, b):
# 使用CBC求解器
model = Model("truck_load_distribution", solver_name="CBC")
# 定义变量:x1代表高负荷运输的卡车数量,x2代表低负荷运输的卡车数量
x1 = [model.add_var(var_type=INTEGER) for i in range(n)] # 高负荷运输卡车数量
x2 = [model.add_var(var_type=INTEGER) for i in range(n)] # 低负荷运输卡车数量
# 设置目标函数,最大化5年内的总利润
model.objective = maximize(xsum(x1[i] * g + x2[i] * h for i in range(n)))
# 初始条件:第一年初的卡车总数为1000辆
model += x1[0] + x2[0] == m
# 状态转移方程:每一年剩余的卡车数量
for i in range(1, n):
model += x1[i] + x2[i] == x1[i - 1] * a + x2[i - 1] * b
# 运行优化求解
model.verbose = 0
model.optimize()
# 输出优化结果:最大利润和每年高、低负荷运输的卡车分配
print("5年内的最大总利润:", model.objective_value)
lis1 = []
lis2 = []
for i in range(n):
lis1.append(int(x1[i].x))
lis2.append(int(x2[i].x))
print("每年高负荷运输的卡车数量:", lis1)
print("每年低负荷运输的卡车数量:", lis2)
# 修改为提供的参数
if __name__ == '__main__':
# 参数:初始卡车数量、年份、每辆车的高负荷利润、低负荷利润、高负荷损坏率、低负荷损坏率
m = 1000 # 初始卡车数量
n = 5 # 5年
high_profit = 25 # 高负荷运输的年利润(万元)
low_profit = 16 # 低负荷运输的年利润(万元)
high_damage = 0.3 # 高负荷运输的年损坏率
low_damage = 0.1 # 低负荷运输的年损坏率
# 调用优化模型
optModel(m, n, high_profit, low_profit, 1 - high_damage, 1 - low_damage)
5年内的最大总利润: 74740.0
每年高负荷运输的卡车数量: [0, 0, 795, 570, 399]
每年低负荷运输的卡车数量: [1000, 900, 15, 0, 0]
总结
动态规划是一种通过将复杂问题分解为多个相互关联的子问题,从而逐步求解全局最优解的数学方法。其核心思想是利用递推关系,通过解每个子问题来最终解决原问题。动态规划的基本要素包括以下几方面:
阶段:动态规划将问题划分为多个阶段,每个阶段代表问题解决过程中的一个步骤。每个阶段的结果会影响下一阶段的决策。
状态:状态是每个阶段所处的具体情况。每个状态能够总结之前的决策过程,描述系统在该阶段的特定情形。
决策:在每个阶段中,针对当前状态,决策者需要选择最佳的行动(决策)来影响下一阶段的状态。
策略:策略是指由一系列决策组成的序列,从初始状态开始一直到最终状态,动态规划通过分析不同策略来找到最优解。
状态转移方程:状态转移方程描述了在做出某个决策后,系统如何从一个状态转移到下一个状态。它是动态规划的递推基础。
指标函数:指标函数衡量决策的优劣,通常是与目标相关的收益、成本或效用。动态规划的目标是最大化(或最小化)该函数的值。
动态规划广泛应用于多领域优化问题,如路径规划(最短路径问题)、资源分配(如企业资源优化)、背包问题(选择最优的物品组合以最大化收益)等。它通过记忆子问题的最优解,避免了重复计算,提高了求解效率。尤其在解决具有重叠子问题和最优子结构的问题时,动态规划展现出显著的优势。