예제 #1
0
def test_gauge_match_minimizes(backend, dtype, chi, d):
    """
  Gauge matching decreases the values of ||A_C - A_L C ||
  and ||A_C - C A_R||.
  """
    A_L, C, A_R, _ = random_hermitian_system(backend, dtype, chi, d)
    A_C = tn.randn((chi, d, chi), dtype=dtype, backend=backend)
    epsL = tn.linalg.linalg.norm(A_C - ct.rightmult(A_L, C))
    epsR = tn.linalg.linalg.norm(A_C - ct.leftmult(C, A_R))
    A_L2, A_R2 = vumps.gauge_match(A_C, C, True)
    epsL2 = tn.linalg.linalg.norm(A_C - ct.rightmult(A_L2, C))
    epsR2 = tn.linalg.linalg.norm(A_C - ct.leftmult(C, A_R2))
    assert epsL2 < epsL
    assert epsR2 < epsR
예제 #2
0
def test_rightmult(backend, dtype, chi, d):
  lam = tn.randn((chi, chi), dtype=dtype, backend=backend, seed=10)
  gam = tn.randn((chi, d, chi), dtype=dtype, backend=backend, seed=10)
  result = ct.rightmult(gam, lam)
  compare = tn.linalg.operations.ncon([gam, lam], [[-1, -2, 1],
                                                   [1, -3]])
  np.testing.assert_allclose(result.array, compare.array)
예제 #3
0
def vumps_initialization(
    d: int,
    chi: int,
    dtype: Optional[DtypeType] = None,
    backend: Optional[Text] = None
) -> Tuple[ThreeTensors, tn.Tensor, TwoTensors]:
    """
  Generate a random uMPS in mixed canonical forms, along with the left
  dominant eV L of A_L and right dominant eV R of A_R.

  Args:
    d: Physical dimension.
    chi: Bond dimension.
    dtype: Data dtype of tensors.
    backend: The backend.
  Returns:
    mps = (A_L, C, A_R): A_L and A_R have shape (chi, d, chi), and are
      respectively left and right isometric. C is the (chi, chi)
      centre of orthogonality.
    A_C: A_L @ C. One of the equations vumps minimizes is
      A_L @ C = C @ A_R = A_C.
    fpoints = [rL, lR]: C^dag @ C and C @ C^dag respectively. Will converge
      to the left and right fixed points of A_R and A_L. Both are chi x chi.
  """
    A_1 = tn.randn((chi, d, chi), dtype=dtype, backend=backend)
    A_L, _ = tn.linalg.linalg.qr(A_1, pivot_axis=2, non_negative_diagonal=True)
    C, A_R = tn.linalg.linalg.rq(A_L, pivot_axis=1, non_negative_diagonal=True)
    C /= tn.linalg.linalg.norm(C)
    A_C = ct.rightmult(A_L, C)
    L0, R0 = vumps_approximate_tm_eigs(C)
    fpoints = (L0, R0)
    mps = [A_L, C, A_R]
    benchmark.block_until_ready(R0)
    return (mps, A_C, fpoints)
예제 #4
0
def vumps_delta(mps: ThreeTensors, A_C: tn.Tensor, oldA_L: tn.Tensor,
                mode: Text):
    """
  Estimate the current vuMPS error.
  Args:
    mps: The MPS.
    A_C: Current A_C.
    oldA_L: A_L from the last iteration.
    mode: gradient_estimate_mode in vumps_params. See that docstring for
      details.
  """
    if mode == "gauge mismatch":
        A_L, C, A_R = mps
        eL = tn.norm(A_C - ct.rightmult(A_L, C))
        eR = tn.norm(A_C - ct.leftmult(C, A_R))
        delta = max(eL, eR)
    elif mode == "null space":
        A_Ldag = tn.pivot(oldA_L, pivot_axis=2).H
        N_Ldag = tn_vumps.polar.null_space(A_Ldag)
        N_L = N_Ldag.H
        A_Cmat = tn.pivot(A_C, pivot_axis=2)
        B = N_L @ A_Cmat
        delta = tn.norm(B)
    else:
        raise ValueError("Invalid mode {mode}.")
    return delta
예제 #5
0
def gauge_match(A_C: tn.Tensor,
                C: tn.Tensor,
                mode: Text = "svd") -> TwoTensors:
    """
  Return approximately gauge-matched A_L and A_R from A_C and C
  using a polar decomposition.

  A_L and A_R are chosen to minimize ||A_C - A_L C|| and ||A_C - C A_R||.
  The respective solutions are the isometric factors in the
  polar decompositions of A_C @ C.H and C.H @ A_C.

  Args:
    A_C: Current estimate of A_C.
    C: C from the MPS.
    mode: Chooses the algorithm for the polar decomposition. See the docstring
     of vumps_params in params.py.

  Returns:
    A_L, A_R: Such that A_L C A_R minimizes ||A_C - A_L C|| and ||A_C - C A_R||,
      with A_L (A_R) left (right) isometric.
  """
    UC = tn_vumps.polar.polarU(C, mode=mode)  # unitary
    UAc_l = tn_vumps.polar.polarU(A_C, mode=mode)  # left isometric
    A_L = ct.rightmult(UAc_l, UC.H)
    UAc_r = tn_vumps.polar.polarU(A_C, pivot_axis=1, mode=mode)  # right iso
    A_R = ct.leftmult(UC.H, UAc_r)
    return A_L, A_R
예제 #6
0
def test_gauge_match_left(backend, dtype, chi, d):
    """
  Gauge matching is a null op on a system gauge matched on the LHS.
  """
    A_L, C, _, _ = random_hermitian_system(backend, dtype, chi, d)
    A_C = ct.rightmult(A_L, C)
    A_L2, _ = vumps.gauge_match(A_C, C, True)
    rtol = 2 * A_L.size * C.size * A_C.size * np.finfo(dtype).eps
    np.testing.assert_allclose(A_L.array, A_L2.array, rtol=rtol)
    I = tn.eye(chi, backend=backend, dtype=dtype)
    XAL2 = ct.XopL(A_L2, I)
    np.testing.assert_allclose(XAL2.array, I.array, atol=rtol)