Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 带Alpha-Beta剪枝的迭代深化Negamax_C++_Algorithm - Fatal编程技术网

C++ 带Alpha-Beta剪枝的迭代深化Negamax

C++ 带Alpha-Beta剪枝的迭代深化Negamax,c++,algorithm,C++,Algorithm,我的程序中有一个有效的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 IterativeDeepeni

我的程序中有一个有效的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_;
}
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函数在同一范围内的全局函数,因此它们可以检查经过的时间
时钟启动;
int迭代深化(电路板当前状态)
{
布尔超时=假;
int深度=0;
tStart=时钟();
搬家者最佳搬家(-1,克沃斯特估值);
while((静态转换(clock()-tStart)/每秒时钟数)
我想我也应该重新排序之前最好的移动到儿童列表的前面,然而,我正在等待实现,直到我得到基本版本的工作。实际的Alpha-Beta函数如下所示:

// 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_;
}
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;
}
MoveHolder AlphaBetaRoot(int alpha、int beta、int剩余深度、板当前状态、bool和超时)
{
移动支架最佳(-1,-1);
如果(加班)
返回移动保持器(0,0);
std::矢量电流_儿童;
当前_状态。GetBoardChildren(当前_子项);
用于(自动i:当前子项)
{
best.evaluation=-AlphaBeta(-beta,-alpha,剩余深度-1,i,超时);
if((静态转换(时钟()-tStart)/每秒时钟数)>kMaxTimePerMove)
{
超时=真;
返回移动保持器(0,0);
}
如果(最佳评估>=beta)
回报最好;
如果(最佳评估u>alpha)
{
alpha=最佳评价;
best.column=i.GetLastMoveColumn();
}
}
回报最好;
}
int AlphaBeta(int alpha、int beta、int剩余深度、Board2当前状态、bool和加班)
{
如果(加班)
返回0;
if((静态转换(时钟()-tStart)/每秒时钟数)>kMaxTimePerMove)
{
超时=真;
返回0;
}
if(剩余_深度==0 ||当前_状态。GetCurrentResult()!=kNoResult)
{
返回当前_状态。GetToMove()*当前_状态。GetCurrentEvaluation();
}
std::矢量电流_儿童;
当前_状态。GetBoardChildren(当前_子项);
用于(自动i:当前子项)
{
int分数=-AlphaBeta(-beta,-alpha,剩余深度-1,i,超时);
如果(分数>=beta)
{
返回β;
}
如果(分数>α)
{
α=分数;
}
}
返回α;
}
当我试着调试时,一切都像预期的那样工作。然而,当我使用迭代深化版本与常规alpha-beta实现对抗时,它总是失败。有时它看起来像是被“卡住”了,然后返回一个可怕的动作

例如,如果该程序在下一回合“被迫”移动,否则对手将获胜,它不会阻止获胜。在这一行动中,它报告说,它正在38米的深度进行搜索。我发现这个算法很难调试,因为如果我破坏了执行,它会破坏计时


我不确定我是否执行了错误的算法,或者这里有一个棘手的bug。如果有人能给我指出正确的方向,我会非常感激。

您正在使用
-best\u move.evaluation\u
作为搜索的beta值,其中
best\u move
是以前深度的最佳移动。这是不正确的:假设一个移动在深度=2时看起来不错,但在深度更大时却不好。这种方法将继续认为它是好的,并导致β截止,不应该发生在其他移动。 您应该搜索(-infinity,infinity)上的每个迭代来解决这个问题。您还可以使用来限制alpha-beta范围


请注意,由于您没有使用上一次迭代来改进下一次迭代的移动顺序,因此迭代深化将导致稍差的结果。理想情况下,您希望移动顺序从换位表和/或上一次迭代的主要变体中选择最佳移动。

您使用
-best\u move.evaluation\u
作为搜索的beta值,其中
best\u move
是从上一次深度开始的最佳移动。这是不正确的:假设一个移动在深度=2时看起来不错,但在深度更大时却不好。这种方法将继续认为它是好的,并导致β截止,不应该发生在其他移动。 您应该搜索(-infinity,infinity)上的每个迭代来解决这个问题。您还可以使用来限制alpha-beta范围


请注意,由于您没有使用上一次迭代来改进下一次迭代的移动顺序,因此迭代深化将导致稍差的结果。理想情况下,您希望移动顺序从换位表和/或上一次迭代的主要变体中选择最佳移动。

我也希望使用吸气窗口,但我有点困惑。这里说你应该使用
alpha=last_eval+window
,但不应该是
-window
,因为alpha是你能达到的最小值。我发现很难找到好的源代码和示例,也许这只是一个坏的源代码


在PVS算法中,我们还研究了
分数>α和分数
的时间。但在这一来源中,它说的是
scorebeta
。这对我来说更有意义。但是为什么这些条件不同呢?

我也想使用吸气窗口,但我有点困惑。这里说你应该使用
alpha=last\u eval+window
,但它不应该是
-window