关于置换表的疑惑(国际象棋编程)

4

我目前在使用置换表进行移动排序。 使用迭代加深搜索,我存储先前迭代的极小极大值,以便为下一次迭代排序移动。这一切都很好。

以下是我的困惑:

如果我在置换表中找到某个位置,则会使用先前计算的得分进行移动排序(来自迭代加深的先前迭代)。 但是,如果此位置的得分已更新(在极小极大返回后),并且在另一个子树中再次找到该位置(迭代加深的同一次迭代)-我不想仅将其用于移动排序……我应该能够返回该值,因为该值现在已经计算出来,并且是绝对的。

这是我的问题:是否有两个置换表是标准的? 一个用于先前的迭代,一个用于当前的迭代加深。 因此,我首先会检查当前迭代的表,看是否已经计算了极小极大值,然后简单地返回此值。 如果不在该表中,则会使用先前迭代的表进行移动排序。 如果在两者中都不存在,则是我在这次搜索中尚未见过的新位置。

这种思路正确吗? 还是有更有效的方法?


这个问题可能会太宽泛/基于观点。我会说值得尝试一下。如果它能帮助你在更短的时间内获得更多的棋谱,那就太好了。如果不行,那就放弃吧。以前有一个国际象棋程序员的新闻组。也许可以试着找到它并在那里提问。这不是这种问题的适当场所。 - Edward Strange
感谢您的快速回复。 - SethCS
2个回答

3

通常情况下,您不仅需要在表格中存储状态的最后找到的极小化值,还要存储在迭代过程中存储状态时使用的深度限制。这样,当您稍后在表格中查找它时,可以通过将表格条目中存储的深度限制与当前深度限制进行比较来判断它是在上一次迭代中还是在当前迭代中最近更新的状态。如果它们相等,您就知道表格条目是在当前迭代中最近更新的,并且可以直接使用表格中存储的值而无需进行任何额外的搜索。


2
我同意 @Dennis_Soemers 的观点。你应该在置换表中保存深度甚至是alpha/beta边界。不,你不需要两个表。
让我们检查一下Stockfish源代码上的这个表。

https://github.com/official-stockfish/Stockfish/blob/master/src/tt.h

/// TTEntry struct is the 10 bytes transposition table entry, defined as below:
///
/// key        16 bit
/// move       16 bit
/// value      16 bit
/// eval value 16 bit
/// generation  6 bit
/// bound type  2 bit
/// depth       8 bit

该表格的保存功能定义如下:
void save(Key k, Value v, Bound b, Depth d, Move m, Value ev, uint8_t g) 

现在,如果您有两个相同的位置,来自深度为d-1d。您可以执行以下操作:
// My hash key is now position + depth
Key my_hash_key = k + d

您可以轻松地检查上一次迭代和当前迭代:
Key previous_iter_key = my_position_key + d-1
probe(previous_iter_key ...)

Key current_iter_key = my_position_key + d
probe(current_iter_key ...)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接