Two Plus Two Newer Archives  

Go Back   Two Plus Two Newer Archives > Internet Gambling > Software
FAQ Community Calendar Today's Posts Search

Reply
 
Thread Tools Display Modes
  #51  
Old 12-27-2006, 03:40 AM
mykey1961 mykey1961 is offline
Senior Member
 
Join Date: Oct 2005
Posts: 249
Default Re: 7 Card Hand Evaluators

[ QUOTE ]
[ QUOTE ]
If someone could figure out a way to assign a unique index value between 1 and 133784560 for 7 unordered cards, you could dump everything into a 133 MB lookup table.


[/ QUOTE ]
Single byte for hand's strength is not enough, so the table must be 266 MB at least.

Andrzej Nironen

[/ QUOTE ]

Actually it can be done in under 133 MB...


I've got an array of approx 30 million integers.

One way of accessing a hand ranking is:


Rank := Eval[Eval[Eval[Eval[Eval[Eval[Eval[c1]+c2]+c3]+c4]+c5]+c6]+c7];

The general idea is there are:

1 card hands. 52x52
2 card hands. 1326x52
3 card hands. 22100x52
4 card hands. 84448x52
5 card hands. 152607x52
6 card hands. 352443x52

For each N card hand, there are 52 vectors to the appropriate N+1 card hand.

For 6 card hands, instead of vectors to the 7 card hand, the array holds the Hand Ranking of the 7 card hand.
Reply With Quote
  #52  
Old 12-27-2006, 02:32 PM
mykey1961 mykey1961 is offline
Senior Member
 
Join Date: Oct 2005
Posts: 249
Default Re: 7 Card Hand Evaluators

[ QUOTE ]
Please could you all run this test on your hand evaluators and let me know the results:

int c1, c2, c3, c4, c5, c6, c7;
int handSetCounters[8] = {0,0,0,0,0,0,0,0};

for(c1 = 0; c1 < 52; c1++) {
for(c2 = c1 + 1; c2 < 52; c2++) {
for(c3 = c2 + 1; c3 < 52; c3++) {
for(c4 = c3 + 1; c4 < 52; c4++) {
for(c5 = c4 + 1; c5 < 52; c5++) {
for(c6 = c5 + 1; c6 < 52; c6++) {
for(c7 = c6 + 1; c7 < 52; c7++) {

CALCULATE RANK
CALCULATE SET ID (HIGH CARD TO STRAIGHT FLUSH)
INCREMENT HANDSETCOUNTERS[SET ID]

}}}}}}}

PRINT HANDSETCOUNTERS


If you could time the speed of your code in that scenario it would be most interesting! Also with a copy of your results (number of flushes etc incase your code is not designed to be 100% accurate).

Thanks for anyone that participates!

Tom

[/ QUOTE ]

<font class="small">Code:</font><hr /><pre>133784560 hands
2.640 secs
50675964 hands/sec
hc 23294460
pr 58627800
tp 31433400
th 6461620
st 6180020
fl 4047644
fh 3473184
fr 224848
sf 41584

using

procedure TForm1.Button2Click(Sender: TObject);
var
Totals : array[0..9] of integer;
c1, c2, c3, c4, c5, c6, c7 : integer;
Count : integer;
Start, Stop : TDateTime;
secs : double;
Score : integer;
begin
Start := Now;
Fillchar(Totals,sizeof(Totals),0);
Count := 0;
for c1 := 0 to 45 do
for c2 := c1+1 to 46 do
for c3 := c2+1 to 47 do
for c4 := c3+1 to 48 do
for c5 := c4+1 to 49 do
for c6 := c5+1 to 50 do
for c7 := c6+1 to 51 do
begin
inc(Totals[Table[Table[Table[Table[Table[Table[Table[c1+52]+c2]+c3]+c4]+c5]+c6]+c7] shr 20]);
inc(Count);
end;
Stop := Now;
secs := (Stop-Start)*86400.0;
memo1.lines.add(format('%d hands',[Count]));
memo1.lines.add(format('%5.3f secs',[secs]));
memo1.lines.add(format('%d hands/sec',[trunc(Count/secs)]));
memo1.lines.add(format('hc %d',[Totals[1]]));
memo1.lines.add(format('pr %d',[Totals[2]]));
memo1.lines.add(format('tp %d',[Totals[3]]));
memo1.lines.add(format('th %d',[Totals[4]]));
memo1.lines.add(format('st %d',[Totals[5]]));
memo1.lines.add(format('fl %d',[Totals[6]]));
memo1.lines.add(format('fh %d',[Totals[7]]));
memo1.lines.add(format('fr %d',[Totals[8]]));
memo1.lines.add(format('sf %d',[Totals[9]]));
end;


and

133784560 hands
1.188 secs
112613302 hands/sec
hc 23294460
pr 58627800
tp 31433400
th 6461620
st 6180020
fl 4047644
fh 3473184
fr 224848
sf 41584

using

procedure TForm1.Button1Click(Sender: TObject);
var
Totals : array[0..9] of integer;
c1, c2, c3, c4, c5, c6, c7 : integer;
u1, u2, u3, u4, u5, u6, u7 : integer;
Count : integer;
Start, Stop : TDateTime;
secs : double;
Score : integer;
begin
Start := Now;
Fillchar(Totals,sizeof(Totals),0);
Count := 0;
for c1 := 0 to 45 do
begin
U1 := Table[52+c1];
for c2 := c1+1 to 46 do
begin
U2 := Table[U1+c2];
for c3 := c2+1 to 47 do
begin
U3 := Table[U2+c3];
for c4 := c3+1 to 48 do
begin
U4 := Table[U3+c4];
for c5 := c4+1 to 49 do
begin
U5 := Table[U4+c5];
for c6 := c5+1 to 50 do
begin
U6 := Table[U5+c6];
for c7 := c6+1 to 51 do
begin
inc(Totals[Table[U6+c7] shr 20]);
inc(Count);
end;
end;
end;
end;
end;
end;
end;
Stop := Now;
secs := (Stop-Start)*86400.0;
memo1.lines.add(format('%d hands',[Count]));
memo1.lines.add(format('%5.3f secs',[secs]));
memo1.lines.add(format('%d hands/sec',[trunc(Count/secs)]));
memo1.lines.add(format('hc %d',[Totals[1]]));
memo1.lines.add(format('pr %d',[Totals[2]]));
memo1.lines.add(format('tp %d',[Totals[3]]));
memo1.lines.add(format('th %d',[Totals[4]]));
memo1.lines.add(format('st %d',[Totals[5]]));
memo1.lines.add(format('fl %d',[Totals[6]]));
memo1.lines.add(format('fh %d',[Totals[7]]));
memo1.lines.add(format('fr %d',[Totals[8]]));
memo1.lines.add(format('sf %d',[Totals[9]]));
end;

</pre><hr />


This was on an AMD 3000+ with 1 gig memory running Win2k

This computer produced

133784560 hands
5.156 secs
25947355 hands/sec
hc 23294460
pr 58627800
tp 31433400
th 6461620
st 6180020
fl 4047644
fh 3473184
fr 224848
sf 41584

using Andrzej Nironen's "Hand Evaluator Speed Demo"
Reply With Quote
  #53  
Old 12-27-2006, 02:52 PM
jukofyork jukofyork is offline
Senior Member
 
Join Date: Sep 2004
Location: Leeds, UK.
Posts: 2,551
Default Re: 7 Card Hand Evaluators

[ QUOTE ]
[ QUOTE ]
Please could you all run this test on your hand evaluators and let me know the results:

int c1, c2, c3, c4, c5, c6, c7;
int handSetCounters[8] = {0,0,0,0,0,0,0,0};

for(c1 = 0; c1 &lt; 52; c1++) {
for(c2 = c1 + 1; c2 &lt; 52; c2++) {
for(c3 = c2 + 1; c3 &lt; 52; c3++) {
for(c4 = c3 + 1; c4 &lt; 52; c4++) {
for(c5 = c4 + 1; c5 &lt; 52; c5++) {
for(c6 = c5 + 1; c6 &lt; 52; c6++) {
for(c7 = c6 + 1; c7 &lt; 52; c7++) {

CALCULATE RANK
CALCULATE SET ID (HIGH CARD TO STRAIGHT FLUSH)
INCREMENT HANDSETCOUNTERS[SET ID]

}}}}}}}

PRINT HANDSETCOUNTERS


If you could time the speed of your code in that scenario it would be most interesting! Also with a copy of your results (number of flushes etc incase your code is not designed to be 100% accurate).

Thanks for anyone that participates!

Tom

[/ QUOTE ]

<font class="small">Code:</font><hr /><pre>133784560 hands
2.640 secs
50675964 hands/sec
hc 23294460
pr 58627800
tp 31433400
th 6461620
st 6180020
fl 4047644
fh 3473184
fr 224848
sf 41584

using

procedure TForm1.Button2Click(Sender: TObject);
var
Totals : array[0..9] of integer;
c1, c2, c3, c4, c5, c6, c7 : integer;
Count : integer;
Start, Stop : TDateTime;
secs : double;
Score : integer;
begin
Start := Now;
Fillchar(Totals,sizeof(Totals),0);
Count := 0;
for c1 := 0 to 45 do
for c2 := c1+1 to 46 do
for c3 := c2+1 to 47 do
for c4 := c3+1 to 48 do
for c5 := c4+1 to 49 do
for c6 := c5+1 to 50 do
for c7 := c6+1 to 51 do
begin
inc(Totals[Table[Table[Table[Table[Table[Table[Table[c1+52]+c2]+c3]+c4]+c5]+c6]+c7] shr 20]);
inc(Count);
end;
Stop := Now;
secs := (Stop-Start)*86400.0;
memo1.lines.add(format('%d hands',[Count]));
memo1.lines.add(format('%5.3f secs',[secs]));
memo1.lines.add(format('%d hands/sec',[trunc(Count/secs)]));
memo1.lines.add(format('hc %d',[Totals[1]]));
memo1.lines.add(format('pr %d',[Totals[2]]));
memo1.lines.add(format('tp %d',[Totals[3]]));
memo1.lines.add(format('th %d',[Totals[4]]));
memo1.lines.add(format('st %d',[Totals[5]]));
memo1.lines.add(format('fl %d',[Totals[6]]));
memo1.lines.add(format('fh %d',[Totals[7]]));
memo1.lines.add(format('fr %d',[Totals[8]]));
memo1.lines.add(format('sf %d',[Totals[9]]));
end;


and

133784560 hands
1.188 secs
112613302 hands/sec
hc 23294460
pr 58627800
tp 31433400
th 6461620
st 6180020
fl 4047644
fh 3473184
fr 224848
sf 41584

using

procedure TForm1.Button1Click(Sender: TObject);
var
Totals : array[0..9] of integer;
c1, c2, c3, c4, c5, c6, c7 : integer;
u1, u2, u3, u4, u5, u6, u7 : integer;
Count : integer;
Start, Stop : TDateTime;
secs : double;
Score : integer;
begin
Start := Now;
Fillchar(Totals,sizeof(Totals),0);
Count := 0;
for c1 := 0 to 45 do
begin
U1 := Table[52+c1];
for c2 := c1+1 to 46 do
begin
U2 := Table[U1+c2];
for c3 := c2+1 to 47 do
begin
U3 := Table[U2+c3];
for c4 := c3+1 to 48 do
begin
U4 := Table[U3+c4];
for c5 := c4+1 to 49 do
begin
U5 := Table[U4+c5];
for c6 := c5+1 to 50 do
begin
U6 := Table[U5+c6];
for c7 := c6+1 to 51 do
begin
inc(Totals[Table[U6+c7] shr 20]);
inc(Count);
end;
end;
end;
end;
end;
end;
end;
Stop := Now;
secs := (Stop-Start)*86400.0;
memo1.lines.add(format('%d hands',[Count]));
memo1.lines.add(format('%5.3f secs',[secs]));
memo1.lines.add(format('%d hands/sec',[trunc(Count/secs)]));
memo1.lines.add(format('hc %d',[Totals[1]]));
memo1.lines.add(format('pr %d',[Totals[2]]));
memo1.lines.add(format('tp %d',[Totals[3]]));
memo1.lines.add(format('th %d',[Totals[4]]));
memo1.lines.add(format('st %d',[Totals[5]]));
memo1.lines.add(format('fl %d',[Totals[6]]));
memo1.lines.add(format('fh %d',[Totals[7]]));
memo1.lines.add(format('fr %d',[Totals[8]]));
memo1.lines.add(format('sf %d',[Totals[9]]));
end;

</pre><hr />


This was on an AMD 3000+ with 1 gig memory running Win2k

This computer produced

133784560 hands
5.156 secs
25947355 hands/sec
hc 23294460
pr 58627800
tp 31433400
th 6461620
st 6180020
fl 4047644
fh 3473184
fr 224848
sf 41584

using Andrzej Nironen's "Hand Evaluator Speed Demo"

[/ QUOTE ]
Very impressive! (I think you have the results mixed up though - 112.5mil when doing extra work of incrementing the hand type counts, 50mil when not... [img]/images/graemlins/smile.gif[/img] )

Have you considered posting this method on the pokersource yahoo group?

Juk [img]/images/graemlins/smile.gif[/img]

EDIT: Sorry, I just noticed you print the hand type counts in both procedures... BTW: How fast does it run without doing this (ie: just assigning an integer the hand evaluation rather than incrementing totals[]?)
Reply With Quote
  #54  
Old 12-27-2006, 04:18 PM
mykey1961 mykey1961 is offline
Senior Member
 
Join Date: Oct 2005
Posts: 249
Default Re: 7 Card Hand Evaluators

[ QUOTE ]
[ QUOTE ]

<font class="small">Code:</font><hr /><pre>
133784560 hands
1.188 secs
112613302 hands/sec
hc 23294460
pr 58627800
tp 31433400
th 6461620
st 6180020
fl 4047644
fh 3473184
fr 224848
sf 41584

</pre><hr />


This was on an AMD 3000+ with 1 gig memory running Win2k

This computer produced

133784560 hands
5.156 secs
25947355 hands/sec
hc 23294460
pr 58627800
tp 31433400
th 6461620
st 6180020
fl 4047644
fh 3473184
fr 224848
sf 41584

using Andrzej Nironen's "Hand Evaluator Speed Demo"

[/ QUOTE ]
Very impressive! (I think you have the results mixed up though - 112.5mil when doing extra work of incrementing the hand type counts, 50mil when not... [img]/images/graemlins/smile.gif[/img] )

Have you considered posting this method on the pokersource yahoo group?

Juk [img]/images/graemlins/smile.gif[/img]

EDIT: Sorry, I just noticed you print the hand type counts in both procedures... BTW: How fast does it run without doing this (ie: just assigning an integer the hand evaluation rather than incrementing totals[]?)

[/ QUOTE ]

0.953 secs
140382574 hands/sec

However I'm doubting the granularity of the timing process used.

I'll switch to the RDTSC method and repost relative values.

Using RDTSC as a timer

133784560 hands
2.640 secs
50675964 hands/sec

becomes

133784560 hands
5752663748 cycles
42.999 cycles/hand

133784560 hands
1.188 secs
112613302 hands/sec

becomes

133784560 hands
2645152642 cycles
19.772 cycles/hand

and

133784560 hands
0.953 secs
140382574 hands/sec

becomes

133784560 hands
2077269818 cycles
15.527 cycles/hand
Reply With Quote
  #55  
Old 12-27-2006, 07:19 PM
A.Nironen A.Nironen is offline
Senior Member
 
Join Date: Oct 2006
Posts: 118
Default Re: 7 Card Hand Evaluators

I've made some revision of my code. Enumeration wasn't optimal. Now it runs 30% faster with the same hand evaluation function.
http://www.pokerbolide.com/files/handeval7cards.exe

Andrzej Nironen
Reply With Quote
  #56  
Old 12-27-2006, 07:48 PM
_D&L_ _D&L_ is offline
Senior Member
 
Join Date: May 2006
Posts: 128
Default Re: 7 Card Hand Evaluators

how big are the LU tables combined under this method?
Reply With Quote
  #57  
Old 12-27-2006, 08:46 PM
_D&L_ _D&L_ is offline
Senior Member
 
Join Date: May 2006
Posts: 128
Default Re: 7 Card Hand Evaluators

Follow up. Trying to figure out how u map from table 5 to 6, or table 6 to a final hand value without large memory requirements. There about 2.5 Million combinations 5 cards, thust your table would seem to require 2.5 million combinations, yielding a table 6 that is lil over 100 MB.

The one way i thought around this is that your tables may already be condensed using equivalence classes, so the numbers could be smaller. That is, maybe if I wrote the big tables, and backwards eliminated duplicates, it would condense.

Did you do something like that, or totally different?

P.s. your tables lookups for c1 through c3 would probably be a pretty small part of your table(s).

Why not just write them as an array (52,52,52) and put duplicate values in the array to that (1,2,3) = (3,2,1). Looking up a single value from a multi dimensional array is usually much faster than looking up values from 3 different arrays, and performing addition between each lookup.
Reply With Quote
  #58  
Old 12-27-2006, 09:52 PM
_D&L_ _D&L_ is offline
Senior Member
 
Join Date: May 2006
Posts: 128
Default 279Mill a second.....

Made some adjustments to my code, am currently getting 279 Million games per second. Although I still think your algorithm may have greater potential (possibly if I can combine it with mine).

Still not ready to share my algorithm...but i'll provide the following sketch of it...i ommitted some parts, changed descriptive names, etc...so that it can't just be copied (at least not easily).

As you can see its speed is primarily due to being able to solve for many hands in one lookup, skipping to more complex analysis as needed. Whether more complex analysis is needed is also determined by a lookup table.

For c1 = 1 To 46
nFTR(1) = CN(c1)
For c2 = c1 + 1 To 47
nFTR(2) = CN(c2)
For c3 = c2 + 1 To 48
nFTR(3) = CN(c3)
For c4 = c3 + 1 To 49
nFTR(4) = CN(c4)
For c5 = c4 + 1 To 50
nFTR(5) = CN(c5)

rec_number = vRec_Num(non-lexographic indexing algorithm...nftr 1 through 5 as input)

With vType(nftr(1 through 5) as input)

If .Type = 0 Then


For c6 = c5 + 1 To 51
For c7 = c6 + 1 To 52

rank = DW_Array(rec_number + sub_index(c6,c7))

' Select Case rank
' Case 0 To 3000
' h1 = h1 + 1
' Case 3001 To 7000
' h2 = h2 + 1
' Case 7001 To 9000
' h3 = h3 + 1
' Case 9001 To 11000
' h4 = h4 + 1
' Case 11001 To 12000
' h5 = h5 + 1
' Case 12001 To 15000
' h6 = h6 + 1
' Case 15001 To 16000
' h7 = h7 + 1
' Case 16001 To 17000
' h8 = h8 + 1
' Case Else
' h9 = h9 + 1
' End Select

Next c7
Next c6

Else

...omitted...

For c6 = c5 + 1 To 51
For c7 = c6 + 1 To 52

vType = .Type
vnumber = .tnumber

If SN(c6) = vType Then vnumber = vnumber + 1: adjust(vnumber) = CN(c6)
If SN(c7) = vType Then vnumber = vnumber + 1: adjust(vnumber) = CN(c7)

Select Case vnumber
Case Is condition1
rank = DW_Array(rec_number + cindex(c6, c7))
Case condition2
rank = SW_Array(Rec_number2 (another non-lexographic indexing algorithm) * XX)
Case condition3
rank = SW_Array(Rec_number2 * XX + fn1(adjust(6)))
Case Else
rank = SW_Array(Rec_number2 * XX + cindex(c6, c7))
End Select

' Select Case rank
' Case 0 To 3000
' h1 = h1 + 1
' Case 3001 To 7000
' h2 = h2 + 1
' Case 7001 To 9000
' h3 = h3 + 1
' Case 9001 To 11000
' h4 = h4 + 1
' Case 11001 To 12000
' h5 = h5 + 1
' Case 12001 To 15000
' h6 = h6 + 1
' Case 15001 To 16000
' h7 = h7 + 1
' Case 16001 To 17000
' h8 = h8 + 1
' Case Else
' h9 = h9 + 1
' End Select

Next c7
Next c6

End If
End With

Next c5
Next c4
Next c3
Next c2
Next c1

'dump counters

'Output.Text = h1 &amp; vbNewLine &amp; h2 &amp; vbNewLine &amp; h3 &amp; vbNewLine &amp; h4 &amp; vbNewLine &amp; h5 &amp; vbNewLine &amp; h6 &amp; vbNewLine &amp; h7 &amp; vbNewLine &amp; h8 &amp; vbNewLine &amp; h9 &amp;
vbNewLine
Reply With Quote
  #59  
Old 12-28-2006, 12:52 AM
mykey1961 mykey1961 is offline
Senior Member
 
Join Date: Oct 2005
Posts: 249
Default Re: 7 Card Hand Evaluators

[ QUOTE ]
Follow up. Trying to figure out how u map from table 5 to 6, or table 6 to a final hand value without large memory requirements. There about 2.5 Million combinations 5 cards, thust your table would seem to require 2.5 million combinations, yielding a table 6 that is lil over 100 MB.

The one way i thought around this is that your tables may already be condensed using equivalence classes, so the numbers could be smaller. That is, maybe if I wrote the big tables, and backwards eliminated duplicates, it would condense.

Did you do something like that, or totally different?

P.s. your tables lookups for c1 through c3 would probably be a pretty small part of your table(s).

Why not just write them as an array (52,52,52) and put duplicate values in the array to that (1,2,3) = (3,2,1). Looking up a single value from a multi dimensional array is usually much faster than looking up values from 3 different arrays, and performing addition between each lookup.

[/ QUOTE ]

The table I use is for best 5 of 7 cards, not best 5 of 6, or just the only 5 given. Therefore I take advantage of that information when identifing the states.

The "compression" occurs starting at the 4th card.

If the first 4 cards of a 7 card hand are all of different suits, there is no way we could make a flush.

Therefore AsKcQdJh is given the State ID of AxKxQxJx.

There are a total of 24 combinations that would map to the same State ID.

A hand like 9c3sTh5c is given the State ID of Tx9c5c3x

The State ID needs to indicate that 2 of the cards are clubs, in case the next 3 cards are also clubs.

5hJdKdAh would get the StateID AhKdJd5h

Since we could end up with either a heart flush or a diamond flush.


If we are at State ID AhKdJd5h and the next card is a 6s, the new State ID would be AxKxJx6x5x since a flush is no longer possible.

The 270725 4-card combos map down to 84448

With 5 cards you need 3 of the same suit, otherwise all suits can be ignored.

Using an array of (52,52,52) probably wouldn't be faster.

Multi-dimension arrays tend to involve a multiply or two internally.
Reply With Quote
  #60  
Old 12-28-2006, 12:57 AM
mykey1961 mykey1961 is offline
Senior Member
 
Join Date: Oct 2005
Posts: 249
Default Re: 279Mill a second.....

[ QUOTE ]
Made some adjustments to my code, am currently getting 279 Million games per second. Although I still think your algorithm may have greater potential (possibly if I can combine it with mine).


[/ QUOTE ]

This is what happens when you let lawyers near compilers [img]/images/graemlins/smile.gif[/img]

I'm not 100% sure about VB, but it's possible that since you commented out where you use 'rank', the optimizer eliminated the code that compute/lookup the value for rank.

You might just be timing "empty" for - next loops.
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 01:05 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2026, vBulletin Solutions Inc.