Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Allocate poker chips optimally with mixed-integer nonlinear programming (github.com/jstrieb)
213 points by jstrieb 6 months ago | hide | past | favorite | 69 comments
Every time I play a casual cash poker game with friends, we spend the first several minutes struggling to figure out chip denominations. I built this to automate that process.

Try it out here (the submitted link goes to the GitHub repo): https://jstrieb.github.io/poker-chipper/

It turns out that picking chip denominations optimally—such that as many chips are distributed as possible, and such that the denominations are nice—is hard (in the computational complexity sense). Upon reflection, the problem seemed to be a perfect fit for constrained optimization.

I first got a CLI prototype working with Z3 (an SMT solver with optimization capabilities https://github.com/Z3Prover/z3) in Python. Then, I cross-compiled SCIP (https://www.scipopt.org/) to web assembly, and ported my code to use SCIP instead of Z3 so it could run in the browser.

The web interface is designed to be fast and easy to use on desktop and mobile.

I would love to answer questions and discuss design choices. I'm also open to feedback and bug reports. Thanks for taking a look!




You've solved the problem with an incorrect assumption. You have assumed that the ideal situation is to use all of the chips in your collection. A better solution is to ask, what is the most playable breakdown for the poker games I am playing. If I am playing 25c/50c no limit hold'em with 8 players... and a typical buy-in of $20 per player... as an experienced poker host at these limits, I maintain that the ideal breakdown is: 12x 25c 12x $1 1x $5

If you have a set with 100x of white, blue, red, green, etc... your total number of chips used for 8 players is: 96x white (25c) 96x blue ($1) 8x red ($5)

If players lose all of their chips... they can re-buy with $5 (red) chips and make change from the players that have all of the lower denomination chips.

What I have proposed above is a proper solution if you want to play poker.


Also an experienced poker player, and this is 100% correct.

Ideally you want to use common casino chip colors (though these are somewhat fungible) and just shift orders of magnitudes.

If 1BI is 20 bucks, you can make it equivalent to a $200 BI at the casino, which really only uses 2 colors 95% of the time: whites for 1 dollar, reds for $5. Deeper games might need a $25 (green) or even $100 (black chip). So whites in your home game are 10c, reds are 50c, greens are $2.50, blacks $10.


As someone who has run many, many home games, including cash and tournaments, also consider how easy it is to stack a fresh buy-in. Having 6 of one color, 5 of another, 3 of another, 8 of the next... Yuck. Many ways to make a mistake. If I'm doing a tournament where the starting small blind is 25, then I'm going to ALWAYS use:

    8 qty 25 chips = 200
    8 qty 100 chips = 800
    4 qty 500 chips = 2000
    N qty 1000 chips = N000, where N controls how much the starting stack is.
When I'm preparing a bunch of new stacks, I mostly just have to deal with stacks 4 or 8 high, which can be measured next to each other in under a second. Also, the first two colors add up to 1000 exactly, and the first three colors add up to 3000 exactly, simplifying the math. Also, standard chip racks hold stacks of 20 chips, so the first three colors can be pre-built and stored in the racks. If I'm doing a cash game, with $0.25/$0.50 blinds, I use the same formula as above, but divide by 100. Just as easy.

For a $1/$2 cash game, I'm going to ALWAYS use:

    20 qty $1 chips = $20, for blinds
    N qty $5 chips for the rest of the buy-in
And that's it. Since again, standard chip racks hold stacks of 20 chips, these can be set up in seconds. Later in the game, we can break out the $25 chips.

Also +1 to using "standard" casino chip colors. In the US, $1 is almost always white, $5 is almost always red, $25 is almost always green, $100 is almost always black, and so on. Don't confuse people.

Buy your chip set based on how you allocate your chips when playing, don't allocate your chips based on whatever chip set you happen to have.


I'm never going to have 500s and 1000s in the same chip set, but in that case you just fill it out with 500s and introduce a larger denomination chip if you're playing deep stacks.


Yep, totally valid option to leave out the $1000s. The point is choose your chip set color distribution based on the expected stacks.


Yea the "optimal" solution shown by the default input is pretty silly. You're giving everyone 5 chips with which they can post blinds, and they're going to use 3 of them per turn through the blinds, so after 1 turn through the blinds someone who has won no hands will need to make change with someone else. And making change from the next smallest denomination will require 5 of that persons small chips!

Other, less important usability consideration is that you would typically want "round" amounts of chips, ideally stacks of 10 or 20, though having a few big chips in odd amounts is fine. Not as big a deal, but again, very much diverging from typical poker ux expectations.

Neat project technically, but highly impractical for actually playing poker.

edit: to be fair, just saw the advanced options, which would allow it to produce a more useful result, so that's cool. maybe just update the defaults :)


The default is 50 chips each color for 7 players, each player can have a maximum of 7 of one color


This comment is correct. This seems like it might have been programmed by someone who has never played poker, or not in a home game. You don't want people to have 112 white chips, no matter how many are in the box.


Note that the players in the described game are buying in really short. A typical buy-in would normally be about 100BB, or $50. The easiest way to handle the extra $30 is with 6 $5 chips. If rebuys start running you low on $5s, you can introduce $25s.


Truth be told... my game is $100 buy-in... and yes, I fill in the rest with $5s.


I'm not very experienced at hosting, but this is pretty close to what I'd do. If chip supply isn't a constraint, I'll aim for halving the quantity each step up then redistribute from there, so 12x25c 7x$1 2x$5 in your example. If chips are limited, I go based on the ratios of available chips.

At first glance, seems like you could do this with linear programming instead of mixed-integer if you're ok shaving off the fractions at the end and handing them out naively. Nobody will mind getting 1-2 more chips than theoretically necessary.


> At first glance, seems like you could do this with linear programming instead of mixed-integer if you're ok shaving off the fractions at the end and handing them out naively. Nobody will mind getting 1-2 more chips than theoretically necessary.

You're almost certainly totally right for this problem, but in general that's one of the pitfalls in beginner mixed-integer programming implementations. Rounding a reasonable real-number solution has almost no guarantees in terms of approximate optimality or error bounds compared to the optimal integer solution.


Yeah, in general it's not this easy. In this case, seems like the worst case is getting x.999 of each chip.


This is bonkers. No need to overthink it.

FWIW, I belong to a forum comprised mostly of game hosts who collect playable sets for their games. This group has gotten optimal breakdowns for various games (from 5¢/10¢ up to nosebleed stakes) down to a science, through actual hosting experience. The collective number of hours hosted by these members is astronomical.

A standard notion is that you rarely need more than 4-6 denoms for most games, with really only 3 of those in any quantity of 100 or more for a one-table cash game.

Also, that the jump between chip denominations functionally should be 4-5x the next lowest denom.

So for example, a typical cash set meant to work for games ranging from 50¢/$1, $1/$2, and $2/$5 could make do with denoms of 50/1/5/25/100.

For any given stakes, there is a “workhorse” denomination, and that’s the chip type you need the most of (e.g. $5 chips on 1/2 games).

The only real divide among this group is those who like to use the fewest possible chips which is still comfortable, without change having to be made too often, vs. those who think poker is more fun with lots and lots of chips on the table, even if many are unnecessary.

The idea of assigning non-denoms (i.e. chips with no value printed on them) all sorts of unstandard but “optimal” amounts is I suppose an interesting intellectual exercise, but in practice seems nuts.

… Especially considering that chips are typically sold with existing amounts printed on them. To host with non-standard denoms requires undenominated chips used with some sort of printed or displayed key to remind players of the weird values.


> This is bonkers. No need to overthink it.

Oh, overthinking can be fun!


> The SCIP solver is designed to run natively, so Poker Chipper bundles it for the browser by compiling SCIP to WebAssembly (WASM)

This is amazing. I wanted to do something similar for a web-based optimization. I ended up just putting a C++ Lambda up to serve the requests.

I wonder how the performance compares? I feel like optimization frameworks make use of a lot of CPU-based heuristics.


So far, even on underpowered Android phones I've tested on, the performance has been really good. It's more of a testament to how fast SCIP is than anything else!

Specifically, I haven't been able to find a reasonable set of parameters that cause the optimization to take longer than ~20 seconds on the slowest device I tried.

To get things to be smooth, though, I had to do debouncing and also run optimization in a web worker (separate, non-blocking thread) so the UI doesn't hang. Doing that was its own challenge since web workers don't use the HTTP cache for security reasons (they're supposed to be an isolated context), and it was re-requesting the ~5MB WASM files every time any of the numbers was adjusted. To solve this I used a service worker with a local cache.

Slow performance of web-based Z3 for optimization was one of the main reasons I switched to SCIP. I originally had a version working using a WASM port of Z3, but it just wasn't fast enough to be usable.


Makes sense. SCIP has been really fast for me. Good to hear it's working for you!

Did you do some local-vs-phone tests? I'm really curious how 20s on android compares to laptop.


Most optimization calls on my laptop happen nearly instantaneously, whereas they can take a few seconds on average on phones. Didn't test super comprehensively.

If you end up wanting to use the version of SCIP compiled to WASM, I have it pre-compiled in the repo here: https://github.com/jstrieb/poker-chipper/tree/fab41bbe8821d0...

To interact with WASM SCIP, I use the CLI with an Emscripten virtual filesystem (as opposed to the C API/FFI): https://github.com/jstrieb/poker-chipper/blob/fab41bbe8821d0...

If you want to compile it yourself, the code and compiler flags I used to do that are documented in a Dockerfile in the repo: https://github.com/jstrieb/poker-chipper/blob/fab41bbe8821d0...


This is nicely made, but as other people have pointed out, it appears to be optimizing in a kind of weird way for a real poker game.

It seems to me that the underlying problem is that cheap pre-mixed chip cases usually have terrible denominations (if printed) and/or too few of each (sometimes only 50), which just doesn't make any sense. Nobody ever needs denominations that differ by a factor of 2, and you need way more than 50 of any one type to play with more than 6 people.

For our 0.05/0.1 10$ cash games with 8-10 people, one day about 15 years ago we just went and filled a 500 chip case with nice ceramics (Old Havana Poker Club, they're still around): 150x 5 200x 25 120x 100 30x 500 (just for good measure)

Obviously we take the numbers printed on the chips to be cents. This system has worked perfectly ever since and still offers sufficient flexibility for the occasional tournament; I can only recommend solving the problem this way once and for all. (Of course you need to adjust for the kind of game you play.)


I bought a custom set from Apache Poker Chips. We have .25, 1.00, 5.00, 25.00, 50.00, and 100.00

Covers all of our use cases. We usually do a 20 dollar buyin and do 12 .25, 12 1.00, and 1 5.00

Works well and we eventually move rebuys to 4 5.00, with players making change off of someone with lots of chips.

Sometimes we flood the game with as many .25 as possible because it's fun to have a massive chip stack, but pain to count at the end.

This has worked well for us in games up to 14 people (2 tables)

Worth the initial investment in the chips, especially because they are thonky ceramic chips which just feel _so nice_


I've noticed that adding a colour can make it go from having a solution to not having a solution. Maybe it should try to come up with a solution using fewer colours in that case, since it's not obvious that manually removing a colour will lead to a solution.


That's a good observation - the UI is a very thin wrapper around the optimizer.

One fix would be changing the minimum number of chips per color under "advanced options > requirements" to 0.


Sometimes when I am at the gym I wonder if there could be a better set of weight denominations.

I feel like 1,3,9,27,81 could be an optimal set; but I am not sure how to prove it.


J. Shallit (2003). "What this country needs is an 18c piece" (PDF). Mathematical Intelligencer. 25 (2): 20–23.


What readers of your comment need is two HN thread references :)

What This Country Needs is an 18¢ Piece (2002) [pdf] - https://news.ycombinator.com/item?id=38665334 - Dec 2023 (272 comments)

What This Country Needs Is an 18¢ Piece [pdf] - https://news.ycombinator.com/item?id=14579635 - June 2017 (45 comments)


Since every positive even integer is the sum of two primes (at least, within the range of weights you're likely to be lifting), maybe [5, ...the list of primes times 5]?

So if the list of primes is 2, 3, 5, 7, 11, etc, you could have weights of 5, 25, 35, 55, 75, 11*5, etc. for 5, 10, 15, 25, 35, 55, etc.


> So if the list of primes is 2, 3, 5, 7, 11, etc, you could have weights of 5, 2*5, 3*5, 5*5, 7*5, 11*5, etc. for 5, 10, 15, 25, 35, 55, etc.

Fixed the formatting for you. You need to put a \ before * symbols to have them reliably render in HN


> You need to put a \ before * symbols to have them reliably render in HN

Alternatively, write two sequential *, like so: **


By the time I'm on my third set, math with multiples of 5 is hard; please don't make me use those...


Optimal in what sense? If you want to have each whole number using each number at most twice then sure.

If you want to get within x% using at most k weights the some kind of logarithmic distribution is also a good bet.

Both you and OP could benefit from being a bit clearer about what you find optimal.


See this comment for a more in-depth explanation of what I meant by "optimal" for poker chip denominations. Hopefully that clarifies. That comment has a link to the code if it's still not clear enough.

https://news.ycombinator.com/item?id=40576198


Nice one! Had this problem last time we ran a tournament.

I also did some constraint programming to solve my poker problems. We play mostly cash games so I did a MiniZinc model for computing the least amount of transactions after the game: https://github.com/SRautila/poker-home-game-calculator


> such that as many chips are distributed as possible, and such that the denominations are nice

Could you expand on what the optimisation criteria are? you want each person to have the maximum number of chips for some set of "nice" denominations where the total number of chips and players are constrained?

What does a "nice" set of denominations mean in this case? Why do you want to distribute a maximal number of chips?


The first constraints are the required ones:

    - The sum of (color value * color quantity) for all colors must equal the buy-in
    - For each color, (color quantity * number of players) must be less than the total number of chips of that color
Theoretically any combination adhering to these constraints would be valid, but it wouldn't necessarily be "nice." The main idea behind the "niceness" constraints are to choose denominations that are easy to remember and easy to work with. To that end, there are a number of requirements and soft constraints that nudge the optimizer towards better denominations if it can. For example, a few are:

    - One chip value should be the small blind, and try to minimize the number of chips required to make the big blind
    - Chip values should try to be multiples of a set number ($0.25 by default, tunable in the UI)
    - Chips above $1 should be multiples of $1
    - Chip values should try and be multiples of smaller chip values so that change can be made in as many ways as possible
    - Distribute as many chips as possible so that people have big stacks to play with
The code for all of the constraints is here, and is commented in English for readability:

https://github.com/jstrieb/poker-chipper/blob/fab41bbe8821d0...


This project is great, but I'm by far not a poker nerd and seems like the answer would be something like "print out a few tables of common options / player-counts, and just pick the closest".

Something like a dive-table planner (which is actually really cool if you know how to read it!):

https://www.baliocean.com/blog/what-is-a-dive-table/

http://www.scubadiverinfo.com/images/Dive_tables_NAUI.jpg


Thanks for the explanation, and the reference to the code.

It is indeed nice and easy to read the constraints. Nice work!


In friendly poker games that I play we just make all the chips have the same value. We do a $40 buy in and you get 50 chips, each worth 80 cents. Since all of the chips have the same value we just mix all of the colors together. No one ever has to think about how the chips break down.


I can't decide whether to be impressed or horrified.


My spreadsheet was really unpopular.


What do you do when there are few players and the blinds are high? Does every player count massive amounts of chips every time?


We had this problem last weekend haha, very cool that someone made a tool!


Can anyone explain why this isn’t a discrete optimisation problem? I don’t understand what aspects of problem would require a non convex approach


Would this also help new poker dealers with starting and doing games with tips and tricks that help them become a better poker dealer or is this purily for the price and buy ins of Poker games


There was a time I tried to convince everyone we should use powers of 2 as chip denominations, partially because that made it easy to handle blinds doubling. In hindsight, not a good idea.


Hm. Maybe powers of 4 would be fine.


You should be able to pick the order of colors in terms of increasing value. White chips should always be the lowest value.


The only color reordering that happens is to assign the color with the largest quantity of chips to have the lowest chip value.

Once the optimization has happened, you can edit the colors, and the order will be preserved. So if you want to swap it so that white is the lowest valued chip, just edit the color of the lowest valued chip to white.


Is there an old man coffee variable?


Very cool


As a professional poker player, using weirdo denominations for cash games is not something anyone ever wants.

The denominations are $1, $5, $25, $100, or $5, $25, $100, $500, or $5, $25, $100, $1000.

In Vegas, the $5s are almost always red, the $25s are almost always green, and the $100s are almost always black.

Even the $10 chips in use for the 5/10 games at the Wynn and Resorts World throw off a lot of players.

Casinos frequently have $2 chips simply because it makes dropping the rake take less volume and allows them to change the boxes less frequently. You don’t need them in a home game.

This might be an interesting math problem, but let’s not pretend that it has any applications in actual poker games.


The default buy-in for the site is about $10, which is perfectly reasonable for a game between friends. I've almost never played a game where the pot exceeded $100 (we had 6 people in a $20 buy in once, I think) and most of my friends have never played a game where having a $100 denomination would be any use at all.

This is something that most amateurs want, it's OK if pros don't want it.


Why have any denominations for chips then? If the total value at risk is $10-20, just play for fake points. This isn’t remotely significant money for anyone.

I play with low stakes amateurs all of the time, as often as not in home games, and the smallest games people play are 1/1 or 1/2. You can’t even buy a cheeseburger in America for $1 anymore, anything less than that and you might as well not be playing for money at all; just use points and don’t worry about denominations.


Depends on the crowd. Our $0.25/$0.50 games often have hands that go to showdown with $100+ pots, sometimes $500. Yet, every time someone says "Should we just do $1/$2 next time?" they get poo-pooed :)


Can relate. We mostly play 0.1/0.2 or 0.25/0.50 but I've seen a friend of mine spend 700 bucks in a game while the rest, at most, 100. It makes it very unbalanced but everyone finds it fun to see the big stacks guy lose it all.


I'm going to "well, actually" here and tell you that plenty of casinos have weird chip denominations. Especially where limit poker might be played.

I've seen $2, $2.50, $3, $10 and $20 chips as well as the normal denominations. This site mentions $8s:

https://wizardofvegas.com/forum/gambling/poker/5999-2-3-and-...


This is because casinos run many different kinds of games (both in the poker room and elsewhere). They also are regularly raking standard amounts for the house, and for promotions, not to mention dealers taking tips.

Few of the above needs apply to casual unraked homes game, unless you are playing limit as noted. (I’ve never encountered a limit home game; more and more these are strictly hold ’em or PLO/PLO8, unless the players are over 70. Once in a while if it gets really late and shorthanded someone might suggest a round of stud, I guess)

And even then you need larger numbers of fewer types of chips for limit, as a rule.


$2.50 chips are used for blackjack, where a blackjack hand pays 3:2, so when the table bet size is a multiple of $5, you need something to represent half of that.


I usually just see them with a stack of $0.50 coins.


I think you missed the point: OP is playing with friends and made a tool for such situations. Nobody suggested using this in a casino.


I’m saying that poker players don’t ever want to play with nonstandard denominations, even in a home game.

It’s just not done. It also makes no sense: it’s confusing and slows down the game for no reason.


in a standard casual home game i feel like we'd be playing with denominations you never see in casinos anymore anyway (5c,10c,25c,50c,$1) etc.


I’ve mostly seen chips treated as a unit-less or self referential unit: white is 1, red is 5, etc. 1 or 5 <whats> is irrelevant if you’re playing tournament style play. At the end the top x% of players get a scaling percentage of the actual monetary pool. Now if you’re playing where you can cash in and out at face value at any point then using chips in a 1:1 mapping to currency would make sense, but it should still probably be fixed rather than each chip being able to change value based on number of players or the size of the pool.


It would also be very annoying at home games. It would take a special group of friends to tolerate or even get a kick out of how optimally you’ve solved a self-imposed problem.

It’s a fun mental exercise and programming problem, but that’s it IMO.


this is hacker news

makes sense to me


You're clearly not playing games with a $0.25 small blind, or a $20 buy in. Meanwhile, it might confuse professional poker players, but in a friendly cash game that's probably a benefit.


There are no “friendly” zero sum games about money. Either you are playing to win, or you are wasting time. Anyone who thinks otherwise is, obviously, just wasting time (which is okay, but don’t pretend it’s a “friendly game”, it’s just a distraction, not a game.)

If you’re not playing for stakes where you care if you win or lose, then just don’t play for money at all.

I know lots of hobby poker players, firmly nonprofessionals, who play in non-serious 2/5 and 5/5 home games where the buyin is $500-3000.

Penny poker is totally pointless for anyone not below the literal/actual poverty line where $40 is actually lifechanging money. If you’re not homeless and want to play $0.25/$0.50, just play for points/chips then instead of cosplaying gambling.


> There are no “friendly” zero sum games about money. Either you are playing to win, or you are wasting time.

Time You Enjoy Wasting Is Not Wasted Time.

https://quoteinvestigator.com/2010/06/11/time-you-enjoy/

> don’t pretend it’s a “friendly game”, it’s just a distraction, not a game.

A bit of friendly competition is still a game. Games can be fun.

> If you’re not playing for stakes where you care if you win or lose, then just don’t play for money at all.

You can still care you win, but not mind if you lose. That’s a sweet spot. Even a small pot (which is still a multiplier of all players) can get people engaged just that extra bit to take it a bit more seriously. That’s more enjoyable for everyone: you get more investment and interesting plays. The winner gets a some pocket money but no one else is bummed by the loss, it becomes a pittance relative to the enjoyment of playing with friends.

> just play for points/chips then instead of cosplaying gambling.

Why does this make you (sound/read) so irate? Let people enjoy themselves, no one is being harmed.


You seem to be strangely offended by the idea of people playing small stakes home games for fun, and frankly, your understanding of a game seems rather skewed to me as well.

I'm really glad for you to know and hopefully be able to make a living off of non-professionals that can afford to lose several thousand dollars in one evening of non-serious playing. That's a great clientèle to have as a professional gambler, and I see nothing wrong with taking advantage of it. But I'll go out on a limb and say it's probably far from the lived experience of most people, and neither should it be.

Obviously for poker to make sense you need to have a minimum of skin in the game. Which is exactly why you basically telling people here to rather go and play with peas comes across as pretty tone deaf, not to say entitled.

You need to understand that you are projecting your standards on people who have no aspirations to play professionally.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: