T3Frame.is_orthogonal#

t3toolbox.frame_variations_format.T3Frame.is_orthogonal(atol=1e-09)#
def is_orthogonal(self, atol: float = 1e-9) -> NDArray:  # bool array, shape = stack_shape (scalar unstacked)

True (per stack element) if the frame cores are orthogonal in their respective senses.

Checks (each stacked block; max absolute deviation from identity <= atol):
  • up_tucker U_i (all i): einsum('...io,...jo->...ij', U, U) = I

  • down/outer D_i (all i): einsum('...iaj,...ibj->...ab', D, D) = I

  • left L_i (i = 0..d-2): einsum('...iaj,...iak->...jk', L, L) = I

  • right R_i (i = 1..d-1): einsum('...iaj,...kaj->...ik', R, R) = I

The last left core and the first right core are the (non-orthogonal) boundary remainders and are not checked. This is a non-enforcing convenience checker; T3Frame does not require orthogonality at construction. Returns a per-stack-element bool array (shape stack_shape; a scalar when unstacked) – different base points in a stack can differ; reduce with .all() for a single verdict.

Orthogonal cores (left/right/outer/Tucker) are defined in Appendix A.1 of Alger et al. (2026), “Tucker Tensor Train Taylor Series” (arXiv:2603.21141).

Examples

>>> import numpy as np
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.frame_variations_format as bvf
>>> np.random.seed(0)
>>> x = t3.TuckerTensorTrain.randn((10, 11, 12), (3, 4, 3), (1, 2, 2, 1))
>>> frame, _ = bvf.t3_orthogonal_representations(x)   # this frame IS orthogonal by construction
>>> print(frame.is_orthogonal())          # unstacked -> a scalar bool
True

Stacked: a per-element bool array. Stack a good frame with a deliberately non-orthogonal one to show the elements differ:

>>> good, _ = bvf.t3_orthogonal_representations(t3.TuckerTensorTrain.randn((5, 6), (2, 2), (1, 2, 1)))
>>> bad = bvf.T3Frame(tuple(np.ones_like(U) for U in good.up_tucker_cores),  # ones cores: not orthogonal
...                   good.down_tt_cores, good.left_tt_cores, good.right_tt_cores)
>>> stacked = bvf.T3Frame.stack([good, bad])
>>> print(stacked.is_orthogonal().shape, stacked.is_orthogonal())   # one bool per stack element
(2,) [ True False]
Parameters:

atol (float)

Return type:

NDArray