t3toolbox.manifold.oblique_gauge_projection#

t3toolbox.manifold.oblique_gauge_projection(variation: t3toolbox.basis_coordinates_format.T3Variation, orthogonal_base: t3toolbox.basis_coordinates_format.T3Base, use_jax: bool = False) t3toolbox.basis_coordinates_format.T3Variation#

Makes variations left-perpendicular while preserving tangent vector.

Straightforward generalization of the method from:

Holtz, Sebastian, Thorsten Rohwedder, and Reinhold Schneider. “On manifolds of tensors of fixed TT-rank.” Numerische Mathematik 120.4 (2012): 701-731.

Parameters:
  • variation (T3Variation,) – The variation that we wish to make gauged

  • orthogonal_base (T3Base,) – Orthogonal representations of the base point on the manifold. If non-orthogonal, this method doesn’t work properly.

  • xnp – Linear algebra backend. Default: np (numpy)

Returns:

Projected variation satisfying Gauge condition. Represents the same tangent vector as the original variation.

Return type:

T3Variation

See also

T3Base, T3Variation, orthogonal_gauge_projection

Examples

>>> import numpy as np
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.manifold as t3m
>>> import t3toolbox.orthogonalization as orth
>>> p = t3.t3_corewise_randn(((14,15,16), (4,5,6), (1,3,2,1)))
>>> base, _ = orth.orthogonal_representations(p)
>>> variation = t3m.tangent_randn(base)
>>> proj_variation = t3m.oblique_gauge_projection(variation, base) # Make gauged via oblique projection
>>> v_dense = t3m.tangent_to_dense(variation, base)
>>> proj_v_dense = t3m.tangent_to_dense(proj_variation, base)
>>> print(np.linalg.norm(v_dense - proj_v_dense)) # Zero since projection preserves represented tangent vector
3.4398319441148304e-15
>>> (U0,U1,U2), (L0,L1,L2), _, _ = base
>>> ((V0,V1,V2), (H0,H1,H2)) = proj_variation
>>> print(np.linalg.norm(V1 @ U1.T)) # Gauge condition for Tucker backend 1
2.931519226677228e-15
>>> print(np.linalg.norm(np.einsum('iaj,iak->jk', H1, L1))) # Gauge condition for TT-backend 1
6.99005312491287e-16

With minimal ranks, orthogonal bases, and gauged variations, the corewise dot product faithfully represents the Hilbert-Schmidt inner product on the ambient space:

>>> import numpy as np
>>> import t3toolbox.tucker_tensor_train as t3
>>> import t3toolbox.manifold as t3m
>>> import t3toolbox.common
>>> import t3toolbox.orthogonalization as orth
>>> import t3toolbox.corewise as cw
>>> p = t3.t3_corewise_randn(((14,15,16), (4,5,6), (1,3,2,1)))
>>> base, _ = orth.orthogonal_representations(p)
>>> u = t3m.tangent_randn(base, apply_gauge_projection=False)
>>> v = t3m.tangent_randn(base, apply_gauge_projection=False)
>>> bad_u_inner_v = cw.corewise_dot(u, v) # u and v are ungauged, so this will not give the right answer
>>> u_dense = t3m.tangent_to_dense(u, base)
>>> v_dense = t3m.tangent_to_dense(v, base)
>>> u_inner_v_true = np.sum(u_dense * v_dense)
>>> print(np.abs(bad_u_inner_v - u_inner_v_true)) # error nonzero because we didn't respect gauge
6.21838915941413
>>> u_gauged = t3m.oblique_gauge_projection(u, base) # make them gauged and try again
>>> v_gauged = t3m.oblique_gauge_projection(v, base)
>>> u_inner_v = cw.corewise_dot(u_gauged, v_gauged)
>>> print(np.abs(u_inner_v - u_inner_v_true)) # Now the error is numerical zero
0.0