日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Python蒙特卡洛树搜索算法实现的黑白棋AI系统

發布時間:2024/3/24 windows 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python蒙特卡洛树搜索算法实现的黑白棋AI系统 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

資源下載地址:https://download.csdn.net/download/sheziqiong/85836329
資源下載地址:https://download.csdn.net/download/sheziqiong/85836329

利用給出的 board.py,使用蒙特卡洛樹搜索算法來完成黑白棋 AI。

AI 需要完成的功能:

  • 在當前棋盤狀態下,選擇一個合法且在算法上最優的落子位置,作為返回值

  • 搜索及決策時間不超過一分鐘,若無合法位置則返回 None

  • 在游戲結束(即雙方均無合法落子位置)時,盡量最大化己方與對方的棋子數量差

  • 設計思想

    While (time_is_enough): For (node = root; all son_node.visited in node.sons; node = choson_son) Choson_son = the son with max UCB of node# Selection,從根往下,選擇一個兒子沒有被完全訪問過的節點Expand_Candidate = x if ((x in node.sons) and (not x.visited))Node_to_expand = random.choice(Expand_Candidate)# Expansion,隨機選擇一個沒有被訪問過的兒子節點Leaf = nodeFor (node = Node_to_sxpand; node has son; node = random.choice(node.sons)) Leaf = node # Simulation,隨機選擇兒子節點直到葉子節點 For (node = Leaf; node != root; node = node.father) Update(node) # Back Propagation, 更新訪問過的信息以及勝負/獎勵分數信息

    在搜索過程中,每一次“采樣”都有四個步驟:選擇,擴展,模擬和反向傳播:

  • 其中選擇主要受到 UCB 函數中 C 值的影響
  • 擴展完全隨機
  • 模擬時由于黑白棋合法落子位置與當前局面的相關性非常大,沒有找到隨機以外的 合適方式進行落子(基于當前局面的貪心甚至不如隨機算法)
  • 反向傳播時更新的收益分數也是可以人為影響算法效益的部分。由于 board.py 提 供了分數差的信息,可以用分數差的相關函數作為獎勵收益(此處采用了分數差*k, k 為人為規定的系數)
  • 但是根據 UCB 的 score 函數組成,其實能發現 k 如果只是作為乘上去的系數,本質上就是 C,不過添加一個 k 可以方便調整也更直觀而已。

    最后就是搜索次數可以對搜索效果產生影響了,由于給出了一分鐘的落子時限,雖然在測試時使用的 25s 采樣時間效果已經不錯了,但在提交的時候應該還是會頂著時間上限吧(笑)

    代碼內容

    ================================================================ //UCB1:def UCB1(self, color, board_in):""":param color: 當前節點對應的顏色:param board_in: 當前棋盤狀態:return : 根據采樣結果,對 AI 方最有利的落子位置"""board = deepcopy(board_in)score_act = Noneact = Noneaction_list = list(board.get_legal_actions(color))rec_sum = 0 # 記錄這個節點的總分(用來算 select 的子節點)for action in action_list:play_board = deepcopy(board)play_board._move(action, color)tmp_key = tuple(np.ravel(play_board._board))# 計算該 action 后對應的棋盤的 key 值if self.rec.get((color, tmp_key)):# 訪問過則繼續計算總分rec_sum += self.rec.get((color, tmp_key))for action in action_list:play_board = deepcopy(board)play_board._move(action, color)tmp_key = tuple(np.ravel(play_board._board))score_tmp = (self.scr.get((color, tmp_key)) / self.rec.get((color, tmp_key)) + self.C * math.sqrt(math.log(rec_sum) / self.rec.get((color, tmp_key))))# 計算鍵值 以及積分if score_act == None:score_act, act = (score_tmp, action)else:if score_act < score_tmp:score_act, act = (score_tmp, action)# 更新積分最高的子節點return act ==================================================================== //選擇:def Select(self, board):""" :param board: 輸入需要被搜索的棋盤:return: color 是 select 到最后的那個節點已經落子的棋子顏色, act 是上一個 落子的位置, tmpkey 是這個棋盤的狀態"""color = self.colorwhile(True):# 一直 select 直到有一個節點沒有完全被擴展action_list = list(board.get_legal_actions(color))if len(action_list) == 0:return None, None, Noneall_explored = True # 這個節點的子節點是否全部訪問過non_vis_son = [] # 記錄沒有訪問過的兒子節點rec_sum = 0 # 記錄這個節點的總分(用來算 select 的子節點)for action in action_list:play_board = deepcopy(board)play_board._move(action, color)tmp_key = tuple(np.ravel(play_board._board))# 計算該 action 后對應的棋盤的 key 值if not self.rec.get((color, tmp_key)):# 沒有訪問過則記錄 該子節點 以及更新節點未訪問信息all_explored = Falsenon_vis_son.append((action, tmp_key))else:# 訪問過則繼續計算總分rec_sum += self.rec.get((color, tmp_key))if all_explored:# 如果全部訪問過,則在該節點中選擇分數最高的兒子act = self.UCB1(color, board)else:# 有未訪問節點,則隨機返回一個未訪問節點,作為 extend 的對象act, tmp_key = (random.choice(non_vis_son))board._move(act, color)return (color, act, tmp_key)# 到這里的時候應該是要 select 下一個節點了board._move(act, color)tmp_key = tuple(np.ravel(board._board))# 落子,更新新棋盤的 key 值self.vis.add((color, tmp_key))# 記錄路徑上的節點信息color = "X" if color == "O" else "O"# 切換顏色 ==================================================================== //擴展:def Expand(self, board, color, act, tmpkey):""":param board: 當前要擴展的棋盤:param color: 當前已經落子的棋子顏色:param act: 當前已經落子的位置:param tmpkey: 當前棋盤狀態:return: 返回乘上系數后得到的分差"""game_state, scr_diff = self.Simulate(board, color)self.rec[(color, tmpkey)] = 1# 記錄該節點下的訪問次數+1if (game_state == 0 and self.color == "O") or (game_state == 1 and self.color == "X"):scr_diff = - scr_diff# 把 scr_diff 改成(AI-對方)的分差,可以為負scr_diff *= 0.4# 加一個系數if color == self.color:# 如果當前決策節點的顏色是 AI 的顏色,則加上分差,否則減去分差self.scr[(color, tmpkey)] = scr_diffelse:self.scr[(color, tmpkey)] = - scr_diffreturn scr_diff ==================================================================== //模擬:def Simulate(self, board, player):"""用隨機來模擬下棋過程:param board: 當前棋盤狀態:param player: 當前剛完成落子的玩家:return: (winner, 分數差), 其中 winner 是 0 黑棋, 1 白棋, 2 平局"""while(True):player = "X" if player == "O" else "O"# 切換執棋方legal_actions = list(board.get_legal_actions(player))if len(legal_actions) == 0:if self.game_over(board):return board.get_winner()# 0 黑棋, 1 白棋, 2 平局# 后面還有個分數差的參數break else:continueif len(legal_actions) == 0:action = Noneelse:action = random.choice(legal_actions)# 用隨機落子來模擬if action is None:continueelse:board._move(action, player)if self.game_over(board):return board.get_winner() ==================================================================== //Back Propagation:def BackPropagate(self, scr_diff):""":param scr_diff: 乘上系數的 AI 與對手的分數差"""for (color, key) in self.vis:self.rec[(color, key)] += 1if color == self.color: # 如果當前決策節點的顏色是 AI 的顏色,則加上分差,否則減去分差self.scr[(color, key)] += scr_diffelse:self.scr[(color, key)] -= scr_diff ==================================================================== //UCTS 的主要部分:def MCTS_choice(self, board_input):""":param board_input: 輸入當前棋盤:return: 返回落子坐標樹的狀態節點用 rec 和 scr 兩個 dict 來存儲,存下了(當前落子方,棋盤狀態): (訪問次數,合計分數)的狀態"""starttime = datetime.datetime.now()count = 0while True: count += 1currenttime = datetime.datetime.now()if (currenttime - starttime).seconds > 3 or count > 1000:break board = deepcopy(board_input)color = "X" if self.color == "O" else "O"# color 是對方的顏色self.vis = set() # 記錄樹上搜索過的路徑,方便更新color, act, tmpkey = self.Select(board) # color 是 select 到最后的那個節點已經落子的棋子顏色# act 是上一個落子的位置# tmpkey 是這個棋盤的狀態if color == None:# 如果沒有可以落子的地方,進入下一輪嘗試continue scr_diff = self.Expand(board, color, act, tmpkey)# Expand 得到當前擴展節點的分數,并用于 bpself.BackPropagate(scr_diff)print(count)return self.UCB1(self.color, board_input)

    實驗結果

    資源下載地址:https://download.csdn.net/download/sheziqiong/85836329
    資源下載地址:https://download.csdn.net/download/sheziqiong/85836329

    總結

    以上是生活随笔為你收集整理的Python蒙特卡洛树搜索算法实现的黑白棋AI系统的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲成人一区二区在线观看 | 青青草欧美 | 亚洲午夜精品 | 国产人与zoxxxx另类 | 一区精品在线观看 | 婷婷丁香激情五月 | 亚洲免费一级片 | 又粗又猛又爽又黄少妇视频网站 | 日本阿v视频| 黄色片在线免费观看视频 | 女性私密整形视频 | 69国产成人精品二区 | 黄视频在线观看免费 | 在线观看黄色大片 | 国产成人在线视频 | 日韩精品系列 | 久久人人澡 | 狠狠操2019| 先锋av在线资源 | 村姑电影在线播放免费观看 | 欧美午夜三级 | 日本欧美久久久久免费播放网 | 国产精品一区二 | 国产精品18 | 男生桶女生肌肌 | 成人av影院 | 狼人精品一区二区三区在线 | 污污网站在线观看 | 国产1区二区| 国产精品美女www | 欧美xxxx非洲 | 亚洲一区 在线播放 | 日本精品人妻无码免费大全 | 人人97 | 久久婷婷热 | 国产乱码精品一区二三区蜜臂 | 日日操夜夜操狠狠操 | 亚洲爆乳无码一区二区三区 | 久久综合五月 | 国产精品黄色av | 激情亚洲色图 | 神马影院午夜伦理 | 黄色仓库av | 亚洲欧洲在线看 | 俺啪也 | 视频在线观看一区 | 老女人网站| 国产精品视频播放 | 亚洲а∨天堂久久精品2021 | 熟妇人妻中文字幕 | 久久久性色精品国产免费观看 | 樱桃av| 久久久ww| 国产午夜手机精彩视频 | 69亚洲精品 | 欧美a级在线免费观看 | 狠狠做深爱婷婷综合一区 | 精品国偷自产国产一区 | 91精品国产免费 | 青青偷拍视频 | 男人懂得网站 | 男人天堂a在线 | 日本三级在线视频 | 亚洲第一色网站 | 女人脱下裤子让男人捅 | 国产综合精品视频 | 欧美日韩午夜爽爽 | 国产sm调教视频 | 91精品视频免费在线观看 | 国产叼嘿视频在线观看 | 亚洲a级在线观看 | 免费成人av在线播放 | 欧美极品在线观看 | 国产精品久久一 | 哪里看毛片 | 欧美成一区二区三区 | 一本久久a精品一合区久久久 | 美女涩涩视频 | 中文字幕免费高清 | 国产精品蜜 | 99久久精品国产亚洲 | 日本在线视频一区二区三区 | 日韩黄色免费电影 | 一级黄色a视频 | 日韩女女同性aa女同 | 亚洲精品久久久蜜桃 | 精品乱子一区二区三区 | 欧美大片网站 | 久久久性色精品国产免费观看 | 日韩黄色短视频 | 国产精品suv一区二区69 | 日韩精品久久久久久免费 | 日韩三级黄色片 | 久久久久久久9 | 国产成人精品一区二区三区网站观看 | av综合在线观看 | 手机看片一区二区 | 女人的天堂av | 在线成人免费 |