Open Side Menu Go to the Top
Register
Will Tipton Video Pack 2 - Solving Poker Will Tipton Video Pack 2 - Solving Poker

08-03-2014 , 08:49 PM
Quote:
Originally Posted by Carlton Banks
I will almost surely buy this pack.

Another question: Is it possible to find near-optimal solutions for "real" poker situations using these methods or are they restricted to push/fold situations? Can i figure out 100bb+ stuff? (not find equilibrium of course, but find something that comes reasonably close or at least eliminates things that are definitely bad strategy)

I like the idea of this as a means to figure out what exactly is going on. To take a deeper look into how poker works. But what can i expect compared to softwares like cardrunnersEV?
Quote:
Originally Posted by Sevendeuceo
Sure, there are many applications to more complex situations. Where simplifications come in is in defining some sub-game tree, with some assumptions about bet sizes, and assuming starting ranges for both players in the spot you wish to analyse. Once this is defined, and assuming the tree isn't too complex, you can solve it exactly and find the Nash equilibrium (or get close to it after many iterations of Will's 'fictitious play' algorithm). Because of the assumptions on bet sizes and the simplification of the tree structure, this can't guarantee that the play truly is GTO in that spot -- though it is, conditionally on those constraints. But it may well be even more instructive and fruitful than possession of the true solution would be. That's because you are forced to connect the analysis to real game situations and decision points as you encounter them.

It's also a great complement to cardrunnersEV.
Yea, I think all of this is fair.

Re: the size of situations you can study, it's hard to say much from the stack depth. If you have a decision tree in mind, then (without any optimizations to the code), you'll need RAM of something like 56MB*(number of boards in the tree)+21kB*(number of actions in the tree).

Re: a comparison to CREV, the goal here is much more to teach you how to do things yourself rather than to provide a ready-made piece of software. Our code's main purpose is to calculate equilibrium strategies, something CREV doesn't do at all, afaik. Both pieces of software can find maximally exploitative strategies, but ours is more general in some ways. Ofc, CREV has a variety of other bells and whistles that our code does not.
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 09:17 PM
Quote:
Originally Posted by Qlka
By studying this video pack will I be able to solve the game for some MTT HU situations for about 20bb? For example villain range is known and hero is closing action on the BB? Or blind vs blind situations where SB plays OOP?
Quote:
Originally Posted by Sevendeuceo
In the case where villain's range is known, then 'solving' the game isn't even required. You just find the strategy that maximizes EV against Villain's range. This is covered early in the video series. But you further can find the optimal strategy in the GTO sense (unexploitable), which would maximize your EV assuming villain also plays optimally against whatever strategy you choose.

In the video series, the min-raise/shove game is solved for some given min-raise size. You can, of course, chose other sizes. This is most relevant to 20bb HU spots in cash games. However, in multi-table tournaments, your goal is to maximize you share in the prize-pool, and not just maximize EV for each individual hands. So, you will need to adapt what is learned to such situations. There is some discussion of this in Tipton's book, vol.2.
Quote:
Originally Posted by Qlka
What I am looking for is to solve min raise/3bet-small/4bet-shove, min raise/3bet-shove, min raise/flat call game with some postflop simplifications where inital min-raise range is fixed.
Is it possible or is to ambitious?
Quote:
Originally Posted by Sevendeuceo
That seems quite feasible.
Yea so all of the preflop-only games you mention will be very easy. Postflop models can vary in size a ton.

Regarding MTTs, the videos assume we're interested in 2-player situations where both players want to maximize their cEV, as is appropriate for HUSNGs and HU cash games. So, I guess there are two issues to address: 3+ player situations and "ICM effects". Both are feasible, and the second seems pretty easy.

I responded a bit about 3+ player spots here:
http://husng.com/content/will-tipton...#comment-41279

Re: ICM effects, there's one function we write that is responsible for computing players' EV at the leaves of the decision tree (getMaxExplEVsAtLeaf). (Essentially, it just ships the pot one way or the other if there was a fold, or gives players their equity in the pot if there was a showdown or all-in.) You'd need to modify this function to translate cEV to $EV using the ICM. So, this is a very small change to our code, and you'd need to additionally write the ICM-specific logic.
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 09:49 PM
Quote:
Originally Posted by Emus
A question, is following logic correct?

flops
We can have 52*51*50/6=22100 different flops.
And such (if we would adapt EQarray code a bit) we would require 22100 stored EQArray ('x','y','z','__','__') of 56Mb =113Gb instead of 52^3=140 608 / or 7690Gb.
Yes, this would be a good idea if you want to generate lots of equity arrays. I believe you can do this with a small change in EquityArray's getFilename() function -- change

Code:
boardAsStrings = pe.card2string(self.board)
to

Code:
boardAsStrings = sorted(pe.card2string(self.board))
Quote:

EQ, all-in at flop
And such, if we set up a tree where a random flop is dealt; the code would each time have to consult one of the 22100 stored EQArray stored at HD.
At first sight, we could say that we are required to generate all these 22100 EQArrays if we get a hand at flop that goes all-in at flop.

However, if we eventually went through all possible flops for each [i,j][a,b] aka went through all the possible EQArrays (that do not conflict); we can conclude that the resulting equity of [i,j][a,b]=sum(1/22100 * EQ('x','y','z','__','__'))
Now, if our code is written correctly, we do not sum 22100 EQ's, we actually sum less as some boards are impossible to be dealt.

And such, instead of having to adapt code; generate and store 22100 EQArray stored at HD; generate each flop; combine the equities; we can actually just use EQArray('__','__','__','__','__') for each hand we get all-in at flop.

Now, EV, all-in at flop
Let's assume that the EV is of algebraic form [a + b EQ('x','y','z','__','__')]
and such
EVflop = sum(1/22100 * [a + b EQ('x','y','z','__','__')])
once again, if our code is written correctly, we do not sum 22100 EV's, we actually sum less as some boards are impossible to be dealt.
= a+b[sum(1/22100 * EQ('x','y','z','__','__'))]
OR = a + b EQ('__','__','__','__','__')

Once again we can just use EQArray('__','__','__','__','__') for each hand we get all-in at flop.
Yea, our equity on average over all flops is just our equity preflop. But if you use this to, say, computing the EV of a flop all-in, you're essentially making the implicit assumption that your flop play is the same on all flops. I.e., your get-it-in range doesn't depend on the board. This is usually not a good assumption.

Quote:
turns
after 4 cards; there are 22100 * 49 = 1 082 900 boards possible.
However, we can once again adapt EQArray code, simply because in the above line each board of 4 cards is present 4 times.
To rephrase it : 52*51*50*49/24 = 270 725
And such we require the software to generate 270 725 EQ('x','y','z','a','__')
or 14.46Tb of information.
Yea, if you're interested in pre-computing a ton of EquityArrays, I mentioned in the video that they're unnecessarily large by a factor of 4, since we only use the upper half of each range array.

But there's another easily-accessible factor of 8 size reduction possible (in the turn case -- it's larger on the river and smaller on earlier streets). We use double precision (8-byte) numbers to store the equities now. However, on the turn, there are only like 48 possible rivers. So a hand-vs-hand equity is:

( (# rivers we tie on) + 2*(# rivers we win on) ) / (2 * 48)

The denominator there is fixed, the numerator is a number we have to store that can have integer values between 0 and 96. We can store such a small integer in one byte instead of 8. Something else to think about if you're interested in precomputing lots of EAs...

Quote:
EQ turns after flop call
If we move to the turn; there are theoretically 49 EQ('x','y','z','a','__') over which we sum the EQ's. However each time 4 EQArrays will not be counted as they conflict with cards present in the starting hands.
However, we once again arrived into:
EQ(turn) = sum(1/49*EQ('x','y','z','a','__'))
which is equal to EQ('x','y','z','__','__') for the specific flop dealt.

And such instead of having to adapt code for turns; generate and store 270 725 EQ('x','y','z','a','__') stored at HD; generate each turn; combine the equities; we can actually just use EQ('x','y','z','__','__') for the specific flop dealt whenever a hand goes all-in at turn after a flop call.

Once again, at this time we can think that we require EQ('x','y','z','__','__') when we go to turn after flop call; however because we will iterate all flops, and after a flop is generated, we will iterate over all turns, we can just use once again EQArray('__','__','__','__','__') whenever a hand goes all-in at turn after a flop call.

EV turn after flop call
EQ river after flop+turn call
EV river after flop+turn call
idem dito

And such we can just use EQArray('__','__','__','__','__') whenever we get a hand all-in; simply because our software will iterate over all possible flops, all possible turns, all possible rivers and combine the results. And instead of letting our software iterate over all these things correctly and combine correctly; this iteration and combination is already done and present into EQArray('__','__','__','__','__')
Yea, again, this is true only if your postflop strategy doesn't depend on the board, but it generally should .
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 10:02 PM
Quote:
Originally Posted by MrPete
Will Thanks, I seem to have made progress as I am not getting any errors anymore. However, when I try and display Range I get a large text block in the output that looks something like this.
Code:
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="260" height "260"><rect x=0" y="0" width="20" height="20" fill="#ffffff"></rect><text x=0 y=20 font-size=12 >AA</text><rect x=0" y="20" width="20" height="20" fill="#ffffff"></rect><text x=0 y=40 font-size=12 >AK</text><rect x=0" y="40" width="20" height="20" fill="#ffffff"></rect><text x=0 y=60 font-size=12 >AQ</text><rect x=0" y="60" width="20" height="20" fill="#ffffff"></rect><text x=0 y=80 font-size=12 >AJ</text><rect x=0" y="80" width="20" height="20" fill="#ffffff"></rect><text x=0 y=100 font-size=12 >AT</text>
My code for the _repr_svg_ function looks identical to yours, indents included.
Hey MrPete,

Is this still an issue? I see a missing "=" sign in your output (bolded) that indicates your code is not quite the same as mine. If you re-check it and still have a problem, please post your _repr_svg_ function and also what browser you're using. If it's no longer an issue, what fixed it?

Thanks,

Will
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 10:07 PM
Quote:
Originally Posted by klondi
Well i think i finally figured it out with the getFilename attribute.
Yup, just to follow up, the EquityArray class doesn't have any "Filename" attribute, however it has a "getFilename()" function that returns the path of a file where the EA should be saved on disk, which is what we want. Glad you found the error.
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 10:09 PM
Quote:
Originally Posted by ZhengHe
Hi,

Regarding the second example.
Bet and check for 7h7s are ~20.9.
My code outputs the same results as stevepa and sevendeuceo, and 19.7 for this example. That should be right, given the soln will sue the getequityvshand somewhere, and board changes will have non-negligible effects. What do you guys think?
Hey ZhengHe, not quite sure I understand your question. Could you possibly rephrase?
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 10:26 PM
Quote:
Originally Posted by Sevendeuceo
Coming to think of it, using pickle to save StrategyPair objects, even if they could be loaded back, will redundantly save the EV arrays for the boards of the associated trees. So, I had better write my own saving and loading method to only save ranges and reconstruct the StrategyPair objects. I'd still be interested to know what Will does, and if pickle can work nonetheless.
Really cool work here, thanks for sharing it. I've not used pickle, but yea I save the ranges and the EVs to disk for later analysis, and can restart calcs using them. It looks like you've pretty much worked out the same way I do it, but a couple small ideas --

- you can automatically zip/unzip files as you write/read them from disk to save some disk space. I do the same thing with equity arrays.
- if you have long-running calculations, automatically save your solutions every few FP iterations so you can easily restart if your computer gets reboot or w/e.
- write the solutions to a temporary file and then move that temp file to your final save location instead of writing to the save location directly, so that your saves don't get corrupted if your program is halted during the writing.
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 10:31 PM
Quote:
Originally Posted by Sevendeuceo
This is a good observation. But I think it is as we should expect. Both players actually know that the 6 is coming, only just not which of the two suits. That's part of the definition of the restricted game that this three represents. This foreknowledge is implemented in the doFP() algorithm when strategies are progressively optimized on the basis of full knowledge of the opponent's strategy -- and this includes knowledge of the opponent's ranges for future actions.

In order to remove this quirk, we would have to allow all possible cards to fall on the river and then, after the solution is at hand, only consider sub-ranges for scenarios we are interested in. But this would be much more computationally intensive.
True story. The game is defined by the decision tree. If all of the rivers in your decision tree are a 6, then that's the game you're playing, and 6's will be more valuable on early streets, insofar as they're guaranteed to pair up on the river.
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 10:45 PM
Quote:
Originally Posted by minotaurs
If i make a lot of possible Turns cards possible (lets say all of them) in the decision tree do i have to make some card removal effects when i define ranges on the flop?
Quote:
Originally Posted by Sevendeuceo
Yes, because card removal effects on the range of a player on some street result from the board cards on that street as well as the opponent player's range on that street. Future streets only are relevant inasmuch as stipulated restrictions on the frequencies of future cards affect overall strategies and hence the opponent's range on the current street (as was the case with the T tree).
Is the question about setting up the starting ranges for a flop-onwards subgame? Generally, I think of it as good practice to explicitly remove hands that conflict with the flop from the players' starting ranges, but actually I don't think it'll cause any problems if you don't bother. And certainly, if you include all turns, you don't need to change the flop starting ranges because they could conflict with some turn...
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 10:59 PM
Quote:
Originally Posted by jesjesjo
Hi,

I'm having a similar problem as minotaurs had, with displaying a gametree.

Made my own tree for flop-play analysis and I get this error when I run the cell: <__main__.Tree instance at 0x08F01C88>
This is the default representation of a tree that iPython will fall back on if it can't find _repr_svg_ or if there's an error when it tries to run it. Unfortunately, it falls back silently and doesn't print the error message. If there's an error, you can see it by running the _repr_svg_ function explicitly. E.g., if you have a range called bob, run bob._repr_svg_(). What's it say?
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 11:13 PM
Quote:
Originally Posted by NC82
I'm getting to solve my setToTop error. however not completely. I'm breaking down the process and apparently i only sort hands up to 46 rather than the full range of possibilities. if i set fraction to 0.20 handsSorted[i] will result iinto handsSorted[265] however handsSorted only contains 47 elements... can somebody help me with this?
Good job tracing the issue as far as you did.

Quote:
Originally Posted by NC82
Code:
 def getHandsSortedAndEquities(self, villainRange, board):
        ea = EquityArray(board)
        result = []
        for i in range(numCards):
            for j in range(i+1, numCards):
                hand = [i,j]
                if not conflicts(board, hand):                    
                    result.append((hand, getEquityVsRange(hand, villainRange, ea)))
            result.sort(key = lambda x: x[1], reverse = 1)
            return result
tips on how to further break the problem down and fix my bug?
Looks like you have an extra tab in your return line! The return statement is inside the "for i" loop, so your function returns prematurely, after only the first value of i.
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 11:20 PM
Quote:
Originally Posted by 307th
Hi, I finished the video pack and my program seems to be working without any problems. Now I want to do a calculation for GTO play in a realgame situation - specifically play on a turn, where all 48 possible boardrunouts are included in the game tree.

Is it possible to do this with the program we have on a laptop? I was thinking I'd have to write a function to help generate the game tree, and I think I could do that with some work, but even assuming I can get it to do that, will there be other problems I haven't thought of popping up?
Great! So, I guess it depends on the laptop and exactly what game you have in mind, but if it's just to add more turns to the turn-and-river game we looked at in the video series, I wouldn't expect any problems. If anything comes up, let us know...
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 11:22 PM
Quote:
Originally Posted by minotaurs
if i make really big tree do i really have to do any "remove hands with conflicts"?
For example i make big tree where decision point 0 is preflop. Than i have like 100's of flops, even more turns and milion rivers.
Is this question the same as this?

http://forumserver.twoplustwo.com/sh...&postcount=134
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 11:33 PM
Quote:
Originally Posted by tagWAG
Made it to the end of the series, but my soln2.dump() to the two street 'T' game gets off to a weird start:

In my (wrong) solution:

At Decision Point 1 (after BB checks) BB has checked zero% of his range
At Decision Point 15 (after BB bets) BB has bet 100% of his range

I checked the result of display(bbStartingRange) and this is definitely correct.

So something is going wrong with the way that BB initially divides his range between checking and betting. I'd be grateful if someone could point to a place in the code where I can solve this. Thanks!
We've actually designed things so that no range should ever actually be completely empty, at least after a not-huge number of iterations. This is because:

1) All of the ranges are initially nonempty (set up by the initialize() function in the StrategyPair class)
2) The frequencies are only changed by multiplication by a positive fraction (in the updateRange(s) functions)

So, I guess one of those two things is not right in your code. Come up with the simplest way you can to test those two functions (initialize and updateRanges) and see which is wrong, and then dig into it as described in post #16 of this thread.
Will Tipton Video Pack 2 - Solving Poker Quote
08-03-2014 , 11:34 PM
Boom! I think I'm all caught up on this thread now. If I've missed anything, please lmk...
Will Tipton Video Pack 2 - Solving Poker Quote
08-04-2014 , 03:42 AM
Quote:
Originally Posted by yaqh
Great! So, I guess it depends on the laptop and exactly what game you have in mind, but if it's just to add more turns to the turn-and-river game we looked at in the video series, I wouldn't expect any problems. If anything comes up, let us know...
Hi Will,

Since I posted that I went ahead and tried to solve the turnspot. Unfortunately a problem did come up.

I wrote a function to make a gametree automatically. I added it as a part of the tree function, basically now when you make a tree you need to give it stackdepth, what street it is, a list of betsizes, a board, SB chips in pot, and BB chips in pot. It uses those to automatically make a tree.

Here's a gametree it made for a river spot:



If the play is on the turn then what should happen is, each time an action makes play go to the river the player will be "Nature" and it will have 48 children, each one being a different board runout. Each child should look somewhat like the tree shown above.

However, when I try to make a game tree for a turn I get an error. It says "MemoryError:". I tried making the equity arrays for all the boardrunouts ahead of time but I still get a memory error. If I had to guess the problem is that it tries to hold all ~49 equity arrays in its memory at once, and I should find a way to make it so it only has to hold 1 in its memory at once. I'm not entirely sure how I should do that though, or whether doing that would fix it.

Can you think of a way to fix this? If you need more info then just let me know.

Thanks!
Will Tipton Video Pack 2 - Solving Poker Quote
08-04-2014 , 04:02 AM
Quote:
Originally Posted by yaqh
Hey MrPete,

Is this still an issue? I see a missing "=" sign in your output (bolded) that indicates your code is not quite the same as mine. If you re-check it and still have a problem, please post your _repr_svg_ function and also what browser you're using. If it's no longer an issue, what fixed it?

Thanks,

Will
Unfortunately its still a problem.

Here is my _repr_svg function

Code:
    def _repr_svg_(self):
        result = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="260" height "260">'
        for i in range(numRanks):
            for j in range(numRanks):
                frac = self.getAmbigFrac(ranks[i], ranks[j], i > j)
                hexcolor = '#%02x%02x%02x' % (255*(1-frac), 255, 255*(1-frac))
                result += '<rect x="' + str(i*20) + '" y="' + str(j*20) + '" width="20" height="20" fill="'\
                          + hexcolor+'"></rect>'
                result += '<text x=' + str(i*20)+' y='+str((j+1)*20) + ' font-size=12 >' + ranks[i]\
                          + ranks[j] + '</text>'
        result += '</svg>'
        return result
My browser is Chrome.
Will Tipton Video Pack 2 - Solving Poker Quote
08-04-2014 , 01:09 PM
Quote:
Originally Posted by 307th
Hi Will,

Since I posted that I went ahead and tried to solve the turnspot. Unfortunately a problem did come up.

I wrote a function to make a gametree automatically. I added it as a part of the tree function, basically now when you make a tree you need to give it stackdepth, what street it is, a list of betsizes, a board, SB chips in pot, and BB chips in pot. It uses those to automatically make a tree.
Cool!
Quote:
Here's a gametree it made for a river spot:



If the play is on the turn then what should happen is, each time an action makes play go to the river the player will be "Nature" and it will have 48 children, each one being a different board runout. Each child should look somewhat like the tree shown above.
Sounds good.

Quote:
However, when I try to make a game tree for a turn I get an error. It says "MemoryError:". I tried making the equity arrays for all the boardrunouts ahead of time but I still get a memory error. If I had to guess the problem is that it tries to hold all ~49 equity arrays in its memory at once, and I should find a way to make it so it only has to hold 1 in its memory at once. I'm not entirely sure how I should do that though, or whether doing that would fix it.

Can you think of a way to fix this? If you need more info then just let me know.

Thanks!
OK, a few ideas:

- MemoryError usually indicates that you're out of memory, but we might as well look into this a bit. Can you verify (by looking at, e.g. the Task Manager in Windows) that your program does use all your memory when you run it?

- Can you verify that the memory usage you're seeing is reasonable given your decision tree. (It should be something like 56MB*(number equity arrays)+3*21kB*(number of actions).)

- The 32-bit version of python can only make use of 3 or 4 GB of memory. If your computer has more, and you want to use it, switch to the 64-bit version. We used the 32-bit one since it's compatible with the poker-eval library we used, but if you've pre-generated all the EquityArrays you need (using the 32-bit version), you don't need poker-eval.

- I guess there are multiple ways to get to the river in your decision tree. Each time, do you re-load the EquityArray for each of the 48 rivers? It could waste a lot of memory if you try to load the EA for the same rivers into memory multiple times. I can see a couple ways to avoid this:
a. load them each once before creating the tree, and then just pass around references, like we did in the examples, or
b. keep a map of, say, filenames to EquityArrays. Whenever you need an EA, before loading the array from disk (or generating it), see if it's present in this map, and use that one if it is. If you do have to pull it from disk or generate it, store it in the map afterwards.
Will Tipton Video Pack 2 - Solving Poker Quote
08-04-2014 , 01:11 PM
Quote:
Originally Posted by MrPete
Unfortunately its still a problem.

Here is my _repr_svg function
You didn't fix the error I pointed out before. Please do that and otherwise re-check the function, and then report if the behavior is unchanged. Remember that you need to re-evaluate cells to make changes take effect.
Will Tipton Video Pack 2 - Solving Poker Quote
08-04-2014 , 02:38 PM
Quote:
Originally Posted by yaqh
You didn't fix the error I pointed out before. Please do that and otherwise re-check the function, and then report if the behavior is unchanged. Remember that you need to re-evaluate cells to make changes take effect.
Sorry, I corrected the missing "=", ran all cells, and I still get the same result.

Edit: When I used the display(bob) I successfully got the result I wanted. Thanks!
Will Tipton Video Pack 2 - Solving Poker Quote
08-04-2014 , 03:23 PM
Quote:
Originally Posted by MrPete
Sorry, I corrected the missing "=", ran all cells, and I still get the same result.

Edit: When I used the display(bob) I successfully got the result I wanted. Thanks!
Glad to hear it.
Will Tipton Video Pack 2 - Solving Poker Quote
08-05-2014 , 05:50 AM
Quote:
Originally Posted by yaqh
OK, a few ideas:

- MemoryError usually indicates that you're out of memory, but we might as well look into this a bit. Can you verify (by looking at, e.g. the Task Manager in Windows) that your program does use all your memory when you run it?
Python uses 1.5GB memory then returns a memory error. It doesn't use all my memory, it'll only use 1.5GB (I have 6GB although my laptop is usually using 2-3GB "at rest") before stopping.

Quote:
Originally Posted by yaqh
- Can you verify that the memory usage you're seeing is reasonable given your decision tree. (It should be something like 56MB*(number equity arrays)+3*21kB*(number of actions).)
Yes, it's reasonable. Using the following code also returns a memory error:
Code:
EA = [0 for x in range(52)]
board = pe.string2card(('Kd', 'Td', '2h', '5c', '__'))
for i in range(52):
    board[4] = i
    EA[i] = EquityArray (board)
since python 32bit on my computer only uses ~1.5GB of memory before returning a memory error, even just holding 52 equity arrays (one for each river card) is too much (56MB * 52 = ~2.9GB)

Quote:
Originally Posted by yaqh
- The 32-bit version of python can only make use of 3 or 4 GB of memory. If your computer has more, and you want to use it, switch to the 64-bit version. We used the 32-bit one since it's compatible with the poker-eval library we used, but if you've pre-generated all the EquityArrays you need (using the 32-bit version), you don't need poker-eval.
I tried this but poker-eval is used for too many things, e.g. when making an equity array it uses pe.card2string. So I don't think using 64-bit python is viable.

Quote:
Originally Posted by yaqh
- I guess there are multiple ways to get to the river in your decision tree. Each time, do you re-load the EquityArray for each of the 48 rivers? It could waste a lot of memory if you try to load the EA for the same rivers into memory multiple times. I can see a couple ways to avoid this:
a. load them each once before creating the tree, and then just pass around references, like we did in the examples, or
b. keep a map of, say, filenames to EquityArrays. Whenever you need an EA, before loading the array from disk (or generating it), see if it's present in this map, and use that one if it is. If you do have to pull it from disk or generate it, store it in the map afterwards.
Loading them all once before creating the tree would also return a memory error I think, since 26 equity arrays is around the max my computer can hold before returning a memory error.

I'm not sure how b. would work, would it allow me to not have to store all 52 equity arrays at once? Is there some way to use an equity array but stop holding it in memory once we're done with it?
Will Tipton Video Pack 2 - Solving Poker Quote
08-05-2014 , 11:49 AM
Quote:
Originally Posted by 307th
I tried this but poker-eval is used for too many things, e.g. when making an equity array it uses pe.card2string. So I don't think using 64-bit python is viable.
Ah, I'd forgotten about card2string and string2card (you say "too many things", but I can't think of any others?) Anyhow, those are easy. Since we have the cards array (cards = ['2h', '3h', ...], we can convert string to number with, e.g.
Code:
print cards.index('3s')
and number to string with
Code:
print cards[40]
.
Put something like this in a for loop to convert a whole array at once like c2s and s2c do, and remember to special case the "empty" card, '__' or 255.

Quote:
Loading them all once before creating the tree would also return a memory error I think, since 26 equity arrays is around the max my computer can hold before returning a memory error.

I'm not sure how b. would work, would it allow me to not have to store all 52 equity arrays at once? Is there some way to use an equity array but stop holding it in memory once we're done with it?
Python is garbage collected language which means that you don't explicitly free memory once you're done with it. The garbage collector kicks in every once in a while and looks for stuff no longer being used and frees it. Our EAs are never available to be freed like this, since we keep references to them in each decision point, so they're never "no longer being used".

You could not store the EAs in decision points, and instead just store the board. Then, you'd have to pull the EA from disk every time you want to do an equity calculation. (That is, whenever you get to the parts of setmaxExplEVsAtLeaf corresponding to a showdown or call of an all-in.) So, that seems like a small change -- give it a try? I'm interested to know how much of a speed penalty you incur...
Will Tipton Video Pack 2 - Solving Poker Quote
08-05-2014 , 01:03 PM
Hi Will and everyone,

For memory reduction on EquityArray, did someone provide a solution?
I was thinking of using an IndexTable pointing on the first hand above the diagonal for every line, like:
Code:
# To do: use indexTable and handTable to use 1/4 memory for EquityArray
indexTable = numpy.zeros(numCards)
def init_indexTable():

    i = -1
    delta = numCards-1

    for j in range(numCards):
        indexTable[j]=i
        delta -= 1
        i += delta

# Input: two cards values in any order
# Output: rank in mono dimensional array of size numHands   
def miniTable(card1,card2):
    
    if card1<card2:
        # card1,card2 = card2,card1
        return indexTable[card1] + card2
    else:
        return indexTable[card2] + card1
So that you can then use an array of [numHands][numHands] for EquityArray.
Am I on right tracks?

Also i am trying to install it on my linux machine.
Despite doing some changes in Makefiles of pypoker-eval-138.0 to port it from 2.6 to 2.7 and recompiling poker-eval-138.0 too, I still get errors with pypoker-eval :

No module named _pokereval_2_7...

If someone managed, could he tell me what versions from freepokerdb he used.
There must be one as the Windows version uses python2.7...

Last edited by X0RR0; 08-05-2014 at 01:22 PM.
Will Tipton Video Pack 2 - Solving Poker Quote
08-05-2014 , 02:08 PM
Quote:
Originally Posted by X0RR0
Hi Will and everyone,

For memory reduction on EquityArray, did someone provide a solution?
I was thinking of using an IndexTable pointing on the first hand above the diagonal for every line, like:
Code:
# To do: use indexTable and handTable to use 1/4 memory for EquityArray
indexTable = numpy.zeros(numCards)
def init_indexTable():

    i = -1
    delta = numCards-1

    for j in range(numCards):
        indexTable[j]=i
        delta -= 1
        i += delta

# Input: two cards values in any order
# Output: rank in mono dimensional array of size numHands   
def miniTable(card1,card2):
    
    if card1<card2:
        # card1,card2 = card2,card1
        return indexTable[card1] + card2
    else:
        return indexTable[card2] + card1
So that you can then use an array of [numHands][numHands] for EquityArray.
Am I on right tracks?
Yea, that's essentially what I've done -- have some scheme to map our two hole cards to a number from 0 up to numHands-1, and then store equities in a numHands-by-numHands array. As you mention, this will save a factor of 4.

Another possible optimization -- using less space to store each equity (on the turn, you only need about 7 bits, on the river, you only need 3 bits) -- is mentioned above.

And then the third possibility is to take advantage of card isomorphisms, but that'll probably be harder to work into our code.


Quote:
Also i am trying to install it on my linux machine.
Despite doing some changes in Makefiles of pypoker-eval-138.0 to port it from 2.6 to 2.7 and recompiling poker-eval-138.0 too, I still get errors with pypoker-eval :

No module named _pokereval_2_7...

If someone managed, could he tell me what versions from freepokerdb he used.
There must be one as the Windows version uses python2.7...
What linux distro are you using? I use Arch and the poker-eval and pypoker-eval packages in the user repository worked just fine. No need to use the version from the freepokerdb project unless you're on Windows.
Will Tipton Video Pack 2 - Solving Poker Quote

      
m