草庐IT

【路径规划】全局路径规划算法——动态规划算法(含python实现)

CHH3213 2024-05-10 原文

文章目录

参考资料

1. 算法简介

  • 动态规划是运筹学的一个分支,是求解多阶段决策过程最优化问题的数学方法。
  • 各个阶段决策的选取不是任意确定的,它依赖于当前面临的状态,又影响以后的发展。当各个阶段的决策确定后,就组成了一个决策序列,因而也就决定了整个过程的一条活动路线,这样的一个前后关联具有链状结构的多阶段过程就称为多阶段决策问题。
  • 动态规划在车辆工程技术领域有着广泛的应用,如“两档变速器最优换挡规律”、“混合动力汽车最优能量管理策略”、“栅格地图最优路径搜索”等。

2. 算法思想

  • 动态规划的思想就是将多阶段决策问题转化为一系列单阶段最优化问题

  • 对最佳路径(最佳决策过程)所经过的各个阶段,其中每个阶段始点到全过程终点的路径,必定是该阶段起始点到全
    过程终点的一切可能路径中的最佳路径(最优决策),这就是Bellman提出的著名的最优化原理

  • 简言之, 一个最优策略的子策略必然也是最优的

DP算法逆向寻优,正向求解,本质由三层循环构成:

  • 第一层遍历每一个阶段;
  • 第二层遍历第 i i i个阶段的每一个状态;
  • 第三层循环遍历第 i i i阶段的第 j j j个状态到第 i − 1 i-1 i1阶段的每一条路径, 更新当前状态的到上一个阶段的状态的最短距离

3. 算法示例

如图,设终点为 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 C1D1E

    • 经过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} C2D2E

    • 经过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 C3D2E

  • 第Ⅱ阶段(B →C): B 到C 有 9 条路线。第Ⅱ阶段的B有3个状态值,类似地,分别讨论经过该状态值的最优路线。

    • 经过B1
      f 2 ( B 1 ) = min ⁡ { d ( B 1 , C 1 ) + f 3 ( C 1 ) d ( B 1 , C 2 ) + f 3 ( C 2 ) d ( B 1 , C 3 ) + f 3 ( C 3 ) } = min ⁡ { 12 + 8 14 + 7 10 + 12 } = 20 f_{2}\left(B_{1}\right)=\min \left\{\begin{array}{l} d\left(B_{1}, C_{1}\right)+f_{3}\left(C_{1}\right) \\ d\left(B_{1}, C_{2}\right)+f_{3}\left(C_{2}\right) \\ d\left(B_{1}, C_{3}\right)+f_{3}\left(C_{3}\right) \end{array}\right\}=\min \left\{\begin{array}{l} 12+8 \\ 14+7 \\ 10+12 \end{array}\right\}=20 f2(B1)=mind(B1,C1)+f3(C1)d(B1,C2)+f3(C2)d(B1,C3)+f3(C3)=min12+814+710+12=20
      最短路线为 B 1 → C 1 → D 1 → E B 1 \rightarrow C 1 \rightarrow D 1 \rightarrow E B1C1D1E
    • 经过B2
      f 2 ( B 2 ) = min ⁡ { d ( B 2 , C 1 ) + f 3 ( C 1 ) d ( B 2 , C 2 ) + f 3 ( C 2 ) d ( B 2 , C 3 ) + f 3 ( C 3 ) } = min ⁡ { 6 + 8 10 + 7 4 + 12 } = 14 f_{2}\left(B_{2}\right)=\min \left\{\begin{array}{l} d\left(B_{2}, C_{1}\right)+f_{3}\left(C_{1}\right) \\ d\left(B_{2}, C_{2}\right)+f_{3}\left(C_{2}\right) \\ d\left(B_{2}, C_{3}\right)+f_{3}\left(C_{3}\right) \end{array}\right\}=\min \left\{\begin{array}{l} 6+8 \\ 10+7 \\ 4+12 \end{array}\right\}=14 f2(B2)=mind(B2,C1)+f3(C1)d(B2,C2)+f3(C2)d(B2,C3)+f3(C3)=min6+810+74+12=14
      最短路线为 B 2 → C 1 → D 1 → E B 2 \rightarrow C 1 \rightarrow D 1 \rightarrow E B2C1D1E
    • 经过B3
      f 2 ( B 3 ) = min ⁡ { d ( B 3 , C 1 ) + f 3 ( C 1 ) d ( B 3 , C 2 ) + f 3 ( C 2 ) d ( B 3 , C 3 ) + f 3 ( C 3 ) } = min ⁡ { 13 + 8 12 + 7 11 + 12 } = 19 f_{2}\left(B_{3}\right)=\min \left\{\begin{array}{l} d\left(B_{3}, C_{1}\right)+f_{3}\left(C_{1}\right) \\ d\left(B_{3}, C_{2}\right)+f_{3}\left(C_{2}\right) \\ d\left(B_{3}, C_{3}\right)+f_{3}\left(C_{3}\right) \end{array}\right\}=\min \left\{\begin{array}{l} 13+8 \\ 12+7 \\ 11+12 \end{array}\right\}=19 f2(B3)=mind(B3,C1)+f3(C1)d(B3,C2)+f3(C2)d(B3,C3)+f3(C3)=min13+812+711+12=19
      最短路线为 B 3 → C 2 → D 2 → E B 3 \rightarrow C 2 \rightarrow D 2 \rightarrow E B3C2D2E
  • 第Ⅰ阶段(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)=mind(A,B1)+f2(B1)d(A,B2)+f2(B2)d(A,B3)+f2(B3)=min2+205+141+19=19
    最短路线为 A → B 2 → C 1 → D 1 → E A \rightarrow B 2 \rightarrow C 1 \rightarrow D 1 \rightarrow E AB2C1D1E

4. python实现

根据第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

有关【路径规划】全局路径规划算法——动态规划算法(含python实现)的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  3. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  4. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  5. 区块链之加解密算法&数字证书 - 2

    目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非

  6. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  7. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  8. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  9. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  10. ruby-on-rails - Rails - 使用/自定义 URL : '/dashboard' 指定根路径 - 2

    如何使此根路径转到:“/dashboard”而不仅仅是http://example.com?root:to=>'dashboard#index',:constraints=>lambda{|req|!req.session[:user_id].blank?} 最佳答案 您可以通过以下方式实现:root:to=>redirect('/dashboard')match'/dashboard',:to=>"dashboard#index",:constraints=>lambda{|req|!req.session[:user_id].b

随机推荐