TuckerTensorTrain.rank_adjustment_sweep#
- t3toolbox.tucker_tensor_train.TuckerTensorTrain.rank_adjustment_sweep(direction='right_to_left')#
def rank_adjustment_sweep(self, direction: str = 'right_to_left') -> 'TuckerTensorTrain':
A single lossless directional sweep that drops structurally-redundant ranks (the separate rank-minimization step;
t3svd()itself does not minimize). Returns the adjusted T3.'right_to_left'returns a right-orthogonal T3;'left_to_right'a left-orthogonal one. A single sweep reaches minimal ranks only if the input is already orthogonal in the opposite direction – e.g. at3svd()result is left-orthogonal, soresult.rank_adjustment_sweep('right_to_left')minimizes it (check withhas_minimal_ranks). That precondition is not enforced: sweeping the wrong direction for the input’s gauge just under-minimizes (it stays lossless here – but the uniformrank_adjustment_sweep()is lossy in that case). Verify the gauge withis_left_orthogonal()/is_right_orthogonal()first, or compose both directions for guaranteed minimal ranks. The represented tensor is unchanged (when used correctly).Examples
>>> import numpy as np >>> import t3toolbox.tucker_tensor_train as t3 >>> np.random.seed(0) >>> x = t3.TuckerTensorTrain.randn((5, 6, 7), (4, 5, 6), (1, 3, 2, 1)) >>> x2, _, _ = x.t3svd(max_tt_ranks=2) # basic T3-SVD: left-orthogonal, NOT minimal >>> print(x2.has_minimal_ranks, x2.tucker_ranks) False (3, 4, 2) >>> x3 = x2.rank_adjustment_sweep('right_to_left') # x2 is left-orthogonal -> R->L minimizes >>> print(x3.has_minimal_ranks, x3.tucker_ranks) True (2, 4, 2) >>> print(np.allclose(x3.to_dense(), x2.to_dense())) # same tensor, redundant rank removed True
Wrong direction for the input’s gauge – the left-orthogonal
x2needs'right_to_left';'left_to_right'here just under-minimizes (lossless, but still non-minimal). Use a bond orphan to show it clearly:>>> np.random.seed(0) >>> y = t3.TuckerTensorTrain.randn((10, 10, 10), (9, 9, 9), (1, 9, 9, 1)) >>> y2, _, _ = y.t3svd(max_tucker_ranks=[9, 1, 9], max_tt_ranks=[1, 9, 2, 1]) # left-orth, non-minimal >>> print(y2.has_minimal_ranks) False >>> wrong = y2.rank_adjustment_sweep('left_to_right') # WRONG direction for a left-orth input >>> print(wrong.has_minimal_ranks, np.allclose(wrong.to_dense(), y2.to_dense())) # non-minimal, but lossless False True >>> print(y2.rank_adjustment_sweep('right_to_left').has_minimal_ranks) # correct direction True
- Parameters:
direction (str)
- Return type: