自作GTOソルバーAlbaの紹介

著者:Stray Cat
公開:
コラム

自作GTOソルバーAlbaの紹介

nlh.pokerの自作GTOソルバー、Albaを紹介します。現時点での検証内容を公開します。

Albaは、nlh.poker の自作 GTO ソルバーです。指定したゲームに対して、相手から搾取されにくい戦略を計算します。GTO という言葉の意味は、GTOポーカーとはにあります。この記事は、Alba の紹介です。

公開にあたり、BTN 対 BB のポストフロップだけを切り出した部分ゲーム 10 本を解きました。ターン開始が 5 本、リバー開始が 5 本です。反復 T=128000 の平均戦略について、厳密な exploitability は 0.002chips 以下でした。開始ポット 550chips の 0.001% 未満です。数字は 2026-10-06 時点の実測です。

Albaとは

Alba は、テキサスホールデムの一部をゲームの木にして、CFR 系の反復で平均戦略を求めます。解の近さは exploitability で見ます。求め方は、このあとの節にあります。今回の公開で数字を出せるのは、次の 2 つです。

  • この 10 本について、Alba の解の厳密な exploitability。
  • exploitability を出す計算を、支払、末端から戻す値、最善応答に分けて照合したこと。値の計算は、既存の経路との比較です。

次の 2 つは、まだ検証していません。

  • プリフロップから続く、全体の戦略の品質。
  • この 10 本以外のボードや、別のサイズの木での一致。

exploitabilityとは

exploitabilityは、相手が最善で応じたときに、その戦略が失う期待値です。片方の席を、木の末端まで含めた最善応答に置き換え、枝を間引かずにその値を計算します。両席についてこれを行い、次の式で 1 つの数にします。

exploitability =(BTN の最善応答の値 + BB の最善応答の値 − ゲームの値)÷ 2

ゲームの値は、戦略によらない定数です。この会計では 50chips で、ポットに含まれるデッドマネーと同じ額です。各席の値は、すでに入れた 250chips を引いた収支なので、両席の和は開始ポットの 550chips にはなりません。零和の節で、この和が 50chips であることを確認します。exploitability が 0 に近いほど、その戦略の組は、このゲームの中で搾取されにくいです。エクスプロイトと GTOでいう搾取されにくさを、1 つのゲームに限って数値にしたものです。

支払いか最善応答のバグは、この数を偽に小さくします。数字がきれいに見えるので、反復が収束しないバグより見つけにくいです。後半の照合は、そのために置いてあります。

ゲームの定義

形式は BTN 対 BB のポストフロップだけです。SB はフォールド済みで、0.5bb(50chips)がデッドマネーです。BTN と BB はそれぞれ 2.5bb(250chips)を入れています。開始ポットは 5.5bb(550chips)です。ポストフロップは BB からアクションします。残りスタックは 97.5bb(9750chips)です。1bb = 100chips です。

項目値
形式BTN 対 BB、ポストフロップのみ。BB が先
開始ポット5.5bb(550chips)。BTN と BB が 250chips ずつ、SB のデッドマネー 50chips
残りスタック97.5bb(9750chips)。両者ともこの額
レンジ両者ともエニハン。ボードとぶつからない全コンボを、同じ重みで持つ
レーキ0
BB のサイズチェック、ポットの 1/3、2/3、125%
対ベットフォールド、コール、レイズ 1 サイズ
対レイズフォールドとコールのみ。再レイズはしない
レイズコール後のポットに対し、ターンは 147.6%、リバーは 730.8% の上乗せ。ターン開始の木のリバーでも、ポットが大きくなった線で同じ 730.8%。残りスタックを超えるときはオールイン
額の丸め有効数字 2 桁

5つのボード

表記のスートは、h がハート、d がダイヤ、c がクラブ、s がスペードです。T は 10 です。各ボードについて、ターン開始の木とリバー開始の木を 1 本ずつ作りました。ターン開始ではフロップとターンまでが公開で、リバー開始ではリバーまでが公開です。

フロップターンリバー
AhQc3d7h9c
Kh8h3h9h2h
QsTs5d2c7d
KsKh7c2d9s
9h8s7d2cAh

5 つは、エースハイ、ハートのモノトーン、ブロードウェイ、キングのペア、ストレートの並び、とテクスチャを分けてあります。

有効数字2桁のサイズ

BB のターンのベットは、5.5bb の 1/3、2/3、125% を有効数字 2 桁にした 1.8bb、3.7bb、6.9bb です。チップにすると 180、370、690 です。レイズの 147.6% は、そのベットをコールしたあとのポットに対する上乗せ額です。上乗せを足したストリートの合計額を、再び有効数字 2 桁にします。

1.8bb を例にします。コール後のポットは 5.5 + 1.8 + 1.8 = 9.1bb、その 147.6% は 13.4316bb、合計額は 1.8 + 13.4316 = 15.2316bb で、有効数字 2 桁では 15bb(1500chips)になります。同じ手順で、3.7bb に対するレイズは 23bb(2300chips)、6.9bb に対するレイズは 35bb(3500chips)です。リバーの 730.8% も同じ規則です。リバー開始で 1.8bb に対するレイズは 68bb(6800chips)、3.7bb 以上へのレイズはオールインです。ターン開始の木のリバーでも割合は 730.8% のままで、ポットが大きい線では計算額が残りスタックを超えてオールインになります。

Albaの解き方

Alba は、CFR 系の反復で解きます。CFR は、後悔を小さくしていく反復で、平均戦略を均衡へ近づけます。役の強さそのものはポーカーの役の通常の序列です。

本番の反復は T=128000 です。収束は T=64000 との比較で見ます。その比較は、次の節の表です。この記事の exploitability は、T=128000 の平均戦略の値です。

測ったexploitability

Alba の解について、片方の席を最善応答に置き換え、木の末端まで含めて厳密に計算しました。標本抽出は入っていません。

木T=64000T=128000
リバー AhQc3d / 7h / 9c0.0020.001
リバー Kh8h3h / 9h / 2h0.0000.000
リバー QsTs5d / 2c / 7d0.0020.001
リバー KsKh7c / 2d / 9s0.0020.000
リバー 9h8s7d / 2c / Ah0.0010.000
ターン AhQc3d / 7h0.0040.002
ターン Kh8h3h / 9h0.0050.002
ターン QsTs5d / 2c0.0030.001
ターン KsKh7c / 2d0.0060.002
ターン 9h8s7d / 2c0.0030.001

単位は chips です。記録は 0.001chips 刻みです。T=128000 でいちばん大きいものでも 0.002chips です。0.002 ÷ 550 は約 0.00036% で、開始ポットの 0.001% を下回ります。T=64000 から T=128000 で、10 本とも横ばいか、下がっています。

部品ごとの独立照合

exploitability は Alba 自身のコードで測っています。測る側が間違っていれば、小さい数字に意味がありません。支払と最善応答は、CFR の実装を呼ばない経路で照合しました。末端から戻す値は、コンボを 1 組ずつ数える既存の経路と比べたもので、CFR の外に新しく書いたコードではありません。

支払

役の評価器は、本体とは別に書きました。7 枚から 5 枚をすべて選び、パックした整数は使いません。記事と同じ 5 ボードについて、ランダムな 200 ペアで、リバーのショーダウン、ターンのショーダウン、フロップからの 990 通りの平均が、本体と 10-12 以内で一致しました。990 通りは、フロップの 3 枚と両席のホールカード 4 枚を除いた 45 枚から、ターンとリバーの 2 枚を選ぶ組み合わせです。

公開されているエクイティとも比べました。特定の AA 対 KK を、残る 48 枚から 5 枚を選ぶ 1,712,304 通りで全列挙すると、勝ち 1,411,956、引き分け 7,220、負け 293,128 で一致します。プリフロップ勝率の目安にあるとおり、AA は KK に対して約 82% です。スーツの組み合わせで、この割合はわずかに動きます。ここでの一致は、この内訳の列挙です。

Ah5h9h 上の KhQh 対 99 は、フロップで完成しているナッツフラッシュ対セットです。ボードのハート 3 枚と KhQh のハート 2 枚で、フラッシュはフロップの時点でできています。KhQh 側は 65.56% で、エクイティ計算ツールの値と 10-3 以内でした。

端子は 100 本を、ゲームエンジンの支払と整数で一致させました。内訳は、フロップ 30、ターン 20、リバー 40 のチェックダウンと、上限の効くオールイン 10 です。この端子の照合は、レーキありの木で行っています。

値の計算

ターン開始の木 1 本(KsKh7c 2d)で、末端から戻した値を、コンボを 1 組ずつ数える既存の経路と比べました。この参照は、CFR の外に新しく書いたコードではありません。照合に使ったのは、数反復で混合の入った戦略と、両席の疎なレンジです。本番の 128000 反復そのものは、この照合にはかけていません。

ターンの全ノードと、リバー 3 枚の全履歴で、値は相対 10-9 以内で一致しました。3 枚は、残る 48 枚のうち先頭、中ほど、末尾です。

最善応答

最善応答の照合は、本体の最善応答のコードを呼ばずに行いました。

  • 常にフォールドする相手への最善応答の値は、ポットの没収額と一致した。
  • 常にチェックする相手への最善応答は、チェックダウンの支払の最大と 10-12 以内で一致した。
  • 1 ストリートの木で、コンボごとに純粋戦略 214 本を全部列挙した。その最大は、混合の入った相手とレーキありでも、本体の最善応答の値と 10-12 以内で一致した。
  • リバーの 2 ノードでは、純粋戦略 864 本を列挙して、10-9 以内で一致した。
  • ランダムな純粋戦略 200 本の値は、どれも最善応答の値を超えなかった。

再現性と零和

レーキありの木では、スレッド数 1、2、4、16 で、平均戦略と exploitability がビット単位で同じでした。命令セットを、汎用の x86-64 と FMA ありとで変えても、同じビットになりました。ビット単位とは、浮動小数のビット列が一致したことです。

ターン開始の木では、スレッド 1 本と 5 本でビット単位で同じでした。各反復で、両席の値の和は 50chips と 10-9 以内で一致します。リバー開始の木 1 本(AhQc3d 7h 9c)では、ダミーの支払で、両席の和は 50chips と 10-6 以内、スレッド 1 本と 2 本の平均戦略は 10-9 以内で一致します。

この10本では未照合の箇所

上の照合のうち、支払、最善応答の全列挙、スレッド数 1・2・4・16、命令セットの再現性は、同じ支払と最善応答のコードを使う、レーキありの別の木で行いました。

照合この 10 本レーキありの別の木
ターン開始で、末端から戻した値1 本(KsKh7c 2d)。リバーは 48 枚中 3 枚—
零和(両席の和は 50chips)ターン開始 1 本(KsKh7c 2d、10-9)。リバー開始 1 本(AhQc3d 7h 9c、ダミーの支払、10-6)—
スレッドを変えた一致ターン開始 1 本で、1 本と 5 本がビット一致。リバー開始 1 本で、1 本と 2 本が 10-9(ダミーの支払)1、2、4、16 がビット一致
命令セット(x86-64 と FMA)まだした
役の評価器、公開エクイティ、端子 100 本間接。同じ 5 ボードで評価器を照合し、ターン開始 1 本で末端から戻した値と参照実装を照合。端子はレーキありした
最善応答の全列挙まだ1 ストリートと、リバー 2 ノード
最善応答の値 ≥ 戦略自身の値ターン開始 1 本(KsKh7c 2d)と、リバー開始 1 本(AhQc3d 7h 9c、ダミーの支払)—

この 10 本の木で、最善応答を全列挙して照合したことは、まだありません。この 10 本で直接見た最善応答は、ターン開始 1 本とリバー開始 1 本で、その値が戦略自身の値以上であることまでです。

まとめ

  • Alba は、nlh.poker の自作 GTO ソルバーです。今回紹介するのは、BTN 対 BB のポストフロップ部分ゲーム 10 本です。
  • その 10 本で、Alba の解の厳密な exploitability は 0.002chips 以下でした。
  • 支払は、本体とは別に書いた評価器と、公開されているエクイティで照合しました。末端から戻す値は、コンボを 1 組ずつ数える既存の経路と照合しました(CFR の外に新しく書いたコードではありません)。最善応答は、本体の最善応答のコードを使わない方法(解析的に決まるケースと、純粋戦略の全列挙)で照合しました。全列挙は、この 10 本ではなく、同じコードを使う別の木で行いました。
  • 支払と最善応答の照合の多くは、レーキありの別の木で行いました。
  • プリフロップから続く全体と、この 10 本以外のボードは、検証が終わっていません。

Alba の開発は、今後も続けます。あわせて、nlh.poker との統合を進めていきます。

この記事をシェア

← 記事一覧に戻る