今年の電王トーナメントでも前評判では「激指先生が出てくるならやねうら王なんかお呼びじゃねーよ」という声が多かった。
それが激指先生がやねうら王に二連敗(予選と本戦)すると、「激指たいしたことねーなw」「激指なんのために出てきたんだ?www」「やねうらおさんはマジ天才だな」とか、手のひら返しがひどすぎる。
今年の電王トーナメントでも前評判では「激指先生が出てくるならやねうら王なんかお呼びじゃねーよ」という声が多かった。
それが激指先生がやねうら王に二連敗(予選と本戦)すると、「激指たいしたことねーなw」「激指なんのために出てきたんだ?www」「やねうらおさんはマジ天才だな」とか、手のひら返しがひどすぎる。
今回はStockfishのbitcount.hです。これは、2進数的に見て1になっているbitの数を数えるというものです。いわゆるpopcountですね。SSE4.1以降であればx86/x64ではpopcnt命令が使えますので簡単なのですが、そうではない環境ではビット演算のテクニックを用いて求めることになります。
Stockfishのbitboardは、チェスなので盤面が8×8 = 64升であり、64bit変数に収まります。(将棋の場合、81升なので128bit変数もしくは、64bit変数が2つ必要になります。)
あと、magic bitboardと言う仕組みが使われています。これは斜めに利く駒の利きのbitboardに対して掛け算を使って連続するビットに移動させるテクニックです。→ Magic Bitboard – Chess Programming Wiki
Haswell以降であればBMIを使うべきでしょう。→ BMI使ってますか?
定跡の生成のため探索をして評価値が一定以上悪くなる指し手は定跡DBには登録しないだとか、探索して棋譜の指し手の評価値を定跡DBに記録しておき、ベストの評価値とかけ離れた評価値の指し手は採用しないだとかして定跡DBを作っていたのですが、少し興味深い現象があったので書いておきます。
今回は擬似乱数生成器です。世間では「乱数と言えばMT(Mersenne twister : メルセンヌツイスター)乱数だろ」と思われているかも知れませんが、MT乱数は生成に結構コストがかかるので、ベストなソリューションとは言えません。かと言って、組み込み系の乱数は乱数の精度が今ひとつですのでそういう部分で偏りが出るのは困ります。(定跡選択で乱数を使うので、乱数に偏りがあると連続自己対戦の勝率に偏りが生じかねない)
Stockfishで採用されているのはRKISSという乱数で、この乱数の実装を見るためだけにでも、Stockfishのソースコードを読む価値はあると私は思います。
今回はStockfishのtypes.hの解説です。このファイルはBonanza6で言うとshogi.hに相当するもので、チェスで使う基本的な構造体の定義が一式書かれています。このファイルの内容を頭においてからソースコードを読み進めれば細部まで理解しやすいでしょう。
KPPというのは玉と玉以外の2駒(合計3駒)の位置関係のことを言います。
将棋の初期局面は角と飛車がいるために左右非対称となっています。
このため、序盤では角側の桂はなるべく跳ねないほうがいいだとか、そういう暗黙のルール(?)があるわけですが、これを評価関数のパラメーターの調整として棋譜から学習させるときに左右対称性を考慮しているとうまく学習できないのではという議論があります。
昨日の記事に対してこんな意見をいただきました。
持ち駒を盤上に投入するときの移動距離はワープに近いのでは。あと、将棋には「どの手を選んでも引き分け」という局面は少なく、狭い選択肢でも勝ちになる手を選ばないといけないのが難しいと思う。> 将棋はチェスに比べてどこが難しいのですか? http://t.co/1vyvTH6eft
— takodori (@takodori) December 21, 2014
「持ち駒を盤上に投入するときの移動距離はワープに近い」ので、持ち駒のある局面(終盤)は、位置評価が相対的に重要ではなくなってくるのでそういう局面はもともとコンピューターが得意とする局面です。昔からコンピューター将棋の終盤は強いですよね…。
このことをもう少し専門的な角度から書いてみます。