Introducing Alba, Our GTO Solver

Author:Stray Cat
Published:
Columns

Introducing Alba, Our GTO Solver

Introducing Alba, nlh.poker's in-house GTO solver. This article publishes what we have verified so far.

Alba is nlh.poker's in-house GTO solver. For a game you specify, it computes a strategy that is hard for an opponent to exploit. What GTO means is covered in What is GTO poker? This article introduces Alba.

For this release we solved 10 postflop subgames of BTN against BB. Five start on the turn and five start on the river. For the average strategy at iteration T=128000, exact exploitability was at most 0.002 chips. That is under 0.001% of the 550-chip starting pot. The figures are measurements as of 2026-10-06.

What Alba is

Alba turns part of Texas Hold'em into a game tree and finds an average strategy with a CFR-family iteration. Closeness of the solution is measured by exploitability. How that number is computed is in the later sections. What this release can report is the following two items.

  • Exact exploitability of Alba's solution on these 10 trees.
  • A check of the calculation behind that number, split into payoffs, values passed back from the end of the tree, and best response. The value check compares an existing code path.

Two things are not verified yet.

  • The quality of a full strategy that continues from preflop.
  • Agreement on boards other than these 10, or on trees of a different size.

What exploitability is

Exploitability is the expected value a strategy loses when the opponent answers as well as possible. One seat is replaced by a best response through the leaves, with no branches sampled away. Doing this for both seats produces one number:

exploitability = (BTN best-response value + BB best-response value − game value) / 2

The game value is a constant that does not depend on the strategy. In this accounting it is 50 chips, the same amount as the dead money in the pot. Each seat's value is profit after the 250 chips that seat has already put in, so the sum of the two seats is not the 550-chip starting pot. The zero-sum section checks that this sum is 50 chips. The closer exploitability is to 0, the harder this pair of strategies is to exploit inside this game. That is the hard-to-exploit idea in exploitative vs GTO, turned into a number for one game.

A bug in the payoff or in the best response makes this number falsely small. The figure still looks clean, so the bug is harder to notice than one that stops the iteration from converging. The checks later in the article are there for that reason.

The game

The format is BTN against BB, postflop only. The small blind has folded, and that 0.5bb (50 chips) is dead money. BTN and BB have each put in 2.5bb (250 chips). The starting pot is 5.5bb (550 chips). After the flop, BB acts first. The remaining stack is 97.5bb (9750 chips). 1bb = 100 chips.

ItemValue
FormatBTN vs BB, postflop only. BB acts first
Starting pot5.5bb (550 chips). 250 chips each from BTN and BB, plus 50 chips from the folded SB
Remaining stack97.5bb (9750 chips) for each player
RangesAny two cards for both. Every combo that does not conflict with the board, at equal weight
Rake0
BB sizesCheck, 1/3 pot, 2/3 pot, 125% pot
Facing a betFold, call, or one raise size
Facing a raiseFold or call only. No reraise
RaiseAdded on top of the pot after the call: 147.6% on the turn and 730.8% on the river. Turn-start trees keep 730.8% on the river even when the pot is already large. Amounts above the remaining stack become an all-in
RoundingTwo significant figures

Five boards

Suit letters are h for hearts, d for diamonds, c for clubs, and s for spades. T is 10. Each board has one turn-start tree and one river-start tree. A turn-start tree deals the flop and the turn. A river-start tree deals through the river.

FlopTurnRiver
AhQc3d7h9c
Kh8h3h9h2h
QsTs5d2c7d
KsKh7c2d9s
9h8s7d2cAh

The five textures are an ace-high board, monotone hearts, broadway, a paired king, and a straight board. They are not claimed to stand for every board.

Sizes to two significant figures

BB's turn bets are 1/3, 2/3, and 125% of 5.5bb, rounded to two significant figures: 1.8bb, 3.7bb, and 6.9bb. In chips that is 180, 370, and 690. The 147.6% raise is the amount added on top of the pot after calling that bet. The street total, including that addition, is rounded to two significant figures again.

Take 1.8bb. The pot after the call is 5.5 + 1.8 + 1.8 = 9.1bb. 147.6% of that is 13.4316bb. The street total is 1.8 + 13.4316 = 15.2316bb, which is 15bb (1500 chips) at two significant figures. The same steps make the raise facing 3.7bb into 23bb (2300 chips), and the raise facing 6.9bb into 35bb (3500 chips). The river uses the same rule at 730.8%. On a river-start tree, the raise facing 1.8bb is 68bb (6800 chips), and a raise facing 3.7bb or more is an all-in. Turn-start trees keep the river percentage at 730.8%. On lines where the pot is already large, the computed amount exceeds the remaining stack and becomes an all-in.

How Alba solves it

Alba solves the game with a CFR-family iteration. CFR shrinks regret over repeated passes and moves the average strategy toward equilibrium. Hand rank itself is the usual order in poker hand rankings.

The production run is T=128000. Convergence is read by comparing T=64000. That comparison is the table in the next section. The exploitability in this article is the value of the T=128000 average strategy.

Measured exploitability

For Alba's solution, one seat was replaced by a best response and the value was computed exactly through the leaves. Nothing was sampled.

TreeT=64000T=128000
River AhQc3d / 7h / 9c0.0020.001
River Kh8h3h / 9h / 2h0.0000.000
River QsTs5d / 2c / 7d0.0020.001
River KsKh7c / 2d / 9s0.0020.000
River 9h8s7d / 2c / Ah0.0010.000
Turn AhQc3d / 7h0.0040.002
Turn Kh8h3h / 9h0.0050.002
Turn QsTs5d / 2c0.0030.001
Turn KsKh7c / 2d0.0060.002
Turn 9h8s7d / 2c0.0030.001

The unit is chips. The record is in steps of 0.001 chips. At T=128000 the largest value is still 0.002 chips. 0.002 / 550 is about 0.00036%, under 0.001% of the starting pot. From T=64000 to T=128000, every tree stayed flat or went down.

Checks on each part

Exploitability is measured by Alba's own code. If the measuring code is wrong, a small number means nothing. Payoffs and best response were checked on paths that do not call the CFR implementation. Values passed back from the end of the tree were compared with an existing path that counts combos one pair at a time. That reference is not new code written outside CFR.

Payoffs

The hand evaluator was written separately from the main one. It tries every 5-card subset of 7 cards and does not use packed integers. On the same five boards as this article, for 200 random pairs, the river showdown, the turn showdown, and the average of the 990 flop runouts matched the main evaluator within 10-12. Those 990 runouts are the ways to choose the turn and the river from the 45 cards left after the three flop cards and the four hole cards.

We also compared published equity. A full enumeration of one specific AA against KK, over all 1,712,304 ways to choose 5 cards from the remaining 48, matches 1,411,956 wins, 7,220 ties, and 293,128 losses. As the preflop equity chart says, AA wins about 82% against KK. The suit layout moves that share slightly. The match here is this enumerated split.

KhQh against 99 on Ah5h9h is a made nut flush against a set. Three hearts on the board plus the two hearts in KhQh mean the flush is already complete on the flop. KhQh has 65.56%, within 10-3 of the figure from an equity calculator.

One hundred terminals matched the game engine's payoff in integers. The split is 30 flop, 20 turn, and 40 river checkdowns, plus 10 capped all-ins. That terminal check was run on raked trees.

Value calculation

On one turn-start tree, KsKh7c 2d, values passed back from the end of the tree were compared with an existing path that counts combos one pair at a time. That reference is not new code written outside CFR. The check used a mixed strategy after a few iterations and sparse ranges on both seats. The production run of 128000 iterations was not put through this check.

Every turn node, and every history on 3 river cards, agreed within a relative 10-9. The 3 cards are the first, middle, and last of the 48 that remain.

Best response

The best-response check did not call the main best-response code.

  • Against an opponent who always folds, the best-response value matched the amount taken from the pot.
  • Against an opponent who always checks, the best response matched the maximum checkdown payoff within 10-12.
  • On a one-street tree, all 214 pure strategies per combo were enumerated. The maximum matched the main best-response value within 10-12, including against a mixed opponent and with rake.
  • On a river tree with two nodes, 864 pure strategies were enumerated and matched within 10-9.
  • None of 200 random pure strategies exceeded the best-response value.

Reproducibility and zero-sum

On raked trees, thread counts 1, 2, 4, and 16 produced a bit-identical average strategy and exploitability. Switching the instruction set between generic x86-64 and FMA also produced the same bits. Bit-identical means the floating-point bit patterns matched.

On the turn-start tree, 1 thread and 5 threads were bit-identical. On each iteration, the sum of the two seats' values matched 50 chips within 10-9. On one river-start tree, AhQc3d 7h 9c, with a dummy payoff, the sum of the two seats matched 50 chips within 10-6, and the average strategies from 1 thread and 2 threads matched within 10-9.

What these 10 trees do not yet confirm

Of the checks above, the payoffs, the full best-response enumeration, thread counts 1, 2, 4, and 16, and the instruction-set check were run on other raked trees that share the same payoff and best-response code.

CheckThese 10 treesOther raked trees
Values passed back, turn-startOne tree (KsKh7c 2d). 3 of 48 rivers—
Zero-sum (the two seats sum to 50 chips)One turn-start tree (KsKh7c 2d, 10-9). One river-start tree (AhQc3d 7h 9c, dummy payoff, 10-6)—
Agreement across thread countsOne turn-start tree: 1 and 5 threads, bit-identical. One river-start tree: 1 and 2 threads within 10-9 (dummy payoff)1, 2, 4, and 16, bit-identical
Instruction set (x86-64 and FMA)Not yetYes
Hand evaluator, published equity, 100 terminalsIndirect. The evaluator was checked on the same five boards, and values passed back were checked against the reference on one turn-start tree. The terminals are rakedYes
Full best-response enumerationNot yetOne street, and a two-node river
Best-response value ≥ the strategy's own valueOne turn-start tree (KsKh7c 2d) and one river-start tree (AhQc3d 7h 9c, dummy payoff)—

Best response has not been fully enumerated on these 10 trees. The best response seen directly on these trees is only that, on one turn-start tree and one river-start tree, its value is at least the strategy's own value.

Summary

  • Alba is nlh.poker's in-house GTO solver. This introduction covers 10 postflop subgames of BTN against BB.
  • On those 10 trees, the exact exploitability of Alba's solution was at most 0.002 chips.
  • Payoffs were checked with an evaluator written separately from the main one, and against published equity. Values passed back from the end of the tree were checked against an existing path that counts combos one pair at a time (that path is not new code written outside CFR). Best response was checked without the main best-response code, using cases that can be settled analytically and a full enumeration of pure strategies. The full enumeration was not run on these 10 trees, but on other trees that use the same code.
  • Most of the payoff and best-response checks were run on other raked trees.
  • A full strategy continuing from preflop, and boards other than these 10, are not finished.

Development of Alba will continue. Integration with nlh.poker will continue with it.

Share this article

← Back to articles