当前位置: 首页 > 知识库问答 >
问题:

带换位表的α-β剪枝,迭代深化

瞿文柏
2023-03-14

我正在尝试用换位表实现增强的α-β-最小-最大修剪。我使用这个伪代码作为参考:

http://people.csail.mit.edu/plaat/mtdf.html#abmem

function AlphaBetaWithMemory(n : node_type; alpha , beta , d : integer) : integer;
    if retrieve(n) == OK then /* Transposition table lookup */
        if n.lowerbound >= beta then return n.lowerbound;
        if n.upperbound <= alpha then return n.upperbound;
        alpha := max(alpha, n.lowerbound);
        beta := min(beta, n.upperbound);
    if d == 0 then g := evaluate(n); /* leaf node */
    else if n == MAXNODE then
        g := -INFINITY; a := alpha; /* save original alpha value */
        c := firstchild(n);
        while (g < beta) and (c != NOCHILD) do
            g := max(g, AlphaBetaWithMemory(c, a, beta, d - 1));
            a := max(a, g);
            c := nextbrother(c);
    else /* n is a MINNODE */
        g := +INFINITY; b := beta; /* save original beta value */
        c := firstchild(n);
        while (g > alpha) and (c != NOCHILD) do
            g := min(g, AlphaBetaWithMemory(c, alpha, b, d - 1));
            b := min(b, g);
            c := nextbrother(c);

    if g <= alpha then 
        n.upperbound := g; 
        store n.upperbound;
    if g >  alpha and g < beta then
        n.lowerbound := g; 
        n.upperbound := g; 
        store n.lowerbound, n.upperbound;
    if g >= beta then 
        n.lowerbound := g; 
        store n.lowerbound;
return g;

这个算法有三个问题:

>

  • 我相信我应该在每个保存的换位表条目中存储深度(=到叶级的距离),并且仅在 entry.depth 时才使用条目

    我想存储每个位置的最佳移动,以便在搜索停止后使用它进行移动排序和提取最佳移动。在纯最小值-最大值中,哪一步是最好的是显而易见的,但是当迭代α-β截止点时,哪一步是最好的呢?我可以假设给定位置的最佳移动是循环结束时找到的最佳移动(有或没有截止)吗?

    当在迭代深化方案中执行此算法时,我应该在每次深度增加之前清除换位表吗?我想不是,我想使用上一次迭代中的存储位置,但我不确定信息是否足以进行更深入的搜索(应该是在检查表条目深度时)?

  • 共有1个答案

    郎意
    2023-03-14

    >

  • 你是对的。entry.depth存储了换位表条目中信息所基于的层数。因此,您只能在entry.depth

    逻辑是,我们不想使用比“正常”搜索弱的结果。

    有时,出于调试目的,条件更改为:

    entry.depth == remaining_depth
    

    这避免了一些搜索不稳定性。无论如何,它不能保证没有换位表的搜索结果相同。

    并不总是有最好的存储方式。

    当搜索失败时,没有“最佳移动”。我们唯一知道的是,没有一个动作足够好,可以产生比alpha更大的分数。没有办法猜测哪一步是最好的。

    因此,您应该将移动存储在哈希表中,仅用于较低的边界(β截止值,即反驳移动)和精确的分数(PV节点)。

    不,你不应该。通过迭代深化,一次又一次地到达相同的位置,换位表可以加快搜索速度。

    您应该在移动之间清除转置表(或者,更好的是使用额外的 entry.age 字段)。

  •  类似资料:
    • 我在为游戏筷子做一个C程序。 这是一个非常简单的游戏,总共只有625个游戏状态(如果考虑到对称性和不可到达的状态,它甚至更低)。我读过minimax和alpha-beta算法,主要是针对tic-tac-toe的,但我遇到的问题是,在tic-tac-toe中,不可能循环回到以前的状态,而这在筷子中很容易发生。因此,当运行代码时,它将以堆栈溢出结束。 我通过添加以前访问过的州的标志来解决这个问题(我不

    • 我不明白为什么表条目的标志被原样使用。例如,考虑具有α-β修剪和转置表的Negamax的伪代码,并集中于TT部分。 没关系。如果条目包含确切值的下限,我们尝试从左侧缩小窗口,依此类推。 而这部分我不明白。如果值太小,为什么我们设置上限标志?值位于搜索窗口的左侧 - 它小于已知的下限 - alpha。所以看起来值应该是一个下限。 从我的测试和每个人都使用那个版本的事实来看,我肯定是错的。但我不明白为

    • 如何知道何时可以停止增加使用negamax alpha beta修剪和换位表的迭代深化算法的深度?以下伪代码取自wiki页面: 这是迭代深化调用: 当然,当我知道游戏中的总移动次数时,我可以使用深度

    • 我正在研究一个简单的tic-tac-toe问题,我正在努力理解Minimax算法是如何工作的。 如果我使用效用函数1表示X win,-1表示O win,0表示正在进行的游戏,那么我不明白算法如何优先考虑较短的解决方案。据我所知,它首先到达最深的节点,如果它不是最短的路径,但它会导致可能的胜利,那么它会选择它。 让我在例子中解释一下。这是电路板的状态和X转角(符号来自https://www.hack

    • 我在网上看到过minimax和alpha-beta修剪算法的实现。这些实现使用数组而不是树结构来生成可能的游戏动作。 有必要为这些算法创建一棵树,使用带节点的结构吗?为什么使用数组来存储游戏树?

    • 我的程序中有一个有效的negamax算法。然而,我需要程序在时间内找到最佳移动。我做了一些研究,似乎用我的negamax算法进行迭代深化是最好的方法。现在,我启动搜索的函数如下所示: 我想我也应该重新排序之前的最佳移动到儿童列表的前面,但是,我在等待实现,直到我得到基本版本的工作。实际的阿尔法-贝塔函数是这样的: 当我尝试调试时,一切似乎都在按预期工作。然而,当我将迭代深化版本与常规的alphab