この節では、Turtleの評価関数について説明します。
評価関数についてはeval.h, eval.cに定義されています。
TurtleではLogistelloと同様にパターンに基づいた評価を行っています。
以下にTurtleにおける評価関数の特徴を挙げます。
- パターンセット
図1に示すようなパターンセットを使っています。
Logistelloで使用されているパターンセットと似ていますが、隅のパターンが少し異なります。
どちらが良いかは私にはわかりません。
これらのパターンに与えられた評価値の合計に、ゲームの段階(何手目まで進んでいるか)に応じた評価値を加えたものを局面の評価値としています。
- ゲームの段階に応じた評価値の変化
各パターンの評価値は、ゲームの段階によって異なる値となっています。
具体的には、0〜12手目、13、14、...、50、51、52〜60手目の41段階に分けられています。
- 対称性
「黒石と白石を交換したパターンは符号が逆になった評価値をもつ」という仮定のもとでの対称性を利用しています。
例えば、図1では、上下のパターンは黒石と白石が逆になっいますが、仮に上のパターンの評価値が10だった場合、下のパターンの評価値は-10になります。
これを利用することによって、パターンの評価値を保存しておくのに必要なデータサイズが約半分になります。
ただし、オセロにおいては「次の手がどちらの番か」ということがしばしば重要になるので、この対称性が実際に成立するかどうかは疑問です。
そのため、これによって評価の精度が落ちる可能性があります。
それでは、パターンに基づいた評価の具体的な方法について説明します。
これは
- 評価関数の初期化
- パターンインデックスの計算
- 評価値の参照
という過程によって行われます。
評価関数の初期化は、eval.cで定義されているInitEval関数によって行われます。
この関数は次の4つの関数を呼び出します。
- InitDiffNote
- InitUnDiffNote
この2つの関数は配列DiffNoteおよびUnDiffNoteの初期化を行います。
これらの配列は石差による評価値と勝率による評価値との変換を行うようですが、詳しいことはよくわかりません。
- InitFeatures
各パターンの評価値をファイルから読みこみます。
- InitInfos
配列EdgeInfoとHor2Infoの初期化を行います。
これら2つの配列は、edge(辺)およびhor2(辺に隣接する1列)のパターンインデックスから、edge+2Xの2Xの分、および2x5-cornerのパターンインデックスを計算するために使われます。
パターンインデックスは、パターンを構成するマスの色に対応する数(黒:-1、白:1、空き:0)に3の累乗をかけた値の和になります。
例えば上から4列目の横1列に対応するパターンインデックスは次のようにして計算されます(実際のソースとは異なります)。
ただしBoardは構造体BOARD型の変数です。
Index=0;
for(I=0; I<8; I++)
Index=Index*3+Board->Square[A4+I];
ただし、この計算は評価値を求めたいときに毎回行うのではなく、あらかじめ探索の前に(mboard.cにあるMCopyBoard関数で)行っておいて、探索の途中では、石を返す際に変更されたパターンのインデックスだけを更新します。
インデックスを更新する処理を行っているのはmboard.cにあるMDoHashFlips関数内の
*Square->Index[0].Index += Square->Index[0].Inc2;
*Square->Index[1].Index += Square->Index[1].Inc2;
...
という部分です。
評価値の参照はeval.cにあるEvalという関数で行っています。
特に複雑な事は行っておらず、各パターンの評価値を合計しているだけです。
この関数の前半は少しごちゃごちゃしていますが、ここではEdgeInfoとHor2Infoからedge+2Xおよび2x5-cornerのパターンインデックスを求めています。
|