Few others Tensor functions#

def test_syntax_other(config_kwargs):
    # Initialization
    config_U1 = yastn.make_config(sym='U1', **config_kwargs)
    # Create config using backend-specific symbols rather than imported aliases.
    if config_U1.backend.BACKEND_ID == 'np':
        cfg_U1 = yastn.make_config(sym=yastn.sym.sym_U1, backend=yastn.backend.backend_np, default_device=config_U1.default_device)
    elif config_U1.backend.BACKEND_ID == 'torch':
        cfg_U1 = yastn.make_config(sym=yastn.sym.sym_U1, backend=yastn.backend.backend_torch, default_device=config_U1.default_device)
    elif config_U1.backend.BACKEND_ID == 'torch_cutensor':
        cfg_U1 = yastn.make_config(sym=yastn.sym.sym_U1, backend=yastn.backend.backend_torch_cutensor, default_device=config_U1.default_device)
    else:
        raise RuntimeError('Unsupported backend')

    legs = [yastn.Leg(cfg_U1, s=-1, t=(-1, 1, 0), D=(1, 2, 3)),
            yastn.Leg(cfg_U1, s=1, t=(-1, 1, 2), D=(4, 5, 6)),
            yastn.Leg(cfg_U1, s=1, t=(-1, 1, 2), D=(7, 8, 9)),
            yastn.Leg(cfg_U1, s=-1, t=(-1, 1, 2), D=(10, 11, 12))]
    a = yastn.rand(config=cfg_U1, legs=legs)
    b = yastn.ones(config=config_U1, legs=legs)

    # Copy/clone/detach API variants.
    tensor = a.copy()
    tensor = a.clone()
    tensor = a.detach()
    tensor = a.shallow_copy()

    # Device and dtype conversion.
    tensor = a.to(device='cpu')
    tensor = a.to(dtype='complex128')

    # Tensor inspection APIs.
    a.print_properties()
    a.print_blocks_shape()
    a.get_rank()
    a.size
    a.get_tensor_charge()
    a.get_signature()
    str(a)
    a.get_blocks_charge()
    a.get_blocks_shape()
    a.get_shape()
    a.shape
    a.get_shape(axes=2)
    a.get_dtype()
    a.dtype
    a.nblocks

    # Leg retrieval
    legs = a.get_legs()
    leg = a.get_legs(axes=2)  # legs[2] = leg
    print(leg.tD)  # dict of charges with dimensions for the leg
    print(leg)

    # Convert to dense and numpy forms.
    array = a.to_dense()
    array = a.to_numpy()
    ls = {1: b.get_legs(axes=1)}
    array = a.to_dense(legs=ls)  # on selected legs, enforce charges in ls
    tensor = a.to_nonsymmetric()

    # Decompositions and truncation.
    U, S, V = yastn.linalg.svd(a, axes=((0, 1), (2, 3)))
    mask = yastn.truncation_mask(S, D_total=2)
    U = yastn.apply_mask(mask, U, axes=2)

    a2 = yastn.tensordot(a.conj(), a, axes=((0, 1), (0, 1)))
    D, U = yastn.linalg.eigh(a2, axes=((0, 1), (2, 3)))
    D, U = yastn.eigh_with_truncation(a2, axes=((0, 1), (2, 3)), D_total=5, tol=1e-12, D_block=2)  # here with truncation

    U, S, V = yastn.eig(a2, axes=((0, 1), (2, 3)))

    # Utility functions.
    entropy = yastn.entropy(S ** 2)

    # Diagonal matrix creation and reconstruction.
    S_matrix = yastn.diag(S)
    S_diag = yastn.diag(S_matrix)

    # Comparison based on existing blocks (extra zero blocks make a difference)
    assert yastn.allclose(S, S_diag)

    # Add and remove a trivial leg.
    tensor = a.add_leg(axis=-1, s=-1, t=(0,))
    tensor = tensor.remove_leg(axis=-1)

    # Fermionic swap gate.
    tensor = yastn.swap_gate(a, axes=((0, 1), (2, 3)))

    # Remove zero or random blocks.
    tensor = a.remove_zero_blocks()
    tensor = a.remove_random_blocks(number=1, keep_legs=True)

    # Consistency checks.
    a.is_consistent()
    a.are_independent(b)