状态空间搜索与a_star
搜索的概念
搜索需要解决的基本问题:
- 是否一定能找到一个解
- 找到的解是否是最佳解
- 时间与空间复杂性
- 是否终止或者是否陷入死循环
搜索的主要过程:
- 从初始状态开始,将它作为当前状态
- 扫描操作算子,将适用当前状态的一些操作算子作用与当前状态而得到新的状态,并建立指向其父节点的指针(便于回溯)
- 检查所生成的新状态是否满足结束状态,如果满足,则得到问题的一个解,并可以沿着指针从结束状态反推回到开始状态;否则将新状态作为当前状态,返回2进行操作。
搜索策略:
- 搜索方向:
- 数据驱动:从初始状态出发的正向搜索
- 目的驱动:从目的状态出发的逆向搜索
- 双向搜索:从初始状态出发的正向搜索,同时又从目的状态出发的逆向搜索,直到两条路径汇合为止
- 盲目搜索和启发式搜索:
- 盲目搜索:不具有对特定问题的任何有关信息的条件下,按照固定的步骤进行搜索
- 启发式搜索:考虑到问题的知识,动态地确定操作算子的步骤,优先选择较合适的操作算子,减少不必要的搜索。
状态空间的搜索策略
状态空间表示法:
状态:表示系统状态、事实等叙述型知识的一组变量或数组
Q
=
[
q
1
,
q
2
,
.
.
.
,
q
n
]
T
Q=[q_1,q_2,...,q_n]^T
Q=[q1,q2,...,qn]T
操作:表示引起状态变化的过程型知识的一组关系或函数
F
=
{
f
1
,
f
2
,
.
.
.
,
f
m
}
F=\{f_1,f_2,...,f_m\}
F={f1,f2,...,fm}
状态空间:利用状态变量和操作符号,表示系统或问题的有关知识的符号体系,状态空间是一个四元组
(
S
,
O
,
S
0
,
G
)
(S,O,S_0,G)
(S,O,S0,G)
S:状态集合
O:操作算子的集合
S 0 S_0 S0:包含问题的初始状态是S的非空子集
G:若干具体状态或满足某些性质的路径信息描述
此时求解的路径就是从 S 0 S_0 S0到 G G G的路径
盲目的图搜索策略
-
回溯策略
一条路走到底,直到死路后,向上回溯到有分支节点的父节点,选择另一条路走到死,重复操作。
-
PS表:保存当前搜索路径上的状态。如果找到了目的,PS就是解路径上的状态有序集
-
NPS表:新的路径状态表。它包含了等待搜索的状态,其后裔状态还未被搜索到,即未被生成扩展 。
-
NSS表:不可解状态集,列出了找不到解题路径的状态。如果在搜索中扩展出的状态是它的元素,则可立即将之排除,不必沿该状态继续搜索。
-
bfs:以接近起始节点的程度(深度)为依据,进行逐层扩展的节点搜索方法。
- 每次选择深度最浅的节点首先扩展,搜索是逐层进行的
- 一种高价搜索,但若有解存在,则必能找到它。
-
dfs:首先扩展最新产生的节点, 深度相等的节点按生成次序的盲目搜索。
- 扩展最深的节点的结果使得搜索沿着状态空间某条单一的路径从起始节点向下进行下去;仅当搜索到达一个没有后裔的状态时,才考虑另一条替代的路径。
启发式图搜索策略
启发式搜索:
启发式搜索又叫有信息的搜索,它利用问题所拥有的启发信息来引导搜索,达到减少搜索范围,降低问题复杂度的目的。
-
无信息搜索对所有的可能路径节点一视同仁,而启发式搜索可以指导搜索向最有希望的方向前进
-
如何评估一个节点的重要性? - 估价函数 f ( x ) = g ( x ) + h ( x ) f(x)=g(x)+h(x) f(x)=g(x)+h(x)
其中g(x)是从初始节点到节点x付出的实际代价;而h(x) 是从节点x到目标节点的最优路径的估计代价。h(x)建模了启发式搜索问题中的启发信息,是算法的关键。启发式函数的设计非常重要,合理的定义才能让搜索算法找到一个最优的问题解。
-
a_star算法:
A*算法可以看作是BFS算法的升级版,在原有的BFS算法的基础上加入了启发式信息
-
a_star算法的估价函数也是 f ( x ) = g ( x ) + h ( x ) f(x)=g(x)+h(x) f(x)=g(x)+h(x)
-
算法描述
从起始节点开始,不断查询周围可到达节点的状态并计算它们的f(x),h(x)与g(x)的值,选取估价函数f(x)最小的节点进行下一步扩展,并同时更新已经被访问过的节点的g(x),直到找到目标节点。
-
算法优缺点:
拥有BFS速度较快的优点,但是因为它要维护“开启列表”以及“关闭列表”,并且需要反复查询状态。因此它的空间复杂度是指数级的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fPin0hhO-1681116454959)(C:\Users\15989\AppData\Roaming\Typora\typora-user-images\image-20230410113803653.png)]
-
算法步骤
- 从起点开始,把其当成待处理点存入一个“开启列表”。
- 搜寻起点周围可能通过的节点,也把它们加入开启列表,为这些节点计算f(x),g(x),h(x),并且将节点A存为“父节点”。
- 从开启列表中删除节点A,将其加入“关闭列表”(列表中保存所有不需要再次检查的节点)循环直到找到目标节点或者“开启列表”为空(无路径)
- 从“开启列表”中找到估价函数值最低的节点C,并将它从“开启列表”中删除,添加到“关闭列表”中。
- 检查C所有相邻节点,将其加入“开启列表”,将C作为它们的父节点。
- 如果新的相邻节点已经在“开启列表”,则更新它们的g(x)值
-
-
-
IDAstar:
IDA* 是迭代加深深度优先搜索算法(IDS)的扩展。因为它不需要去维护表,因此它的空间复杂度远远小于A*。在搜索图为稀疏有向图的时候,它的性能会比A*更好。
-
IDA*算法的估价函数也是 f ( x ) = g ( x ) + h ( x ) f(x)=g(x)+h(x) f(x)=g(x)+h(x)
-
算法描述:
在算法迭代的每一步,IDA*都进行深度优先搜索,在某一步所有可访问节点对应的最小可估价函数值大于某个给定的阈值的时候,将会剪枝。
-
算法优点:
当问题要求空间复杂度比较低的时候,IDA*更有优势。
-
算法步骤:
对于给定的阈值bound,定义递归过程
- 从开始节点C,计算所有邻居节点的估价函数,选取估价函数最小的节点作为下一个访问节点。
- 对于某个节点,如果估价函数大于阈值,则返回当前节点的估值函数值。
- 对于某个节点,如果是目标节点,则返回状态 ”到达”。
-
-
启发函数的设计:
启发式函数h(n)告诉算法从任何节点到目标节点的最小代价估计值,它的选取很大程度影响算法性能。h(n) 的值 描述 性能变化 h(n) = 0 只有g(n)起作用,退化为Dijkstra算法 保证找到最短路径 h(n) <= h*(n) 保证能找到最短路径 h(n) = h*(n) 只遵循最佳路径不会扩展其它节点 运行速度快并且能找到最短路径 h(n) > h*(n) 不能保证找到最短路径 -
性质一:可采纳的(admissible)
当估价函数的预估值小于等于真实值时,算法必然可以找到一条从起始节点到最终节点的最短路径。这种性质叫做相容。 h ( n ) ≤ h ∗ ( n ) h(n)\leq h^*(n) h(n)≤h∗(n)
-
性质二:单调的 (consistent)
-
保证找到最短路径 |
-
性质一:可采纳的(admissible)
当估价函数的预估值小于等于真实值时,算法必然可以找到一条从起始节点到最终节点的最短路径。这种性质叫做相容。 h ( n ) ≤ h ∗ ( n ) h(n)\leq h^*(n) h(n)≤h∗(n)
-
性质二:单调的 (consistent)
当节点n的估价函数值永远小于等于它的扩展节点n’的估价函数值加上扩展代价时,则启发式函数设计是单调的。 h ( n ) ≤ c o s t ( n , n ′ ) + h ( n ′ ) h(n)\leq cost(n,n')+h(n') h(n)≤cost(n,n′)+h(n′)