t3weights_to_ut3weights#
- t3toolbox.backend.ut3_conversions.t3weights_to_ut3weights(weights, n=None, r=None)#
def t3weights_to_ut3weights( weights: typ.Tuple[ typ.Sequence[NDArray], # tucker_weights, len=d, elm_shape=stack_shape+(ni,) typ.Sequence[NDArray], # tt_weights, len=d+1, elm_shape=stack_shape+(ri,) ], n: int = None, # padded Tucker rank (default max(tucker rank)); pass to force a larger pad r: int = None, # padded TT rank (default max(tt rank)) ) -> typ.Tuple[ NDArray, # tucker_weight_supercore, shape=(d,) +stack_shape+(n,) NDArray, # tt_weight_supercore, shape=(d+1,)+stack_shape+(r,) typ.Tuple[NDArray, NDArray], # (tucker_edge_mask, tt_edge_mask), HOST bool, static ]:
Pack a ragged
T3Weightscore pair into uniform weight supercores + masks (the.datalayout).The weight twin of
t3_to_ut3(), and much simpler: a weight is one vector per edge, so there is nothing to pad but the last axis and no physicalshapeat all (weights live only on internal edges). Each vector is zero-padded to the common width and the real extent recorded as a prefix mask.The zero pad matters and is not a free choice: masking downstream works by multiplication, so the fill must stay finite (
docs/uniform_equivalence_contract.md), and zero is the layer’s canonical clean padding. It is emphatically not an identity for weighting – absorbing a zero-padded weight zeroes the padding of the object it weights, which is exactly right (that padding is don’t-care), but it is whyut3_reciprocal_weightscannot naively divide (1/0 = inf).Pass
n/rto match the padding of the object these weights will pair with; the defaults pad tightly to the weights’ own max rank.use_jaxis inferred for the SUPERCORES; the masks are always numpy (host) structure.