上一节我们完成了最大最小搜索树,加上alhpa-beta剪枝算法实现了围棋落子走法。它存在一个问题是,树搜索的层次不高,尽管如此,围棋机器人下棋时还是要多次扫描棋盘,进行复杂的运算比较后才能做出决定,这个过程异常耗时,以至于好几分钟都无法运算完。
在计算机科学中,当面对一个计算量大的复杂问题时,一种常用的做法就是引入概率和随机性,我们不一定要寻找理论上的最优做法,我们只要以一定的概率寻找到相对优越的做法即可。本节我们引入一种带有随机性的树搜索算法叫蒙特卡洛树搜索,它属于蒙特卡洛随机化算法中的一个分支,这种算法的特性是使用概率和随机化的方法去分析极度复杂和棘手的问题。之所以把这类算法叫做蒙特卡洛,是因为在摩洛哥有一片赌场区就叫蒙特卡洛。
接下来我们看看蒙特卡洛算法步骤。该算法有两个特点,一是对棋盘进行随机模拟,二是根据模拟的结果进行统计。假设当前有一个棋局,其中轮到黑棋落子:
根据上图,我们把当前棋盘状况抽象成一个树节点,它有两个值,’/'左边的值是获胜的数量,右边的值是模拟次数,比如说给定一个棋盘局面,我让两个围棋机器人在当前局面下随机落子直到分出胜负为止,假设当前棋盘是黑棋落子,我们让机器人下100盘后,黑棋赢了70盘,那么节点中的值就是70/100。
算法第二部是根据当前节点展开,如果当前棋盘是黑棋落子,同时黑棋有3种走法,于是上面节点就可以展开三个子节点,每个子节点对应黑棋采取相应走法后的棋盘状况:
接着我们构造两个机器人,然他们基于三个叶子节点的棋盘状况随机落子,直到分出胜负:
父节点对应的棋盘轮到黑棋落子,黑棋有三种落子方式,于是衍生出三个子节点,然后我们构造机器人在三个子节点对应的棋盘上模拟对弈直到分出胜负,假设第一个节点模拟结果是黑棋胜,第二个棋盘模拟结果是黑棋输,第三个节点模拟结果是黑棋胜,于是三个子节点的值变为1/1,0/1,1/1,然后我们把子节点的结果上传到父节点:
算法每次都会以某种规则选择一个叶子节点进行机器人模拟对弈,然后将结果上传到它的所有父节点。上图模拟后表明第一个节点胜率是100%,第二个节点是0,第三个节点是100%,如此说明黑棋以第一种和第三种方式落子所得的赢面更大,当然这是不一定的,因为当前结果只是一次随机模拟的结果,很可能中间节点对应走法更好,只不过随机模拟时,因概率性问题没得到好结果而已,对于这个问题我们后面会有办法处理。
接下来我们选择一个赢率大的节点继续展开,例如我们选择第二层第一个节点,此时轮到白棋落子,假设此时白棋有两种落子方式,于是我们根据这两种落子方式形成两种棋盘,对应两个子节点:
接着我们在展开后的节点对应棋盘上进行随机模拟对弈,也就是让两个机器人在当前棋盘上随机落子,得到结果后,将结果上传到父节点进行综合:
注意到此时第二层第一个节点的赢率下降