有信息搜索与无信息搜索
人工智能中的搜索策略大体分为两种:无信息搜索和有信息搜索。无信息搜索是指我们不知道接下来要搜索的状态哪一个更加接近目标的搜索策略,因此也常被成为盲目搜索;而有信息搜索则是用启发函数f(n)来衡量哪一个状态更加接近目标状态,并优先对该状态进行搜索,因此与无信息搜索相比往往能够更加高效得解决问题。
要衡量一个搜索策略的好坏,我们需要从四个方面对其进行判断:完备性、时间复杂度、空间复杂度和最优性。因此以下通过这四个方面来比较常见搜索策略之间的优劣。
无信息搜索策略
宽度优先搜索(BFS)
首先扩展根节点,然后扩展根节点的所有后继,接着再扩展它们的后继,从而一层一层的对节点进行扩展。BFS是一个简单的搜索策略,在搜索过程中会对所有状态进行遍历,因此它是完备的;假设搜索树每个节点有b个后继,深度为d,则时间复杂度和空间复杂度均为O(bd);最后考虑最优性,因为我们总会在最浅那一层找到目标状态,因此当且仅当每一步的代价都一致的时候,BFS可以得到最优解。
一致代价搜索
在BFS的基础上,一致代价搜索不在扩展深度最浅的节点,而是通过比较路径消耗g(n),并选择当前代价最小的节点进行扩展,因此可以保证无论每一步代价是否一致,都能够找到最优解。
深度优先搜索(DFS)
DFS扩展根节点的一个后继,然后扩展它的一个后继,直到到达搜索树的最深层,那里的节点没有后继,于是DFS回溯到上一层,扩展另外一个未被扩展的节点。在有限状态空间中,DFS是完备的,因为它可以把所有空间遍历一遍;而在无限空间中,DFS则有可能会进入深度无限的分支,因此是不完备的。DFS的时间复杂度为为O(bd),而空间复杂度仅为O(d),因为我们只需要保存当前分支的状态,因此空间复杂度远远好于BFS。然而DFS并不能保证找到最优解。
深度受限搜索
深度受限搜索设定一个最大深度dmax,当搜索深度大于dmax的时候立即回溯,从而避免了在无穷状态空间中陷入深度无限的分支。
迭代加深的深度有限搜索
迭代加深的深度有限搜索也设定一个最大深度dmax,开始我们把dmax设为1,然后进行深度受限搜索,如果么有找到答案,则让dmax加一,并再次进行深度有限搜索,以此类推直到找到目标。这样既可以避免陷入深度无限的分支,同时还可以找到深度最浅的目标解,从而在每一步代价一致的时候找到最优解,再加上其优越的空间复杂度,因此常常作为首选的无信息搜索策略。
有信息搜索
贪婪最佳优先搜索
贪婪最佳优先搜索总是扩展距离目标最近的节点,其启发函数f(n)=h(n)其中:
f(n)=节点n到目标节点的最小代价路径的估计值
贪婪最佳优先搜索的最大问题是它往往不能找到最优解。
A*
为了找到最优解,A*算法对一个节点的评估结合了h(n)和g(n)从开始节点到节点n的路径代价,即f(n)=g(n)+h(n)
f(n)=经过节点n的最小代价解的估计代价
因为A*搜索总是搜索f(n)最小的点,因此它总能找到最优解。
- Kafka源码系列之副本同步机制及isr列表更新
- Kafka源码系列之topic创建分区分配及leader选举
- Kafka源码系列之如何删除topic
- Kafka源码系列之kafka如何实现高性能读写的
- Kafka源码系列之分组消费的再平衡策略
- Kafka源码系列之Consumer高级API性能分析
- Kafka源码系列之源码解析SimpleConsumer的消费过程
- Spark调优系列之序列化方式调优
- Spark源码系列之foreach和foreachPartition的区别
- kafka源码系列之mysql数据增量同步到kafka
- Hbase源码系列之BufferedMutator的Demo和源码解析
- Kafka源码系列之0.10版本的Producer源码解析及性能点讲解
- Spark源码系列之spark2.2的StructuredStreaming使用及源码介绍
- Hbase源码系列之scan源码解析及调优
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法