QuantEcon / QuantEcon/QuantEcon.py

DISCUSS: Numba rewrite of PolymatrixGame — is numba.typed.Dict the right representation?

Open
#956 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

discuss performance
Dominant language
Python
Stars
2.4k
Forks
2.3k
Avg merge
3d 3h
Merged PRs (30d)
3

Description

Context

#812 (a codeflash optimisation of PolymatrixGame.range_of_payoffs) was closed on 9 Sep. It replaced the per-matrix min/max with np.concatenate([M.ravel() for ...]), which buys speed by materialising a copy of every payoff in the game — the allocation we would least want at the sizes where this call is slow enough to matter.

The reason given for closing was that a Numba rewrite of the class is the intended direction. That intent currently lives only on an unmerged branch, with no issue recording it, which this issue fixes.

What exists today

Branch polymatrix_numba_dict, commit 66c4037, "RFC: Build PolymatrixGame.polymatrix as numba.typed.Dict" (15 Nov 2025). One commit, 53 behind main, +38/−12 in quantecon/game_theory/polymatrix_game.py. It is an RFC, not active work.

It does two things:

  • Adds a jitted _min_max(polymatrix)@jit(nopython=True, cache=True) — which walks every matrix in one pass tracking the running min and max, with no intermediate array. range_of_payoffs becomes return _min_max(self.polymatrix).
  • To make that callable from nopython mode, builds self.polymatrix as a numba.typed.Dict (key_type=types.UniTuple(types.int_, 2), value_type=types.float64[:, :]) in both __init__ and from_nf, rather than a plain dict.
Questions to settle
  1. Is numba.typed.Dict the right representation for polymatrix? It is a documented public attribute, currently dict[tuple(int), ndarray(float, ndim=2)]. Moving to a typed dict changes what users get back: different construction cost, different repr, typed keys and values, and no longer a plain mapping. That is a user-visible API change and the main thing to agree before any of the rest.
  2. Which operations actually benefit? range_of_payoffs is the one the RFC converts. Is it a real bottleneck for anyone, or is this optimisation ahead of demand? If other methods on the class would benefit more, they should shape the design rather than follow it.
  3. Is a typed dict needed at all for the win? The measured cost in #812 was the concatenation. A plain-Python single pass tracking min and max — no allocation, no Numba — captures most of that without touching the public attribute type. Worth measuring against the jitted version before accepting the API change.
  4. Does this ship on its own or with other Numba work? The suggestion when #812 was closed was that it lands with other Numba rewrites rather than as a standalone PR. Which rewrites, and is there a natural release for them?
  5. _min_max itself is unverified. It uses next(iter(polymatrix.values())) in nopython mode for its seed value; that needs confirming against the Numba version we support, along with a check that cache=True behaves in the browser (see #930 and #944 for the caching problems we have hit there).
Why now

polymatrix_numba_dict carries one unmerged commit, and #894 proposes deleting merged and abandoned remote branches. Its own guidance is to check for unmerged commits before each deletion — this is exactly that case. If the branch is swept up without a decision here, the work and the reasoning behind closing #812 both disappear.

Refs #812, #894.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read the RFC commit on branch polymatrix_numba_dict and the changes in quantecon/game_theory/polymatrix_game.py, especially _min_max and range_of_payoffs. Compare the proposed typed-dict approach with a plain-Python single pass, and check the Numba cache concerns referenced by #930 and #944. Done means the representation, measured benefit, compatibility, and release scope have a maintainer decision.

Written by the indexing model from the issue text.

Assessment

Tech stack
numpy, python
Domain
performance
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.