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)
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)
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)
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)
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)
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)
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)
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)
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))