Created
March 15, 2013 01:47
-
-
Save dabd/5166904 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let equities_file = "preflop_equities.dat" | |
let combos_file = "preflop_combos.dat" | |
let num_hands = 169 | |
let sb_minr_range = Array.make num_hands 0.5 | |
let sb_call_range = Array.make num_hands 0.5 | |
let bb_shove_range = Array.make num_hands 0.5 | |
(* All equities between hand i and j *) | |
let pf_equities = Array.make_matrix num_hands num_hands 0.0 | |
(* pf_combos is a matrix m where m(i,j) = #non-conflicting combos when matching i against j, i.e. how many combos of j there are after removing the conflicting cards in i. | |
Ex: m(0,1) = 6 because i=22 and j=32o and when matching 22 against 32o there are only 6 combos of 32o after removing the two deuces in 22. *) | |
let pf_combos = Array.make_matrix num_hands num_hands 0.0 | |
let preflop_hands = [|"22";"32o";"42o";"52o";"62o";"72o";"82o";"92o";"T2o";"J2o";"Q2o";"K2o";"A2o";"32s";"33";"43o";"53o";"63o";"73o";"83o";"93o";"T3o";"J3o";"Q3o";"K3o";"A3o";"42s";"43s";"44";"54o";"64o";"74o";"84o";"94o";"T4o";"J4o";"Q4o";"K4o";"A4o";"52s";"53s";"54s";"55";"65o";"75o";"85o";"95o";"T5o";"J5o";"Q5o";"K5o";"A5o";"62s";"63s";"64s";"65s";"66";"76o";"86o";"96o";"T6o";"J6o";"Q6o";"K6o";"A6o";"72s";"73s";"74s";"75s";"76s";"77";"87o";"97o";"T7o";"J7o";"Q7o";"K7o";"A7o";"82s";"83s";"84s";"85s";"86s";"87s";"88";"98o";"T8o";"J8o";"Q8o";"K8o";"A8o";"92s";"93s";"94s";"95s";"96s";"97s";"98s";"99";"T9o";"J9o";"Q9o";"K9o";"A9o";"T2s";"T3s";"T4s";"T5s";"T6s";"T7s";"T8s";"T9s";"TT";"JTo";"QTo";"KTo";"ATo";"J2s";"J3s";"J4s";"J5s";"J6s";"J7s";"J8s";"J9s";"JTs";"JJ";"QJo";"KJo";"AJo";"Q2s";"Q3s";"Q4s";"Q5s";"Q6s";"Q7s";"Q8s";"Q9s";"QTs";"QJs";"QQ";"KQo";"AQo";"K2s";"K3s";"K4s";"K5s";"K6s";"K7s";"K8s";"K9s";"KTs";"KJs";"KQs";"KK";"AKo";"A2s";"A3s";"A4s";"A5s";"A6s";"A7s";"A8s";"A9s";"ATs";"AJs";"AQs";"AKs";"AA"|] | |
let read_pf_data file matrix = | |
let ic = open_in file in | |
try | |
for i=0 to num_hands-1 do | |
for j=0 to num_hands-1 do | |
let line = input_line ic in | |
matrix.(i).(j) <- float_of_string line | |
done | |
done; | |
close_in ic (* close the input channel *) | |
with e -> (* some unexpected exception occurs *) | |
close_in_noerr ic; (* emergency closing *) | |
raise e (* exit with error: files are closed but | |
channels are not flushed *) | |
;; | |
let print_range r = | |
print_string "{"; | |
for i=0 to num_hands-1 do | |
print_string preflop_hands.(i); | |
print_string ":"; | |
print_float r.(i); | |
if i < num_hands-1 | |
then | |
print_string ","; | |
done; | |
print_string "}" | |
;; | |
let update_strategy range new_range iter = | |
let mix_factor = 1.0 /. ( (float_of_int iter) +. 1.0) in | |
for i=0 to num_hands-1 do | |
range.(i) <- mix_factor *. new_range.(i) +. (1.0 -. mix_factor) *. range.(i) | |
done | |
;; | |
let get_equity hand range = | |
let eq_sum = ref 0.0 in | |
let sum = ref 0.0 in | |
for i=0 to num_hands-1 do | |
eq_sum.contents <- !eq_sum +. pf_combos.(hand).(i) *. range.(i) *. pf_equities.(hand).(i); | |
sum.contents <- !sum +. pf_combos.(hand).(i) *. range.(i) | |
done; | |
!eq_sum /. !sum | |
;; | |
let get_frac_of_all_hands_without_conflict hand range = | |
let total_combos_dont_confl = ref 0.0 in | |
let sum = ref 0.0 in | |
for i=0 to num_hands-1 do | |
total_combos_dont_confl.contents <- !total_combos_dont_confl +. pf_combos.(hand).(i); | |
sum.contents <- !sum +. range.(i) *. pf_combos.(hand).(i) | |
done; | |
!sum /. !total_combos_dont_confl | |
;; | |
let get_sb_best_response new_sb_minr_range new_sb_call_range | |
bb_shove_range stack_size ante = | |
let total_ev = ref 0.0 in | |
for i=0 to num_hands-1 do | |
let ev_fold_vs_shove = stack_size -. 2.0 -. ante in | |
let eq_i = get_equity i bb_shove_range in | |
let ev_call = 2.0 *. stack_size *. eq_i in | |
let bb_shove_freq = get_frac_of_all_hands_without_conflict i bb_shove_range in | |
let ev_open_fold = stack_size -. 0.5 -. ante in | |
let ev_minr = (1.0 -. bb_shove_freq) *. (stack_size +. 1.0 +. ante) +. bb_shove_freq *. max ev_fold_vs_shove ev_call in | |
let ev = max ev_minr ev_open_fold in | |
total_ev.contents <- !total_ev +. ev; | |
if ev_minr > ev_open_fold | |
then | |
new_sb_minr_range.(i) <- 1.0 | |
else | |
new_sb_minr_range.(i) <- 0.0; | |
(* if the hand was minraised *) | |
if ev_minr > ev_open_fold && ev_call > ev_fold_vs_shove | |
then | |
new_sb_call_range.(i) <- 1.0 | |
else | |
new_sb_call_range.(i) <- 0.0 | |
done; | |
!total_ev | |
;; | |
let get_bb_best_response new_bb_shove_range sb_minr_range | |
sb_call_range stack_size ante = | |
for i=0 to num_hands-1 do | |
let ev_fold = stack_size -. 1.0 -. ante in | |
let eq_i = get_equity i sb_call_range in | |
let sb_minr_freq = get_frac_of_all_hands_without_conflict i sb_minr_range in | |
let sb_call_freq = get_frac_of_all_hands_without_conflict i sb_call_range in | |
(* if sb_minr_freq is zero, sb_call_freq will be also zero causing ev_shove to be nan and setting the hand i freq to zero in new_sb_shove_range *) | |
let ev_shove = (1.0 -. sb_call_freq /. sb_minr_freq) *. | |
(stack_size +. 2.0 +. ante) +. sb_call_freq /. sb_minr_freq *. eq_i *. 2.0 *. stack_size in | |
if ev_shove > ev_fold then | |
new_bb_shove_range.(i) <- 1.0 | |
else | |
new_bb_shove_range.(i) <- 0.0 | |
done | |
;; | |
let get_num_hands_in range = | |
let sum = ref 0.0 in | |
for i=0 to num_hands-1 do | |
sum.contents <- !sum +. range.(i) | |
done; | |
!sum | |
;; | |
(* let main = *) | |
(* read_pf_data equities_file pf_equities; *) | |
(* read_pf_data combos_file pf_combos; *) | |
(* let stack_size = float_of_string Sys.argv.(1) in *) | |
(* let num_iter = int_of_string Sys.argv.(2) in *) | |
(* Printf.printf "Running minr/shove game solver at %f BBs for %d iterations...\n" stack_size num_iter; *) | |
(* for i=0 to num_iter do *) | |
(* (\* update SB strategy *\) *) | |
(* let new_sb_minr_range = Array.make num_hands 0.0 in *) | |
(* let new_sb_call_range = Array.make num_hands 0.0 in *) | |
(* let total_ev = get_sb_best_response new_sb_minr_range new_sb_call_range bb_shove_range stack_size in *) | |
(* update_strategy sb_minr_range new_sb_minr_range i; *) | |
(* update_strategy sb_call_range new_sb_call_range i; *) | |
(* (\* update BB strategy *\) *) | |
(* let new_bb_shove_range = Array.make num_hands 0.0 in *) | |
(* get_bb_best_response new_bb_shove_range sb_minr_range sb_call_range stack_size; *) | |
(* update_strategy bb_shove_range new_bb_shove_range i; *) | |
(* done; *) | |
(* (\* print results *\) *) | |
(* Printf.printf "SB Minr Range (%f ambiguous hands):\n" (get_num_hands_in sb_minr_range); *) | |
(* print_range sb_minr_range; *) | |
(* Printf.printf "\nSB Call Range (%f ambiguous hands):\n" (get_num_hands_in sb_call_range); *) | |
(* print_range sb_call_range; *) | |
(* Printf.printf "\nBB Shove Range (%f ambiguous hands):\n" (get_num_hands_in bb_shove_range); *) | |
(* print_range bb_shove_range; *) | |
(* print_string "\n" *) | |
(* ;; *) | |
let main = | |
read_pf_data equities_file pf_equities; | |
read_pf_data combos_file pf_combos; | |
let m = float_of_string Sys.argv.(1) in | |
let ante = float_of_string Sys.argv.(2) in | |
(* epsilon value is half a bb every 100 hands. | |
If the difference between total EVs for the SB between iterations is less than this it stops the fictitious play *) | |
let epsilon = 1e-5 in | |
let i = ref 0 in | |
let prev_total_ev = ref infinity in | |
let total_ev = ref 0.0 in | |
let stack_size = m *. (1.5 +. (2.0 *. ante)) in | |
while abs_float (!total_ev -. !prev_total_ev) >= epsilon do | |
incr i; | |
prev_total_ev.contents <- !total_ev; | |
(* update SB strategy *) | |
let new_sb_minr_range = Array.make num_hands 0.0 in | |
let new_sb_call_range = Array.make num_hands 0.0 in | |
total_ev.contents <- get_sb_best_response new_sb_minr_range | |
new_sb_call_range bb_shove_range stack_size ante; | |
(* Printf.printf "EV diff %f iteration %d\n" (abs_float (!total_ev -. !prev_total_ev)) !i; *) | |
update_strategy sb_minr_range new_sb_minr_range !i; | |
update_strategy sb_call_range new_sb_call_range !i; | |
(* update BB strategy *) | |
let new_bb_shove_range = Array.make num_hands 0.0 in | |
get_bb_best_response new_bb_shove_range sb_minr_range | |
sb_call_range stack_size ante; | |
update_strategy bb_shove_range new_bb_shove_range !i | |
done; | |
Printf.printf "Converged minr/shove game solver after %d iterations...\n" !i; | |
(* print results *) | |
Printf.printf "SB Minr Range (%f ambiguous hands):\n" (get_num_hands_in sb_minr_range); | |
print_range sb_minr_range; | |
Printf.printf "\nSB Call Range (%f ambiguous hands):\n" (get_num_hands_in sb_call_range); | |
print_range sb_call_range; | |
Printf.printf "\nBB Shove Range (%f ambiguous hands):\n" (get_num_hands_in bb_shove_range); | |
print_range bb_shove_range; | |
print_string "\n" | |
;; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment