Wednesday, April 27, 2011

AK vs half-dead pair (User Request)

I got a fun question from a user today. "How does AK (suited or unsuited) fare against any pair assuming that one of the pair's set outs are dead?"

We can answer this with a little PQL hackery. I say "hackery" because there isn't a way to connect dead cards with other hand ranges in PQL at the moment. We will perform an all in equity simulation with AK vs any pair. If the pair gets quads by the river, we throw out the sim, since one of the set cards is supposed to be dead. If the pair does not get a matching card by the river, we keep the sim, since the dead card never appeared. If the pair hits exactly one of its set cards but doesn't have quads, we have a 50/50 chance that the sim should be thrown out. Here's where the hack comes in - we can just throw out all sims in this case where one of the pair cards is a heart, as 50% of pairs have a heart in them. Note that if the pair is Aces or Kings, then we should not be able to hit the board at all, so we need to exclude that as well.

Here is the PQL query I came up with:

select avg(riverEquity(hero))
from game='holdem', hero='AK', villain='AA-22', syntax='Generic'
case handBoardIntersections(villain, river)
when 0 then true
when 2 then inRange(villain,'*!h!AA-KK')
and not (handtype(villain, river) = quads)

Answer - AK has 48% equity.

Tuesday, April 19, 2011

Whence PQL?

"A-ha!" vs. "Ho-hum"

In the popular imagination, innovation comes from a flash of genius - a sudden, almost supernatural insight that often catches the inventor himself unawares. In reality, most innovation is far more mundane - small, incremental (and often obvious) improvements combine to make something new possible. Indeed, almost everything "new" on has found its genesis in incremental improvements - new games, graphs, and tools that build on what came before. After all, the very first version of was an answer to the question "What would an online version of PokerStove look like?"

PQL is the exception - it is the closest I've come to a "Eureka" moment yet.

Three as One

Here are three questions that have been answerable at one time or another via propokertools:
  • Given that player one has XX, player two has YY, and the board is ZZZ, what is the all-in equity for player one?
  • Given that player one has XX, player two has YY, and the board is ZZZ, how often does player one have at least two pair by the river?
  • Given that player one has XX, player two has YY, and the board is ZZZ, what does the graph of equities look like for player one?
Notice anything? These questions all have the same setup, namely "Given that p1 has ..., p2 has...". Let's call this the situation. After each situation, there is a question, which we can refer to as, well, the question. The three questions can all be rewritten as:
  • Given situation S, what is the answer to question Q?
In programmer-speak, we can say that we have abstracted out the concept of a situation and a question. This process of abstraction is one of the principal (some would say the principal) jobs of a programmer. And there is nothing particularly noteworthy about the abstraction above - any programmer worth her salt would spot it almost immediately.

Exposing the Abstraction

I spent a few weeks rewriting propokertools in December of 2010 (yes, all of propokertools (except for razz) got rewritten). One of the first things I did after throwing out several years' worth of accumulated cruft was to see how easy it would be to answer new poker questions with my re-written code. I began to write small programs to answer questions like "Given situation S, how often does player one win when he was an underdog before the flop?" and "Given situation R, how often is the winning hand a straight or better?". These programs were, for the most part, satisfyingly short and sweet. At first, I thought I would expose these little mini-programs as individual tools on the website. Then it hit me.

Why not let the users ask the questions?

Enter the DSL

"DSL" stands for "domain-specific language". A DSL is a language, usually small, used to describe a very particular area, or domain. For a somewhat contrived example of a DSL in action, one need only step up to the counter at a popular chain of coffee-shops during the morning rush. "Half-caf grande iced americano" means "using half regular beans and half decaffeinated beans, brew an espresso and dump it in a large to-go container, adding ice cubes and cold water." The key behind a successful DSL is that it is concise and unambiguous. An even more concise version of our coffee DSL can be seen behind the counter, as the people at the cash-registers write only a few characters of text on each coffee cup to completely describe what is to be brewed.

Another DSL you may be familiar with is the ProPokerTools "range of hands" DSL. For instance, in omaha, "AA**" means a hand with at least two aces in it.

Why Invent What You Can Steal?

To allow users to ask custom questions, I needed to create a new DSL. I had a number of requirements:
  • Need to be able to ask multiple questions
  • Need to be able to compose questions using boolean operators (such as AND, OR, and NOT)
  • Need to be able to fully describe the situation
  • Need a semantics that is easy to explain
As it happens, there is a language that has been used for decades in another domain that provides pretty much all of what we want. That language is SQL, or Structured Query Language. SQL is the industry-standard way to query databases. While the correspondence between SQL and our poker situation is not perfect, it is good enough, and given the availability of free tools around SQL, it became the obvious choice. Thus was born PQL - Poker Query Language.

Eating Your Own Dog Food

The most obvious way to make sure PQL was truly useful was to use it myself. As a result, all of the major features on the website and in the downloadable Odds Oracle are powered by PQL queries.