使用Alpha-Beta修剪的迭代深化Negamax
Iterative Deepening Negamax with Alpha-Beta Pruning
我的程序中有一个有效的negamax算法。然而,我需要程序在kMaxTimePerMove
时间内找到最佳移动。我做了一些研究,似乎在negamax算法中使用迭代深化是最好的方法
// this is a global in the same scope as the alpha-beta functions, so they can check the elapsed time
clock_t tStart;
int IterativeDeepening(Board current_state)
{
bool overtime = false;
int depth = 0;
tStart = clock();
MoveHolder best_move(-1, kWorstEvaluation);
while ((static_cast<double> (clock() - tStart)/CLOCKS_PER_SEC) < kMaxTimePerMove)
{
MoveHolder temp_move = AlphaBetaRoot(kWorstEvaluation, -best_move.evaluation_,++depth, current_state, overtime);
if (!overtime)
best_move = temp_move;
}
return best_move.column_;
}
我认为我也应该将之前的最佳移动重新排序到儿童列表的前面,然而,我正在等待实现它,直到我的基本版本开始工作。实际的Alpha Beta功能如下所示:
MoveHolder AlphaBetaRoot(int alpha, int beta, int remaining_depth, Board current_state, bool &overtime)
{
MoveHolder best(-1, -1);
if (overtime)
return MoveHolder(0,0);
std::vector<Board> current_children;
current_state.GetBoardChildren(current_children);
for (auto i : current_children)
{
best.evaluation_ = -AlphaBeta(-beta, -alpha, remaining_depth - 1, i, overtime);
if ((static_cast<double> (clock() - tStart)/CLOCKS_PER_SEC) > kMaxTimePerMove)
{
overtime = true;
return MoveHolder(0,0);
}
if (best.evaluation_ >= beta)
return best;
if (best.evaluation_ > alpha)
{
alpha = best.evaluation_;
best.column_ = i.GetLastMoveColumn();
}
}
return best;
}
int AlphaBeta(int alpha, int beta, int remaining_depth, Board2 current_state, bool &overtime)
{
if (overtime)
return 0;
if ((static_cast<double> (clock() - tStart)/CLOCKS_PER_SEC) > kMaxTimePerMove)
{
overtime = true;
return 0;
}
if (remaining_depth == 0 || current_state.GetCurrentResult() != kNoResult)
{
return current_state.GetToMove() * current_state.GetCurrentEvaluation();
}
std::vector<Board> current_children;
current_state.GetBoardChildren(current_children);
for (auto i : current_children)
{
int score = -AlphaBeta(-beta, -alpha, remaining_depth - 1, i, overtime);
if (score >= beta)
{
return beta;
}
if (score > alpha)
{
alpha = score;
}
}
return alpha;
}
当我尝试调试时,一切似乎都如预期的那样工作。然而,当我让迭代深化版本与常规的alpha-beta实现对抗时,它总是失败。有时,它似乎被"卡住"了,然后做出了可怕的举动。
例如,如果该程序在下一个回合"被迫"移动,否则对手将获胜,则不会阻止获胜。据报道,在这一行动中,它正在搜索到38深处。我发现算法极难调试,因为如果我中断执行,就会破坏时间。
我不确定我是错误地实现了算法,还是这里有一个棘手的错误。如果有人能为我指明正确的方向,我将不胜感激
您使用-best_move.evaluation_
作为搜索的beta值,其中best_move
是上一深度的最佳移动。这是不对的:假设一个动作在深度=2时看起来不错,但在更大的深度时却不好。这种方法将继续被认为是好的,并导致测试版的中断,这在其他移动中是不应该发生的。
您应该在(-ninfinity,infinity)上搜索每个迭代来解决这个问题。您也可以使用抽吸窗口来限制α-β范围。
请注意,由于您没有使用上一次迭代来改进下一次迭代的移动顺序,因此迭代深化将导致稍差的结果。理想情况下,您希望移动排序从换位表和/或上一次迭代的主要变体中选择最佳移动。
相关文章:
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 迭代时从向量和内存中删除对象
- 如何在c++迭代器类型中包装std::chrono
- 带过滤器的现代迭代c++集合
- 在c++中检查长方体是否尽可能快地重叠(无迭代)
- C++矢量迭代
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 擦除while循环中迭代的元素
- 实现一个在集合上迭代的模板函数
- 对于set上的循环-获取next元素迭代器
- 在向量内的向量上迭代
- 为什么output_editor Concept不需要output_e迭代器标记
- TSP递归解的迭代形式
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 使用Alpha-Beta修剪的迭代深化Negamax