Deferred and rejected — the ledger#
Deliberately-not-built features and considered-and-rejected designs, each with its why and a source pointer, so settled calls are not re-litigated and deferred ideas are not lost. (Entries that already have their own note or live in another internals doc appear here as one-line cross-references.)
Rejected#
Truncation kwargs on dense tangent projection (
project_dense_onto_tangent). Rejected: with the library’s full-SVDtruncated_svd, the t3svd-then-project path’s first unfolding SVD costsO(Nᵈ·N₀)regardless of any tolerance — truncation only shrinks steps that are not the bottleneck — while the contraction method’s dominant step isO(Nᵈ·n)withn ≤ N₀the Tucker rank. Contraction therefore dominates everywhere; the literature agrees (projection is contractions; the SVD belongs to retraction/rounding). The't3svd'method is kept solely as an independent cross-check oracle (it is a second implementation of the same map, which is what verified the contraction code). Source: the t3m-swap planning session,dev/archive/t3m-swap-planning_2026-06-13.md(“keep both methods, contraction as default, skip the truncation options”).A kwarg-unified derivative interface (
probe(..., order=)instead of separate*_derivativesmethods). Rejected (locked decision): the derivative output gains a leadingorderaxis, so a unified method would have return-rank polymorphism — output rank depending on whether a kwarg was passed — which fights the shape-comment-as-contract style, makes generic consumption harder, and is worse still for the transposes (the residual input rank becomes context-dependent). A named*_derivativesmethod also self-documents an otherwise-buried advanced feature. Source:dev/archive/derivatives_mirror_plan.md§”Frontend design decision”.Any global / ambient jit toggle (context manager, module flag, contextvar). Rejected: the bar for global toggles is very high (
safety.py’s contextvar is the one sanctioned global, justified as correctness-neutral); the jit choice must be per-function, at the call site — which is what theuse_jitper-optimizer parameters and the close-over recipe deliver. Source:dev/archive/jit_oo_handoff.md.
Deferred (would be built if the need materializes)#
The bidiagonal-
trsjet optimization. The pushthrough/assembly contractions convolve a full-order jet with the input/perturbation jet, which is capped at 2 orders (s ∈ {0,1}), sotrs[t,r,s]is nonzero only atr ∈ {t, t−1}— bidiagonal. The code computes these as a dense(K+1)×(K+1)einsum (O(K²)) where the math isO(K); exploiting it (two slice-contractions) would cut the order-mixing by~K/2on those contractions (only the combine in probe is a genuine fullO(K²)convolution). Design-time measurement (W=300, ranks 4): derivative apply forward ~32× the plain op at order 4, transpose ~78×. Deliberately not built: training cost is secondary,K ≤ dis small, and it trades away the clean uniform-trsabstraction. Source:dev/archive/derivatives_mirror_plan.md§”Future-work / perf optimization”.Structured tangent stacks (
K) — open idea (Nick, 2026-06-12). When theKtangent vectors carry special structure — e.g. an orthonormal block within one tangent spaceT_x M— can𝒥⁽ˢ⁾be applied more cheaply than the general 3-group sweep? Plausible angles: shared sub-contractions across the block, a factored form of the perturbation edge variables, work that cancels under orthonormality. Not pursued; the general (arbitrary-K) path stays the default regardless. Source:dev/archive/probing_section6_notes.md.Riemannian L-BFGS with vector transport — see the deferred list in
fitting_internals.md(which also records why plain L-BFGS is deliberately not a library optimizer: the scipy bridge is the intended pattern).The ambient derivative transpose — has its own analysis-and-deferral note:
ambient_derivative_transpose_note.md(intrinsically exponential-rank back-projection; no use case).numpy 2-operand einsum:
optimize=Falseis not BLAS (unresolved; low priority — Nick, 2026-07-15)._grouped_einsum’s docstring claims “2-operand contractions are already BLAS, so they pass straight through on both.” For numpy that is false: passing through meansoptimize=False, which runsc_einsum, never BLAS. Forcing the path (_pairwise_pathalready returns the correct('einsum_path', (0,1))for 2 operands) buys BLAS but pays a fixed ~20–25µs dispatch overhead, so there is a real crossover, measured on'WCi,Cio->WCo': 0.1× at W=1, 0.7× at W=32, 1.8× at W=64, 9.0× at W=2048. It loses up to 10× below W≈64 and wins up to 9× above. So the short-circuit’s effect is a defensible default for small contractions — a regime-dependent tradeoff, not a bug. The library’s operating point sits well above the crossover (Windexes the samples being fitted, so it is large by construction; the core dims are tied to it,r ≈ a ≈ i ≈ branging 1..sqrt(W)/2for probing, 1..cbrt(W)/2for entries/apply). But numpy is not the performance path — jax is, and jax’s einsum has good path selection — so the bar here is “not doing something dumb”, not “optimal”. Not free either: the BLAS path is not bit-identical (~1.7e-16, one ULP — different summation order). (Not to be confused with the MULTI-operand case, where numpy’s own optimizer picks a FLOP-tied non-BLAS path and_pairwise_pathis 22× faster on the 4-operandtrscontraction. That machinery is doing real work and must not be touched.) Source:dev/archive/contractions_sharding_plan.md§8.Backend
ut3_norm/ut3_innertwins (wanted eventually; low priority — Nick, 2026-07-15). The ragged backend has self-containedt3_norm(x, use_orthogonalization=True)/t3_inner_product(x, y, use_orthogonalization=True), which orthogonalize internally. The uniform backend exposes only the already-orthogonalized fast pathut3_norm_orthogonalized(plus a no-orthut3_inner_product), leaving the orthogonalize-then-norm composition to the frontend (UniformTuckerTensorTrain.norm/.inner). So a raw-.datauser must know to callut3_left_orthogonalize_tt_cores(ut3_down_orthogonalize_tucker_cores(x))first — two functions, in that order — which the backend/frontend razor says belongs in the backend (non-obvious, easy to get wrong, and the ragged twin already provides it). Unlike the gaps in../naming_conventions.md§”Intended asymmetries”, this one is not a design decision — it is an unfinished port. Noticed while writingut3_weighted_norm(uniform weighting S1), which had to reproduce the chain; it is parked in that module’s private_ut3_left_orthogonalizedhelper, so filling the gap means promoting that helper into realut3_norm/ut3_innerand having the frontend + weighted twins delegate. Source:weighted_internals.md(S1),backend/ut3_linalg.py.