Ejemplo n.º 1
0
def test_eig(nr_sites, local_dim, rank, which, var_sites, rgen, request):
    if nr_sites <= var_sites:
        pt.skip("Nothing to test")
        return  # No local optimization can be defined
    if not (_pytest_want_long(request) or
            (nr_sites, local_dim, rank, var_sites, which) in {
                (3, 2, 4, 1, 'SA'), (4, 3, 5, 1, 'LM'), (5, 2, 1, 2, 'LA'),
                (6, 2, 4, 2, 'SA'),
            }):
        pt.skip("Should only be run in long tests")
    # With startvec_rank = 2 * rank and this seed, eig() gets
    # stuck in a local minimum. With startvec_rank = 3 * rank,
    # it does not.
    mpo = factory.random_mpo(nr_sites, local_dim, rank, randstate=rgen,
                             hermitian=True, normalized=True)
    mpo.canonicalize()
    op = mpo.to_array_global().reshape((local_dim**nr_sites,) * 2)
    v0 = factory._zrandn([local_dim**nr_sites], rgen)
    eigval, eigvec = eigsh(op, k=1, which=which, v0=v0)
    eigval, eigvec = eigval[0], eigvec[:, 0]

    eig_rank = (4 - var_sites) * rank
    eigval_mp, eigvec_mp = mp.eig(
        mpo, num_sweeps=5, var_sites=1, startvec_rank=eig_rank, randstate=rgen,
        eigs=ft.partial(eigsh, k=1, which=which, tol=1e-6, maxiter=250))
    eigvec_mp = eigvec_mp.to_array().flatten()

    overlap = np.inner(eigvec.conj(), eigvec_mp)
    assert_almost_equal(eigval, eigval_mp, decimal=14)
    assert_almost_equal(1, abs(overlap), decimal=14)
Ejemplo n.º 2
0
def test_block_diag_simple(rgen):
    rows = (4, 7)
    cols = (3, 6)
    summands = [factory._zrandn((rows[i], cols[i]), randstate=rgen)
                for i in range(len(rows))]
    blockdiag_sum = utils.block_diag(summands)
    blockdiag_sum_scipy = block_diag(*summands)
    assert_array_almost_equal(blockdiag_sum, blockdiag_sum_scipy)
Ejemplo n.º 3
0
def test_povm_probability_map(local_dim, nopovm, rgen):
    # Use a random matrix rho for testing (instead of a positive matrix).
    rho = factory._zrandn((local_dim, local_dim), rgen)
    # Compare output from `povm.localpovm.POVM.probability_map` with
    # calculating probabilities element by element.
    probab_direct = np.array([np.trace(np.dot(elem, rho)) for elem in nopovm])
    probab_pmap = np.dot(nopovm.probability_map, rho.ravel())
    assert_array_almost_equal(probab_pmap, probab_direct)
Ejemplo n.º 4
0
def test_block_diag_simple(rgen):
    rows = (4, 7)
    cols = (3, 6)
    summands = [
        factory._zrandn((rows[i], cols[i]), randstate=rgen)
        for i in range(len(rows))
    ]
    blockdiag_sum = utils.block_diag(summands)
    blockdiag_sum_scipy = block_diag(*summands)
    assert_array_almost_equal(blockdiag_sum, blockdiag_sum_scipy)
Ejemplo n.º 5
0
def test_update_normalization(mpa_norm,
                              upd_pos,
                              upd_norm,
                              rgen,
                              n_sites=UPDATE_N_SITES):
    """Verify normalization after local tensor update

    We test two things:
    1. The normalization info after update is what we expect
       (in some special cases, see `norm_expected`)
    2. The normalization info is actually correct (in all cases)

    """
    n_sites = UPDATE_N_SITES
    ldim = 4
    rank = 3
    mpa = factory.random_mpa(n_sites, ldim, rank, rgen)
    assert_correct_normalization(mpa, 0, n_sites)

    mpa.canonicalize(*mpa_norm)
    assert_correct_normalization(mpa, *mpa_norm)

    dims = mpa.lt.shape[upd_pos]
    tensor = factory._zrandn(dims, rgen)
    if upd_norm == 'left':
        tensor = tensor.reshape((-1, dims[-1]))
        tensor, _ = np.linalg.qr(tensor)
        tensor = tensor.reshape(dims)
    elif upd_norm == 'right':
        tensor = tensor.reshape((dims[0], -1)).T
        tensor, _ = np.linalg.qr(tensor)
        tensor = tensor.T.reshape(dims)

    norm_expected = {
        # Replacing in unnormalized tensor
        (0, n_sites, 0, None): (0, 4),
        (0, n_sites, 3, None): (0, 4),
        # Replacing in left-normalized part with unnormalized tensor
        (3, n_sites, 3, 'left'): (3, 4),
        (3, n_sites, 0, 'left'): (0, 4),
        # Replacing in right-normalized part with unnormalized tensor
        (0, 1, 0, None): (0, 1),
        (0, 1, 3, None): (0, 4),
        # Replacing in left-normalized part with normalized tensor
        (3, 4, 2, 'left'): (3, 4),
        (3, 4, 2, 'right'): (2, 4),
        # Replacing in right-normalized part with normalized tensor
        (0, 1, 2, 'right'): (0, 1),
        (0, 1, 2, 'left'): (0, 3),
    }
    expected = norm_expected.get((mpa_norm[0], mpa_norm[1], upd_pos, upd_norm),
                                 ())

    mpa.lt.update(upd_pos, tensor, upd_norm)
    assert_correct_normalization(mpa, *expected)
Ejemplo n.º 6
0
def test_block_diag(rgen):
    leftmargin = 3
    rightmargin = 5
    rows = (4, 7)
    cols = (3, 6)
    nr_blocks = len(rows)
    nr_summands = 3
    leftvecs = factory._zrandn((nr_blocks, nr_summands, leftmargin),
                               randstate=rgen)
    middlematrices = [
        factory._zrandn((nr_summands, rows[i], cols[i]), randstate=rgen)
        for i in range(nr_blocks)
    ]
    rightvecs = factory._zrandn((nr_blocks, nr_summands, rightmargin),
                                randstate=rgen)
    blockdiag_summands = []
    for i in range(nr_blocks):
        summand = np.zeros((leftmargin, rows[i], cols[i], rightmargin),
                           dtype=complex)
        for j in range(nr_summands):
            summand += np.outer(
                np.outer(leftvecs[i, j, :], middlematrices[i][j, :, :]),
                rightvecs[i, j, :]).reshape(summand.shape)
        blockdiag_summands.append(summand)
    blockdiag_sum = utils.block_diag(blockdiag_summands, axes=(1, 2))
    blockdiag_sum_explicit = np.zeros(
        (leftmargin, sum(rows), sum(cols), rightmargin), dtype=complex)

    for i in range(nr_blocks):
        for j in range(nr_summands):
            summands = [
                middlematrices[i2][j]
                if i2 == i else np.zeros_like(middlematrices[i2][j])
                for i2 in range(nr_blocks)
            ]
            middle = block_diag(*summands)
            blockdiag_sum_explicit += \
                np.outer(np.outer(leftvecs[i][j], middle), rightvecs[i][j]) \
                .reshape(blockdiag_sum_explicit.shape)

    assert_array_almost_equal(blockdiag_sum, blockdiag_sum_explicit)
Ejemplo n.º 7
0
def test_update_normalization(mpa_norm, upd_pos, upd_norm, rgen,
                              n_sites=UPDATE_N_SITES):
    """Verify normalization after local tensor update

    We test two things:
    1. The normalization info after update is what we expect
       (in some special cases, see `norm_expected`)
    2. The normalization info is actually correct (in all cases)

    """
    n_sites = UPDATE_N_SITES
    ldim = 4
    rank = 3
    mpa = factory.random_mpa(n_sites, ldim, rank, rgen)
    assert_correct_normalization(mpa, 0, n_sites)

    mpa.canonicalize(*mpa_norm)
    assert_correct_normalization(mpa, *mpa_norm)

    dims = mpa.lt.shape[upd_pos]
    tensor = factory._zrandn(dims, rgen)
    if upd_norm == 'left':
        tensor = tensor.reshape((-1, dims[-1]))
        tensor, _ = np.linalg.qr(tensor)
        tensor = tensor.reshape(dims)
    elif upd_norm == 'right':
        tensor = tensor.reshape((dims[0], -1)).T
        tensor, _ = np.linalg.qr(tensor)
        tensor = tensor.T.reshape(dims)

    norm_expected = {
        # Replacing in unnormalized tensor
        (0, n_sites, 0, None): (0, 4),
        (0, n_sites, 3, None): (0, 4),
        # Replacing in left-normalized part with unnormalized tensor
        (3, n_sites, 3, 'left'): (3, 4),
        (3, n_sites, 0, 'left'): (0, 4),
        # Replacing in right-normalized part with unnormalized tensor
        (0, 1, 0, None): (0, 1),
        (0, 1, 3, None): (0, 4),
        # Replacing in left-normalized part with normalized tensor
        (3, 4, 2, 'left'): (3, 4),
        (3, 4, 2, 'right'): (2, 4),
        # Replacing in right-normalized part with normalized tensor
        (0, 1, 2, 'right'): (0, 1),
        (0, 1, 2, 'left'): (0, 3),
    }
    expected = norm_expected.get((mpa_norm[0], mpa_norm[1], upd_pos, upd_norm),
                                 ())

    mpa.lt.update(upd_pos, tensor, upd_norm)
    assert_correct_normalization(mpa, *expected)
Ejemplo n.º 8
0
def test_block_diag(rgen):
    leftmargin = 3
    rightmargin = 5
    rows = (4, 7)
    cols = (3, 6)
    nr_blocks = len(rows)
    nr_summands = 3
    leftvecs = factory._zrandn((nr_blocks, nr_summands, leftmargin),
                               randstate=rgen)
    middlematrices = [factory._zrandn((nr_summands, rows[i], cols[i]),
                                      randstate=rgen)
                      for i in range(nr_blocks)]
    rightvecs = factory._zrandn((nr_blocks, nr_summands, rightmargin),
                                randstate=rgen)
    blockdiag_summands = []
    for i in range(nr_blocks):
        summand = np.zeros(
            (leftmargin, rows[i], cols[i], rightmargin), dtype=complex)
        for j in range(nr_summands):
            summand += np.outer(
                np.outer(leftvecs[i, j, :], middlematrices[i][j, :, :]),
                rightvecs[i, j, :]).reshape(summand.shape)
        blockdiag_summands.append(summand)
    blockdiag_sum = utils.block_diag(blockdiag_summands, axes=(1, 2))
    blockdiag_sum_explicit = np.zeros(
        (leftmargin, sum(rows), sum(cols), rightmargin), dtype=complex)

    for i in range(nr_blocks):
        for j in range(nr_summands):
            summands = [middlematrices[i2][j]
                        if i2 == i else np.zeros_like(middlematrices[i2][j])
                        for i2 in range(nr_blocks)]
            middle = block_diag(*summands)
            blockdiag_sum_explicit += \
                np.outer(np.outer(leftvecs[i][j], middle), rightvecs[i][j]) \
                .reshape(blockdiag_sum_explicit.shape)

    assert_array_almost_equal(blockdiag_sum, blockdiag_sum_explicit)
Ejemplo n.º 9
0
def test_eig(nr_sites, local_dim, rank, which, var_sites, rgen, request):
    if nr_sites <= var_sites:
        pt.skip("Nothing to test")
        return  # No local optimization can be defined
    if not (_pytest_want_long(request) or
            (nr_sites, local_dim, rank, var_sites, which) in {
                (3, 2, 4, 1, 'SA'),
                (4, 3, 5, 1, 'LM'),
                (5, 2, 1, 2, 'LA'),
                (6, 2, 4, 2, 'SA'),
            }):
        pt.skip("Should only be run in long tests")
    # With startvec_rank = 2 * rank and this seed, eig() gets
    # stuck in a local minimum. With startvec_rank = 3 * rank,
    # it does not.
    mpo = factory.random_mpo(nr_sites,
                             local_dim,
                             rank,
                             randstate=rgen,
                             hermitian=True,
                             normalized=True)
    mpo.canonicalize()
    op = mpo.to_array_global().reshape((local_dim**nr_sites, ) * 2)
    v0 = factory._zrandn([local_dim**nr_sites], rgen)
    eigval, eigvec = eigsh(op, k=1, which=which, v0=v0)
    eigval, eigvec = eigval[0], eigvec[:, 0]

    eig_rank = (4 - var_sites) * rank
    eigval_mp, eigvec_mp = mp.eig(mpo,
                                  num_sweeps=5,
                                  var_sites=1,
                                  startvec_rank=eig_rank,
                                  randstate=rgen,
                                  eigs=ft.partial(eigsh,
                                                  k=1,
                                                  which=which,
                                                  tol=1e-6,
                                                  maxiter=250))
    eigvec_mp = eigvec_mp.to_array().flatten()

    overlap = np.inner(eigvec.conj(), eigvec_mp)
    assert_almost_equal(eigval, eigval_mp, decimal=14)
    assert_almost_equal(1, abs(overlap), decimal=14)
Ejemplo n.º 10
0
def nopovm(request, local_dim, rgen):
    """Provide different POVMs and non-POVMs for testing

    We provide instances of :class:`povm.localpovm.POVM` with the
    following elements:

    * `pauli`: Generated by :func:`povm.pauli_povm()`

    * `random`: Random (non-Hermitian, non-positive) elements for
      testing. (These elements do not constitute a POVM. We use them
      to distinguish elem.conj() from elem.T in our code.)

    """
    nopovm_name = request.param
    if nopovm_name == 'pauli':
        return povm.pauli_povm(local_dim)
    elif nopovm_name == 'random':
        d = local_dim
        return povm.localpovm.POVM(factory._zrandn((2 * d**2, d, d), rgen))
    else:
        raise ValueError('Unknown fixture name {}'.format(nopovm_name))