国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于博弈樹(shù)的開(kāi)源五子棋AI教程[7 多線程搜索]

這篇具有很好參考價(jià)值的文章主要介紹了基于博弈樹(shù)的開(kāi)源五子棋AI教程[7 多線程搜索]。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

引子

多線程加快搜索速度這一認(rèn)知是經(jīng)受住實(shí)踐考驗(yàn)的。博弈樹(shù)搜索的并行搜索方式有很多種,例如葉子并行,根并行,樹(shù)分裂等算法。筆者給出一種實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單的根并行算法。
在是實(shí)現(xiàn)時(shí)需要注意兩點(diǎn),第一,怎么安全的剪枝;第二,如何進(jìn)行線程間的通信。對(duì)于AB剪枝有三點(diǎn)發(fā)現(xiàn)可以指導(dǎo)我們?cè)O(shè)計(jì)多線程的并行算法:

  1. 當(dāng)某一節(jié)點(diǎn)搜索完成,其分?jǐn)?shù)才能安全的更新父親節(jié)點(diǎn)的AB值。
  2. 一個(gè)節(jié)點(diǎn)的AB值可以安全的更新其所有子孫節(jié)點(diǎn)的AB值。
  3. 如果一個(gè)節(jié)點(diǎn)alpha >= beta, 這個(gè)節(jié)點(diǎn)可以安全的被剪枝

這樣一來(lái),就可以知道一個(gè)節(jié)點(diǎn)搜索完成后,如何更新博弈樹(shù)所有節(jié)點(diǎn)的AB值,如何剪枝。通信方式使用的全局變量+讀寫(xiě)鎖控制的,全局變量保存所有節(jié)點(diǎn)狀態(tài)的AB值。當(dāng)搜索開(kāi)始,從根節(jié)點(diǎn)沿著搜索路徑開(kāi)始更新沿路的所有節(jié)點(diǎn)AB值,然后從全局變量中讀取該節(jié)點(diǎn)的AB值。搜索完成后,更新父親節(jié)點(diǎn)AB值。

定義

struct parallelNABSearchNode{
    int alpha, beta;
    parallelNABSearchNode() : alpha(-INT_MAX), beta(INT_MAX){}
    parallelNABSearchNode(int aalpha, int abeta) : alpha(aalpha), beta(abeta){}
    QString str();
    //返回值:true已經(jīng)更新,false表示沒(méi)更新
    bool getAlphaBeta(int &aalpha, int &abeta);

    bool updateLeaf2RootAlphaBeta(int score);

    //返回值:true已經(jīng)更新,false表示沒(méi)更新
    bool updateRoot2LeafAlphaBeta(int aalpha, int abeta);
};
    //并行化搜索技術(shù)
    static QReadWriteLock parallelSearchTableLock;
    static QHash<quint64, parallelNABSearchNode> parallelSearchTable;

函數(shù)實(shí)現(xiàn)三個(gè)方法,一個(gè)getAlphaBeta(int &aalpha, int &abeta)是從全局變量中獲取AB值,一個(gè)updateLeaf2RootAlphaBeta是從更新該節(jié)點(diǎn)的父親的AB值,還有一個(gè)updateRoot2LeafAlphaBeta是更新兒子節(jié)點(diǎn)的AB值。

bool parallelNABSearchNode::getAlphaBeta(int &aalpha, int &abeta){
    if(!globalParam::utilGameSetting.IsOpenParallelSearch) return false;
    if(aalpha >= alpha && beta >= abeta) return false;
    if(aalpha < alpha){
        aalpha = alpha;
    }
    if(beta < abeta){
        abeta = beta;
    }
    return true;
}
bool parallelNABSearchNode::updateLeaf2RootAlphaBeta(int score){
    if(!globalParam::utilGameSetting.IsOpenParallelSearch) return false;
    if(score > alpha){
        alpha = score;
        return true;
    }
    return false;
}
bool parallelNABSearchNode::updateRoot2LeafAlphaBeta(int aalpha, int abeta){
    if(!globalParam::utilGameSetting.IsOpenParallelSearch) return false;
    if(alpha >= aalpha && abeta >= beta) return false;
    if(alpha < aalpha){
        alpha = aalpha;
    }
    if(abeta < beta){
        beta = abeta;
    }
    return true;
}

實(shí)現(xiàn)

現(xiàn)在已經(jīng)實(shí)現(xiàn)了線程間通信的工具,只需要在搜索時(shí)調(diào)用這些利器就可以了,總體的實(shí)現(xiàn)思路和常規(guī)負(fù)極大搜索如出一撤。為了能后續(xù)兼容樹(shù)分裂的算法,這里給出了并行化搜索指定深度的接口。

//fail-soft negMax Alpha-Beta pruning search
int GameAI::NABParallelSearch(int depth, int alpha, int beta, bool maximizingPlayer, quint8 searchSpaceType)
{
    int score = -INT_MAX;
    QWriteLocker writeLock(&globalParam::parallelSearchTableLock);
    // 更新根節(jié)點(diǎn)->當(dāng)前節(jié)點(diǎn)搜索路徑上AB值
    for(int pid = 0;pid < parallelSsearchHistoryPlayersHash.size() - 1; ++pid){
        //表項(xiàng)不存在會(huì)自動(dòng)調(diào)用默認(rèn)構(gòu)造函數(shù)
        parallelNABSearchNode *curNode = &globalParam::parallelSearchTable[parallelSsearchHistoryPlayersHash[pid]];
        parallelNABSearchNode *sontNode = &globalParam::parallelSearchTable[parallelSsearchHistoryPlayersHash[pid + 1]];
        //更新下一層的AB值
        sontNode->updateRoot2LeafAlphaBeta(- curNode->beta, - curNode->alpha);
    }
    // 獲取當(dāng)前AB值
    globalParam::parallelSearchTable[zobristSearchHash.hash()].getAlphaBeta(alpha, beta);
//    // 更新AB值后可能引發(fā)剪枝
//    if(alpha >= beta){   // AB剪枝
//        aiCalInfo.cutTreeTimesCurrentTurn ++;
//        return beta;
//    }
    writeLock.unlock();

    //探查置換表中值
    if(zobristSearchHash.getNABTranspositionTable(score, depth, alpha, beta)) {
        return score;
    }

    // ??或 分?jǐn)?shù)過(guò)大過(guò)小
//    if (qAbs(score) > globalParam::utilGameSetting.MaxScore){
//        //保存置換表
//        return score;
//    }

    int evalPlayer = globalParam::AIPlayer;
    MPlayerType searchPlayer = maximizingPlayer ? evalPlayer : UtilReservePlayer(evalPlayer);

    // 達(dá)到搜索深度
    if (depth == 0 || checkSearchBoardWiner() != PLAYER_NONE){
        //保存置換表
        score = evaluateBoard(evalPlayer);//負(fù)極大搜索中評(píng)估必須searchPlayer
        if(!maximizingPlayer) score *= -1;

//        //VCF
//        QList<MPoint> vcf, vcfpath;
//        if(VCXSearch(globalParam::utilGameSetting.MaxVctSearchDepth, maximizingPlayer, VCT_SEARCH, vcf, vcfpath)){
//            qDebug() << "NABsearch : find vct";
//            if(maximizingPlayer) return globalParam::utilGameSetting.MaxScore;
//            else return -globalParam::utilGameSetting.MaxScore;
//        }
        return score;
    }

    // 著法生成
    QVector<MPoint> searchPoints;
    getSortedSearchSpace(searchPoints, evalPlayer, searchPlayer, searchSpaceType);

    int scoreBest = -INT_MAX;
    int hashf = hashfUperBound;
    MPoint moveBest(InvalidMPoint);
    quint16 savedSearchBoardPatternDirection[boardSize][boardSize];

    for (const auto &curPoint : searchPoints) {
        if (!searchBoardHasPiece(curPoint)) {
            setSearchBoard(curPoint, searchPlayer, savedSearchBoardPatternDirection);// searchPlayer落子
            score = -NABParallelSearch(depth - 1, -beta, -alpha, !maximizingPlayer,searchSpaceType);
            setSearchBoard(curPoint, PLAYER_NONE, savedSearchBoardPatternDirection);// 撤銷落子

            if (score > scoreBest) {
                scoreBest = score;
                moveBest = curPoint;
                if (score >= beta) {
                    hashf = hashfLowerBound;
                    appendSearchKillerTable(curPoint, depth, hashf);
                    aiCalInfo.cutTreeTimesCurrentTurn ++;
                    break; // Alpha-Beta 剪枝
                }
                if (score > alpha) {
                    alpha = score;
                    hashf = hashfExact;

                    //更新當(dāng)前層的AB值
                    writeLock.relock();
                    parallelNABSearchNode *curNode = &globalParam::parallelSearchTable[zobristSearchHash.hash()];
                    curNode->alpha = scoreBest;
                    writeLock.unlock();
                }
            }
        }
    }

//    writeLock.relock();
//    //更新當(dāng)前層的AB值
//    parallelNABSearchNode *curNode = &globalParam::parallelSearchTable[zobristSearchHash.hash()];
//    curNode->alpha = scoreBest;
//    writeLock.unlock();
    writeLock.relock();
    //更新上一層的AB值:只有當(dāng)前所有節(jié)點(diǎn)搜索完成后,得到的值才是可靠的,才能用來(lái)更新父親節(jié)點(diǎn)的AB值
    if(parallelSsearchHistoryPlayersHash.size() >= 2){
        const quint64& fatherHash = parallelSsearchHistoryPlayersHash[parallelSsearchHistoryPlayersHash.size()-2];
        parallelNABSearchNode *fatherNode = &globalParam::parallelSearchTable[fatherHash];
        fatherNode->updateLeaf2RootAlphaBeta(-scoreBest);
    }
    writeLock.unlock();

    //更新歷史表
    appendSearchHistoryTable(moveBest, depth, hashf);
    // 更新置換表
    zobristSearchHash.appendNABTranspositionTable(depth, scoreBest, hashf, moveBest, UtilReservePlayer(searchPlayer));

    return scoreBest;
}

結(jié)果

這里實(shí)現(xiàn)的并行化搜索效果并不出眾,只能說(shuō)是有一定效果。在深度為6搜索情況下,線程數(shù)為4的并行化搜索能加速2~3倍。這一點(diǎn)也是可以理解的,因?yàn)樨?fù)極大搜索的節(jié)點(diǎn)如果排序較好,搜索量主要集中在PV路徑的搜索上。簡(jiǎn)單的分裂根節(jié)點(diǎn)能提升的速度是可預(yù)見(jiàn),只有動(dòng)態(tài)的分裂樹(shù),把算力平攤到PV路徑搜索,加速PV路徑產(chǎn)生能提高博弈樹(shù)搜索的瓶頸。

尾記

這里實(shí)現(xiàn)并行化搜索還存在一些值得思考的問(wèn)題,如何能提高搜索的穩(wěn)定性,在發(fā)生截?cái)喾祷貢r(shí),仍能正確的搜索到PV路徑,而不是會(huì)因?yàn)樘崆暗牟话踩募糁εcPV路徑失之交臂。后面也希望有時(shí)間繼續(xù)研究下如何高效的分裂樹(shù),而不是盲目的根分裂。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-789385.html

到了這里,關(guān)于基于博弈樹(shù)的開(kāi)源五子棋AI教程[7 多線程搜索]的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 五子棋游戲AI智能算法設(shè)計(jì)

    五子棋游戲AI智能算法設(shè)計(jì)

    五子棋游戲C語(yǔ)言AI智能算法設(shè)計(jì)? 近來(lái)發(fā)現(xiàn)編制五子棋游戲很有趣,尤其是AI智能算法很燒腦。網(wǎng)上介紹有什么貪心算法,剪枝算法,博弈樹(shù)算法等等,不一而足。 對(duì)于人機(jī)對(duì)戰(zhàn)的電腦智能應(yīng)子算法,參閱很多五子棋書(shū)籍棋譜和五子棋競(jìng)賽的對(duì)抗棋譜。我感到白棋的后手防御

    2024年02月06日
    瀏覽(20)
  • C++ 實(shí)現(xiàn)對(duì)戰(zhàn)AI五子棋

    C++ 實(shí)現(xiàn)對(duì)戰(zhàn)AI五子棋

    ?個(gè)人主頁(yè): 日刷百題 系列專欄 : 〖C/C++小游戲〗 〖Linux〗 〖數(shù)據(jù)結(jié)構(gòu)〗 ? 〖 C語(yǔ)言 〗 ?? 歡迎各位 → 點(diǎn)贊 ??+ 收藏 ??+ 留言 ??? ? ? ? ? ?為了能夠快速上手一門語(yǔ)言,我們往往在學(xué)習(xí)了基本語(yǔ)法后,采用寫(xiě)一個(gè)小項(xiàng)目的方式來(lái)加深理解語(yǔ)言的語(yǔ)法及運(yùn)用,本文采

    2024年02月03日
    瀏覽(25)
  • 五子棋AI算法和開(kāi)局定式(直指13式)破解

    五子棋AI算法和開(kāi)局定式(直指13式)破解

    五子棋AI算法和開(kāi)局定式( 直指13式 )破解 先前發(fā)了幾篇五子棋游戲程序設(shè)計(jì)的博文,設(shè)計(jì)了游戲程序,也設(shè)計(jì)了AI智能奕棋的算法,運(yùn)行程序檢測(cè)算法的可行性,完成人機(jī)模式游戲功能的設(shè)置。這還不夠,還要提高算法的實(shí)戰(zhàn)水平。 對(duì)于人機(jī)對(duì)戰(zhàn)的電腦智能應(yīng)子算法,參閱

    2024年02月20日
    瀏覽(18)
  • 基于C#的五子棋游戲設(shè)計(jì)

    基于C#的五子棋游戲設(shè)計(jì)

    目 錄 一、 畢業(yè)設(shè)計(jì)內(nèi)容 3 二、 畢業(yè)設(shè)計(jì)目的 3 三、 工具/準(zhǔn)備工作 3 四、 設(shè)計(jì)步驟和方法 3 (一) 總體設(shè)計(jì) 3 1. 總體設(shè)計(jì)思路及設(shè)計(jì)圖 3 2. 界面設(shè)計(jì) 4 3. 全局變量設(shè)計(jì) 4 (二) 詳細(xì)設(shè)計(jì) 5 1. 刷新棋盤(pán) 5 2. 繪制棋盤(pán) 5 3. 分步計(jì)時(shí) 5 4. 顯示光標(biāo) 6 5. 判斷勝負(fù) 8 6.

    2024年02月04日
    瀏覽(21)
  • 基于FPGA的五子棋游戲設(shè)計(jì)

    基于FPGA的五子棋游戲設(shè)計(jì)

    基于FPGA的五子棋游戲設(shè)計(jì) 本文基于FPGA設(shè)計(jì)五子棋游戲,使用按鍵輸入,使用VGA接口輸出。五子棋的棋具與圍棋相同,棋子分為黑白兩色,棋盤(pán)為10×10,棋子放置于棋盤(pán)線交叉點(diǎn)上。兩人對(duì)局,各執(zhí)一色,輪流下一子,先將橫、豎或斜線的5個(gè)或5個(gè)以上同色棋子連成不間斷的

    2024年02月05日
    瀏覽(27)
  • 基于Python的五子棋人機(jī)對(duì)戰(zhàn)

    基于Python的五子棋人機(jī)對(duì)戰(zhàn)

    在之前的博文基于tkinter的五子棋游戲中使用tkinter做了一個(gè)簡(jiǎn)單的五子棋游戲,只能實(shí)現(xiàn)人人對(duì)戰(zhàn),后來(lái)想著加上人機(jī)對(duì)戰(zhàn)的功能。 不過(guò),最初想想還是挺麻煩的,計(jì)算機(jī)怎么評(píng)估當(dāng)前的棋局,找到最佳或者較佳的落子點(diǎn)呢,腦子真是越來(lái)越不靈光了。站在巨人的肩膀上,科

    2024年02月04日
    瀏覽(25)
  • 基于Java的五子棋游戲的設(shè)計(jì)與實(shí)現(xiàn)

    基于 Java 的五子棋游戲的設(shè)計(jì) 摘? 要 五子棋作為一個(gè)棋類競(jìng)技運(yùn)動(dòng),在民間十分流行,為了熟悉五子棋規(guī)則及技巧,以及研究簡(jiǎn)單的人工智能,決定用Java開(kāi)發(fā)五子棋游戲。主要完成了人機(jī)對(duì)戰(zhàn)和玩家之間聯(lián)網(wǎng)對(duì)戰(zhàn)2個(gè)功能。網(wǎng)絡(luò)連接部分為Socket編程應(yīng)用,客戶端和服務(wù)器端的

    2023年04月23日
    瀏覽(23)
  • 基于Android Studio的五子棋游戲的簡(jiǎn)單設(shè)計(jì)

    基于Android Studio的五子棋游戲的簡(jiǎn)單設(shè)計(jì)

    【摘要】: 隨著時(shí)代的發(fā)展,現(xiàn)代科技的飛躍,我們的日常娛樂(lè)生活變得豐富多彩。而手機(jī)游戲被業(yè)內(nèi)人士稱為繼通信之后的有一座“金礦”,手機(jī)休閑娛樂(lè)應(yīng)用將成為PC休閑娛樂(lè)之后又一重要業(yè)務(wù)增長(zhǎng)點(diǎn)。本文針對(duì)該趨勢(shì),從用戶需求出發(fā),基于Android對(duì)五子棋游戲進(jìn)行設(shè)計(jì)

    2024年02月11日
    瀏覽(24)
  • 基于C#開(kāi)發(fā)五子棋游戲 大作業(yè) 課程設(shè)計(jì)源碼

    基于C#開(kāi)發(fā)五子棋游戲 大作業(yè) 課程設(shè)計(jì)源碼

    基于C#開(kāi)發(fā)五子棋游戲(大作業(yè)/課程設(shè)計(jì)) 開(kāi)發(fā)環(huán)境:??Windows操作系統(tǒng) 開(kāi)發(fā)工具: Microsoft Visual Studio 運(yùn)行效果圖: ? ?基于C#開(kāi)發(fā)五子棋游戲(大作業(yè)/課程設(shè)計(jì)) 開(kāi)發(fā)環(huán)境:? Windows操作系統(tǒng) 開(kāi)發(fā)工具:Microsoft Visual Studio 基于C#開(kāi)發(fā)五子棋游戲(大作業(yè)/課程設(shè)計(jì)) 開(kāi)發(fā)環(huán)境

    2024年02月04日
    瀏覽(22)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包