如何解决通过迭代加深实现Minimax搜索
我在做什么:我正在用C ++编写国际象棋引擎。我最近更新了引擎的minimax搜索算法,该算法使用alpha-beta修剪功能来利用迭代加深,以便可以在时间限制下播放。看起来是这样:
//I return a string,int pair. The string represents the best move found,while the int represents the engine evaluation for the node after said move is made
static std::pair<string,int> iterativeDeepeningSearch(Board initialPosition,int maxDepth,milliseconds maxSearchTime)
{
std::pair<string,int> bestMove;
milliseconds startTime = duration_cast<milliseconds>(
system_clock::Now().time_since_epoch());
for (int currentDepth = 1; currentDepth <= maxDepth; currentDepth++)
{
milliseconds currentTime = duration_cast<milliseconds>(
system_clock::Now().time_since_epoch());
if (currentTime > startTime + maxSearchTime)
{
return bestMove;
}
std::pair<string,int> bestMoveFoundFromMinimax = minimax(initialPosition,currentDepth,INT_MIN,INT_MAX,"",startTime + maxSearchTime);
if (bestMoveFoundFromMinimax.first != "") {
bestMove = bestMoveFoundFromMinimax;
}
}
return bestMove;
}
我的问题:此实现的问题是,当以任何大于1的深度进行搜索时,它将在搜索所需深度之前先搜索所有先前的深度。也就是说,此迭代加深搜索首先搜索深度1处的所有移动。然后,它不再搜索下一次搜索的深度2,而是再次搜索深度1 ,然后搜索深度2。将在搜索深度3之前先搜索深度1和2。依此类推。
我的问题:这应该是迭代加深的工作方式吗?每次增加深度时,我们也会搜索所有父节点吗?我以为每次我们增加深度时,它只会搜索新深度的所有同级节点。如果实际上这是迭代加深的工作方式,那么如何只搜索新的深度而不搜索所有父节点呢?
我的迭代加深极小值是每次我们增加深度时,将整棵树搜索到给定深度:
我期望随着迭代加深的minimax每次增加深度时仅搜索新深度:
作为参考,这是我的(草率的)利用alpha beta修剪的minimax函数:
static std::pair<string,int> minimax(Board node,int depth,int alpha,int beta,string move,string firstMove,milliseconds breakOffTime)
{
if (breakOffTime != std::chrono::milliseconds(0))
{
milliseconds currentTime = duration_cast<milliseconds>(
system_clock::Now().time_since_epoch());
if (currentTime > breakOffTime)
{
return std::make_pair("",0);
}
}
Moves &moves = Moves::getInstance();
if (moves.isCheckmate(node))
{
if (node.getWhitetoMove())
{
return std::make_pair(firstMove,INT_MIN);
}
else
{
return std::make_pair(firstMove,INT_MAX);
}
}
if (depth == 0)
{
return std::make_pair(firstMove,rating::getCentipawnValue(node));
}
if (node.getWhitetoMove())
{
string bestMove = firstMove;
int bestValue = INT_MIN;
string pseudoLegalMoves = moves.pseudoLegalMovesW(node);
if (pseudoLegalMoves.length() == 0)
{
return std::make_pair(firstMove,0);
}
for (int i = 0; i < pseudoLegalMoves.length(); i += 4)
{
string individualMoveString;
individualMoveString += pseudoLegalMoves[i];
individualMoveString += pseudoLegalMoves[i + 1];
individualMoveString += pseudoLegalMoves[i + 2];
individualMoveString += pseudoLegalMoves[i + 3];
Board tNode = moves.makeMoveAll(node,individualMoveString);
if ((moves.unsafeForWhite(tNode) & tNode.getWK()) == 0)
{
std::pair<string,int> ab;
if (firstMove == "")
{
ab = minimax(tNode,depth - 1,alpha,beta,individualMoveString,breakOffTime);
}
else
{
ab = minimax(tNode,firstMove,breakOffTime);
}
int val = ab.second;
string move = ab.first;
if (val > bestValue || (val == bestValue && bestMove == ""))
{
bestValue = val;
bestMove = move;
}
alpha = max(alpha,bestValue);
if (alpha >= beta)
{
break;
}
}
}
return std::make_pair(bestMove,bestValue);
}
else
{
string bestMove = firstMove;
int bestValue = INT_MAX;
string pseudoLegalMoves = moves.pseudoLegalMovesB(node);
if (pseudoLegalMoves.length() == 0)
{
return std::make_pair(firstMove,individualMoveString);
if ((moves.unsafeForBlack(tNode) & tNode.getBK()) == 0)
{
std::pair<string,breakOffTime);
}
int val = ab.second;
string move = ab.first;
if (val < bestValue || (val == bestValue && bestMove == ""))
{
bestValue = ab.second;
bestMove = ab.first;
}
beta = min(beta,bestValue);
}
}
此外,如果有人感兴趣,这是我的完整项目:https://github.com/ChopinDavid/Maestro-cpp
我不是C ++开发人员,所以可能很累。
解决方法
这应该是迭代加深的工作方式吗?每次增加深度时,我们也会搜索所有父节点吗?
是的-但是,由于在进行迭代加深时会保存先前搜索中的最佳移动,并且会先尝试向下移动这些移动,因此您经常会在每个级别的第一移动中找到最佳移动,因此修剪将非常有效。
如何只搜索新深度而不搜索所有父节点呢?
如果这是您想要的,则可以放弃迭代加深,而只搜索所需的深度-但这可能是一个错误。在寻求该解决方案之前,计算经过迭代和不进行迭代加深的评估板的数量。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。