文章目录
-
- [📚 核心结论(塔尖)](#📚 核心结论(塔尖))
- 一、问题形式化:通过五个核心要素定义问题
- 二、搜索算法:根据信息可用性选择策略
- 三、方法选择:根据信息可用性权衡
- 附:术语小词典(Glossary)
-
- [状态空间(State Space)](#状态空间(State Space))
- 广度优先搜索(BFS)
- 深度优先搜索(DFS)
- [A*搜索(A* Search)](#A搜索(A Search))
- 可采纳性(Admissibility)
📌 适合对象 :希望深入理解基础搜索算法原理的学习者
⏱️ 预计阅读时间 :50-60分钟
🎯 学习目标:学会怎么把实际问题转换成可搜索的形式,怎么根据有没有线索选择搜索方法
📚 核心结论(塔尖)
基础搜索策略解决搜索问题的核心思路是分两步走:
- 问题形式化用五个核心要素(你现在在哪、你能做什么、你想达到什么、做了动作会变成什么样、做这个动作要花多少代价)把实际问题转换成可搜索的形式,就像把现实问题画成一张搜索地图;
- 搜索算法根据有没有额外信息选择搜索方法。没线索时用无信息搜索(按层、按代价、按深度系统化地探索),有线索时用启发式搜索(利用线索引导,就像有地图指引)。
那么,怎么用五个核心要素把实际问题转换成可搜索的形式?不同的扩展策略怎么在找全解、找最优解、找得快之间权衡?当有额外信息时,怎么利用线索引导搜索?这些正是本文要解决的核心。
搜索问题
找路/拼图 问题形式化
画成搜索地图
五个核心要素 搜索算法 无信息搜索
没线索时
系统化探索 启发式搜索
有线索时
利用线索引导 找全解vs找得快
一、问题形式化:通过五个核心要素定义问题
这五个要素是:
- 你现在在哪(状态空间,定义所有可能的位置)、
- 你能做什么(动作,定义状态之间的转换,比如能往哪走)、
- 你想达到什么(目标测试,判断是否达到目标)、
- 做了动作会变成什么样(状态转移函数,描述状态如何变化)、
- 做这个动作要花多少代价(路径代价,评估解的质量,比如走这条路要花多少时间)。
好的形式化是高效搜索的前提,就像画地图,要标出起点、终点、能走的路、每条路的距离。
这五个要素是相互依赖的:
- 状态空间设计是基础,定义了所有可能的状态,就像画地图要先标出所有可能的位置;
- 动作定义依赖于状态空间,定义状态之间的转换,就像知道你在哪,才能知道你能往哪走;
- 目标测试设计依赖于状态空间,判断状态是否是目标,就像知道所有位置,才能判断哪个是终点;
- 状态转移函数设计依赖于状态空间和动作定义,描述状态如何变化,就像知道你在哪、能做什么,才能知道做了动作后会变成什么样;
- 路径代价设计依赖于状态转移函数,评估解的质量,就像知道状态怎么变化,才能知道走这条路要花多少代价。
状态空间设计
你现在在哪
所有可能的位置 动作定义
你能做什么
能往哪走 目标测试设计
你想达到什么
判断是否到达终点 状态转移函数设计
做了动作会变成什么样
描述状态变化 路径代价设计
做这个动作要花多少代价
评估解的质量
实际问题
从A点到B点 状态空间
所有可能的位置
A/B/C/D/E 动作
能往哪走
A→B/A→C 目标
到达B点
判断是否在B 状态转移
A→B后变成B
描述位置变化 路径代价
A→B要花5分钟
评估时间成本
在实际应用中,你需要在几个方面权衡:
- 状态的完整性与简洁性:状态表示需要包含解决问题所需的所有信息,但也要简洁,避免冗余信息,就像画地图要标出所有重要信息,但不能太复杂;
- 搜索空间要足够小:状态表示需要便于执行动作和状态转移,但形式化后的搜索空间也要足够小,便于搜索,就像地图要清晰易读,但也不能太详细导致搜索太慢。
二、搜索算法:根据信息可用性选择策略
搜索算法根据有没有线索选择策略。
- 没线索时用无信息搜索,通过不同的扩展策略(按层、按代价、按深度)和优化技术(双向搜索、图搜索)在找全解、找最优解、找得快之间权衡;
- 有线索时用启发式搜索,通过线索提供信息引导,结合实际代价和估计代价在有信息情况下搜索。
无信息搜索:通过扩展策略系统化探索
想象一下,你什么线索都没有,只能系统化地探索。不同的扩展策略有不同的特点:
- 按层扩展保证找到最短路径但内存消耗大,
- 按深度扩展节省内存但可能找不到解,
- 按代价扩展保证代价最小但需要计算路径代价。
无信息搜索通过不同的扩展策略(按层、按代价、按深度)系统化探索解空间,不同的扩展策略在找全解、找最优解、找得快之间权衡。如下图各个搜索的特点:
起点 BFS
按层扩展
像水波扩散
保证最短路径 UCS
按代价扩展
优先走短的路
保证代价最小 DFS
按深度扩展
一条路走到底
节省内存 一层一层
向外扩展
内存消耗大 优先探索
代价小的路径
需要计算代价 一条路
走到底
可能找不到解
算法优化:
- 限制深度(DLS,深度有限搜索) 在DFS基础上设置最大深度限制,避免无限路径问题,就像走迷宫时设置最多走多少步,走不到就回头。
- 迭代深入(IDDFS,迭代深入深度优先搜索) 先尝试深度1,找不到就尝试深度2,逐步加深,兼顾BFS和DFS的优点,就像先浅尝辄止,找不到再深入。
否 否 是 是 IDDFS策略 深度1
浅尝辄止
快速探索 找到解? 深度2
再深入一点
继续探索 找到解? 深度3
再深入
逐步加深 找到解
兼顾BFS和DFS优点
- 双向搜索 从起点和终点同时搜索,在中间相遇,大幅减少搜索节点数,就像两个人从两端同时找,在中间碰头。
- 图搜索 记住已经走过的位置,避免重复探索,特别适用于有大量重复状态的问题,就像走迷宫时记住已经走过的路,不走回头路。
起点 已访问
记住走过的路
不走回头路 未访问
继续探索 已访问
避免重复探索 终点
起点 向前搜索
从起点开始 终点 向后搜索
从终点开始 相遇点
两个人碰头
大幅减少搜索节点数
启发式搜索:利用信息引导搜索
当有额外信息时,可以利用这些信息引导搜索,减少搜索空间,提高搜索效率。
- 贪婪最佳优先搜索 只考虑启发函数 h ( n ) h(n) h(n)(估计代价),总是选择离目标最近的节点扩展,快速但不一定最优,就像看到目标就直奔过去,但可能走错路。
- A*搜索 结合实际代价 g ( n ) g(n) g(n)(已经走过的路)和估计代价 h ( n ) h(n) h(n)(估计还要走多远), f ( n ) = g ( n ) + h ( n ) f(n)=g(n)+h(n) f(n)=g(n)+h(n)(总代价),优先扩展总代价最小的节点,既能利用信息提高效率,又能保证最优性,就像既考虑已经走了多远,又考虑还要走多远,选总路程最短的路。
贪婪搜索 只考虑h(n)
估计代价
看到目标就直奔
快速但不一定最优 A*搜索 f(n)=g(n)+h(n)
实际代价+估计代价
选总路程最短
效率高且最优
可采纳性 (启发函数 h ( n ) ≤ h ∗ ( n ) h(n) \leq h^*(n) h(n)≤h∗(n),估计值不超过真实值)保证A* 能找到最优解,就像估计距离不能比实际距离还远,否则可能走错路。
一致性(启发函数满足三角不等式)保证A* 图搜索的最优性,就像从A到B再到C的距离,不能比直接从A到C的距离还短。启发函数的质量直接影响搜索效率,好的启发函数可以显著提高搜索效率,就像有准确的地图指引,能更快找到目标。
启发函数性质 可采纳性
h(n)≤h*(n)
估计值≤真实值
不能估计太远 一致性
满足三角不等式
h(n)≤c(n,n')+h(n')
不能绕远路更短 保证A*
能找到最优解
不会走错路 保证A*图搜索
的最优性
不会漏掉最优解
三、方法选择:根据信息可用性权衡
问题形式化(定义你现在在哪、你能做什么、你想达到什么等)是搜索的前提,只有把问题形式化后,才能应用搜索算法。好的形式化是高效搜索的前提,就像画好地图才能找路,状态空间、动作、目标测试、状态转移函数、路径代价五个要素共同构成搜索问题的形式化。
搜索问题
找路/拼图 问题形式化
画成搜索地图
五个核心要素 搜索算法 无信息搜索
没线索时
系统化探索 启发式搜索
有线索时
利用线索引导
从基础策略(BFS、UCS、DFS)到改进策略(DLS、IDDFS),在找全解、找最优解、找得快之间权衡。
从快速到最优,贪婪策略(快速但不一定最优)到A*策略(完备且最优),从只考虑估计代价快速搜索,到综合考虑实际代价和估计代价保证最优性。
在实际选择时,你需要在几个方面权衡:
- 问题形式化在完整性、简洁性、可操作性和效率之间权衡,就像画地图要详细但不能太复杂;
- 无信息搜索通过不同的扩展策略和优化技术在找全解、找最优解、找得快之间权衡;
- 启发式搜索通过利用额外信息提高效率,同时保证最优性。
设计搜索算法的核心就是在这些维度之间找到平衡点。没有完美的算法,只有适合不同场景的算法。
设计权衡 找全解
vs
找得快 找最优解
vs
找得快 时间
vs
空间 信息利用
vs
最优性保证
附:术语小词典(Glossary)
状态空间(State Space)
定义所有可能的状态集合,包括初始状态、目标状态和中间状态。状态表示需要完整描述问题的当前状态,同时保持简洁和可操作。就像绘制地图,需要标明所有可能的位置,同时保持地图的清晰和易读。很多人以为"状态空间"就是所有状态的列表,实际上它是搜索问题的基础,定义了搜索的所有可能状态,就像画地图要先标出所有可能的位置。
广度优先搜索(BFS)
按层扩展,一层一层向外扩展,保证找到最短路径,但内存消耗大。就像水波扩散一样,从起点开始,逐层向外扩展,先探索距离为1的所有位置,再探索距离为2的所有位置。很多人以为"广度优先"就是横向搜索,实际上它是按层扩展,保证找到最短路径,但需要存储所有已访问的节点,就像要记住所有已经探索过的位置。
深度优先搜索(DFS)
按深度扩展,一条路走到底,内存消耗小,但可能找不到解或不是最短路径。就像走迷宫一样,一直往前走,直到走不通再回头,不需要记住所有走过的路,只需要记住当前路径。很多人以为"深度优先"就是纵向搜索,实际上它是按深度扩展,节省内存但可能失去完备性和最优性,就像可能走到死胡同,或者找到的不是最短路径。
A搜索(A Search)
结合实际代价 g ( n ) g(n) g(n)(已经走过的路)和估计代价 h ( n ) h(n) h(n)(估计还要走多远), f ( n ) = g ( n ) + h ( n ) f(n)=g(n)+h(n) f(n)=g(n)+h(n)(总代价),优先扩展总代价最小的节点,既能利用信息提高效率,又能保证最优性。就像既考虑已经走了多远,又考虑还要走多远,选总路程最短的路。很多人以为"A*"就是选择最小代价的节点,实际上它是综合考虑实际代价和估计代价,既能利用信息又能保证最优性。
可采纳性(Admissibility)
启发函数 h ( n ) ≤ h ∗ ( n ) h(n) \leq h^*(n) h(n)≤h∗(n),估计值不超过真实值,保证A能找到最优解。就像估计距离不能比实际距离还远,否则可能走错路。很多人以为"可采纳性"就是启发函数要准确,实际上它是要求估计值不超过真实值,这是A算法最优性保证的基础。