• 极小化极大估计


    上图中第0层为空棋盘,第1层是×方所有可能的步骤,第2层是〇方所有可能的步骤。
    在第1层,×方需要选择使其优势最大的选择,而在第2层,〇方则需要选择使×方优势最小即己方优势最大的选择。
    Minimax的含义就是极小化对手的最大利益,在上图中,在第2层〇方一定会选择使自己优势最大的选择,而对于×方需要做的就是选择〇方最大选择中的极小值。

    以上内容来源于百度百科,作为引子。
    假如下棋,平均敌对两方平均可以下50步,那么博弈树的深度,就有100层,即deepth=100;
    假如每一层,能平均衍生出10种局势,即b=10,那么最终棋局有10的100种;
    假如,在某层,棋局的值是可以量化的,使用s = g(f1,f2,....fn)来表示,(f1~fn可能是重要棋子的数量,紧密度等等);
    s越大,代表一方胜利可能性越大;反之,s越小,则代表另一方胜利的可能性越大;

    假如棋局进行到某一步,只需要预测到,下一层,哪一个方向更合适;

    那么,如果直到最后的各个“局势”值,那么就可以逆回去,“综合”求得,当前应该选哪一个方向。

    如何用算法,表现这个过程??

    如果棋局进行到2层A处,轮到极小者玩家下棋,那么极小值玩家,肯定会偏向2;

    如果棋局进行到2层B处,轮到极小者玩家下棋,那么极小值玩家,肯定会偏向1;

    那么在1层C处,轮到极大值玩家下棋,他只能选择往A,因为选择往B,轮到极小者玩家下棋时,必定选1;

    所以如果极大者玩家,他最优的选择是A;


    alpha-beta 剪枝

    就是优化算法,不对deepth处所有的节点进行遍历计算

    function alphabeta(node, depth, α, β, Player)         
        if  depth = 0 or node is a terminal node
            return the heuristic value of node
        if  Player = MaxPlayer // 极大节点
            for each child of node // 极小节点
                α := max(α, alphabeta(child, depth-1, α, β, not(Player) ))   
                if β ≤ α // 该极大节点的值>=α>=β,该极大节点后面的搜索到的值肯定会大于β,因此不会被其上层的极小节点所选用了。对于根节点,β为正无穷
                    break                             (* Beta cut-off *)
            return α
        else // 极小节点
            for each child of node // 极大节点
                β := min(β, alphabeta(child, depth-1, α, β, not(Player) )) // 极小节点
                if β ≤ α // 该极大节点的值<=β<=α,该极小节点后面的搜索到的值肯定会小于α,因此不会被其上层的极大节点所选用了。对于根节点,α为负无穷
                    break                             (* Alpha cut-off *)
            return β 
    (* Initial call *)
    alphabeta(origin, depth, -infinity, +infinity, MaxPlayer)

    *每一个node,就是一个局势,一种下一步要落棋子的局势。虽然可以对小于deepth的Node,求得s,但是显然没看到最后,暂时s是极大或极小,不代表后边不能走向相反的结果;

    *算法本身是返回node的值,所以,对于A点,需要获得B,C的值,然后选择最大的值,作为“下一步棋”;

    直接以A的Node调用,看看如何“裁枝”,提高效率

    参考:  https://blog.csdn.net/joshualiunsw/article/details/52131507

    当遍历到I节点的时候,刚遍历完Q,得到3;

    按照算法,I节点获得β=3,那他的下一个分支,目标是找≤3,找不到就用β=3做为I处的值;

    同时,知道对手,想要使得a≥7;因为β=3<a足够阻止对手,所以不用看R了;

     当遍历到E节点的时候,刚遍历完J,得到8;

    按照算法,J节点获得a=8,那他的下一个分支,目标是找≥8,找不到就用a=8做为J处的值;

    同时,知道对手,想要使得β≤7;因为a=8>β足够阻止对手,所以不用看J1了;

    一句话,知道上一步对手想要什么,自己先遍历一侧得到的值,足以阻止对手的话,另一侧就不用遍历了;

  • 相关阅读:
    继承关系·
    对象第复制operator=
    关于类拷贝造函数
    静态数据成员与静态成员函数
    linux新内核的时钟机制代码
    RTC系统
    Android关机闹钟实现
    更改printk打印级别
    vncserver 配置全屏显示
    vnc里鼠标拖动终端就会产生ctrl+c终端
  • 原文地址:https://www.cnblogs.com/pylblog/p/10304632.html
Copyright © 2020-2023  润新知