Poker-AI.org
http://poker-ai.org/phpbb/

Omaha Hand Evaluator (C/C++)
http://poker-ai.org/phpbb/viewtopic.php?f=24&t=3326
Page 1 of 1

Author:  HontoNiBaka [ Fri Mar 27, 2020 10:43 am ]
Post subject:  Omaha Hand Evaluator (C/C++)

I am currently adding PLO to my solver and I have been doing some research on evaluators. The most common approach seems to be to take a 5 card evaluator and iterate over all possible combinations of board and holecards.
There are (4 choose 2) = 6 hole card combinations and (5 choose 3) board card combinations, resulting in 60 combinations to check. Being around 60 times slower than Hold'em doesn't sound like a great solution.
The evaluators that I have found so far that would support this approach are:

1. Poker-Eval
https://github.com/atinm/poker-eval

I was not able to compile it on my Windows machine so far.

2. Steve Brecher:
I am able to use it on my machine, I have used it for Hold'em before. But having to test all combinations is still slow.

I have also found code written by Pulser which does not require checking multiple combinations, it looks faster than the other approach.
viewtopic.php?f=26&t=2705
download/file.php?id=67

I was also thinking about creating a LUT. K. Waugh's isomorphism algorithm (viewtopic.php?f=25&t=2660) tells me there are 502,018,902 river indexes, if I store the rank as a 4 byte integer that would mean a 2GB LUT. It's doable but not perfect. Unlike Hold'em I think the distinction between the hole cards and board cards is important for omaha, so my indexer code looks like this:
Code:
   const uint8_t cards_per_round_river[2] = { 4, 5 };
   hand_indexer_init(2, cards_per_round_river, &riverIndexer);

instead of this
Code:
   const uint8_t cards_per_round_river[1] = { 9 };
   hand_indexer_init(1, cards_per_round_river, &riverIndexer);


I will see if I find better solutions and keep the thread updated. Is anyone else working on PLO and has any tips how to improve the performance?

Author:  nbiresev [ Fri Mar 27, 2020 10:15 pm ]
Post subject:  Re: Omaha Hand Evaluator (C/C++)

I use the solution " card evaluator and iterate over all possible combinations of board and holecards.".
The trick i use in addition when evaluating equity of range vs range, is to first iterate over all hands in both ranges and find best combination of board and holecard and write in dictionary (for fast access later). This is quite fast. Then when calculating range over range, it simply compares for every hand vs hand, the best combination of board nad holecard of hand1 with hand2, no need to find best combination in every iteration when calculating range vs range equity.
Still the issue i have is that ranges in omaha are quite huge, and it still gets slow to calculate range vs range.

Author:  HontoNiBaka [ Wed Apr 01, 2020 2:56 pm ]
Post subject:  Re: Omaha Hand Evaluator (C/C++)

pulser wrote:
Attached a standalone version of the code here, with a simple profiler running 10 mill random hands. Seems it only does 17M hands/s for me now, not sure if it's my compiler settings or if I did something wrong last time i tested it.

Didn't go through the comments, but guess they can be ignored for the most part :p

Quote:
Also if you dont mind sharing, how do you create ranges of cards, if you do? I mean for example from a string "AAhh:(23+,35+)", ie. PPT style. That is what I am working on now and it seems tougher than i thought.
Guess I could share code for this too, but don't think I'll do so publicly.

Anyway, I read in hands at a format similar to what you mentioned, creating Range-objects hierarchically, combined with and or or links. After connecting all the rules it feeds hands through the different Rule-filters, eventually storing the final range as Hand-objects in a vector.

In no way rocket science, but it allows for complex combination of rules and a fast final product.


I downloaded the code and the test with random hands looks good so far, however I am not sure what card each integer represents.
Is it like 0 = "2c", 1 = "2d", 2 = "2h", 3 = "2s", 4 = "3c" ...

After anylysing the code I assume that the second encoding is used but currently I am having problems with detecting straights. I am not sure if it's the evaluator code or if I'm using it incorrectly.
or is it like
0 = "2c", 1 = "3c", 2 = "4c", 3 = "5c", 4 = "6c" ...

Author:  HontoNiBaka [ Wed Apr 01, 2020 2:57 pm ]
Post subject:  Re: Omaha Hand Evaluator (C/C++)

nbiresev wrote:
I use the solution " card evaluator and iterate over all possible combinations of board and holecards.".
The trick i use in addition when evaluating equity of range vs range, is to first iterate over all hands in both ranges and find best combination of board and holecard and write in dictionary (for fast access later). This is quite fast. Then when calculating range over range, it simply compares for every hand vs hand, the best combination of board nad holecard of hand1 with hand2, no need to find best combination in every iteration when calculating range vs range equity.
Still the issue i have is that ranges in omaha are quite huge, and it still gets slow to calculate range vs range.


This sound interesting, but I am not trying to compute equity. I need it for monte carlo cfrm and the board and cards are random in each iteration, so I don't think I could use that optimization.

Author:  HontoNiBaka [ Wed Apr 01, 2020 3:02 pm ]
Post subject:  Re: Omaha Hand Evaluator (C/C++)

I tried Pulser's own benchmark code and set a breakpoint in the line that returns the rank of a straight. In 10 million hands not one seems to be recognised as a straight, I think the straight detection code is probably wrong.

Author:  HontoNiBaka [ Wed Apr 01, 2020 6:13 pm ]
Post subject:  Re: Omaha Hand Evaluator (C/C++)

I think I found the error, I don't know if it was a bug, or maybe it was just not meant to be used in a 64 bit app, old code:
Code:
#define countBits(x) ((x * 0x200040008001ULL & 0x111111111111111ULL) % 0xf)

new code:
Code:
unsigned short countBits(uint64_t n) {
   return __popcnt64(n);
}

__popcnt64() is also a bit faster, but that might depend on the compiler and cpu.
I have also run some benchmarks and it seems that the code is around 5 times faster than testing all combinations with Steve Brecher's code. I will write some more tests tomorrow and try to compare a few mio random hands between both algorithms and check if they, and my usage, are correct.

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/