人工智能基础复习2——问题求解

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)
最优?是的,若单步代价=1
对于b=10,d=5,
N(IDS)=50+400+3000+20000+100000=123450
N(BFS)=10+100+1000+10000+100000+999990=1111100
IDS表现更优,因为在深度为d的节点不需展开
无信息搜索策略对比表格:见第三版课本P81

重复状态:未检测到重复状态可能导致一个线性的问题变成一个指数的问题
图搜索
function GRAPH-SEARCH(problem,fringe) returns a solution, or failure
    closed ← an empty set
    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 node
    if STATE[node] is not in closed then
        add STATE[node] to closed
        fringe ← INSERTALL(EXPAND(node,problem),fringe)
    end

04 Informed search

无信息的搜索:除了问题中提供的定义之外没有任何关于状态的附加信息
有信息的搜索:在问题本身的定义之外还可利用问题的特定知识

Outline
最佳优先搜索:贪婪最佳优先搜索、A*搜索
启发式搜索
局部搜索算法:爬山法搜索、模拟退火搜索、局部束搜索、遗传算法

最佳优先搜索
对每个结点利用评价函数f(n),扩展最需要扩展的还未扩展过的节点
实现:边缘是一个根据需求的降序进行排列的队列(优先级队列)
特殊情况:贪婪搜索、A*搜索
一致代价搜索
策略是扩展最小路径成本
优点:UCS完备且最优
缺点:在每个方向上进行搜索、没有最优目标的信息
最佳优先搜索
策略是扩展离目标最近的节点
启发函数:将状态映射到距离的函数
一种普遍的情况是最佳优先搜索会使得直接找到错误的目标
最坏情况是像badly-guided DFS

贪婪搜索
评价函数f(n)=h(n)=节点n到目标节点的最低耗散路径的耗散值估计值
h(n)是特定问题的函数,若n是目标节点,则h(n)=0,如hSLD(n)为从n到Bucharest的直线距离
贪婪搜索试图扩展离目标节点最近的点
完备性?否,可能导致死循环,在有限空间中进行重复性检查可构成完备性
时间?O(b^m),如果有一个好的启发式函数,复杂度可以有效降低
空间?O(b^m),保存所有节点在内存中
最优?否

UCS与贪婪算法结合:Uniform-cost按路径代价g(n)排序,Greedy-search按目标距离h(n)排序
A*按两者的和f(n)=g(n)+h(n)排序
A*搜索
评价函数:f(n)=g(n)+h(n)
g(n):到达节点n的耗散
h(n):启发函数:从节点n到目标节点的最低耗散路径的耗散估计值
f(n):经过节点n的最低耗散的估计函数
A*搜索使用可采纳启发式,即h(n)<=h*(n),h*(n)是到n的实际代价,h(n)>=0
如hSLD(n)从不会高估实际路径长
对任一节点n,有h(n)<=h*(n),则称h(n)是可采纳的
可采纳启发式从不会过高估计到达目标的代价,即乐观的
定理:如果h(n)是可采纳的,A*使用的TREE-SEARCH是最优的
A*的最优性证明:略
一致性启发函数:如果对于任一节点n,n'是n的后继,对于某一行动a,有h(n)<=c(n,a,n')+h(n'),则A*启发式是一致的
若h是一致的,有f(n')=g(n')+h(n')=g(n)+c(n,a,n')+h(n')>=g(n)+h(n)=f(n)
f(n)值沿任何路径都是非递减的
定理:如果h(n)是一致的,则A*使用的GRAPH-SEARCH是最优的
A*的最优性证明:略
A*的性质:
完备性?是的(除非f<=f(G)的节点是无穷的)
时间?A*算法对于任何给定的启发函数都是效率最优的,但仍为指数级
空间?保存所有节点在内存中
最优?是的
A*扩展所有f(n)<C*的节点、部分f(n)=C*的节点,不扩展f(n)>C*的节点

8数码问题——把棋子水平或者竖直地滑动到空格中,直到目标局面:
平均解步数是22步,分支因子约为3
到达深度为22的穷举搜索将考虑约3^22≈3.1×10^10
状态个数O((n+1)!),NP完全问题
可采纳启发式函数:
h1(n)=错位的棋子数,h2(n)=所有棋子到其目标位置的水平竖直距离和
统治:
若对于所有n,有h2(n)>=h1(n),则称h2统治h1(dominate,统治、占优),h2更利于搜索
h(n)=max(ha(n);hb(n))同样是可采纳的,且统治ha,hb
使用f(n)=g(n)+h(n)搜索,h(n)=错放数字个数,g(n)=节点深度

松弛:减少行动限制
一个松弛问题的最优解的耗散是原问题的一个可采纳的启发式
如果棋子可以任意移动,则h1给出最短的确切步数
如果棋子可以移动到任意相邻的位置,则h2给出最短的确切步数
松弛问题的最优解不大于实际问题的最优解
构造松弛问题
原问题:一个棋子可以从方格A移动到方格B,如果A与B水平或者垂直相邻而且B是空的
松弛1:一个棋子可以从方格A移动到方格B,如果A与B相邻——h2
松弛2:一个棋子可以从方格A移动到方格B,如果B是空的
松弛3:一个棋子可以从方格A移动到方格B——h1
如果有一个可采纳启发式的集合{h1,...,hm},h(n)=max(h1(n),...,hm(n)}可采纳并比成员启发式更有优势

评价函数f(n)
h(n)——节点n到目标节点的最低耗散路径的耗散估计值
g(n)——初始节点到这个节点的路径损耗的总和
f(n)=g(n): Uniform Cost
f(n)=h(n): Greedy
f(n)=g(n)+h(n): A*

局部搜索算法
对大规模问题,A*存在不足:状态空间太大、不能访问所有f值小于最优解的状态、不能存储整个边缘值
解决办法:更好的启发式、贪婪爬山算法(fringe size = 1)、束搜索(limited fringe size)
有限的内存选择:无足够的内存来存储整个边缘
爬山搜索:只有最佳节点保持不变,无边缘,优先根据h选择后继(贪婪爬山)与贪婪回溯相比,后者仍旧拥有边缘
束搜索(限制内存搜索):在边缘保留K个节点、转储所需的最低优先节点、可以单独根据h来优先排序(贪婪束搜索)、h+g(限制内存的A*)
状态空间=一系列完全状态
局部搜索算法:保持单一的一个当前状态,尝试去改进它,直至无法变得更好
常数空间,适合在线和离线搜索
通常更有效(但不完备)

例子:n皇后问题
优化问题:
爬山法搜索
从任何地方开始
总是选择最优的相邻值
如果所有相邻值均未比当前值的得分高,则退出
像健忘的人在大雾中试图登顶珠穆朗玛峰,不能一下子看到全局
function HILL-CLIMBING(problem) returns a state that is a local maximum
    inputs:problem, a problem
    local variables: current, a node
                     neighbor, a node
    current ← MAKE-NODE(INITIAL-STATE[problem])
    loop do 
        neighbor ← a highest-valued successor of current
        if VALUE[neighbor] <= VALUE[current] then return STATE[current]
        current ← neighbor
问题:依赖于初始状态,可能会陷入局部最大值的困境
随机重启爬山法克服了局部极大值 极度完备,易实现(只要不太崎岖)
随机侧移逃离山肩,极大循环
随机重启爬山算法:
1. When stuck, pick a random new starting state and re-run hill-climbing from there
2. Repeat this k times
3. Return the best of the k local optima

模拟退火搜索:通过允许一些“坏”的移动,但逐渐降低它们的频率逃离局部最大值
function SIMULATED-ANNEALING(problem, schedule) returns a solution state
    inputs: problem, a problem
            schedule, a mapping from time to "temperature"
    local variables: current, a node
                     next, a node
                     T, a "temperature" controlling prob. of downward steps
    current ← MAKE-NODE(INITIAL-STATE[problem])
    for t ← 1 to ∞ do
        T ← schedule[t]
        if T=0 then return current
        next ← a randomly selected successor of current
        ΔE ← VALUE[next] - VALUE[current]
        if ΔE > 0 then current ← next
        else current ← net only with probability e^(ΔE/T)
模拟退火搜索的性质:
如果调度让T下降得足够慢,算法找到全局最优解的概率逼近于1
广泛应用于VLSI布局、航空调度等

Local Beam Search(局部剪枝搜索)
记录k个状态,而不是1个,从k个随机生成的状态开始,每次迭代,全部k个状态的所有后继全部生成,如果有目标状态,停止,否则选择k个最佳后继,重复该过程
问题:很多时候,所有k个状态最终停留在相同的局部最大值上

遗传算法
利用自然选择的隐喻,通过结合两个父状态生成后继状态
从k个随机生成的状态开始(种群),一个状态被表示为一个有限长度字符串(0、1串)
评价函数:适应度函数(fitness function),越好的状态值越高
通过选择、杂交、变异产生下一代
8皇后的遗传算法图解:见课本P111

有信息/无信息搜索——主要思想
好的启发式搜索能大大提高搜索性能
但由于启发式搜索需要抽取与问题本身有关的特征信息,而这种特征信息的抽取有时会比较困难,因此盲目搜索仍不失为一种有用的搜索策略
好的搜索策略应该:引起运动——避免原地踏步;系统——避免兜圈;运用启发函数——缓解组合爆炸
搜索树 vs 搜索图
搜索树:结点有重复,但登记过程简单
搜索图:结点无重复,但登记过程复杂(每次都要查重),省空间,费时间

05 CSP

Constraint Satisfaction Problems 约束满足问题

Outline
CSP实例
CSP的回溯搜索
问题结构和问题分解
CSP局部搜索

标准搜索问题:状态是一个黑盒——任何可以由目标测试、评价函数、后继函数访问的数据结构
CSP:状态由值域Di中的变量Xi定义;每个约束包括一些变量的子集,并指定这些子集的值之间允许进行的合并
形式化表示方法的简单例子
实例:地图着色问题
变量:WA,NT,Q,NSW,V,SA,T
值域:Di={red,green,blue}
约束:相邻区域染上不同颜色
解:满足所有约束的颜色分配

约束图
Binary CSP:每个约束和两个变量相关
Constraint graph:节点是变量,弧是约束
通用的CSP算法利用图结构来加速搜索,如Tasmania是独立的子问题

CSP的种类
离散变量:
有限区域:n个变量,值域大小d → O(d^n)完全分配
例如:Boolean CSPs, incl. Boolean satisfiability (NP-complete)
无限值域(integers,strings,etc.),如作业调度
需要一种约束语言
线性约束可解,非线性不可判定
连续变量:
如:哈勃太空望远镜观测的开始、结束时间
线性规划方法在多项式时间内是线性约束可解的

约束的种类
一元约束涉及单一变量,如 SA≠green
二元约束涉及变量对,如SA≠WA
高阶约束涉及3个或更多变量,如密码算数的列约束
偏好约束(软约束),如红色比绿色更好;偏好约束通常被处理成个体变量赋值的耗散——约束优化问题(COP)

例子:密码算数
变量:F T U W R O X1 X2 X3
值域:{0,1,2,3,4,5,6,7,8,9}
约束:alldiff (F,T,U,W,R,O)
O + O = R + 10.X1
X1 + W + W = U + 10.X2
X2 + T + T = O + 10.X3
X3 = F , T ≠ 0, F ≠ 0

真实世界的CSP
指派问题:谁教授哪一节课、谁阅读哪篇文献
时间安排问题:何时何地上什么课
硬件布局、交通调度、工厂调度、平面布置
注意真实世界问题包含了实数值变量

标准搜索的增量形式化
初始状态:空,{}
后继函数:分配一个值给未赋值的变量,并且新赋值与当前赋值不冲突(如果不存在合法赋值则失败)
目标测试:当前分配是完备的
这和所有的CSP是一样的,每个解在深度n出现n个变量,利用深度优先搜索
由于路径是不相关的,所以可以使用完全状态形式化
在深度l,b=(n-1)d,所以n!.d^n 个叶子 !!!!

回溯搜索
变量赋值具有可交换性,如
[WA = red then NT = green] 等价于 [NT = green then WA = red]
只需考虑对每个节点的单一变量的赋值:b = d  所以有d^n个叶节点
在CSP中,对深度优先搜索的单一变量赋值称为回溯搜索
回溯搜索是CSP中基本的无信息搜索算法
可以解决规模为n≈25的n皇后问题
function BACKTRACKING-SEARCH(csp) returns solution/failure
     return RECURSIVE-BACKTRACKING({},csp)
function RECURSIVE-BACKTRACKING(assignment,csp) returns soln/failure
    if assignment is complete then return assignment
    var ← SELECT-UNASSIGNED-VARIABLE(VARIABLES[csp],assignment,csp)
    for each value in ORDER-DOMAIN-VALUES(var, assignment,csp) do
        if value is consistent with assignment given CONSTRAINTS[csp] then
            add {var = value} to assignment
            result ← RECURSIVE-BACKTRACKING(assignment,csp)
            if result ≠ failure then return result
            remove {var = value} from assignment
    return failure

另一个回溯搜索例子:满足{┐a∨b,┐b∨c,┐c,┐a}的值
枚举法:{a,b,c} = 1 1 1,1 1 0, 1 0 1, 1 0 0, 0 1 1, 0 1 0, 0 0 1, 0 0 0
回溯法:{a,b,c} = 1 -  -, 0 1 1, 0 1 0, 0 0 1, 0 0 0

提高回溯法的效率
通常的算法有很大的改善空间:
1.下一次赋值应该对哪个变量进行?
2.尝试的变量应该按照什么顺序?
3.是否可以尽早地发现不可避免的失败?
4.是否可以利用问题结构?

1. Minimum remaining values 最小剩余值(MRV):选择拥有最少合法值的变量
约束最多的变量先开始,按照最快失败的顺序进行

Degree heuristic 度启发式
Tie-breaker among MRV variables
度启发式:通过选择与其他未赋值变量约束最多的变量来试图降低未来的分支因子

2. Least constraining value 最少约束值
给定一个变量,选择最少约束值:优先选择的值是给邻居变量留下更多的选择;可能会需要更大的计算量

Forward checking——前向检验
思路:对剩下的未赋值的变量的合法值进行跟踪检查,如果发现任一变量不再拥有合法值则终止搜索算法

3. Constraint propagation——约束传播
前向检查从已赋值的变量向未赋值的变量传播信息,但是不对早期的失败提供早期的发现
NT和SA不能都是蓝色(具体例子见课本P181)
约束传播局部重复地实施约束

Arc consistency——弧相容(定义见课本P174)
使每条弧保持相容(consistent)的最简单的传播形式
X → Y is consistent iff for every value x of X there is some allowed y
if X loses a value, neighbors of X need to be rechecked
弧相容比前向检验更早地发现失败,可以作为预处理器或在每次赋值之后进行
弧形容算法AC-3:
function AC-3(csp) returns the CSP, possibly with reduced domains
    inputs:csp, a binary CSP with variables {X1,X2,...,Xn}
    local variables:queue, a queue of arcs, initially all the arcs in csp
    while queue is not empty do
        (Xi,Xj) ← REMOVE-FIRST(queue)
        if REMOVE-INCONSISTENT-VALUES(Xi,Xj) then
            for each Xk in NEIGHBORS[Xi] do
                add (Xk,Xi) to queue
function REMOVE-INCONSISTENT-VALUES(Xi,Xj) returns true iff succeeds
    removed ← false
    for each x in DOMAIN[Xi] do 
        if no value y in DOMAIN[Xj] allows (x,y) to satisfy the constraint Xi ↔ Xj
            then delete x from DOMAIN[Xi]; removed ← true
    return removed

4.
问题结构和问题分解
对Tasmain着色和对mainland着色是两个独立的子问题,独立性可以通过在约束图中寻找连通域来确定
假设每个子问题包含了n个变量中的c个变量,最坏情况下的工作量是n/c.d^c,是n的线性函数
如:n=80,d=2,c=20,4*2^20

树结构的CSP
定理:如果约束图无环,则CSP可以在O(n*d^2)时间内解决;任何一个树状结构的CSP问题可以在变量个数的线性时间内求解
与通常的CSP比较,后者的最坏时间为O(d^n)
这个定理也可以用逻辑和概率性原因解释:在语法约束和推理复杂性之间的一个重要例子

CSP的树结构算法
1. 选择一个变量作为根节点,从根节点到叶子节点进行排序,使每个节点的父节点在该节点之前
2. 对j从n到2,执行函数REMOVEINCONSISTENT(Parent(Xi),Xi)
3. 对j从1到n,对Xi相容地赋值Parent(Xi)
复杂度:O(n*d^2)

近似树结构的CSP
调整:实例化一个变量,删除其邻居节点的值域
Cutset conditioning(割集调整):实例化变量的一个集合,使剩余的约束图变成树
割集大小c → 运行时间O(d^c(n-c)d^2),对于很小的c速度很快
寻找一个最小的割集是个NP问题

CSP局部搜索
爬山、模拟退火工作于完全状态化的形式化,即所有已赋值的变量
应用于CSP:允许未满足约束的状态、操作对变量的值重新赋值
变量选择:对任意冲突的变量进行随机选择
最小冲突启发式变量选择:选择会造成与其他变量的冲突最小的值,如爬山h(n)=违背约束的总数

例子:4皇后问题
状态:4个皇后在棋盘的4列(4^4=256个状态)
行动:在列方向上移动皇后
目标测试:没有互相攻击的皇后
评价:h(n)=互相攻击的对数

最小冲突的性能评价
给定随机初始状态,可以在常数时间内解决任意大概率n值的n皇后问题
R=(number of constraints) / (number of variables)

例子:3-SAT问题
每个约束涉及3个变量。。。
加速1:模拟退火
思路:通过一些“坏”的行动来逃离局部最大值,但是逐渐降低它们的频率
If 新状态比现有状态好,移动到新状态
Else  以某个小于1的概率接受该移动,此概率随温度“T"降低而下降
加速2:最小最大值优化
Putweights on constraints
repeat
    Primal search: update assignment to minimize weighted violation, until stuck
    Dual step: update weights to increase weighted violation, until unstuck
until solution found, or bored

06 GAME PLAYING

博弈被认为是人工智能研究的一个很好的问题
博弈是不平凡的
- 玩家需要类似人类的智能
- 游戏可以很复杂(象棋、围棋等)
- 在有限的时间内需要作出决定
游戏通常是
- 明确的和可重复的
- 充满可观察和有限的环境
可以直接比较人类和计算机

Outline
- 游戏
- 最优策略
    - 极小极大算法
    - α-β剪枝
- 资源限制和近似评估
- 包含几率因素的游戏
- 不完全信息的游戏

游戏 vs. 搜索问题
- 不可预测的对手=>解决方案是对对手的每种可能的回应选择一种移动的策略
- 时间限制=>游戏对于低效率有严厉的惩罚

游戏的种类
                            确定型的                                     随机的
完全信息          象棋跳棋围棋奥赛罗                  西洋双陆棋
不完全信息    战列舰、盲的井棋           桥牌、扑克、拼字游戏核战争

博弈树(2个玩家、确定性、轮流)

确定性、两人制
- 一字棋、象棋、跳棋
- 游戏搜索
    - 状态空间搜索树
    - 玩家轮流
    - 每一层,包含一轮的移动
    - 选择移动到效用值最高的位置
- 零和游戏
    - 一个玩家最大化结果
    - 另一个玩家最小化结果

极大极小原则
- 假设双边玩家均作最优选择
- 计算机假设在它移动之后,对手会选择最小值的移动
- 计算机选择的最佳移动考虑了它的移动以及对手的最优移动

极大极小值
- 对确定性、完全信息博弈的最优策略
- 策略:选择移动到具有最高的极大极小值的位置,在对手也使用最优策略的条件下,能导致至少不比其它策略差的结果。
- 假设两个游戏者都按照最优策略进行,那么节点的极小极大值就是对应状态的效用值(对于MAX)
    - MAX优先选择有极大值的状态
    - MIN优先选择有极小值的状态
- MINMAX-VALUE(n)=
UTILITY(n) 当n为终止状态
max MINMAX-VALUE(s) 当n为MAX节点
min MINMAX-VALUE(s) 当n为MIN节点 

极大极小值算法
function MINIMAX-DECISION(state) returns an action
    inputs: state, current state in game
    return the a in ACTIONS(state) maximizing MIN-VALUE(RESULT(a,state))

function MAX-VALUE(state) returns a utility value
    if TERMINAL-TEST(state) then return UTILITY(state)
    v ← -∞
    for a, s in SUCCESSORS(state) do v ← MAX(v, MIN-VALUE(s))
    return v

function MIN-VALUE(state) returns a utility value
    if TERMINAL-TEST(state) then return UTILITY(state)
    v ← ∞
    for a, s in SUCCESSORS(state) do v ← MIN(v,MAX-VALUE(s))
    return v

性质
- 完备性:仅当树是有限的(国际象棋有特定的规则),在一个无限的树中甚至存在有限的策略
- 最优性:是的,对战一个最优策略的对手,不然呢
- 时间复杂度:O(b^m)
- 空间复杂度:O(bm) (深度优先搜索)

α-β剪枝
- 如果对战一个聪明的对手,博弈树的一些树枝不会被遍历到。
- 剪枝可以忽略一些树枝
- 为什么称为α-β
- α是到目前为止在路径上的任意选择点发现 的MAX的最佳(即最大值)选择,β的定义类似

α-β算法
function ALPHA-BETA-DECISION(state) returns an action 
    return the a in ACTIONS(state) maximizing MIN-VALUE(RESULT(a, state)

function MAX-VALUE(state,α,β) returns a utility value
    inputs: state, current state in game
        α, the value of the best alternative for MAX along the path to state
        β, the value of the best alternative for MIN along the path to state
    if TERMINAL-TEST(state) then return UTILITY(state)
    u ← -∞
    for a, s in SUCCESSORS(state) do 
        v ← MAX(v, MIN-VALUE(s,α,β))
        if v ≥ β then return v
        α ← MAX(α,v)
    return v

function MIN-VALUE(state,α,β) returns a utility value
    same as MAX-VALUE but with roles of α,β reversed

α-β的效率
- 效果取决于后继的检查顺序,如果最优的后继最先被检查则效果更好。
- 最坏的情况:
    - 顺序排列所以没有树枝被修剪
    - 对穷举算法没有改进
- 最好的情况:
    - 每个玩家的最优移动都被最先评价
- 在实践中,性能接近最佳,而不是最坏的

α-β的性质
- 剪枝不影响最后的结果
- 好的移动顺序提高了剪枝的效率
- 在好的移动顺序情况下,时间复杂度=O(b^(m/2))

资源限制
- 标准方法:有限深度搜索
    - 利用截断测试代替终止测试
        - 例如深度限制(可能增加静态搜索)
    - 利用可以估计棋局效用值的启发式评价函数EVAL取代效用函数
        - 即估计位置期望值的评价函数

评价函数
- 理想函数:返回位置的效用值
- 实际上:典型特征的线性加权和
   Eval(s)=w_1f_1(s)+w_2f_2(s)+...+w_nf_n(s)
- 越重要的特征,加权值越高
- 确定性博弈的结果作为一个序数效用函数

有限时间的解决
- 在实际游戏中,通常对每一步移动有个时间限制T
- 怎么考虑进去呢
    - 不能中途停止α-β,有信心利用期望的结果
    - 所以,我们可以设置一个保守的极限深度,保证我们会在小于T的时间内找到下一步
    - 但是,搜索可能会提前停止,进行更多搜索的机会被浪费掉了
- 实际中,常用迭代加深搜索(IDS)
    - 以逐渐增加的深度限制进行α-β搜索
    - 当时间到时,使用最后一次完成的α-β搜索的策略(即已完成的最深的搜索)

在实践中的确定性游戏
- 国际象棋:深蓝在1997年一场六局的比赛中打败人类世界冠军,深蓝每秒搜索2亿个位置,使用非常复杂的评估,并扩大到40层。
    - 计算机能够预见它的决策中的长期棋局序列。机器拒绝走一步有决定性短期优势的棋—显示了非常类似人类的对危险的感觉。
- 西洋跳棋:Chinook,世界人机跳棋冠军
    - Chinook在1994年结束了人类长达40年的世界冠军统治
    - 2007年,跳棋得到解决,最佳算法最终导致平局
    - Chinook不会输
    - 使用了一个提前计算好的存有443,748,401,247个不多于8个棋子的棋局数据库,使它的残局走棋没有缺陷
- 奥赛罗:人类冠军拒绝对战强大的电脑
- Go,围棋:人类冠军拒绝对战弱小的计算机。在围棋中,b>300(棋盘为19×19),所以大多数程序使用模式的知识基础,提出合理的动作。人工智能的试金石。
    - AlphaGl:首次在19×19的棋盘上打败人类
    - 谷歌电脑棋手DeepMind
    - 深度神经网络:
        - 价值网络:评价板的位置
        - 政策网络:选择移动
- 训练于:
        - 有监督的学习
        - 增强自我发挥学习
- 搜索算法
- 蒙特卡罗模拟+价值/政策网络

AlphaGo:背景
- 减少搜索空间
    - 减少深度
        - 位置评价
- 减少分支
    - 基于政策的移动采样
    - 政策=概率分布 p (a|s)

AlphaGo中的深度神经网络
- AlphaGo使用两种类型的神经网络
    - 政策网络:下一步的行动是什么
        - 从人类专家的行动学习
    - 价值网络:状态的值是什么
        - 利用政策网络从自我学习
- SL=监督学习,RL=强化状态

不确定的游戏:西洋双陆棋
- 在不确定的游戏中,机会由骰子、洗牌决定,简化的例子用掷硬币表示。
- 最大期望效用
    - 为什么对效用求平均,而不是极大极小值
    - 最大期望效用原则:一个agent应该根据其知识选择期望效用最大化的行为
    - 决策的一般原则
    - 经常作为理性的定义

不确定的游戏算法
- ......
if state is a chance node then
return average of EXPECTIMINIMAX-VALUE of SUCCESSORS(state)

随机的两个玩家
- TDGammon采用depth-2搜索+很好的eval函数+强化学习:世界冠军的水平
- 评价函数应该是棋局的期望效用值的正线性变换

不完全信息的游戏
- 例如,纸牌游戏,对手的初始牌未知,通常我们对每一次出牌计算一次概率值,就像游戏开始时有一个大骰子一样。
- 策略:在评价一个有未知牌的给定行动过程时,首先计算出每副可能牌的出牌行动的极小极大值,然后再用每副牌的概率来计算得到对所有发牌情况的期望值。

正确的分析
- 行动的价值是在所有的实际状态的平均值的直觉是错误的。
- 局部可观测性,行动的价值取决于信息的状态或agent所在的信度状态。
- 可以生成和搜索一棵信息状态树

计算机玩德克萨斯扑克

总结

- 游戏是非常有趣的工作
    - 完美是不可能实现的,必须近似
- 游戏的最好模型是搜索问题
    - 博弈搜索树表示电脑/对手的轮流移动
- 评价函数估计给定每个玩家的板的配置质量、
- 极大极小算法选择最佳移动的假设是对手总是选择最好的移动
- α-β是可以避免搜索树的很大一部分来深化搜索深度的算法—消除无关的子树以提高效率

搜索总结
- 无信息的搜索策略
    - 深度优先搜索(BFS),一致代价搜索,深度优先搜索(DFS),深度受限搜索,迭代加深的深度优先搜索
- 有信息的搜索策略
    - 最佳优先搜索:贪婪、A*
    - 局部搜索:爬山、模拟退火等
- 约束满足问题
    - 回溯=深度优先搜索的给每个节点分配一个变量
    - 增强:变量的顺序和值选择启发式,向前检查,约束传播

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页