我试图用转置表实现alpha beta修剪,我在维基百科中找到了算法的伪代码:https://en.wikipedia.org/wiki/Negamax#cite_note-Breuker-1 但是我相信这个psudocode是错误的,我认为alphaOrig是没用的,而不是:
if bestValue ≤ alphaOrig
ttEntry.Flag := UPPERBOUND
应该是:
if bestValue ≤ α
ttEntry.Flag := UPPERBOUND
任何人都可以确认我是对的还是向我解释为什么我错了,谢谢!
这里是伪代码:
function negamax(node, depth, α, β, color)
alphaOrig := α
// Transposition Table Lookup; node is the lookup key for ttEntry
ttEntry := TranspositionTableLookup( node )
if ttEntry is valid and ttEntry.depth ≥ depth
if ttEntry.Flag = EXACT
return ttEntry.Value
else if ttEntry.Flag = LOWERBOUND
α := max( α, ttEntry.Value)
else if ttEntry.Flag = UPPERBOUND
β := min( β, ttEntry.Value)
endif
if α ≥ β
return ttEntry.Value
endif
if depth = 0 or node is a terminal node
return color * the heuristic value of node
bestValue := -∞
childNodes := GenerateMoves(node)
childNodes := OrderMoves(childNodes)
foreach child in childNodes
v := -negamax(child, depth - 1, -β, -α, -color)
bestValue := max( bestValue, v )
α := max( α, v )
if α ≥ β
break
// Transposition Table Store; node is the lookup key for ttEntry
ttEntry.Value := bestValue
if bestValue ≤ alphaOrig
ttEntry.Flag := UPPERBOUND
else if bestValue ≥ β
ttEntry.Flag := LOWERBOUND
else
ttEntry.Flag := EXACT
endif
ttEntry.depth := depth
TranspositionTableStore( node, ttEntry )
return bestValue
答案 0 :(得分:2)
有可用的转置表进行alpha beta修剪的不同实现。例如来自Marsland的那个:A REVIEW OF GAME-TREE PRUNING,Breuker:Memory versus Search in Games和Carolus:Alpha-Beta with Sibling Prediction Pruning in Chess
对于我的回答,我将引用Talk:Negamax页面的片段:
当Breuker中的alphaOrig在转置表查找后(而不是之前)存储α时,Marsland转置表逻辑是等效的。但是在negamax函数调用期间考虑以下情况:
- 转置表查找更新α,因为它是“下限”(Breuker:
alphaOrig < α
Marsland:alphaOrig = α
)- 移动评估返回与未更改
α
相同的bestValue(得分)- 使用相同的bestValue(得分)
更新节点的转置表条目在Breuker的逻辑中,节点的转置表条目将更新为“exact”标志(自
alphaOrig < bestValue < β
起)。在Marsland中,更新将具有“上限”标志(自score ≤ α
起)。最佳地,分数的标志应该是“精确的”而不是在上限和下限之间交替。所以我认为Breuker的版本更好? 在卡罗勒斯,没有alphaOrig,没有相应的东西。移动评估期间的alpha更新。在这种情况下,在移动评估之后,最好永远不会大于alpha,并且为转置表条目设置“exact”标志是不可能的。
在Negamax文章的谈话页面上有更多关于此的讨论。