← Notes

Minimizing Transactions After a Poker Game

When I play poker with friends, we don't keep a designated banker who manages buy-ins before the game. Instead, we figure out the transactions later. This works well for our small group, but scaling this up to 9 players makes coordinating the transactions non-obvious. Imagine you have an outcome like this:

PlayerNet $
Turing+39
Church−23
Gödel+2
Curry−75
Hoare+11
Kleene−12
McCarthy+8
Dijkstra−37
Shannon+87

Who sends money to who?

The Banker

It would be smart to designate a centralized banker, which we can still do after the game. Anyone who ended with a loss sends money to the banker, and the banker sends money to all those who ended with a net gain. For a game with nn outstanding balances, this clears them all in n1n-1 transactions.

A Decentralized Method

What if we don't want the burden of payouts to be put on one person? Players who ended in a loss should be able to pay out players who ended in a gain directly. We can do this while still maintaining our bound of n1n-1 transactions by using a simple greedy approach.

Imagine the player with the most negative balance pays the player with the most positive balance. In doing so, at least one of those two players will have their balance perfectly zeroed out. Because every single transaction guarantees at least one player is completely settled, and the total sum of the table is zero, it will take a maximum of n1n-1 transactions to clear everyone.

NP-hardness

Our upper bound on the number of transactions for both methods was n1n-1. However, this is not always a tight bound: it's possible for a single transaction to perfectly clear two balances at once (if a loser's debt exactly matches a winner's gain). So, can we write an algorithm to find the absolute minimum bound?

Surprisingly, we can't! At least not in polynomial time. It turns out that this problem is NP-hard. We can show this by reducing a known NP-hard problem to our problem in polynomial time. If we can do that, then we can say that a polynomial-time solution to our problem would be a polynomial-time solution to an NP-hard problem, which would prove P=NPP=NP.

Let's reduce the Partition Problem to our problem: Given a multiset SS of positive integers, is it possible to partition SS into two multisets S1S_1, S2S_2, such that the sum of S1S_1 equals the sum of S2S_2.

Given a multiset SS, we construct an instance of our poker problem as follows: Let mm be the number of elements in SS, and TT be the total sum of all elements. For each element aiSa_i \in S we say that there's a player with a net gain of aia_i. Then we add two players p1p_1 and p2p_2, each with a net loss of T2\frac{T}{2}. Thus we have m+2m+2 players, with all outstanding balances summing to 0.

Given this construction, we run our theoretical algorithm to determine the minimum number of transactions needed to clear all balances. If the number of transactions is mm, we return YES to the partition problem. Otherwise we need m+1m+1 transactions and return NO.

To see why this works, let's prove that SS can be partitioned into two sets of equal sum if and only if our construction needs exactly mm transactions to clear balances.

(    )(\implies) SS can be partitioned into two sets of equal sum, say XX and YY. SS had its elements summing to TT, so both XX and YY must have their elements sum to T2\frac{T}{2}. Let's partition the winning players in our game into the same two sets. Now p1p_1 can make X|X| payments, one to each player in XX for their full amount. This clears balances for all players in XX, and it clears p1p_1's balance because XX sums to T2\frac{T}{2}. In the same way, p2p_2 can make Y|Y| payments and clear the remaining balances. This took X+Y=S=m|X|+|Y|=|S|=m transactions. Furthermore, we know this is the lower bound because there are mm individual players with a net gain that each need a separate transaction.

(    )(\impliedby) Our construction needs exactly mm transactions to clear all balances. There are mm players with a net gain, so each one was involved in exactly one transaction for their full amount. But both p1p_1 and p2p_2 also cleared their balance in these transactions. This means that every transaction must have been between some winning player aia_i and one of {p1,p2}\{p_1, p_2\}. And every aia_i was involved in some transaction. Thus we can partition all aia_i by which pip_i they were paid from. Let S1S_1 be the set of players paid by p1p_1 and S2S_2 the set of players paid by p2p_2. The sum of elements in S1S_1 must be the same as the balance of p1p_1, which is T2\frac{T}{2}. Similarly the sum of S2S_2 is also T2\frac{T}{2}. Since all aia_i came from our input set SS, we showed that SS can be partitioned into two sets of equal sum.

Fairness

Okay, so we're stuck with our n1n-1 solution. This is still the minimal number of transactions in the general case. But what if we want to minimize the maximum number of transactions performed by a single person? Even in our decentralized solution we could have a single player performing all n1n-1 transactions.

Surprisingly, we can get away with just (up to) 1 transaction per person. The intuition here is that since each losing player can only transfer money once, they must send their entire outstanding balance in one transaction. To deal with splitting payments, let's chain together players and let payments from losing players accumulate, while winning players can "hold back" their wins.

Let's arrange everyone in a chain, from lowest net result to highest: p1,p2,...,pnp_1, p_2, ..., p_n. As before, let bib_i be the outstanding balance of player pip_i.

We start with player p1p_1 sending b1-b_1 to p2p_2, clearing their own balance. (bib_i itself is a negative value if pip_i ended in a loss)

Then p2p_2 sends b2b1-b_2 - b_1 to player p3p_3: their own outstanding balance b2b_2, plus what they received from p1p_1. This clears their own balance.

p3p_3 sends b3b2b1-b_3-b_2-b_1 to p4p_4, and so on.

In general, pip_i sends Σj=1ibj-\Sigma_{j=1}^{i} b_j to pi+1p_{i+1}.

So a particular player pip_i receives Σj=1i1bj-\Sigma_{j=1}^{i-1} b_j from the previous player and sends Σj=1ibj-\Sigma_{j=1}^{i} b_j to the next. This means their net change after these transactions is

(Σj=1i1bj)(Σj=1ibj)(-\Sigma_{j=1}^{i-1} b_j) - (-\Sigma_{j=1}^{i} b_j)

=Σj=1i1bj+Σj=1ibj= -\Sigma_{j=1}^{i-1} b_j + \Sigma_{j=1}^{i} b_j

=Σj=1i1bj+(Σj=1i1bj)+bi= -\Sigma_{j=1}^{i-1} b_j + (\Sigma_{j=1}^{i-1} b_j)+b_i

=bi=b_i

Which is exactly the outstanding balance they needed to clear!

(Arranging the players in increasing order of their result gives us the guarantee that the amount being sent is never negative. If it were to be negative, they would actually be requesting money from the next player, but that player is already sending money to someone else so our goal of 1 transaction per player would be violated.)

Thus we cleared all balances without forcing any player to perform more than a single transaction. This also gives us an upper bound of n1n-1 total transactions: only players p1p_1 to pn1p_{n-1} are sending money. Therefore this is undoubtedly the most optimal and fair way to handle transactions after a poker game!

Come to think of it, it's been a while since my friends have invited me to a game...


Credits

When asking Claude to proof read this post, it surfaced a blogpost with a similar premise -- I really liked the complexity theory analysis, which inspired me to find a similar reduction myself.