Hi, all.
I am trying to understand poker isomorphism. Right now I'm trying to reproduce the "canonical one player" combination counts that are presented in this paper. My results match the 1,286,792 number for flop. But for turn I get 48,540,726 instead of 55,190,538.
My approach consists of two steps: 1) canonical board sequences 2) strategically different hands for a given board.
1) canonical board sequences.
On PREFLOP the board is empty.
On FLOP two boards are equivalent if one can be obtained from the other by permutating the suits. I pick the board whose suits are lexicographically ordered as the "canonical" one.
On TURN the canonical boards are found as follows. Assume the suits are ordered as follows: cdhs. So we will say that clubs precedes diamonds, diamonds precedes spaces (by transitivity) etc. When obtaining a TURN board from a FLOP board we see if there are suits with the same sets of cards. An example of such board would be (2c, 4d, 4h). In such cases we add the 4th card only to the first of the equivalent suits. So, for example, (2c, 4d, 4h, 5d) would be a "canonical" TURN board, while (2c, 4d, 4h, 5h) woudln't.
I haven't yet got to thinking about canonical RIVER boards.
2) canonical hands for a given board.
Here I have implemented a function that given a board and a pair of hole cards converts these hole cards to a "canonical" pair. Equivalent hole card sets should be converted to the same pair of cards.
My logic here is as follows. If it is possible that there will be 3+ cards of a suit on the 5-card board then we say that this suit "can be a flush". For example for a FLOP board (5c, Qc, 2d) clubs and diamonds can be a flush while hearts and spades can't. So if in our hand we have a card of a suit that can be a flush, then we cannot freely change this card's suit. We can only do this if there is another suit that has exactly the same cards on the board. On the other hand if we have a card of a non-flush suit, then we are free to change the suit to any other non-flush suit (subject to not having duplicate cards afterwards). The code for "normalizing" hands is provided below.
Code:
void NormalizeHand( const Cards_set& board, short c1, short c2, short& c1Out, short& c2Out )
{
unsigned mask[4] = {0};
unsigned cardCount[4] = {0};
for( unsigned i = 0; i < board.cards.size(); ++i )
{
mask[board.cards[i].get_suit()] |= (1 << board.cards[i].get_power());
++cardCount[board.cards[i].get_suit()];
}
bool canBeFlush[4];
for( int i = 0; i < 4; ++i )
canBeFlush[i] = ( 3 <= cardCount[i] + 5 - board.cards.size() );
Card card1;
card1.set_number( std::min(c1, c2) );
Card card2;
card2.set_number( std::max(c1, c2) );
int newSuit1 = card1.get_suit();
int newSuit2 = card2.get_suit();
if( canBeFlush[card1.get_suit()] )
{
for( int i = 0; i < card1.get_suit(); ++i )
if( mask[i] == mask[card1.get_suit()] )
{
newSuit1 = i;
break;
}
}
else
{
for( int i = 0; i < 4; ++i )
{
if( !canBeFlush[i] && ( (mask[i] & (1 << card1.get_power()) ) == 0 ) )
{
newSuit1 = i;
mask[i] |= (1 << card1.get_power());
break;
}
}
}
if( canBeFlush[card2.get_suit()] )
{
if( card2.get_suit() == card1.get_suit() )
newSuit2 = newSuit1;
else
{
for( int i = 0; i < 4; ++i )
if( (mask[i] == mask[card2.get_suit()]) && (i != newSuit1) )
{
newSuit2 = i;
break;
}
}
}
else
{
for( int i = 0; i < 4; ++i )
{
if( !canBeFlush[i] && ( (mask[i] & (1 << card2.get_power()) ) == 0 ) )
{
newSuit2 = i;
break;
}
}
}
card1.set_suit( newSuit1 );
card2.set_suit( newSuit2 );
c1Out = card1.get_number();
c2Out = card2.get_number();
}
The overall structure of the algorithm at the TURN stage is as follows. I iterate over all "canonical" TURN boards. From each board I obtain the PREFLOP board (the first 3 cards). Then I go over all possible hand card combinations h1 and obtain the normalized preflop hand h1_preflop, the normalized flop hand h1_flop and the normalized turn hand h1_turn. Then I check if there exists h2 - another pair of hand cards that normalizes to the same h1_preflop, h1_flop, h1_turn and such that h2 precedes h1 in the lexicographic order. If there is no such h2 then h1 in combination with the given turn board is one of the canonical combinations.
Can anyone please point me to an error in my reasoning or suggest an idea for narrowing the search down?
Many thanks.