Poker-AI.org Poker AI and Botting Discussion Forum 2013-04-18T23:04:39+00:00 https://poker-ai.org/phpbb/feed.php?f=25&t=2396 2013-04-18T23:04:39+00:00 2013-04-18T23:04:39+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3884#p3884 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]> alex wrote:

My thinking was that if the payoffs are the same then the strategies will have to be the same.

That's definitely wrong. It's pretty simple to come up with a toy game where two different strategies have the same payoff.

Statistics: Posted by Coffee4tw — Thu Apr 18, 2013 11:04 pm


]]>
2013-04-18T05:47:04+00:00 2013-04-18T05:47:04+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3867#p3867 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]>
I have the same gut feeling that suit rotation is what it boils down to. It would still be nice to have some kind of formal proof of that.

Statistics: Posted by alex — Thu Apr 18, 2013 5:47 am


]]>
2013-04-17T22:18:31+00:00 2013-04-17T22:18:31+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3864#p3864 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]>
I don't think this is possible. There might be very similar cases that might not make a great deal of difference strategically but there are subtle things that do matter. To make your idea work you would need to condense cases where a certain suit hits your holecards with suits that didn't hit your holecards, which is a mistake strategically because they are different in the amount of information they give you as it impacts the possible holdings of your opponent.

For LUTs this might not matter, depending on what kind of LUT you are building but in a strategy sense it matters.

Statistics: Posted by Coffee4tw — Wed Apr 17, 2013 10:18 pm


]]>
2013-04-17T12:41:28+00:00 2013-04-17T12:41:28+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3861#p3861 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]> I am curious whether "being suit isomorphic" is the same as "being strategically equivalent". I realize my example was wrong, but I don't see why there can't be two hand/board combinations that are strategically equivalent and not suit-isomorphic.

My attempt at defining being strategically equivalent is:
There exists a mapping between chance events, such that
- All events that have occured in hand/board combination (1) are mapped to events that have occured in hand/board combination(2)
- If we follow the tree down to the leaves (substituting chance events in tree(1) to what they map to in tree (2)) the payoff should be the same in tree (1) and in tree (2). This must be true for every node that belongs to the round.

Statistics: Posted by alex — Wed Apr 17, 2013 12:41 pm


]]>
2013-04-17T01:01:27+00:00 2013-04-17T01:01:27+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3853#p3853 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]>
@p2bb: I have code that does isomorphism but keeps the order of turn and river intact. That's what you are looking for right? I didn't create an LUT with it but it's actually fairly simple.

Along those lines I actually experimented with just generalizing turn and river suits to 'x' if they can't fill a flush but that became a little too difficult to handle with the Meerkat Card data structure so I scratched the idea. In general it should be possible though. Not sure how much memory you would actually save though and if it's really worth it.

Statistics: Posted by Coffee4tw — Wed Apr 17, 2013 1:01 am


]]>
2013-04-11T07:01:27+00:00 2013-04-11T07:01:27+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3806#p3806 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]>
Let's say we are holding AdAh and the turn board is AcKcQc2d. What cards are left to the other player? 9 clubs, 11 diamonds, 12 hears and 13 spades. The number of possible suited pairs he might be holding is:
45 + 66 + 78 + 91 = 280.
On the other hand if we are holding AhAs the remaining cards are 9 clubs and 12 diamonds, hearts and spades each. The number of suited pairs the other player could possibly have is:
45 + 3 * 78 = 279.

This suggests that there can be no 1-to-1 correspondace between possible opponent's hands in the AdAh and AhAs cases.

Apologies for the statement in my previous post.

Statistics: Posted by alex — Thu Apr 11, 2013 7:01 am


]]>
2013-04-11T05:20:27+00:00 2013-04-11T05:20:27+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3805#p3805 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]>
I am not 100% sure this will not give false positives. Neither do I know at this point how to prove that this will be the MINIMAL combination count.

Statistics: Posted by alex — Thu Apr 11, 2013 5:20 am


]]>
2013-04-11T04:53:34+00:00 2013-04-11T04:53:34+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3804#p3804 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]>
It's a pity that the definition of "canonical" (or a link to one) is not given in this paper. So I believe, strictly speaking, this paper doesn't give the exact MINIMAL amounts of memory needed to store stuff.

Statistics: Posted by alex — Thu Apr 11, 2013 4:53 am


]]>
2013-04-11T02:44:30+00:00 2013-04-11T02:44:30+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3800#p3800 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]> Statistics: Posted by proud2bBot — Thu Apr 11, 2013 2:44 am


]]>
2013-04-10T21:39:28+00:00 2013-04-10T21:39:28+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3797#p3797 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]>
In the example you gave, AdAh and AhAs on a AcKcQc2d board aren't isomorphic by the standard definition of isomorphism I gave above. You can't only do a suit rotation to turn one into the other.

By reasoning about when flushes are and aren't possible, you're trying to get a little bit more of a reduction than is had with the usual definition. That probably can work; you might be able to get a slightly lower number, but it'd be a different type of isomorphism than is usually implied. I don't see a problem so far with the reasoning in your example.

But it might be tricky to tell exactly when you can shrink the number a little more by reasoning about flushes being impossible. For example, lets say we're on the river, there were two spades on the flop and the other three board cards are a club, a heart and a diamond, and we have the ace of spades in our hand. No flushes are possible for anyone in any suit. However, even though we can't make a flush, this state is not strategically identical to hands where our ace was a different suit, because our holding that ace tells us something about the opponent's hand: namely, that they couldn't have been trying for an ace-high flush on the flop. If our ace was a different suit, then they might have been trying for that ace-high flush. Meaning that on the river, my opponent might have a different distribution of hands in these two states. So they aren't strategically equivalent by the usual definition or by your extended one. So yep - you might be able to get a slightly smaller number through this type of reasoning, but (at least so far) I'm not sure it'll be completely simple to tell when hands are strategically equivalent when they aren't isomorphic in the cards.

[Edit: After my example, I should have said that changing the ace to a different suit wouldn't be isomorphic by the usual definition, and they wouldn't be strategically identical because I might rationally choose to act differently in the two states. If your extended notion of isomorphism would say that they're equivalent, then that seems like an error.]

Statistics: Posted by MBJ — Wed Apr 10, 2013 9:39 pm


]]>
2013-04-10T09:28:32+00:00 2013-04-10T09:28:32+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3753#p3753 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]>
Hi, proud2bBot.

Thanks for replying. I found some information in this thread: https://poker-ai.org/archive/www.pokerai.org/pf3/viewtopic3c0f.html?f=3&t=2881&hilit=. Kevin says there that 55190538 is the number of turn combinations "taking into account only suit isomorphisms". MegaZhiraf later replies to this that this number is actually is wrong.

I am not 100% sure what "taking into account only suit isomorphisms" means. But I am starting to feel that 55190538 is actually GREATER than the "number of canonical card combinations from one player's point of view" - the term used in the tech report.

I have put together a piece of C++ code that counts turn combinations. It reprocuces the number from the article - 55190538. But imagine the turn board is AcKcQc2d (on turn the new public card was 2d). This code will treat the following two hands as different: AdAh, AhAs. But I believe they are strategically the same, after flop the diamond suit had no chance of becoming a flush. So (if I haven't made an error in my reasoning) they should have defined properly what they mean by "canonical combinations".

Code:
int CountUniqueTurnHands( int (&flopMask)[4], int (&turnMask)[4] )
{
    int result = 0;
    for( int c1 = 0; c1 + 1 < 52; ++c1 )
    {
        if( turnMask[c1 % 4] & (1 << (c1 / 4)) ) // card is already on the board
            continue;
        for( int c2 = c1 + 1; c2 < 52; ++c2 )
        {
            if( turnMask[c2 % 4] & (1 << (c2 / 4)) )
                continue;
           
            bool isDuplicate = false;
           
            for( int c1x = 0; c1x <= c1; ++c1x )
            {
                if( turnMask[c1x % 4] & (1 << (c1x / 4)) )
                    continue;
                for( int c2x = c1x + 1; c2x < 52; ++c2x )
                {
                    if( c1 == c1x && c2x >= c2 ) // we only check lexicographically preceding hands
                        continue;
                    if( turnMask[c2x % 4] & (1 << (c2x / 4)) )
                        continue;
                   
                    // hands must have the same suited-ness
                    if( ((c1%4)==(c2%4)) && ((c1x%4)!=(c2x%4)) )
                        continue;
                    if( ((c1%4)!=(c2%4)) && ((c1x%4)==(c2x%4)) )
                        continue;
                   
                    // checking if (c1, c2) is equivalent to (c1x, c2x) or to (c2x, c1x)
                    if( (c1/4 == c1x/4) && (flopMask[c1%4]==flopMask[c1x%4]) && (turnMask[c1%4]==turnMask[c1x%4]) && (c2/4 == c2x/4) && (flopMask[c2%4]==flopMask[c2x%4]) && (turnMask[c2%4]==turnMask[c2x%4]))
                        isDuplicate = true;
                    if( (c1/4 == c2x/4) && (flopMask[c1%4]==flopMask[c2x%4]) && (turnMask[c1%4]==turnMask[c2x%4]) && (c2/4 == c1x/4) && (flopMask[c2%4]==flopMask[c1x%4]) && (turnMask[c2%4]==turnMask[c1x%4]))
                        isDuplicate = true;
                }
            }
           
            if( !isDuplicate )
                ++result;
        }
    }
   
    return result;
}

void CountTurnCombinationsTurnPart( int& result, int (&flopMask)[4] )
{
    int turnMask[4] = { flopMask[0], flopMask[1], flopMask[2], flopMask[3] };
   
    for( int i = 0; i < 4; ++i )
    {
        bool skipSuit = false;
        for ( int j = 0; j < i; ++j ) // checking if there is another suit with exactly the same cards
            skipSuit = skipSuit || ( flopMask[i] == flopMask[j] );
       
        if( skipSuit )
            continue;
       
        for( int j = 0; j < 13; ++j )
        {
            if( (flopMask[i] & (1 << j)) != 0 ) // if there already is a card with rank j
                continue;
           
            turnMask[i] |= ( 1 << j ); // adding the 4th card to the mask
           
            result += CountUniqueTurnHands( flopMask, turnMask );
           
            turnMask[i] ^= ( 1 << j ); // removing the 4th card
        }
    }
}

void CountTurnCombinationsFlopPart( int& result )
{
    int mask[4] = {0};
    for( int c1 = 0; c1 + 2 < 52; ++c1 )
    {
        mask[c1%4] |= ( 1 << (c1/4) );
       
        for( int c2 = c1 + 1; c2 + 1 < 52; ++c2 )
        {
            mask[c2%4] |= ( 1 << (c2/4) );
       
            for( int c3 = c2 + 1; c3 < 52; ++c3 )
            {
                mask[c3%4] |= ( 1 << (c3/4) );       
       
                if( mask[0] >= mask[1] && mask[1] >= mask[2] && mask[2] >= mask[3] )
                    CountTurnCombinationsTurnPart( result, mask );
               
                mask[c3%4] ^= ( 1 << (c3/4) );
            }
           
            mask[c2%4] ^= ( 1 << (c2/4) );
        }
       
        mask[c1%4] ^= ( 1 << (c1/4) );
    }
}

int main()
{
    int n = 0;
    CountTurnCombinationsFlopPart(n);
    std::cout << n << "\n";
    return 0;
}

Statistics: Posted by alex — Wed Apr 10, 2013 9:28 am


]]>
2013-04-09T13:02:49+00:00 2013-04-09T13:02:49+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3729#p3729 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]> Statistics: Posted by proud2bBot — Tue Apr 09, 2013 1:02 pm


]]>
2013-04-09T10:59:54+00:00 2013-04-09T10:59:54+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3726#p3726 <![CDATA[Re: Measuring the Size of Large No-Limit Poker Games (2013)]]>
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.

Statistics: Posted by alex — Tue Apr 09, 2013 10:59 am


]]>
2013-03-15T12:13:37+00:00 2013-03-15T12:13:37+00:00 https://poker-ai.org/phpbb/viewtopic.php?t=2396&p=3226#p3226 <![CDATA[Measuring the Size of Large No-Limit Poker Games (2013)]]> PROPERTIES

type = "techreport"
title = "Measuring the Size of Large No-Limit Poker Games"
author = "JOHANSON, Michael"
year = "2013"
organization = "University of Alberta - Department of Computing Science"
url = "http://poker.cs.ualberta.ca/publications/2013-techreport-nl-size.pdf"
language = "en"
size = "16"


SUBJECT

abstract = "In the field of computational game theory, games are often compared in terms of their size. This can be measured in several ways, including the number of unique game states, the number of decision points, and the total number of legal actions over all decision points. These numbers are either known or estimated for a wide range of classic games such as chess and checkers. In the stochastic and imperfect information game of poker, these sizes are easily computed in "limit" games which restrict the players' available actions, but until now had only been estimated for the more complicated "no-limit" variants. In this paper, we describe a simple algorithm for quickly computing the size of two-player no-limit poker games, provide an implementation of this algorithm, and present for the first time precise counts of the number of game states, information sets, actions and terminal nodes in the no-limit poker games played in the Annual Computer Poker Competition."

Statistics: Posted by Joshua — Fri Mar 15, 2013 12:13 pm


]]>