TuckerTensorTrain.get_minimal_ranks#

static t3toolbox.tucker_tensor_train.TuckerTensorTrain.get_minimal_ranks(shape, tucker_ranks, tt_ranks, sharing=None)#
def get_minimal_ranks(
        shape: Sequence[int],
        tucker_ranks: Sequence[int],
        tt_ranks: Sequence[int],
        sharing: typ.Optional[typ.Sequence] = None,  # len=d, static; one hashable group label per mode (None = unshared)
) -> Tuple[
    Tuple[int, ...],  # new_tucker_ranks
    Tuple[int, ...],  # new_tt_ranks
]:

Find minimal ranks for a hypothetical TuckerTensorTrain with given shape and ranks.

Minimal ranks satisfy:
  • Left TT core unfoldings are full rank: r(i+1) <= (ri*ni)

  • Right TT core unfoldings are full rank: ri <= (ni*r(i+1))

  • Down TT core unfoldings are full rank: ni <= (ri*r(i+1))

  • Tucker ranks do not exceed shape: ni <= Ni

In this function, minimal ranks are defined with respect to a generic Tucker tensor train of the given form based on its structure. We do not account for possible additional rank deficiency due to the numerical values within the cores.

Minimal ranks always exist and are unique.
  • Minimal TT ranks are equal to the ranks of (N*...*Ni) x (N(i+1)*...*N(d-1)) matrix unfoldings.

  • Minimal Tucker ranks are equal to the ranks of Ni x (N1*...*N(i-1)*N(i+1)*...*N(d-1)) matricizations.

With sharing (one hashable group label per mode), minimality is with respect to Tucker factors tied within each group: reductions apply group-wide, and the per-mode Tucker ceiling ni <= min(Ni, ri*r(i+1)) is replaced by the group ceiling n_g <= min(N_g, sum_{i in g} min(N_g, ri*r(i+1))). Per-mode ceilings ADD across a group (a shared basis column is useless only if it is useless for every mode of the group), so a shared rank may exceed ri*r(i+1) at individual modes. See compute_minimal_ranks().

Examples

>>> import t3toolbox.tucker_tensor_train as t3
>>> print(t3.TuckerTensorTrain.get_minimal_ranks((10,11,12,13), (14,15,16,17), (98,99,100,101,102)))
((10, 11, 12, 13), (1, 10, 100, 13, 1))

The group ceiling can keep a shared rank the per-mode reduction would clip (and, by clipping one mode of the group but not another, untie):

>>> print(t3.TuckerTensorTrain.get_minimal_ranks((6, 6, 4), (4, 4, 3), (1, 2, 2, 1)))
((2, 4, 2), (1, 2, 2, 1))
>>> print(t3.TuckerTensorTrain.get_minimal_ranks((6, 6, 4), (4, 4, 3), (1, 2, 2, 1), sharing=(0, 0, 1)))
((4, 4, 2), (1, 2, 2, 1))
Parameters:
  • shape (collections.abc.Sequence[int])

  • tucker_ranks (collections.abc.Sequence[int])

  • tt_ranks (collections.abc.Sequence[int])

  • sharing (Optional[Sequence])

Return type:

Tuple[Tuple[int, …], Tuple[int, …]]