Skip to content

Add optional Rust-accelerated triangulation backend for LearnerND#493

Merged
basnijholt merged 2 commits into
mainfrom
rust-triangulation-backend
Jun 10, 2026
Merged

Add optional Rust-accelerated triangulation backend for LearnerND#493
basnijholt merged 2 commits into
mainfrom
rust-triangulation-backend

Conversation

@basnijholt

Copy link
Copy Markdown
Member

Summary

If the optional adaptive-triangulation package (>= 0.2.1) is installed, its Rust Triangulation is now used automatically as a drop-in replacement for the pure-Python implementation, making LearnerND significantly faster (~3.7x end-to-end on ring_of_fire, and ~7x faster than Learner2D at 5k points).

pip install "adaptive[rust]"

How it works

  • New adaptive/learner/triangulation_backend.py selects the backend at import time: the Rust package when importable and >= 0.2.1, otherwise the pure-Python implementation. learnerND.py, learner1D.py, and learner2D.py import Triangulation / circumsphere / point_in_simplex / simplex_volume_in_embedding from it.
  • Per-learner control: LearnerND(..., triangulation_backend="auto" | "python" | "rust"), or pass a Triangulation-compatible class directly. "rust" raises a helpful ImportError when the package is missing or too old.
  • Global override: ADAPTIVE_TRIANGULATION_BACKEND=auto|python|rust environment variable.
  • The pure-Python adaptive.learner.triangulation names are deliberately never shadowed, so existing pickles that reference adaptive.learner.triangulation.Triangulation by qualified name keep loading, and old LearnerND pickles fall back to a class-level _triangulation_class attribute.

Bug fix

_pop_highest_existing_simplex evaluated None in self._subtriangulations[simplex].simplices for stale queue entries. Python sets return False; the Rust proxy raises TypeError. Now guarded with subsimplex is not None.

Testing

  • 8 new tests in adaptive/tests/unit/test_triangulation_backend.py covering auto-selection, env-var override, constructor argument, custom class pass-through, and error paths.
  • Full suite passes with the Rust backend absent (282 passed) and with Rust 0.2.1 active, except 7 curvature-loss tests that hit a known remaining divergence in adaptive-triangulation (simplex_volume_in_embedding raises on collinear input where the reference returns 0.0) - to be fixed there; only a _MIN_RUST_VERSION bump is needed here afterwards.

Note: the rust extra is not added to the test/dev extras yet; consider adding a CI job with the Rust backend once the degenerate-simplex fix is released.

basnijholt and others added 2 commits June 10, 2026 12:41
If the optional adaptive-triangulation package (>= 0.2.1) is installed,
its Rust Triangulation implementation is now used automatically as a
drop-in replacement for the pure-Python one, making LearnerND
significantly faster.

- New adaptive/learner/triangulation_backend.py selects the backend at
  import time; ADAPTIVE_TRIANGULATION_BACKEND=auto|python|rust overrides
  the automatic selection globally.
- LearnerND gains a triangulation_backend keyword argument accepting
  "auto" (default), "python", "rust", or a Triangulation-compatible
  class for per-learner control.
- The pure-Python adaptive.learner.triangulation names are never
  shadowed, so existing pickles that reference them keep loading.
- Fix _pop_highest_existing_simplex evaluating `None in ...simplices`
  for stale queue entries (Python sets return False; the Rust proxy
  raises TypeError).
- Add the `rust` optional-dependency extra, tests, and docs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant