← Back to all sparks
T

tulpa

ANALYTICS
Velocity6.3

Template Unified Latent Process Architecture for Bayesian Hierarchical Models

A Bayesian spatial engine reshaping itself so downstream packages own their own diagnostics.

bayesian-inferencenested-laplacediagnosticss3-genericsnumerical-determinismgpu
Current state
tulpa is the C++/R inference engine sitting under a family of ecological occupancy packages, tagging releases several times a week in the 0.0.x range. The current window splits cleanly in two: an API move that turns its calibration and goodness-of-fit entry points into S3 generics, and a run of numerical-correctness work in the nested-Laplace grid. A notable share of releases exist to record a measurement that produced no code change at all.
Where it's heading
The generics conversion and the new cross-Hessian return value point the same way: the engine is being reshaped into something downstream packages extend rather than wrap, with the extension points made explicit. The correctness fixes cluster tightly on the joint nested-Laplace driver — indefinite Hessians hitting negative pivots, chunk counts read from live machine load, grid cells silently dropped from a fit — which is where the remaining risk visibly sits. Reported numbers have moved more than once in this window, so the project is still finding cases where earlier answers were wrong rather than merely imprecise.
Prediction
Expect the rest of the diagnostics layer to finish migrating onto generics, and continued hardening of the batched joint driver's dense path, which is the one route that recently diverged from its own single-species equivalent.

Recent moves

  1. 1d ago

    tulpa_re_aghq() exposes the mode/theta cross-Hessian

    Adds blup_cross, the per-group cross-Hessian block needed to draw a group's BLUP jointly with theta instead of independently, plus the full per-group joint covariance across random-effect terms. It declines to NA rather than silently returning zero where no analytic theta_score exists. This is the engine-side unblock for the last family registration downstream, and fits the pattern of exposing internals that consumers previously had to reconstruct.

    View source ↗
  2. 4d ago

    Dense batched joint path could silently drop a grid cell

    The batched joint driver's dense branch was solving through the fixed-ridge-only path rather than the PD-escalating one its sparse branch and the single-species driver already used, so an indefinite Hessian could produce NaN, drop that outer-grid cell's weight, and shift every reported summary. The fix aligns the dense branch with the rest. It lands in the same coupled-driver area as the determinism work earlier in the window.

    View source ↗
  3. 5d ago

    Calibration and goodness-of-fit entry points become S3 generics

    ⚡ SPARK

    The move that reframes tulpa from a library you call to a layer you extend: sbc(), pit_residuals(), test_dispersion(), test_outliers() and test_zero_inflation() now dispatch, with existing bodies demoted to default methods. It is the upstream half of the breaking cleanup tulpaObs shipped a minute later, and it sets the extension contract the rest of the diagnostics layer will likely follow.

    View source ↗
  4. 6d ago

    CUDA backend had two definitions; link order decided if it ran

    The batched-CUDA entry points were defined twice — real implementations in one header, FALSE-returning stubs in another — so which one survived was an ODR coin flip resolved by the linker, and nothing could report what had been built. With a single definition, GPU acceleration engages when a device is present and degrades cleanly when it isn't. A build-level defect, but the user-visible effect is that the GPU path is now reliably reachable.

    View source ↗
  5. 6d ago

    Hyperparameter bounds now flag when they leave the node range

    An interval endpoint past the outermost grid node is an extrapolation rather than a bound the design supports, and theta_ci_outside_nodes now records that per axis instead of leaving the two indistinguishable on the fit. The companion finding keeps max_sd_u at 3 on evidence, after establishing that earlier inconclusive ladders were measuring the extrapolation rather than the ceiling. Continues the engine's habit of recording a limitation rather than papering over it.

    View source ↗
  6. 7d ago

    Neither candidate outer-cell rule promoted, decided on coverage

    A paired 200-seed comparison across three resolutions concluded that neither alternative outer-cell rule should ship: the placement rule sits closer to the fine grid yet gives up 72 seeds of coverage, and the mass rule only widens intervals. Nothing changes for users — the shipped rule stays — but it closes the question with numbers. Representative of a project that treats a settled negative result as a release-worthy outcome.

    View source ↗