QuantEcon / QuantEcon/QuantEcon.py

WASM: JupyterLite proof-of-concept deployment and browser smoke suite

Open
#928 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

[!NOTE]
Updated 2026-08-21. Phase 0 was overtaken by ad-hoc browser runs: the _LAPACK question (#927) was answered on the public numba-ecosystem demo, the intp question (#929) was settled in the #942 review, and PR #938 (merged as 481947d) has landed the deployment config and smoke suite under ci/wasm/. The checklist below is reworded to match those findings and the upstream Numba change that removed the expected gini_coefficient failure (patch 0010, emscripten-forge/recipes#6293); items with recorded browser evidence are ticked and a results table is maintained in the comments. The original text is preserved in the edit history.

Part of #925 (Phase 0). This issue was meant to gate #927 and calibrate #929 and #930; #927 was resolved by ad-hoc browser runs and #929 by the #942 review instead (see the checklist), so its remaining gating value is the cold/warm import timing for #930 and the first full-suite browser run via #933.

Goal

Prove the stack end-to-end with zero code changes, and convert every "should work" in the audit into a known. Because quantecon is noarch: python on conda-forge, there is a real chance it installs and imports in JupyterLite today with no packaging work.

Setup

Build a minimal JupyterLite deployment with jupyterlite-xeus:

name: qe-lite
channels:
  - https://prefix.dev/emscripten-forge-4x
  - https://prefix.dev/conda-forge
dependencies:
  - xeus-python
  - numba
  - quantecon

This file is now committed as ci/wasm/environment.yml (PR #938). numba is unpinned, so a fresh build resolves the current emscripten-forge-4x build — numba 0.67.0 build 1 as of 2026-08-18, which carries patch 0010 (emscripten-forge/recipes#6293) forcing @njit(parallel=True) to the serial pipeline on Emscripten. Note that the browser results recorded so far did not come from this deployment: they came from the public numba-ecosystem demo (Numba 0.66.0) and the #942 review, so the versions per result are recorded in the table.

Smoke checklist

One representative function per Numba feature class used in the library:

  • import quanteconworks (implicitly confirmed by the _numba_linalg_solve reproducer in #927 and the simplex_grid reproducer in #942; no timing recorded)
  • import quantecon — timed, cold cache and warm cache (feeds #930; #930's "measure first" gate and PR #943 are currently proceeding without this number)
  • qe.tauchen — plain lazy @njit (_fill_tauchen); qe.rouwenhorst is pure NumPy with no Numba at all, kept as a no-JIT control case
  • MarkovChain.simulate — lazy @njit kernel writing into a Python-allocated array (NRT allocation inside jitted code is exercised by simplex_grid and nelder_mead below)
  • qe.random.probvec — exercises the parallel-ufunc → cpu fallback (emscripten patch 0007)
  • qe.random.sample_without_replacement — eager guvectorize, explicit i8 signature
  • optimize: nelder_mead, brent_max, newton
  • game_theory.lemke_howson
  • game_theory.vertex_enumerationnumba.typed.Dict; also a jitted generator (_vertex_enumeration_gen), so expected to hang for the same reason as support_enumeration (#927) — not yet run
  • game_theory.support_enumerationFAILS: first call never returns. The _LAPACK question is answered (LAPACK works, see the next two items); the cause is the jitted generator _support_enumeration_gen — emscripten-forge patch 0002 exports only Numba_make_generator, not the lowercase numba_make_generator the generator wrapper imports (#927, not yet reported upstream)
  • minimal @njit generator (for i in range(n): yield i) — FAILS (hangs on first call), recorded 2026-08-19 in #927; isolates the generator mechanism from quantecon's code
  • np.linalg.solve inside a scratch @njitworks (correct result on Numba 0.66.0; _numba_linalg_solve also works), recorded in #927 on 2026-08-15 and 2026-08-19
  • qe.gini_coefficientexpected to work, serially, on emscripten-forge numba ≥ 0.67.0 build 1 (patch 0010, emscripten-forge/recipes#6293, 2026-08-18); the @njit(parallel=True) failure mode this item originally expected no longer exists. Confirm it runs and time it — the serial O(n²) path is why the O(n log n) rewrite in #926 / PR #937 still matters. No browser run of gini is recorded anywhere yet
  • simplex_gridFAILS on a warm persistent cache: RuntimeError: no compiled object yet for <Library 'comb_jit'> at qe.simplex_grid(3, 4) (#944; upstream emscripten-forge/recipes#6309, open). The 32-bit intp boundary is now a documentation question (#929 is doc-only); left unticked because the boundary check itself was never reached and stays blocked behind #944
  • quantecon.util.array.searchsorted — the deprecated objmode() shim

Deliverables

  • Results recorded in this issue as a table: function → works / fails / notes — started in the comments on 2026-08-21 with the rows that already had evidence (import, np.linalg.solve, support_enumeration, bare generator, simplex_grid); the remaining items are not yet run
  • The deployment config committed somewhere reusable — done: ci/wasm/environment.yml plus the suite ci/wasm/smoke_test.py (16 tests mapping onto the 13 checklist items, all passing natively), the Playwright harness ci/wasm/test_jupyterlite.py and a native gate in .github/workflows/ci_wasm_smoke.yml (PR #938, merged 2026-08-21 as 481947d). The Emscripten runner job is parked in #933

Coverage of the browser harness

What actually runs on Emscripten today is test_jupyterlite.py (driven by the job parked in #933), and it covers 5 of the 13 checklist items: import quantecon (untimed), tauchen, bare np.linalg.solve in @njit, support_enumeration and gini_coefficient. smoke_test.py is not yet shipped into the kernel, so rouwenhorst, MarkovChain.simulate, probvec, sample_without_replacement, the three optimize routines, lemke_howson, vertex_enumeration, simplex_grid, searchsorted and the import timing have no browser test until #933 wires in-kernel execution of smoke_test.py. A first green run of the parked job therefore fills at most 5 rows of the table, not 13.

Several of the committed tests also encode expectations that are already out of date; #933 (the runner job) currently notes only the test_support_enumeration hang, so the rest are being handed to it as follow-ups: test_gini_coefficient (xfail(IS_EMSCRIPTEN, strict=True)) and test_gini_fails_on_emscripten expect a failure that patch 0010 has removed; test_support_enumeration and test_vertex_enumeration have no hang guard; test_simplex_grid cites #929 where it should cite #944.

Related

  • #927 — jitted-generator hang (support_enumeration, vertex_enumeration); _LAPACK verified working
  • #944 — simplex_grid fails with no compiled object yet for comb_jit on a warm cache; decision is to wait for upstream (emscripten-forge/recipes#6309)
  • #926 / PR #937 — gini_coefficient O(n log n) rewrite; the browser confirmation of gini belongs here, not in #926's acceptance criteria
  • #930 / PR #943 — import-time eager compilation; #930's gate still calls for the cold/warm import timing from this checklist, and PR #943 is proceeding without it
  • #933 — Emscripten runner job; the test fixes listed above are to be recorded there
  • PR #938 — merged 481947d; delivered the config, suite and harness

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

Start with ci/wasm/test_jupyterlite.py, ci/wasm/smoke_test.py, ci/wasm/environment.yml, and .github/workflows/ci_wasm_smoke.yml, then follow the parked runner work in #933. The deployment and native suite are already delivered by merged PR #938; remaining browser coverage, timing, results, and outdated expectations are split across #933, #930, and #944.

Written by the indexing model from the issue text.

Assessment

Tech stack
github-actions, playwright, python, wasm
Domain
ci-cd, testing-qa, web-dev
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.