Skip to content

Commit

Permalink
Merge branch 'main' into fix-abstraction-loading
Browse files Browse the repository at this point in the history
  • Loading branch information
krukah authored Oct 18, 2024
2 parents 2ab0c92 + a8e163e commit 62f895e
Show file tree
Hide file tree
Showing 23 changed files with 1,489 additions and 408 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
.swp
profile.json
*.pgcopy
analysis/*.png
2 changes: 0 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ RUN cargo build --release

# Binary stage
FROM debian:bookworm-slim AS binary

WORKDIR /output

RUN apt-get update && \
apt-get install -y libssl3 ca-certificates && \
rm -rf /var/lib/apt/lists/*
Expand Down
77 changes: 77 additions & 0 deletions analysis/analysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import sqlalchemy as sql

# Create a database connection
engine = sql.create_engine('postgresql://localhost:5432/robopoker')
query = """
WITH unique_abstraction AS (
SELECT DISTINCT abs
FROM turn_abs
),
self_join_abstraction AS (
SELECT
a.abs as abs1,
b.abs as abs2,
(a.abs # b.abs)::numeric as xor_result
FROM unique_abstraction a
CROSS JOIN unique_abstraction b
WHERE a.abs > b.abs
)
SELECT
c.abs1,
c.abs2,
COALESCE(m.dst, 0) as dst
FROM self_join_abstraction c
LEFT JOIN turn_met m ON m.xab = c.xor_result::bigint
"""


# Read the query directly into a pandas DataFrame
df = pd.read_sql(query, engine)

df['x'] = df['abs1']
df['y'] = df['abs2']

# After loading the data
abstractions_hex = sorted(set(df['x'].unique()) | set(df['y'].unique()))
complete_index = pd.MultiIndex.from_product([abstractions_hex, abstractions_hex], names=['x', 'y'])
complete_df = df.set_index(['x', 'y']).reindex(complete_index).reset_index()
complete_df['dst'] = complete_df['dst'].fillna(0) # Fill NaN with 0 or another appropriate value

# Create a pivot table with the complete dataset
pivot_df = complete_df.pivot(index='x', columns='y', values='dst')

# Create a heatmap
plt.figure(figsize=(24, 20)) # Increased figure size further
sns.heatmap(pivot_df, cmap='YlOrRd', annot=False, square=True, xticklabels=True, yticklabels=True)
plt.title('Turn Abstraction Distances')
plt.xlabel('Abstraction 2')
plt.ylabel('Abstraction 1')
plt.xticks(rotation=90, fontsize=6)
plt.yticks(rotation=0, fontsize=6)
plt.tight_layout()
plt.savefig(f'{int(pd.Timestamp.now().timestamp()) >> 8}.turn.metric.heatmap.png', dpi=300)
plt.close()

print("\nbasic statistics:")
print(df['dst'].describe())

print("\ntop 10 furthest pairs:")
print(df.nlargest(10, 'dst')[['x', 'y', 'dst']])

print("\ntop 10 closest pairs:")
print(df.nsmallest(10, 'dst')[['x', 'y', 'dst']])

# Distribution of distances
plt.figure(figsize=(10, 6))
sns.histplot(df['dst'], kde=True)
plt.title('distribution of turn abstraction distances')
plt.xlabel('dst')
plt.savefig(f'{int(pd.Timestamp.now().timestamp()) >> 8}.turn.metric.distribution.png')
plt.close()

print("Shape of pivot_df:", pivot_df.shape)
print("Number of non-zero entries:", (pivot_df != 0).sum().sum())
22 changes: 22 additions & 0 deletions analysis/analysis.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-- Create and prepare abstraction table
CREATE TABLE IF NOT EXISTS turn_abs (obs BIGINT, abs BIGINT);
TRUNCATE TABLE turn_abs;
ALTER TABLE turn_abs
SET UNLOGGED;
DROP INDEX IF EXISTS idx_turn_abs_observation;
COPY turn_abs (obs, abs)
FROM 'turn.abstraction.pgcopy' WITH (FORMAT BINARY);
ALTER TABLE turn_abs
SET LOGGED;
CREATE INDEX IF NOT EXISTS idx_turn_abs_observation ON turn_abs (obs);
-- Create and prepare metric table
CREATE TABLE IF NOT EXISTS turn_met (xab BIGINT, dst REAL);
TRUNCATE TABLE turn_met;
ALTER TABLE turn_met
SET UNLOGGED;
DROP INDEX IF EXISTS idx_turn_xab_abstraction;
COPY turn_met (xab, dst)
FROM 'turn.metric.pgcopy' WITH (FORMAT BINARY);
ALTER TABLE turn_met
SET LOGGED;
CREATE INDEX IF NOT EXISTS idx_turn_xab_abstraction ON turn_met (xab);
872 changes: 872 additions & 0 deletions analysis/poetry.lock

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions analysis/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[tool.poetry]
name = "analysis"
version = "0.1.0"
description = ""
authors = ["Kelechi Ukah <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.13"
pandas = "^2.2.3"
numpy = "^2.1.2"
matplotlib = "^3.9.2"
seaborn = "^0.13.2"
SQLAlchemy = "^2.0.36"
psycopg2-binary = "^2.9.10"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
7 changes: 7 additions & 0 deletions src/cards/hole.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::card::Card;
use super::hand::Hand;
use super::observation::Observation;

#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, PartialOrd, Ord)]
pub struct Hole(Hand);
Expand Down Expand Up @@ -28,6 +29,12 @@ impl From<Hole> for Hand {
}
}

impl From<Observation> for Hole {
fn from(obs: Observation) -> Self {
Self(Hand::from(obs.pocket().clone()))
}
}

impl From<(Card, Card)> for Hole {
fn from(cards: (Card, Card)) -> Self {
let a = u64::from(cards.0);
Expand Down
5 changes: 2 additions & 3 deletions src/cards/isomorphism.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::play::game::Game;

use super::observation::Observation;
use super::permutation::Permutation;
use crate::play::game::Game;

/// because of the equivalence of Suit,
/// many Observations are strategically equivalent !
Expand All @@ -23,7 +22,7 @@ use super::permutation::Permutation;
/// but it's approx 4 (* 5) times smaller, as youd expect for without-replacement
/// sampling on the last two Streets.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, PartialOrd, Ord)]
pub struct Isomorphism(Observation);
pub struct Isomorphism(pub Observation);

impl From<Observation> for Isomorphism {
fn from(ref observation: Observation) -> Self {
Expand Down
4 changes: 4 additions & 0 deletions src/cards/observations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,27 +91,31 @@ mod tests {
use super::*;

#[test]
#[ignore]
fn n_pref() {
let street = Street::Pref;
let iter = ObservationIterator::from(street);
assert_eq!(iter.combinations(), street.n_observations());
assert_eq!(iter.combinations(), iter.count());
}
#[test]
#[ignore]
fn n_flop() {
let street = Street::Flop;
let iter = ObservationIterator::from(street);
assert_eq!(iter.combinations(), street.n_observations());
assert_eq!(iter.combinations(), iter.count());
}
#[test]
#[ignore]
fn n_turn() {
let street = Street::Turn;
let iter = ObservationIterator::from(street);
assert_eq!(iter.combinations(), street.n_observations());
assert_eq!(iter.combinations(), iter.count());
}
#[test]
#[ignore]
fn n_rive() {
let street = Street::Rive;
let iter = ObservationIterator::from(street);
Expand Down
8 changes: 4 additions & 4 deletions src/cards/street.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ impl Street {
impl std::fmt::Display for Street {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Pref => write!(f, "Preflop"),
Self::Flop => write!(f, "Flop"),
Self::Turn => write!(f, "Turn"),
Self::Rive => write!(f, "River"),
Self::Pref => write!(f, "preflop"),
Self::Flop => write!(f, "flop"),
Self::Turn => write!(f, "turn"),
Self::Rive => write!(f, "river"),
}
}
}
7 changes: 7 additions & 0 deletions src/clustering/abstraction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ impl From<i64> for Abstraction {
}
}

/// lossless preflop abstraction
impl From<Hole> for Abstraction {
fn from(hole: Hole) -> Self {
Self::Pocket(hole)
}
}

impl std::fmt::Display for Abstraction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expand Down
Loading

0 comments on commit 62f895e

Please sign in to comment.