UPI (Universal Poker Interface) documentation.

This protocol is used by PioVIEWER and other tools to communicate with PioSOLVER.

The architecture was inspired by UCI (http://en.wikipedia.org/wiki/Universal_Chess_Interface). Similarly to UCI, UPI allows programmers to create their own tools based on PioSOLVER engine as well as easy scripting for non­programmers.

LAST EDITED: June 2021 (PioSOLVER 2.0.6)

Essentials

­When you try to understand how to obtain data or results from the solver the best way is to follow the above mentioned points and do it in PioViewer. PioViewer is not a privileged program in any way, it uses the very same text interface which is available to you.

UPI Basics

UPI Commands

Breaking changes with PioSolver 1.10 UPI

Writing first program communicating with PioSolver

UPI Basics

Solver input and output  link

Solver is a program that communicates via standard I/O.

Commands

Solver responds to commands from viewer.

  • Command from viewer is a single line sent to solver's Standard Input but empty lines and lines starting with hash character (#) are ignored.
  • Each command from solver gets a response from a solver.
    • The client can send many commands without waiting for a reply from solver
    • The solver will answer all commands in the same order in which they are sent to the solver.
  • Solver's reponse can be one or more lines or an error.
  • When running solver from another program it's recommended to call "set_end_string END" command at the start. The solver will print the END string after each response.

If the given command doesn't request data of any kind solver will respond with<command> ok!.

Other communication

Solver sometimes can print to stdout lines which are not command responses. Notably they are:

  • Lines sent by solver at the startup.
PioSOLVER-edge 2.0 (Jan 01 2021, 00:00:01)
(c) Piotr Lopusiewicz
registered to piosolver@piosolver.com

it's recommended to send some command to a solver (e.g. set_end_string END or is_ready) and start parsing communication after receiving expected response (e.g. is_ready ok!)

  • Solver Updates

Solver calculation is run in the background and it prints solving updates every now and then. It can be either single line of a from:

SOLVER: stopped (requested)

or a multiline message starting with a line SOLVER: and ending with END string. It's guaranteed that it will not overlap with command responses.

SOLVER:
running time: 52.977
EV OOP: 181.767
EV IP: 293.233
OOP's MES: 242.008
IP's MES: 343.408
Exploitable for: 55.209
END

UPI Commands

General  link

The following list contains commands which are general commands like global solver settings etc.


Request Arguments Response format Description Possible errors
is_ready n/a is_ready ok! useful for checking if solver is initialized
exit n/a n/a kills solver's process
set_end_string string set_end_string ok! sets the string that should terminate every solver response
reset_end_string n/a reset_end_string ok! clears end string setting
show_version n/a number or text human-readable program version
show_build_version n/a number or text build version
show_hand_order n/a List poker hands. E.g.
“AcAd AdAh AdAs ...”
This command always returns all 1326 hands
in the same order. Other commands return
1326 numbers representing e.g. frequency of
hands in a certain spot in this order.
Format: 1326 hands separated by “ “: “2d2c 2h2c 2h2d …”
show_preflop_order n/a List of 169 preflop categories As used for calc_eq_preflop
show_settings n/a many lines with name: value pairs some global solver settings
bench n/a Time taken: float builds a tree about 2.7GB big, runs 6 full
iterations on it; returns running time for those
(but not time taken to build/free the tree).
Shoud take 2s on a good modern CPU.
load_script filename load_script ok! reads commands from file; line after line and
executes them as if they were inserted on
stdin; after reaching EOF goes back to receiving input from stdin.
WARNING: it's not recommended to run this command from another program. Use load_script_silent or manually execute commands one after another.
load_script_silent filename load_script_silent ok! version of load_script that acts as a single command returns only one END string at the end.

The following are the commands related to running / solving the tree.


Request Arguments Response format Description Possible errors
go [n seconds | steps] go ok!
Solver will emit:
SOLVER: started
once running
optional argument runs solver for n seconds or steps;
if omitted solver will run indefinitely (unless accuracy is set and reached)
Returs immediately (it's a non-blocking operation)
stop n/a go ok!
Solver will emit:
SOLVER: started
once running
stop signal and waits for solver to stop (SOLVER: stopped) and then issues stop ok!
Can take considerable amount of time on large trees.
wait_for_solver n/a wait_for_solver ok! waits until solver stops before reading rest ofthe commands from stdin. Useful for scripts if one wants to solve multiple trees (or solve and save for example)
take_a_break int take_a_break ok! stops the solver (if it’s running) and waits n seconds
before going back to reading the input
solver_time n/a a float The time since the current solver instance started in seconds
set_threads int set_threads ok! sets number of threads used by solver and
all functions requaring tree traversal
(like show_range, calc_ev etc.)
set_info_freq int set_info_freq ok! sets how often solver info is released (defeault is every 25 steps)
set_accuracy float [chips | fraction] set_accuracy ok! accuracy at which solver stops. default is 0 (never).
If optional argument is provided the value is treated either asabsolute value (chips) or fraction of the pot (fraction). “chips” is the default.
set_recalc_accuracy float float float set_recalc_accuracy ok! sets accuracy for flop/turn/river recalculations
(which occur when calling solve_partial or
browsing incomplete tree or
browsing a tree with auto_recalc on.
set_always_recalc street timeout set_always_recalc ok! Enables automatic recalculation of nodes.
First argument is street (3 for Flop etc., 4 Turn, 5 River).
The second argument is timeout in miliseconds.
If street is set to 0 then the feature is disabled.
When the feature is enabled then solver will always recalculate specified streets
to recalc_accuracy or specified time limit (whichever is reached first)
Example: set_always_recalc 4 5000 will always recalculate turn branches when visiting turn / river nodes.
set_isomorphism int int set_isomorphism ok! 1st argument ­ isomorhism on/off for flop trees
2nd argument ­ isomorphism on/off for turn trees
the default is on on the flop off on the turn
change_step float change_step ok! Change solving step parameter (the higher the more aggresive changes solver will make).
show_step n/a float returns current value of step parameter.
show_iters n/a int shows the number of solving iterations performed on the current tree.
set_first_iteration_player OOP | IP set_first_iteration_player ok! Setting determines during a full iteration if OOP or IP does strategy adjustment first.

Commands related to building the tree.

Building a postflop tree consists of

  • setting global state first (range, stacks, board)
  • adding betting lines
  • executing build_tree command

Building a preflop tree consists of

  • setting global state first (ranges, stacks)
  • adding preflop betting lines
  • building pure preflop tree
  • setting postflop trees and adding them to postflop exits
  • specifying flops subset
  • building full preflop tree by executing add_all_flops command

Postflop tree building  link


Request Arguments Response format Description Possible errors
set_range OOP IP 1326 floats set_range ok! sets range for IP/OOP in global state
set_eff_stack int Set_eff_stack ok! Sets effective stack in a global state. This is used in tree building to recognize which nodes are all­in nodes and which aren’t.
set_board cards (e.g. AcKdJc) set_board ok! sets board in a global state
set_pot int int int set_pot ok! Sets starting pot (oop, ip, dead)
add_line series of numbers representing bet sizes (cumulative) add_line ok! 0 30 30 30 90 represents
a check OOP, bet IP, a call, a check on the turn and a bet of 60 (90 total invested).
See more examples in sample scripts.
remove_line series of numbers representing a line to remove remove_line ok! remove_line uses the same syntax as add_line. It’s possible to remove calls and folds as well:
0 30 0 removes a fold for OOP player in response to c­bet
force_line series of numbers representing bet sizes force_line ok! removes all the lines which don’t lead to the one being forced (so any line of which forced line isn’t a prefix of)
clear_lines n/a clear_lines ok! resets the state created by add_line, remove_line and force_line
build_tree [mem_pessimistic mem_ignore] build_tree ok! build a tree based on a config created by global state and calling add_line and remove_line.
Optional argument specifies the behavior in context of memory estimation.
mem_ignore - no memory check should be performed
default (no argument) - The tree will only be build if there is enough free memory to build it.
mem_pessimistic - The tree will only be build if there is enough free memory to build a tree on an unpairded rainbow board.

Preflop tree building  link


Request Arguments Response format Description Possible errors
add_preflop_line Series of numbers representing bet sizes (cumulative) Add_preflop_line ok! Identical as add_line but builds a pure preflop tree (one street)
remove_preflop_line Series of numbers representing a line to remove remove_preflop_line ok! Same as remove_line but for preflop
clear_preflop_lines n/a Clear_preflop_lines ok! Clears preflop tree structure created by add_preflop_line
build_preflop_tree n/a Build_preflop_tree ok! Builds a pure preflop tree using a descriptioin as defined by add_preflop_line’s commands.
add_to_subset float card card card Add_to_subset ok! Adds a specified board with specified weight to a flop subset.
That subset can be then used to build a full preflop tree with selected flops
reset_subset n/a Reset_subset ok! Clears the current flop subset
show_subset n/a (multiline)
weight1 board1
weight2 board2
….
Prints current flops with weights from the flop subset.
recover_subset n/a recover_subset ok! if preflop tree is loaded then it replaces current flop subset with the subset from this tree.
add_schematic_tree nodeID add_schematic_tree ok! Attaches a postflop abstraction to a chosen preflop exit. NodeID must point to a SPLIT_NODE which is a valid preflop exit.Current schematic tree (one created by add_line commands) is attached.
The way to use this command is to build a postflop tree with add_line commands,attach it to a chosen preflop exit; reset it, build another postflop tree,attach it to another preflop exit etc.
add_all_flops n/a add_all_flops ok! Uses flops in a current flop subset to build a full preflop tree.

Additional tree building settings  link


Request Arguments Response format Description Possible errors
list_algorithms n/a n lines with 3 comma separated values
code, name, description
example line:
original_pio,Original PioSolver,Original PioSolver algorithm that uses less memory
set_algorithm algorithm_code set_algorithm ok! Sets one of the available algorithms.
Algorithm is a property of a tree. It's decided at the moment of building a tree(not solving) and can't be changed afterwards.
Possible values: auto, pio_cfr, original_pio
ignore_mem_check on | off ignore_mem_check ok! if set to "on" then the memory check will not be performed before building a tree.
small_strats on | off small_strats ok! The setting controls if float32 or float16 should be used to hold strategies.
Possible values:
on: use float16
off: use float32
auto: use float16 for preflop trees and float 32 for other.
estimate_tree n/a human readable estimate Estiamtes preflop tree with current subset
estimate_schematic_tree n/a human readable estimate Estiamtes postflop tree with different algorithms
show_memory n/a Total Physical Memory: 65214 MB
Available Phys Memory: 45093 MB
information about available memory in the system

Traversing the tree / strategies / etc  link


Request Arguments Response format Description Possible errors
is_tree_present n/a true | false returns true if a tree the solver is operating on exists
show_node nodeID (multiline)
nodeID
NODE_TYPE
board
pot
children_no
flags: f1 … f2
the number of flags can vary from 0 to 64
they are separated by space
show_children nodeID (multiline)
child 0:
….
…..
child 1:
….
are in the same format as show_node
show_effective_stack n\a int shows the effective starting stack of the current tree
show_range OOP | IP [nodeID] 1326 floats range in given node
dead hands have weight 0.If only one argument is given then IP/OOPrange from solver state is shown (the one set by set_range)
show_strategy nodeID (multiline)
1326 floats
1326 floats
….
n'th line represents frequency of n’th action with i’th hand
Error if nodeID doesn’t represent decision node
show_strategy_pp nodeID human readable sorted (by equity vs ALL) output Error if nodeID doesn’t represent decision node
calc_ev OOP | IP nodeID (2 lines)
1326 floats
1326 floats
EV of a given player in a given node for all hands. Numbers in the first line are EV, in the second are matchups.
calc_ev_pp OOP | IP nodeID wins / matchups in human readable format EV of a given player in a given node for all hands. Numbers in the first line are EV, in the second are matchups.
calc_eq OOP | IP (2 lines)
1326 floats
1326 floats
eq in the first line, matchups in 2nd
board/ranges taken from solver state (set_range, set_board to set)
calc_eq_pp OOP | IP in human readable form
calc_eq_node OOP | IP nodeID (3 lines)
1326 floats
1326 floats
1 float
calculate equity for given player assuming ranges in given node
Output format:
1st line: equities
2nd line: matchups
3rd line: total
calc_eq_preflop OOP | IP ( 3lines)
169 floats
169 floats
1 float
Calculates preflop equity from IP/OOP range as set by set_range command.
It assumes weights for isomorphic (7s6s = 7h6h) combos is the same.
The results are unpredictable/incorrect if that’s not the case.
Output format:
1st line: equities
2nd line: matchups
3rd line: total
calc_results n/a (multiline)
running time: float
EV OOP: float
EV IP: float
OOP’s MES: float
IP’s MES: float
exploitable for: float
calculates EV’s/MES’es in root and prints the whole info
calc_matchups_line nodeID float The total number of matchups in given line. (can be used to calculate relative probability of different lines)
calc_line_freq nodeID float Absolute probabality of reaching certain line.
calc_global_freq nodeID float Absolute probabality of reaching certain node (assuming the node's runout has been selected).
show_all_lines n/a (multiline)
All lines
Lists all lines in the tree.
show_all_freqs global | local [pp] (multiline)
All lines with corresponsing frequencies
Lists all lines in the tree with corresponding frequncies either local (probability of takinglast action) or global (probability of this line being played); optional argument pp (prettyprint) makes the output easier to read for a human
show_win_evs IP | OOP nodeId 3 numbers This command can be used to see the ICM structure of a tree.
NodeID must denote a final node (either fold, allin or last node on the River)
The result numbers tell what will be the EV of a given player in this node in case he wins / loss / tie.
For non-ICM trees the OOP and IP values are always the same.
For fold nodes three numbers are always identical.
Example values wihtout ICM:
show_win_evs OOP r:0:b99:b200:c
380 -200 90
show_win_evs IP r:0:b99:b200:c
380 -200 90
Example values from the same tree after adding some ICM structure:
show_win_evs OOP r:0:b99:b200:c
29.2733116 -20.3105125 7.67309189
show_win_evs IP r:0:b99:b200:c
32.3092041 -25.1925144 8.78540993

Tree Information  link


Request Arguments Response format Description Possible errors
add_info_line text add_info_line ok! adds a line to tree information.
reset_tree_info n/a reset_tree_info ok! clears tree information.
show_tree_info n/a (multiline) shows all lines either added by add_info_line or loaded from the tree.

small trees


Request Arguments Response format Description Possible errors
rebuild_forgotten_streets n/a rebuild_forgotten_streets ok! rebuilds all turns/rivers if this is a small tree. It's possible to resume solving after that
estimate_rebuild_forgotten_streets n/a One line e.g:
Rebuild tree. Memory needed: 50519 MB; available: 47930 MB
Memory needed to rebuild current tree and available memory.
solve_partial nodeID solve_partial ok! solve a tree from given node to accuracy in settings.accuracy
solve_all_splits n/a solve_all_splits ok! solve all unsolved parts of the tree (after rebuilding forgotten streets of a small save). Solves to accuracy defined in settings.recalc_accuracy(it may take a long time)
explo_partial nodeID float returns exploitability for a subtree strating from given node

Additional commands  link


Request Arguments Response format Description Possible errors
stdoutredi filename - ­ redirects stdout to file
stdoutredi_append filename ­- redirects stdout to file but appends it instead of overwriting
stdoutback n/a stdoutback ok! standard output back to console (might be useful when using text interface, not for GUI)
print_all_strats n/a many lines - each line has either nodeID or 1326 numbers prints nodeID for all nodes in the tree and additionaly strategies for decision nodes.
node_count n/a many lines counting different types of nodes e.g.
H_DEC: 339
FLOP 0
TURN 3
RIVER 336
for each type of node (H_DEC, V_DEC, SPLIT, END, ROOT) prints how many nodes of this kind are in the tree on each street.
clear_cache n/a clear_cache ok! clears cached results in the tree
show_cpu_info n/a e.g. number of CPUs: 16
max threads: 16
thread limit is: 2147483647
affinity policy is: 0
Some information about CPU
show_nuts OOP | IP board one line per live hand
hand - number
show how many combos in villain range are winning against given hadn (0 for nuts)

Range Explorer  link


Request Arguments Response format Description Possible errors
show_category_names n\a 2 lines:
hand strength categories
draw categories
Shows names of hand/draws categories which are then used for range analysis. E.g.
nothing king_high ace_high (...) top_fullhouse quads straight_flush
no_draw 4out_straight_draw 8out_straight_draw flush_draw combo_draw
show_categories board 2 lines:
1326 ints
1326 ints
In the first line the are made hand category assignments for each combo and in the second line are draw category assignments for each combo.
Number 0 in the first line denotes nothing, number 1 denotes king_high etc. In the second line number 0 denotes no_draw, etc.
show_cats board 6 lines: 1326 ints each 1st line: hand eval (the higher number the stronger made hand)
2nd line: category (as in 1st line of show_categories)
3rd line: total number of draw outs
4th line: number str8 draw outs
5th line: number of flush draw outs
6th line: number of fullhouse draw outs
show_cats_pp board many lines same as show_cats but in human readable format
echo some text some text prints back the first argument
repeat int some text some text
some text
prints back some text specified number of times (can be useful to test i/o throughput)

Alternative EV models  link

The EV in a tree can be adjusted either with set_rake or set_icm command. It's not possible to use both at the same time.


Request Arguments Response format Description Possible errors
set_rake float int set_range ok! Sets rake in the tree. First argument is fraction of the final pot that is taken as a rake.Second argument is maximum rake taken. E.g. The following command sets 5% rake up to 10 chips
set_rake 0.05 10
To turn off rake set_rake 0 0
set_icm_point OOP | IP int float set_icm_point ok! Sets ICM point for a given player.
For a given final stack size in chips it sets the ICM value of this stack.
The final stacks in chips should be stacks from ICM structure set with set_icm (one player can have higher starting stack than effective stack).
reset_icm_tables n/a reset_icm_tables ok! clears all set icm points
set_icm int int set_icm ok! numbers are player's stacks (OOP and IP). Smaller of these two numbers should be equal to effective stack.

Setting strategies and node locking  link


Request Arguments Response format Description Possible errors
eliminate_path nodeID eliminate_path ok! Sets strategy to 0 for this action in specified line across all runouts.
lock_node nodeID lock_node ok! Locks the strategy in given node for all hands.
unlock_node nodeID unlock_node ok! Unlocks the strategy in a given node.
combo_lock_node nodeID 1236 ints combo_lock_node ok! Locks the strategy in a given node for specified combos.Range argument should have 1 for hands that are meant to be locked and 0 for hands that are not supposed to be locked.
show_locked_combos nodeID 1326 numbers 1 for locked hands 0 for not locked
set_strategy nodeID N x 1326 floats Sets strategy in a given node.
i-th out of N group of 1326 floats denotes strategy for the i-th child of a node (in the order returned by show_children).
The numnbers for each combo should add to 1. If they don't the solver will adjust them so that they do.
set_equal_strats n/a set_equal_strats ok! sets equal strategies in the whole tree.
set_mes OOP | IP set_mes ok! sets most explotive strategy for a player in the whole tree.
round_up_to OOP | IP int street E.g. round_up_to IP 5 flop
Will round all strategies of an IP player in the tree on the flop to multiples of 1/5.
round_up_to OOP 2 river
Will round all strategies of an OOP player.

Scripting   link


Request Arguments Response format Description Possible errors
skip_if_done filename label skip_if_done ok! checks if a filename exists if yes, skips all the lines in the script until label is encountered
LABEL: labelname none labels a place in the script; this is used by skip_if_done command above(remember to include a space after a colon and before the label name)

Save / load / read files  link


Request Arguments Response format Description Possible errors
load_tree filename load_tree ok! Loads the tree from the content of the save file into memory.
State.root points to this tree
i/o errors, file format error, out of memory
dump_tree Filename [full | no_turns no_rivers ]\ dump_tree ok! saves current tree to disc; if optional argument is provided (no_turns or no_rivers)a small save will be made while the whole tree is preserved in memory.
free_tree n/a free_tree ok! deletes current tree and frees the memory.
show_metadata filename (multiline) shows metadata about the specified save file Without loading a tree it prints information ontains information from following commands:
show_node r
show_range OOP r
show_range IP r
show_tree_info
show_save_version filename one line tells if the save is a piosolver tree file and shows internal version number of save file.

Activating / deactivating licence  link


Request Arguments Response format Description Possible errors
deactivate filename label Deactivation successful! Deactivates licence and exits solver.

If the program is not activated then the PioSolver will print only one line requesting user to provide a key.

Enter your activation key:

If the activation is successful the solver will print

ERROR code 0:
OK!
Activation ok!

and start normally.

Breaking changes with PioSolver 1.10 UPI

Overview  link

Listed below are changes that could break existing client code and not all changes between 1.x and 2.x version of UPI.

End strings  link

PioSolver 2.x behavior

The client is expected to call set_end_string at the start of communication and then output from all commands will end with specified END string.

If the set_end_string command is not called then END string is never shown.

> set_end_string END
set_end_string ok!
END
> is_ready
is_ready ok!
END

PioSolver 1.x behavior

Some commands are single line (the result is always a single line) and some are multi-line (the result is many lines terminated with END).

> is_ready
is_ready ok!
> calc_results
EV OOP: 132.353
EV IP: 47.647
OOP's MES: 331.413
IP's MES: 247.089
Exploitable for: 199.251
END

set_strategy  link

PioSolver 2.x behavior

set_strategy takes as an argument N * 1326 floats where N is the number of children and each block of 1326 numbers denotes strategy for subsequent child.

set_strategy r:0 <1326 floats> <1326 floats> <1326 floats>

PioSolver 1.x behavior

In PioSolver 1.x the client is required to call set_strategy N times each time with 1+1326 arguments, where the first argument was an index of a child node and following 1326 floats were strategy.

set_strategy r:0 0 <1326 floats>
set_strategy r:0 1 <1326 floats>
set_strategy r:0 2 <1326 floats>

set_board, show_categories  link

PioSolver 2.x behavior

All commands which expect board as an argument require that cards are not separated by space.

> set_board AcAdAh
set_board ok!
END
> set_board Ac Ad Ah
ERROR: set_board incorrect or missing argument
END
> show_categories Qc8c7d
<numbers>
<numbers>
END
> show_categories Ac Ad Ah
ERROR: show_categories incorrect or missing argument
END

PioSolver 1.x behavior

set_board and show_categories expect board as N separated cards.

> set_board Ac Ad Ah
set_board ok!
> set_board AcAdAh
ERROR: set_board incorrect or missing argument
> show_categories Ac Ad Ah
<numbers>
<numbers>
END
> show_categories AcAdAh
ERROR: show_categories incorrect or missing argument

Writing first program communicating with PioSolver

What is UPI client?  link

UPI client is a program that communicates with PioSolver via UPI.

Do you have any example code?  link

We have a github project which contains example code in C# and python that can help you easily start writing your own programs that communicate with the solver.