boundlab.polysp.PolySp#
- final class boundlab.polysp.PolySp[source]#
Bases:
ExprA polynomial expression component with sparse representation.
One generator stores mixed-order monomials with
-1-padded indices; all monomials index error symbols through one shared span table.Methods
Bound on the magnitude: \(\max(|lb|, ub) \ge \sup |x|\).
Same-class addition;
__add__dispatches here when classes match and otherwise groups the addends in anExprGroup.Center/halfwidth form:
c = (ub + lb) / 2,w = (ub - lb) / 2.The set of component classes present in this value.
Re-express the value over at most
nterms - 1fresh symbols, with a certified residual, vialasso.lad.admm_dict_learning()(LAD-lasso dictionary learning from thepytorch-lassopackage).Lift an
Error/Noisesymbol or a denseZonointo a sparse polynomial.Hook: convert
selfintoexpr_type, orNonewhen this class does not know how.Apply the linear map described by an integer-label einsum.
Diagonal polynomial scaling each component of
errbyamplitude.Lift a tensor/scalar into a broadcast
Bias; passExprthrough.Reinterpret a dense zonotope as an order-1 sparse polynomial.
Sound elementwise lower bound on every concrete value represented.
(lb, ub)in one call; components override it when computing both at once is cheaper than two passes.Build a
PolySp, padding and merging its generators.Apply a concrete quadratic
a x^2 + b x + celementwise via the sparse pair product, with the sameeps/ordertruncation.Matrix product with sound truncation.
Split into
(matching, rest)so thatmatching + rest == self.Convert to another component class, exactly.
Collapse to the box hull
Bias(c) + Noise(w).Diagnostics as a
TensorFormat.Sound elementwise upper bound on every concrete value represented.
- property shape_dtype: ShapeDtype#
Allocation-free
(shape, dtype)metadata of the value.
- property nbytes#
Estimated memory of all generators’ data and indices, in bytes.
- classmethod convert_from(expr)[source]#
Lift an
Error/Noisesymbol or a denseZonointo a sparse polynomial.Biashas no polynomial counterpart, so anIntervalsgroup keeps its center outside thePolySpand only itsNoisepart converts.
- static error(err, amplitude=1.0)[source]#
Diagonal polynomial scaling each component of
errbyamplitude.
- lbub()[source]#
(lb, ub)in one call; components override it when computing both at once is cheaper than two passes.
- einsum(subscripts, *operands)[source]#
Apply the linear map described by an integer-label einsum.
subscriptsholds one label tuple per input followed by the output labels (seeboundlab.utils.einsum_parser()). This is the single linear primitive:__mul__,__matmul__,sumandmeanall lower to it, so implementing it soundly makes every derived linear operation sound.
- add(other)[source]#
Same-class addition;
__add__dispatches here when classes match and otherwise groups the addends in anExprGroup.
- sparse_matmul(other, eps=0.001, order=2)[source]#
Matrix product with sound truncation.
Every pair of monomials multiplies exactly — \((d_r \prod_{k \in I_r} \varepsilon_k)(d_s \prod_{k \in I_s} \varepsilon_k)\) is a monomial of degree \(|I_r| + |I_s|\) — and the result keeps those whose degree fits
orderand whose magnitude clearseps; everything discarded is enclosed by the returnedNoise(each dropped monomial contributes at most its coefficient magnitude, since every \(\varepsilon\) factor lies in \([-1, 1]\)).
- sparse_applypoly(poly, eps=0.001, order=2)[source]#
Apply a concrete quadratic
a x^2 + b x + celementwise via the sparse pair product, with the sameeps/ordertruncation.
- torch_print(group='reason')[source]#
Diagnostics as a
TensorFormat.The result is safe to hand to
Torch diagnostic outputunder tracing: only plain arrays cross the callback boundary, never expression metadata (which may hold tracers, e.g. reason weights).
- compress(nterms, lam=0.5, max_iter=20, tol=0.001, max_cols=None)[source]#
Re-express the value over at most
nterms - 1fresh symbols, with a certified residual, vialasso.lad.admm_dict_learning()(LAD-lasso dictionary learning from thepytorch-lassopackage).Warning
Not fully tested: soundness is covered by sampling unit tests and the defaults were tuned on real barrier matrices, but no complete end-to-end verified run has exercised compression yet.
Every non-constant monomial \(\mu_r = \prod_{k \in I_r} \varepsilon_k\) ranges in \([-1, 1]\), so the value is a linear map of the monomial vector: \(x = d_0 + A \mu\) with \(A \in \mathbb{R}^{p \times R}\) holding one flattened coefficient column per monomial. LAD-LASSO factorizes \(A \approx D S\) with \(k' = nterms - 1\) dictionary atoms; each row of \(S\), rescaled into the dictionary, defines a fresh symbol
\[\varepsilon'_j = \frac{S_{j\cdot}\,\mu}{\|S_{j\cdot}\|_1} \in [-1, 1],\]sound when treated as a new independent symbol (the true \(\varepsilon'\) set is a subset of the box). The factorization error is enclosed coefficient-wise — element \(i\) of the returned
Noiseis \(\sum_r |A - DS|_{ir}\) — which is exactly the LAD fit term the solver minimizes, while the L1 penalty keeps \(\|S_{j\cdot}\|_1\), and with it the new symbols’ amplitudes, from inflating.The fresh symbols carry the value’s blended
Reasons; the residual is tagged"compress". Correlation with other live values is severed — the compressed value no longer references the old symbols (see the cross-value correlation caveat indocs/guide/polysp-plan.md).Only the
max_cols(default16 * nterms) largest monomials by coefficient l1 mass are handed to the solver; the tail joins the residual noise directly. Coefficient mass is heavily concentrated in practice (on the SST barrier matrices the tail beyond16 * 1024columns carries ~0.2% of the mass), and this keeps the solve tractable — LAD-LASSO on all 350k+ monomials of a real attention barrier would take hours.The solver runs with
init="topk"(dictionary seeded with the heaviest monomials, codes warm-started with the matching diagonal, so iteration 0 is exactly the top-k truncation solution and the iterations move tail mass from the residual into the atoms), the ISTA inner lasso solver and the vectorized least-squares + projection dictionary update (dict_update="lstsq");tolis accepted for interface stability but the ADMM loop runs a fixedmax_itersteps. This matters because residualNoisepropagates through downstream linear layers as|W| h(no sign cancellation) while generator rows propagate asW d: on the real barrier-0 matrix, cold-started solves leave ~90% of the mass in the residual and inflate downstream width ~7.7x, whereas the warm-started defaults (lam=0.5,max_iter=20) reach ~1.02x mean / ~1.4x worst-element with 0.6% of the mass inNoisein ~12 s — an order of magnitude below plain truncation’s 3.8%.
- __add__(other)#
- __mul__(other)#
- absub()#
Bound on the magnitude: \(\max(|lb|, ub) \ge \sup |x|\).
- chw()#
Center/halfwidth form:
c = (ub + lb) / 2,w = (ub - lb) / 2.
- classset()#
The set of component classes present in this value.
A single component reports
{type(self)}, anExprGroupits member classes, andZerosthe empty set. Handlers use this to decide which part of a value they know how to transform.
- convert_to(expr_type)#
Hook: convert
selfintoexpr_type, orNonewhen this class does not know how. The other half ofto().
- static from_exprlike(expr, shape)#
Lift a tensor/scalar into a broadcast
Bias; passExprthrough.
- matmul(other)#
- mean(axis, keepdims=False)#
- numel()#
- rmatmul(other)#
- split(ty)#
Split into
(matching, rest)so thatmatching + rest == self.The main way handlers peel off the component class they transform while passing the remainder through untouched.
- squeeze(axes=None)#
- sum(axis, keepdims=False)#
- to(expr_type)#
Convert to another component class, exactly.
Identity short-circuits; otherwise the target’s
convert_fromis tried, then this class’sconvert_to. RaisesTypeErrorwhen neither side knows the conversion — conversions never approximate.
- to_intervals(name='')#
Collapse to the box hull
Bias(c) + Noise(w).Sound but lossy: every correlation between error symbols is dropped, so downstream cancellation (
x - x = 0) no longer happens.
- unsqueeze(axes)#