定跡の作成 - mizar/YaneuraOu GitHub Wiki
やねうら王で用いる定跡のフォーマットは、次の形式です。
[定跡フォーマット]
sfen sfen文字列
この局面での指し手1 相手の応手1 この指し手を指したときの評価値 そのときの探索深さ その指し手が選択された回数
この局面での指し手2 相手の応手2 この指し手を指したときの評価値 そのときの探索深さ その指し手が選択された回数
…
sfen xxxx..
相手の応手がないときは"none"と書いておく。
例)
sfen lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1
7g7f 3c3d 0 32 2
sfen lnsgkgsnl/1r5b1/ppppppppp/9/9/2P6/PP1PPPPPP/1B5R1/LNSGKGSNL w - 2
3c3d 2g2f 0 32 1
あと、先頭にDBのフォーマットのバージョン識別用の文字列として次の文字列を入れておく。
#YANEURAOU-DB2016 1.00
🖋 備考
- やねうら標準定跡のように評価値なしの定跡DBにおいては出現頻度の高い順で並んでいることが保証されている。
- やねうら大定跡のように評価値つきの定跡DBにおいては手番側から見て評価値の良い順に並んでいることは保証されている。
1),2)から、1つ目に書かれている指し手がベストの指し手と言えます。
指し手の出現頻度(「その指し手が選択された回数」)のところは、やねうら大定跡のように評価値つきの定跡の場合、意味をなさないので、エンジンのバージョンを100倍したもの(V3.21なら321)を記入してあります。これにより、「古いエンジンで思考させた指し手は採用しない」などの処理を行うことが出来るようになります。
⚠ ファイル形式はASCIIとする。UTF-8のBOM付きでも読み込めるはずなのだが保証はしない。
定跡生成系のコマンドはmakebookというコマンドです。
makebookコマンドは、MAKE_BOOK_CMD,EVAL_LEARN をdefineしてコンパイルしたときにのみ有効となります。
- やねうら王では、NNUEのLEARN版などで使えます。
- ふかうら王では、標準でMAKE_BOOK_CMDは有効になっているので、makebookコマンドが使えます。
拡張子が.sfenというファイルは、
startpos moves 7g7f ...
のようにUSIプロトコルの局面コマンド("position")の形式で1局の棋譜が1行に収められている棋譜ファイルであるとします。("position"という文字列は省略されていると考えてください。)
例えば、5局分の棋譜であれば、5行からなるテキストファイルです。(改行があるまでを1行とする)
拡張子が.dbというファイルは、やねうら王で用いる定跡ファイルです。
DBとは言うものの、単なるテキスト形式のファイルなので、テキストエディタで開いて編集することができます。
このファイルを思考エンジンの実行ファイルがあるのと同じフォルダに"book"というフォルダを作って配置します。
makebook from_sfen book.sfen standard_book.db moves 16
- | 意味 |
---|---|
book.sfen | 読み込ませたい棋譜ファイル |
standard_book.db | 書き出したい定跡ファイル名 |
moves 16 | 16手目まで |
棋譜を読み込ませてそれを定跡DBに変換する。
各局、"moves"のあとに指定した手数の局面までを出力する。
makebook from_sfen bw black_book.sfen white_book.sfen standard_book.db moves 16
"from_sfen"の直後に"bw"(black and whiteの意味)を指定した場合、sfenファイルとして2つのファイルが指定できます。
- 1つ目のsfenファイルは、そのsfenファイルから先手の局面だけを抽出して使う。
- 2つ目のsfenファイルは、そのsfenファイルから後手の局面だけを抽出して使う。
また、このとき、sfenファイル名として"no_file"を指定すると、先手用 or 後手用のsfenファイルは無しであるというのを指定できます。
例)
makebook from_sfen bw no_file white_book.sfen standard_book.db moves 16
例)
makebook think 2016.sfen yaneura_book.db moves 16 depth 32
2016.sfenという棋譜を読みこみ、その16手目までをdepth 32(思考する時の深さ)で思考させて、そのときの上位3手を定跡ファイルに書き出します。
💡 nodes 100000000 のように、探索node数を指定することもできる。
⚠ やねうら王のLEARN版 など、この機能に対応している思考エンジンが必要となります。
- 定跡ファイル上に、すでにそれ以上深い深さで探索した結果がある場合は、その局面については探索しません。
- 同じ深さの場合、登録されている手の数がMultiPVで指定されている手の数以上登録されている場合もその局面については探索しません。
🖋 Hash、Threads、MultiPVの設定に従い思考されるので、事前にこれらのパラメーターを適切な値に設定しておくこと。
- '.'が1局面終わった合図。'S'がセーブ(ファイルに保存)したという合図。一定間隔ごとに自動的に保存されます。
- 中断するときはこの'S'マークが出たのを確認してから終了させると良いでしょう。
- 保存中に終了させるとファイルが破損する可能性があります。
- 前回から新たな指し手が追加されていないときは's'(小文字)を表示して、ファイルには書き出しません。
- Contemptの値は無視されます。(0だとみなされる)
- IgnoreBookPlyオプションは無視されます(falseとみなされます)
💡 book_save_interval 【秒数】 というオプションでbookの保存間隔を指定できます。(デフォルト15分)
例)
Hashメモリ4096MB、スレッド数8(それぞれのスレッドが1局面ずつ担当して検討)、MultiPV 5(それぞれの局面で候補手5手書き出し)、
棋譜2016.sfenの16手目までを深さ32で探索して定跡ファイルuser_book1(すでに存在すれば該当局面のみを上書き更新)を生成。
Hash 4096
Threads 8
MultiPV 5
makebook think 2016.sfen user_book1.db moves 16 depth 32
makebook think 2016.sfen yaneura_book.db startmoves 5 moves 16 depth 32
startmovesを指定すると、思考対象局面をそこからにします。(省略時は1が指定されているものとみなされます。)
上の例だと、(初期局面を1手目として)5手目から16手目の局面を思考対象とします。
makebook think 2016.sfen yaneura_book.db startmoves 5 moves 16 depth 32 cluster 1 3
makebook think 2016.sfen yaneura_book.db startmoves 5 moves 16 depth 32 cluster 2 3
makebook think 2016.sfen yaneura_book.db startmoves 5 moves 16 depth 32 cluster 3 3
上の例は、PCを複数台で定跡を並列生成するときに用います。
"cluster 【X】【Y】"の形で指定して、Y台あるうちのX台目ということを意味します。
上の例は、3台あって、1台目、2台目、3台目のPCで上のように入力すると思考対象局面を分散させています。もちろん3台以外の場合であってても同様にすれば並列生成できます。
makebook think bw black_2016.sfen white_2016.sfen yaneura_book.db startmoves 5 moves 16 depth 32 cluster 3 3
"from_sfen"のときと同様に、直後に"bw"を指定した場合、sfenファイルとして2つのファイルが指定できます。
- 1つ目の.sfenファイルは、その.sfenファイルから先手の局面だけを抽出して使う。
- 2つ目の.sfenファイルは、その.sfenファイルから後手の局面だけを抽出して使う。
makebook merge yaneura_book1.db yaneura_book2.db yaneura_book3.db
定跡のマージ機能。上の例は、yaneura_book1.dbとyaneura_book2.dbとをマージ(合体)させてyaneura_book3.dbを作成します。
- 1つの局面に対して、深く探索されたほうの結果を優先。
- 1つの局面に対して、2つの定跡ファイルがどちらも同じ深さで探索されている場合は、候補手(MultiPV)が多いほうを採用。
makebook thinkコマンドで自動生成した定跡をマージするのに用います。
makebook sort book_src.db book_sorted.db
局面の文字列(sfen文字列)でソートします。
上例では、book_src.dbを読み込み、並び替えられた、book_sorted.dbを出力しています。
対局時に、定跡をメモリに丸読みしたくないときには(BookOnTheFlyオプションがオンの時)は、sfen文字列順に並んでいないといけません。(sfen文字列順でソートされていないとバイナリサーチが出来ないため。)
そのため、sortされていない定跡ファイルを読み込んで並べ替えて出力する機能が必要となります。それがこのmakebook sortコマンドです。
💡 このコマンドを用いてsortしなくとも、mergeコマンドなど、定跡DBファイルの書き出し時にはsortをしてから書き出します。なので、普段はこのコマンドを使う必要はありません。手で定跡を編集した場合などに用います。
makebook extract_sfen_from_db
定跡の変換コマンドです。定跡DBから局面をsfen形式で抽出します。
book/read_book.db
を読み込んで、そのなかの局面図のみのsfenファイル
book/write_sfen.txt
を書き出します。
// こんなコマンド使わずとも、grep等でsfenで始まる行を抽出すればいいだけなのだが…。
ここで書き出された局面をスーパーテラショック定跡の生成の時に棋譜として与えれば、この棋譜の局面をある程度優先して掘ってくれるので特定の定跡を狙い撃ちするような定跡を作る時に役立ちます。
makebook extract_sfen_from_sfen
USIのPositionコマンドで指定できる形で書かれた棋譜ファイルなどを読み込み、その各局面をsfen形式で書き出すコマンド
book/read_sfen.txt
を読み込んで、そのなかの局面図のみのsfenファイル
book/write_sfen.txt
を書き出す。
Positionコマンドなので"startpos moves xxx.."とか"sfen xxx moves yyy.."のような形式の棋譜が指定できる。
makebook build_tree read_book.db write_book.db
このコマンドは、テラショック化コマンドと呼ばれるものです。
read_book.dbには、thinkコマンドで実戦で出現した局面に評価値がついているものとして、leaf node(末端の局面)についている評価値を使ってMinimax探索のようなことをして、それぞれの局面での最善手write_book.dbに書き出す機能です。
⚠ IgnoreBookPlyオプションの値は反映されます。これをtrueにしている場合、手数無視で定跡にhitするものとしてtreeを生成します。(write_book.dbに書き出されます) IgnoreBookPlyはtrueにしたほうが良いと思います。
makebook build_tree read_book.db write_book.db black_contempt 50 white_contempt 150
build_treeで千日手に至るときにそのとき、千日手を評価値いくらにみなすかというのを先手・後手個別に設定できます。
👉 例えば、black_contempt = 50を指定すると先手の千日手時のスコアを-50とみなします。
makebook extend_tree read_book.db read_sfen.txt write_sfen.txt
定跡ツリーの延長を行います。
上の例では、read_book.dbの定跡に対して、read_sfen.txtのsfenの局面から開始して定跡DBの末端の局面まで行き、延長する枝をwrite_sfen.txtに書き出します。
延長する枝を選ぶアルゴリズム)
read_sfen.txtの局面から、評価値が先手で-50以上、後手で-150以上の値がついている枝だけを延長していきます。
💡 ここで言う「枝」とは指し手とそこに続く局面のことです。定跡を木のような構造だと見立てているので、このような表現になっています。
💡 ここで書き出されたsfenファイルを、makebook thinkコマンドで思考させるのを繰り返すと定跡ツリーが成長していきます。
read_sfen.txtにはこの延長を行う開始局面を複数指定できます。(わからなければ、"startpos"とだけ書いたテキストを用意すれば、平手の開始局面からになるのでそれで問題ないはずです。)
"startpos moves.."の形で複数の局面を指定します。"sfen ..."や、"sfen ... moves ..."のような形式で指定することもできます。
🌙 このコマンドにIgnoreBookPlyオプションの値は反映されます。
makebook extend_tree read_book.db read_sfen.txt write_sfen.txt black_eval_limit -200 white_eval_limit -300
extend_treeのときに展開する枝の評価値の下限を先手/後手個別に指定できます。
- black_eval_limit 延長する時の、先手の指し手の評価値の下限
- white_eval_limit 延長する時の、後手の指し手の評価値の下限
makebook extend_tree read_book.db read_sfen.txt write_sfen.txt extend_range -1 1
extend_rangeを指定すると、その範囲のleaf node(末端の局面)の候補手だけを延長対象とします。
(MultiPVで思考させ複数の指し手が登録されている場合、このextend_rangeの範囲内の候補手で進めた局面だけが延長されます)
extend_range -1 1 と指定したならば、leaf nodeでextend_treeの引き分けの評価値(-1,0,+1)の局面だけを延長します。makebook thinkのときの引き分けの評価値を0にしておけば、千日手局面が延長されます。
👉 引き分けの評価値がついているけども、定跡ツリー上ではまだ千日手のように循環していない場合、延長することによって、そこまでの手順に循環(合流)するので、この延長をさせたいことがあります。
extend_rangeとblack_eval_limit,white_eval_limitの併用は可能です。(leaf以外の局面で、そこを辿るかどうかをblack_eval_limit/white_eval_limitで制限しつつ、leafで延長するところをextend_rangeで制限する)
makebook endless_extend_tree book/user_book1.db book/kadai_sfen.txt book/think_sfen.txt depth 8 startmoves 1 moves 32 loop 100 black_eval_limit -50 white_eval_limit -150 nodes 1000000000
makebook extend_treeとthinkを合体させたコマンド。
think_sfen.txtのところは、思考対象局面を書き出す一時ファイル。
- このときbook/kadai_sfen.txtに "startpos" とだけ書いておけば、平手の初期局面が課題局面になるので、そこから自動的に定跡が掘られていきます。
- loopの回数だけ繰り返されます。
- max_game_ply(最大手数)の指定も可能。
- 検討用の局面をbook/kadai_sfen.txtに入れて、そこから定跡を掘るのに使えるかと思います。
例)
思考エンジンを起動して、
Hash 4096
Threads 8
makebook endless_extend_tree book/user_book1.db book/kadai_sfen.txt book/think_sfen.txt depth 36 startmoves 1 moves 70 loop 100 black_eval_limit -50 white_eval_limit -150 nodes 1000000000
みたいな感じで。
🌙 このコマンドにIgnoreBookPlyオプションの値は反映されます。
makebook endless_extend_tree book/user_book1.db book/kadai_sfen.txt book/think_sfen.txt depth 8 startmoves 1 moves 32 loop 100 black_eval_limit -50 white_eval_limit -150 nodes 1000000000 extend_range -1 1
endless_extendの千日手局面だけを延長したい時。
makebook s_tera
スーパーテラショック定跡の生成コマンドです。
- スーパーテラショック定跡についてはこちらの記事をご覧ください。👉 スーパーテラショック定跡が76歩に34歩を全否定
⚠ これは、ふかうら王のみ使えるコマンドです。
パラメーター | 意味 |
---|---|
read_book 【ファイル名】 | 前回このコマンドで書きだした定跡ファイル名(デフォルトでは "book/read_book.db") |
write_book 【ファイル名】 | 今回書き出す定跡ファイル名 (デフォルトでは "book/write_book.db") |
root_sfens_name | 探索開始局面集のファイル名。デフォルトでは"book/root_sfens.txt"。 このファイルがなければ平手の初期局面から。 平手の初期局面をrootとすると後手番の定跡があまり生成されないので(先手の初手は26歩か34歩を主な読み筋としてしまうので)初期局面から1手指した局面をこのファイルとして与えたほうがいいかも? あと駒落ちの定跡を生成するときは同様に駒落ちの初期局面と、そこから1手指した局面ぐらいをこのファイルで指定すると良いかも。 |
kif_sfens_name | 棋譜のファイル名。この棋譜上の局面かつPVまわりを思考させることもできる。 |
book_save_interval | この局面数だけ思考するごとに定跡ファイルを書き出す。 "book/read_book.db.000001"のようなファイルに通しナンバー付きで書き出していく。このコマンドが終了するときにも書き出すので、数時間に1度保存される程度のペースでも良いと思う。 |
nodes_limit | 1局面について思考するnode数。30knps出るPCで30000を指定すると1局面1秒。 |
think_limit | この局面数思考したらこのコマンドを終了する。 |
search_delta | PVのbest_valueとの差がsearch_deltaのleaf nodeを拾い上げて思考する。 このパラメーターに0を指定すると、その処理はskipされる。 |
search_delta_on_kif | PVのbest_valueとの差がsearch_delta_on_kifのleaf nodeでかつ、 kif_sfens_nameで指定した棋譜上の局面について思考する。 このパラメーターに0を指定すると、その処理はskipされる。 |
それぞれのファイルフォーマット
入力)
book/root_sfens.txt
// 探索開始局面
例)
sfen lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1
↑のようなsfen形式か、
startpos moves 7g7f ...
のようなUSIプロトコルの"position"コマンドとして送られる形式でも可。
// この場合、それぞれの局面が探索開始対象となる。
book/kif_sfens.txt
読み込ませたい棋譜。この棋譜上の局面かつ、PVまわりを思考する。
例)
startpos moves 7g7f ...
// このファイルはなければなくとも良い。
book/read_book.db
前回出力された出力ファイル(book/write_book.db)をread_book.dbとrenameしたもの。
// 配置するとその続きから掘ってくれる。
(初回はこのファイルは不要)
出力)
book/write_book.db
→ このあと、このファイルをテラショック化コマンドでテラショック定跡化して使う。
例)
> makebook build_tree book/write_book.db book/user_book1.db
注意点)
高速化のために、局面をSFEN文字列ではなく、局面のhash値で一致しているかどうかをチェックするので
局面のhash値は衝突しないように128bit以上のhashを用いる。(べき)
→ 具体的には、config.hでHASH_KEY_BITSのdefineを128にしてビルドする。
makebook stera_convert
スーパーテラショック定跡コマンド("makebook stera")で生成した定跡を超高速にテラショック化するコマンドです。
💡 テラショック化とは、定跡ツリー上のleaf node(末端の局面)の評価値を用いてMinimax探索のようなことをして、一番評価値の良いleaf nodeに到達するような定跡に変換すること。
book/read_book.db
を読み込んで
book/write_tera_book.db
を書き出す。
前者は、スーパーテラショック定跡コマンドで生成された定跡。
(デフォルトでは book/write_book.db として書き出されている)
定跡生成に関して参考になりそうな記事
定跡フォーマットについて
定跡生成コマンドについて
スーパーテラショック定跡について