03 Problem solving search
很多AI任务都可以形式化为搜索问题:寻找路径、过河问题、解谜题(魔方、数码问题)、酒壶分水
Outline
问题求解智能体:基于目标Agent
问题形式化
问题实例
基本搜索算法
问题求解Agent
function SIMPLE-PROBLEM-SOLVING-AGENT(percept) returns an action
static:seq, an action sequence, initially empty
state, some description of the current world state
goal, a goal, initially null
problem, a problem formulation
state ← UPDATE-STATE(state,percept)
if seq is empty then do
goal ← FORMULATE-GOAL(state)
problem ← FORMULATE-PROBLEM(state, goal)
seq ← SEARCH(problem)
action ← FIRST(seq)
seq ← REST(seq)
return action
这是离线问题,在求解问题时是闭眼执行的,而联机问题在解决问题时不需要完整的知识
搜索问题
搜索问题包括:状态空间、后继函数、开始状态和目标测试
问题的解是从初始状态到目标状态的一组行动序列
搜索树:计划和结果的“what if"树;开始状态对应根结点;孩子结点对应后继函数;结点标记为状态,分别对应这些状态的计划;对大多数问题不可能建立整个树
状态空间图:每个状态是一个结点,每个后继是一条发出的边
实例:罗马尼亚问题
构造目标:在Bucharest
构造问题:状态:各个城市;行为:驾驶往返于各个城市
寻找问题的解:城市序列,如Arad,SIbiu,Fagaras,Bucharest
单状态问题形式化:
初始状态,如“at Arad”
行动或后继函数,S(x)=set of action-state pairs,如S(Arad) = { <Arad→Zerind, Zerind>,... }
目标测试:明确的,如x = "at Bucharest",隐含的,如Checkmate(x)
路径损耗:如距离,行动执行的次数等,c(x,a,y)>=0
问题的解是一组从初始状态到目标状态的行动序列
选择一个状态空间
真实世界中状态空间必须抽象化
(抽象)状态=真实状态的集合
(抽象)行动=真实行动的复杂组合
(抽象)解=真实世界解决方案的真实路径集合
每个抽象动作都应该比原问题更简单
例子:吸尘器状态空间图
状态:地板是否脏、机器人的位置
行动:Left, Right, Suck, NoOp
目标测试:没有灰尘
路径损耗:每次行动消耗1,NoOp则消耗0
例子:8数码
状态:数码块的位置
行动:move blank left, right, up, down
目标测试:给定的数码块位置状态
路径损耗:每次行动消耗1
注意:求解n数码问题的最优解是NP完全的
基本搜索算法
Tree search algorithms——搜索树
function Tree-Search(problem, strategy) returns a solution, or failure
initialize the search tree using the initial state of problem
loop do
if there are no candidates for expansion then return failure
choose a leaf node for expansion according to strategy(根据不同策略选择扩展节点)
if the node contains a goal then return the corresponding solution
else expand the node and add the resuling nodes to the search tree
end
实现:状态 vs. 节点
状态是物理配置的一种表现形式
一个节点是一个数据结构构成的搜索树的一部分,包括状态、父节点、行动、路径成本g(n)、深度
实现:生成树搜索
function TREE-SEARCH(problem, fringe) returns a solution, or failure
fringe ← INSERT(MAKE-NODE(INITIAL-STATE[problem],fringe)
loop do
if fringe is empty then return failure
node ← REMOVE-FRONT(finge)
if GOAL-TEST[problem](STATE[node]) then return SOLUTION(node)
fringe ← INSERTALL(EXPAND(node, problem), fringe)
function EXPAND(node, problem) returns a set of nodes
successors ← the empty set
for each action, result in SUCCESSOR-FN[problem](STATE[node]) do
s ← a new NODE
PARENT-NODE[s] ← node; ACTION[s] ← action; STATE[s] ← result
PATH-COST[s] ← PATH-COST[node] + STEP-COST(node,action,s)
DEPTH[s] ← DEPTH[node] + 1
add s to successors
return successors
搜索策略:节点扩展顺序的选取
性能评价:完备性、时间复杂度、空间复杂度、最优性
衡量时间和空间复杂度相关的项:分支因子b、最浅的目标节点的深度d、最大深度m
无信息搜索策略:只利用问题定义中提供的状态信息
广度优先搜索、一致代价搜索、深度优先搜索、深度受限搜索、迭代加深的深度优先搜索
1.广度优先搜索:扩展未扩展过的最浅节点,将边缘组织成FIFO队列实现,新的厚积节点加入到队列尾
完备性?是的(若d有限)
时间?1+b+b^2+b^3+...+b^d+b(b^d-1) = O(b^(d+1)),即d的指数
空间?O(b^(d+1))(保存所有节点在内存中)
最优?是的(若每步的路径损耗为1),通常情况下不是最优的
空间代价是最大的问题,生成节点的速度可达100MB/sec,24hrs = 8640GB
2.一致代价搜索:扩展代价最小的未扩展的节点,边缘组织成按路径损耗排序的队列实现,若单步代价均相等则等价于广度优先搜索
完备性?是的,若单步代价>=ε
时间?空间? C*为最优解的代价,对于g<=C*,O(b^(ceiling(C*/ε)))
最优?是的,节点根据g(n)的递增顺序扩展
3.深度优先搜索:扩展深度最深的未扩展过的节点,边缘=LIFO队列,后继结点放在队列前
完备性?否,只在有限状态空间中完备
时间?O(b^m),若m比d大很多,时间消耗更多,但若解是密集的,则比广度优先搜索更快
空间?O(b^m),即线性
最优?否
4.深度受限搜索:设置界限l,解决无限深度路径问题
若l<d,不完备,若l>d,非最优
递归实现
5.迭代加深的深度优先搜索:每轮增加深度限制的深度受限搜索
function ITERATIVE-DEEPENING-SEARCH(problem) returns a solution
inputs:problem, a problem
for depth o to ∞ do
result DEPTH-LIMITED-SEARCH(problem, depth)
if result ≠ cutoff then return result
end
完备性?是的
时间?(d+1)b^0 + db^1 + (d-1)b^2 + ... + b^d = O(b^d)
空间?O(bd)