我对扑克股票进行了研究。我做的是使用pokerstove程序和一些选定的。并使用该程序使用枚举所有方法计算股票。所以pokerstove结果:
我还制作了一个表格,用于存储随机结果:
CREATE TABLE poker_results
(
id int NOT NULL AUTO_INCREMENT,
matches_id int NOT NULL, -- just for filtering in case I will want another starting hands.
result varchar(255) NOT NULL,
winner_hands varchar(255) NOT NULL,
PRIMARY KEY (id)
)
结果列数据如下所示:Jd,9d,Qh,5c,Kc - 这表示卡上的卡片。
Winner_hands列数据如下所示:Ks-Ac,6c-Ad,3c-Ah(可以1手赢,可以全部赢8手)。
以下是向数据库生成结果的代码。它在codeigniter框架上。而且为了不复制整个poker.php,我只是复制了几个使用它们的函数:
protected function get_probabilities($hands, $board_cards = array()) {
$players = count($hands);
$board = implode('', $board_cards);
$board = trim($board);
if (empty($board)) {
$board = '-';
}
$hx = '';
$hand_counter = 1;
foreach ($hands as $hand) {
$hx .= '&h' . $hand_counter++ . '=' . $hand[0] . $hand[1];
}
$url = 'http://' . $this->poker_server . '/?board=' . $board . $hx . '&auth=' . $this->auth;
//Output exm. string '0.1342, 0.2042, 0.13525, 0.52635'
//WAR!! check if alive
$result = $this->parse_url_link($url);
if (substr($result, 0, 3) == 'Err') {
$this->utils->logging('ERROR', 'Poker server authorization failed!');
}
//echo $result;
return array(
'hands' => $hands,
'prob' => explode(', ', $result),
'board' => $board_cards
);
}
// protected because in child class needed
protected function get_poker_winner($table_winners) {
$to_return = array();
foreach($table_winners['prob'] as $key => $val) {
if ($val > 0) {
$to_return[] = $table_winners['hands'][$key][0] . '-' . $table_winners['hands'][$key][1];
}
}
return $to_return;
}
poker_tests.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
include_once(APPPATH . 'controllers/poker.php');
require_once APPPATH . "libraries/downloaded/Mersenne_twister.php";
use mersenne_twister\twister;
class Poker_tests extends Poker {
public function __construct() {
parent::__construct();
}
/**
* Generates data in database with such structure:
* CREATE TABLE matches
* (
* id int NOT NULL AUTO_INCREMENT,
* player_cards varchar(255) NOT NULL,
*
* PRIMARY KEY (ID)
* )
*
* CREATE TABLE poker_results
* (
* id int NOT NULL AUTO_INCREMENT,
* result varchar(255) NOT NULL,
* PRIMARY KEY (id)
* )
*
*
* Here 1 match will have many results, because we use same preflop cards.
*
* Text results appended to pokerstove.txt
*
* 376,992 games 0.013 secs 28,999,384 games/sec
*
* Board:
* Dead:
*
* equity win tie pots won pots tied
* Hand 0: 20.925% 20.53% 00.40% 77382 1504.50 { KhQs }
* Hand 1: 06.215% 03.50% 02.72% 13190 10239.00 { 9c4d }
* Hand 2: 06.396% 04.08% 02.32% 15379 8734.00 { 8d4c }
* Hand 3: 18.906% 18.15% 00.76% 68426 2847.50 { AcKs }
* Hand 4: 08.767% 06.91% 01.86% 26032 7019.50 { 9h2c }
* Hand 5: 10.204% 09.83% 00.38% 37044 1424.00 { Ad6c }
* Hand 6: 09.046% 08.67% 00.38% 32678 1424.00 { Ah3c }
* Hand 7: 19.541% 18.08% 01.46% 68154 5514.50 { 8c7c }
*
*
* ---
*
*
*/
public function run() {
$this->benchmark->mark('start');
$this->output->enable_profiler(TRUE);
//close the current connection, because its not needed
$this->db->close();
$db_poker = $this->load->database('poker_test', TRUE);
$sql = "INSERT INTO poker_results (result, winner_hands, matches_id) VALUES (?, ?, ?)";
// matches_id = 1. Insert new match
$table8_hands = 'Kh,Qs,4d,9c,4c,8d,Ks,Ac,2c,9h,6c,Ad,3c,Ah,7c,8c'; // do test with this. Do those win the right amount of time?
for ($i=0; $i < 400000; $i++) { // pradejus id 100194
$flop = $this->poker_flop($table8_hands);
$turn = $this->poker_turn($flop, $table8_hands);
$river = $this->poker_stop($turn, $table8_hands);
//echo json_encode($river) . '<br>';
$db_poker->query($sql, array($river['river_board'], implode(',', $river['winner_hands8']), 2));
}
$db_poker->close();
$this->benchmark->mark('end');
echo $this->benchmark->elapsed_time('start', 'end') . '<br>';
}
/**
*
* Override - remove unneeded things for test from that function in poker.php
* Generates 3 flop cards
*/
public function poker_flop($table8_hands) {
$table8_cards = explode(',', $table8_hands);
$table8_results = $this->random_result($table8_cards, 3);
return $table8_results;
}
/**
* Generates 1 turn card
* @param $table8_hands - same as match score in database. But here we have hardcoded in run function
*
*/
public function poker_turn($table8_flop, $table8_hands) {
$table8_cards = explode(',', $table8_hands);
//Join players cards and opened board cards
$table8_reserved_cards = array_merge($table8_cards, $table8_flop);
//Pass all opened cards and get one new board card
$table8_results = $this->random_result($table8_reserved_cards, 1);
//Merge all opened board cards
$table8_results = array_merge($table8_flop, $table8_results);
// this is flop and turn both
return $table8_results;
}
/**
*
* Generates 1 river card
*/
public function poker_stop($table8_flop_turn, $table8_hands) {
$table8_cards = explode(',', $table8_hands);
$table8_reserved_cards = array_merge($table8_cards, $table8_flop_turn);
$table8_results = $this->random_result($table8_reserved_cards, 1);
$table8_results = array_merge($table8_flop_turn, $table8_results);
$table8_hands = $this->array_to_hands_array($table8_cards);
$flop_turn_results = implode(',', $table8_results);
// $this->benchmark->mark('code_start');
//Get new probabilities - they will be needed to determine if hand has won or not. When prob. > 0 - then won
$table8_prob = $this->get_probabilities($table8_hands, $table8_results);
// $this->benchmark->mark('code_end');
// echo $this->benchmark->elapsed_time('code_start', 'code_end');
return array(
'winner_hands8' => $this->get_poker_winner($table8_prob),
'river_board' => $flop_turn_results
);
}
/**
* for second generation - new random function
* @param array $reserved_cards
* @param integer $cards_amount
* @return array
*/
protected function random_result($reserved_cards, $cards_amount = 5) {
$card_types = array('s', 'c', 'h', 'd');
$card_values = array('A', 2, 3, 4, 5, 6, 7, 8, 9, 'T', 'J', 'Q', 'K');
$deck = array();
foreach ($card_values as $value) {
foreach ($card_types as $type) {
$deck[] = $value . $type;
}
}
$remaining_deck = array_diff($deck, $reserved_cards);
// make keys sequence:
$remaining_deck = array_values($remaining_deck);
$results = array();
while (count($results) != $cards_amount) {
$rand_card_key = $this->random(0, (count($remaining_deck) - 1));
$results[] = $remaining_deck[$rand_card_key];
// remove from deck
unset($remaining_deck[$rand_card_key]);
// make keys sequence:
$remaining_deck = array_values($remaining_deck);
}
return $results;
}
/**
* Picks random element from range
* @param integer $from
* @param integer $to
* @return integer
*/
private function random($from, $to) {
if (file_exists('/dev/urandom')) {
$twister4 = new twister;
$twister4->init_with_file("/dev/urandom", twister::N);
return $twister4->rangeint($from, $to);
}
else {
return mt_rand($from, $to);
}
}
}
正如我们在随机函数中看到的那样 - 当我在linux上进行测试时,我使用带有linux dev / urnadom的twister库,当我在windows上时,我使用本机mt_rand。没有注意到差异。
因此,为了选择结果,我使用如下查询:
获得结果总数
select count(*) from poker_results where matches_id = 2 and id < 296351
获得手牌的总胜利(胜利+平局):
select count(*) from poker_results where matches_id = 2 and id < 296351 and winner_hands like '%Kh-Qs%'
获得多少手提壶:
select count(*) from poker_results where matches_id = 2 and id < 296351 and winner_hands like '%Kh-Qs%' and winner_hands != 'Kh-Qs'
扑克服务器用于获得手中的资产。通过河上的手工资产,我确定手是否赢了 - 当手资产为&gt; 0然后赢了。
这个工具在另一台服务器上使用 - 有运行python程序的php代码,但这并不重要。
http://pokersleuth.com/programmable-poker-calculator.shtml
该工具就像pokerstove但它有命令行版本。顺便说一句,不买这个工具,我们买了,他们没有发送许可证密钥,有点像他们不在乎。
现在的结果是:
现在,如果我们进行比较,那么双手胜过+平局比pokerstove或pokersleuth表现出平等。当我看起来蚂蚁领带% - 它比啤酒炉显示更大。样本不是那么小。 Pokerstove使用了近400K的游戏,虽然它有点少,但是tendencty仍然是相同的。首先,我尝试了更小的样本,如10K游戏 - 同样的趋势。因此,当我生成100K以上时,如果结果大致相同,我并不感到惊讶。此示例也是在linux上生成的。但是关于同样的样本也是在Windows上生成的,并且胜利仍然超过pokerstove节目,胜利%的总和也是110-112%。
所以我们不理解 - 我生成的东西是坏的还是那些程序显示错误?显示错误股票的计划不太可能,因为它们被广泛使用,并且可能已经进行了大量测试。
更新
我想我终于明白了:) Pokersleuth计算了一个机会 知道板上的5张牌,获胜(两张牌)。你是 然后将这些机会与真实结果进行比较(了解双手的情况) 所有其他球员)。正确?
右。我不得不在这里写,因为它不允许在评论中进行扩展讨论。
更新:
生成更多行 - 目前在Linux服务器上为515989,%仍然与以前大致相同。所以不动了
答案 0 :(得分:4)
您有296350个生成的结果,但332911胜出&amp;的关系。
这个过程的任何部分是否都会调和这样一个事实:当有一个平局时,它是在两手或更多手之间?看起来关系正在被计算在内。
获得总胜率和平局百分比,112.3371014%。乘以(生成的结果除以胜利和关系)。你会得到100%。这表明了什么?
另外,看看Ad6c和Ah3c。他们的领带数完全相同,很可能是同一只手(胜利是一对A)。
但对于他们打平的牌,该牌数被计算/加权两次(一次用于Ad6c,一次用于Ah3c)。这就是为什么你的领带%至少是他们应该的两倍。你必须按领带数量
来规范领带数