动态规划的思想就是将多阶段决策问题转化为一系列单阶段最优化问题。
对最佳路径(最佳决策过程)所经过的各个阶段,其中每个阶段始点到全过程终点的路径,必定是该阶段起始点到全
过程终点的一切可能路径中的最佳路径(最优决策),这就是Bellman提出的著名的最优化原理。
简言之, 一个最优策略的子策略必然也是最优的。
DP算法逆向寻优,正向求解,本质由三层循环构成:
如图,设终点为 E E E,逆向运用DP算法:
第Ⅳ阶段(D →E): D 有两条路线到终点E ,权重分别为
f 4 ( D 1 ) = 5 f 4 ( D 2 ) = 2 f_4(D_1)=5\\ f_4(D_2)=2\\ f4(D1)=5f4(D2)=2
第Ⅲ阶段(C →D): C 到D 有 6 条路线。第3阶段的C有3个状态值,分别讨论经过该状态
值的最优路线。
经过C1
f 3 ( C 1 ) = min { d ( C 1 , D 1 ) + f 4 ( D 1 ) d ( C 1 , D 2 ) + f 4 ( D 2 ) } = min { 3 + 5 9 + 2 } = 8 \begin{aligned} f_{3}\left(C_{1}\right)=\min &\left\{\begin{array}{l} d\left(C_{1}, D_{1}\right)+f_{4}\left(D_{1}\right) \\ d\left(C_{1}, D_{2}\right)+f_{4}\left(D_{2}\right) \end{array}\right\}=\min \left\{\begin{array}{l} 3+5 \\ 9+2 \end{array}\right\}=8 \\ \end{aligned} f3(C1)=min{d(C1,D1)+f4(D1)d(C1,D2)+f4(D2)}=min{3+59+2}=8
最短路线为 C 1 → D 1 → E C 1 \rightarrow D 1 \rightarrow E C1→D1→E
经过C2
f 3 ( C 2 ) = min { d ( C 2 , D 1 ) + f 4 ( D 1 ) d ( C 2 , D 2 ) + f 4 ( D 2 ) } = min { 6 + 5 5 + 2 } = 7 \begin{aligned} f_{3}\left(C_{2}\right)=\min \left\{\begin{array}{l} d\left(C_{2}, D_{1}\right)+f_{4}\left(D_{1}\right) \\ d\left(C_{2}, D_{2}\right)+f_{4}\left(D_{2}\right) \end{array}\right\}=\min \left\{\begin{array}{l} 6+5 \\ 5+2 \end{array}\right\}=7 \\ \end{aligned} f3(C2)=min{d(C2,D1)+f4(D1)d(C2,D2)+f4(D2)}=min{6+55+2}=7
最短路线为 C 2 → D 2 → E C2\rightarrow D2 \rightarrow \mathrm{E} C2→D2→E
经过C3
f 3 ( C 3 ) = min { d ( C 3 , D 1 ) + f 4 ( D 1 ) d ( C 3 , D 2 ) + f 4 ( D 2 ) } = min { 8 + 5 10 + 2 } = 12 f_{3}\left(C_{3}\right)=\min \left\{\begin{array}{l} d\left(C_{3}, D_{1}\right)+f_{4}\left(D_{1}\right) \\ d\left(C_{3}, D_{2}\right)+f_{4}\left(D_{2}\right) \end{array}\right\}=\min \left\{\begin{array}{l} 8+5 \\ 10+2 \end{array}\right\}=12 f3(C3)=min{d(C3,D1)+f4(D1)d(C3,D2)+f4(D2)}=min{8+510+2}=12
最短路线为 C 3 → D 2 → E C 3 \rightarrow D 2 \rightarrow E C3→D2→E
第Ⅱ阶段(B →C): B 到C 有 9 条路线。第Ⅱ阶段的B有3个状态值,类似地,分别讨论经过该状态值的最优路线。
第Ⅰ阶段(A →B): A 到B 有 3 条路线。
f 1 ( A ) = min { d ( A , B 1 ) + f 2 ( B 1 ) d ( A , B 2 ) + f 2 ( B 2 ) d ( A , B 3 ) + f 2 ( B 3 ) } = min { 2 + 20 5 + 14 1 + 19 } = 19 f_{1}(A)=\min \left\{\begin{array}{l} d\left(A, B_{1}\right)+f_{2}\left(B_{1}\right) \\ d\left(A, B_{2}\right)+f_{2}\left(B_{2}\right) \\ d\left(A, B_{3}\right)+f_{2}\left(B_{3}\right) \end{array}\right\}=\min \left\{\begin{array}{l} 2+20 \\ 5+14 \\ 1+19 \end{array}\right\}=19 f1(A)=min⎩⎨⎧d(A,B1)+f2(B1)d(A,B2)+f2(B2)d(A,B3)+f2(B3)⎭⎬⎫=min⎩⎨⎧2+205+141+19⎭⎬⎫=19
最短路线为 A → B 2 → C 1 → D 1 → E A \rightarrow B 2 \rightarrow C 1 \rightarrow D 1 \rightarrow E A→B2→C1→D1→E
根据第3节的分析,我们可以写出以下python程序(程序参考自知乎):
INF = float('INF')
### 状态节点定义
graph = {
'4': {'D1': {'E': 5}, 'D2': {'E': 2}},
'3': {'C1': {'D1': 3, 'D2': 9}, 'C2': {'D1': 6, 'D2': 5}, 'C3': {'D1': 8, 'D2': 10}},
'2': {'B1': {'C1': 12, 'C2': 14, 'C3': 10}, 'B2': {'C1': 6, 'C2': 10, 'C3': 4}, 'B3': {'C1': 13, 'C2': 12, 'C3': 11}},
'1': {'A': {'B1': 2, 'B2': 5, 'B3': 1}}
}
### 最优路径及其距离值定义
INF = float('INF')
# 初始时距离为无穷大
dists = {
'A': INF,
'B1': INF,
'B2': INF,
'B3': INF,
'C1': INF,
'C2': INF,
'C3': INF,
'D1': INF,
'D2': INF,
'E': 0
}
path_opt = {
'A': ['A'],
'B1': ['B1'],
'B2': ['B2'],
'B3': ['B3'],
'C1': ['C1'],
'C2': ['C2'],
'C3': ['C3'],
'D1': ['D1'],
'D2': ['D2'],
'E': ['E']
}
# 每一个节点的父节点
parents = {
'A': None,
'B1': None,
'B2': None,
'B3': None,
'C1': None,
'C2': None,
'C3': None,
'D1': None,
'D2': None,
'E': None
}
# 动态规划函数
def DP(graph, dists, parents):
for period_key in graph.keys(): # 遍历每一个阶段
for key_i in graph[period_key].keys(): # 遍历每个阶段的每一个状态节点
min_key = None
for key_i_dist in graph[period_key][key_i].keys(): # 遍历当前阶段的每个状态节点到下一阶段的每一条路径
if graph[period_key][key_i][key_i_dist] + dists[key_i_dist] < dists[key_i]:
dists[key_i] = graph[period_key][key_i][key_i_dist] + dists[key_i_dist]
parents[key_i] = key_i_dist
min_key = key_i_dist # 找出最小距离值的节点
path_opt[key_i].extend(path_opt[min_key]) # 将最小距离值的节点添加到最优路径集合
DP(graph, dists, parents)
print("E到每个节点的最短距离:\n",dists)
print("====================")
print("最优时每个节点的父节点:\n",parents)
print("====================")
print("最优路径:\n",path_opt)
代码仓库见github