def test_sparse(self): i = eye(2, sparse=True) a = qu(rand_matrix(2), sparse=True) b = eyepad(a, [2, 2, 2], 1) # infer sparse assert(issparse(b)) assert_allclose(b.A, (i & a & i).A) a = rand_matrix(2) b = eyepad(a, [2, 2, 2], 1, sparse=True) # explicit sparse assert(issparse(b)) assert_allclose(b.A, (i & a & i).A)
def test_sparse(self): i = qu.eye(2, sparse=True) a = qu.qu(qu.rand_matrix(2), sparse=True) b = qu.ikron(a, [2, 2, 2], 1) # infer sparse assert (qu.issparse(b)) assert_allclose(b.A, (i & a & i).A) a = qu.rand_matrix(2) b = qu.ikron(a, [2, 2, 2], 1, sparse=True) # explicit sparse assert (qu.issparse(b)) assert_allclose(b.A, (i & a & i).A)
def test_hamiltonian_builder(sparse, stype, dtype): from quimb.gen.operators import hamiltonian_builder @hamiltonian_builder def simple_ham(sparse=None, stype=None, dtype=None): H = qu.qu([[0.0, 1.0], [1.0, 0.0]], sparse=True, stype='csr', dtype=dtype) return H @hamiltonian_builder def simple_ham_complex(sparse=None, stype=None, dtype=None): H = qu.qu([[0.0, 1.0j], [-1.0j, 0.0]], sparse=True, stype='csr', dtype=dtype) return H if dtype == "don't pass": H = simple_ham(sparse=sparse, stype=stype) else: H = simple_ham(sparse=sparse, stype=stype, dtype=dtype) if dtype == "don't pass" or dtype is None: # check that passng no actual dtype keeps it as float assert H.dtype == np.float64 else: # check that explicit dtypes are respected assert H.dtype == dtype assert qu.issparse(H) == sparse assert qu.isdense(H) != sparse if sparse: assert H.format == stype with pytest.raises(ValueError): # check immutability H[0,0] = 100 if dtype == "don't pass": H = simple_ham_complex(sparse=sparse, stype=stype) elif dtype is np.float64: with pytest.warns(np.ComplexWarning): H = simple_ham_complex(sparse=sparse, stype=stype, dtype=dtype) else: H = simple_ham_complex(sparse=sparse, stype=stype, dtype=dtype) if dtype == "don't pass" or dtype is None: # check that passng no actual dtype keeps it as float assert H.dtype == np.complex128 else: # check that explicit dtypes are respected assert H.dtype == dtype assert qu.issparse(H) == sparse assert qu.isdense(H) != sparse if sparse: assert H.format == stype with pytest.raises(ValueError): # check immutability H[0,0] = 100 return
def test_construct(self, gate, dtype, sparse): if gate in ['Rx', 'Ry', 'Rz']: args = (0.43827, ) else: args = () G = getattr(qu, gate)(*args, dtype=dtype, sparse=sparse) assert G.dtype == dtype assert qu.issparse(G) is sparse
def test_eigs_sparse_wvecs(self, mat_herm_sparse, backend): u, a = mat_herm_sparse assert qu.issparse(a) lk, vk = qu.eigh(a, k=2, backend=backend) assert_allclose(lk, (-3, -1)) for i, j in zip([3, 0], [0, 1]): o = u[:, [i]].H @ vk[:, [j]] assert_allclose(abs(o), 1.) vk = qu.eigvecsh(a, k=2, backend=backend) for i, j in zip([3, 0], [0, 1]): o = u[:, [i]].H @ vk[:, [j]] assert_allclose(abs(o), 1.)
def test_seigsys_sparse_wvecs(self, mat_herm_sparse, backend): u, a = mat_herm_sparse assert issparse(a) lk, vk = seigsys(a, k=2, backend=backend) assert_allclose(lk, (-3, -1)) for i, j in zip([3, 0], [0, 1]): o = u[:, i].H @ vk[:, j] assert_allclose(abs(o), 1.) vk = seigvecs(a, k=2, backend=backend) for i, j in zip([3, 0], [0, 1]): o = u[:, i].H @ vk[:, j] assert_allclose(abs(o), 1.)
def test_construct(self, gate, dtype, sparse): if gate in ('Rx', 'Ry', 'Rz', 'phase_gate'): args = (0.43827, ) elif gate in ('U_gate'): args = (0.1, 0.2, 0.3) else: args = () G = getattr(qu, gate)(*args, dtype=dtype, sparse=sparse) assert G.dtype == dtype assert qu.issparse(G) is sparse psi = qu.rand_ket(G.shape[0]) Gpsi = G @ psi assert qu.expec(Gpsi, Gpsi) == pytest.approx(1.0)
def svds_numpy(a, k, return_vecs=True, **_): """Partial singular value decomposition using numpys (full) singular value decomposition. Parameters ---------- a : array_like Operator to decompose. k : int, optional Number of singular value triplets to retrieve. return_vecs : bool, optional whether to return the computed vecs or values only Returns ------- (uk,) sk (, vkt) : Singlar value triplets. """ if return_vecs: uk, sk, vkt = nla.svd(a.A if qu.issparse(a) else a, compute_uv=True) return qu.qarray(uk[:, :k]), sk[:k], qu.qarray(vkt[:k, :]) else: sk = nla.svd(a.A if qu.issparse(a) else a, compute_uv=False) return sk[:k]
def test_controlled_z_sparse(self): cz = qu.controlled('z', sparse=True) assert (qu.issparse(cz)) assert_allclose(cz.A, np.diag([1, 1, 1, -1]))
def test_eigs_small_sparse_novecs(self, mat_herm_sparse, backend): _, a = mat_herm_sparse assert qu.issparse(a) lk = qu.eigvalsh(a, k=2, backend=backend) assert_allclose(lk, (-3, -1))
def test_give_sformat_only(self, qtype, shape, format_out): x = [[1], [0], [2], [3j]] y = qu.qu(x, qtype=qtype, stype=format_out) assert qu.issparse(y) assert y.shape == shape assert y.format == format_out
def test_seigsys_small_sparse_novecs(self, mat_herm_sparse, backend): _, a = mat_herm_sparse assert issparse(a) lk = seigvals(a, k=2, backend=backend) assert_allclose(lk, (-3, -1))
def eigs_numpy(A, k, B=None, which=None, return_vecs=True, sigma=None, isherm=True, P=None, sort=True, **eig_opts): """Partial eigen-decomposition using numpy's dense linear algebra. Parameters ---------- A : array_like or quimb.Lazy Operator to partially eigen-decompose. k : int Number of eigenpairs to return. B : array_like or quimb.Lazy If given, the RHS operator defining a generalized eigen problem. which : str, optional Which part of the spectrum to target. return_vecs : bool, optional Whether to return eigenvectors. sigma : None or float, optional Target eigenvalue. isherm : bool, optional Whether `a` is hermitian. P : array_like or quimb.Lazy Perform the eigensolve in the subspace defined by this projector. sort : bool, optional Whether to sort reduced list of eigenpairs into ascending order. eig_opts Settings to pass to numpy.eig... functions. Returns ------- lk, (vk): k eigenvalues (and eigenvectors) sorted according to which """ if isinstance(A, qu.Lazy): A = A() if isinstance(B, qu.Lazy): B = B() if isinstance(P, qu.Lazy): P = P() # project into subspace if P is not None: A = qu.dag(P) @ (A @ P) generalized = B is not None eig_fn = _DENSE_EIG_METHODS[(isherm, return_vecs, generalized)] if generalized: eig_opts['b'] = B # these might be given for partial eigsys but not relevant for numpy eig_opts.pop('ncv', None) eig_opts.pop('v0', None) eig_opts.pop('tol', None) eig_opts.pop('maxiter', None) eig_opts.pop('EPSType', None) if return_vecs: # get all eigenpairs lk, vk = eig_fn(A.A if qu.issparse(A) else A, **eig_opts) # sort and trim according to which k we want sk = sort_inds(lk, method=which, sigma=sigma)[:k] lk, vk = lk[sk], vk[:, sk] # also potentially sort into ascending order if sort: so = np.argsort(lk) lk, vk = lk[so], vk[:, so] # map eigenvectors out of subspace if P is not None: vk = P @ vk return lk, qu.qarray(vk) else: # get all eigenvalues lk = eig_fn(A.A if qu.issparse(A) else A, **eig_opts) # sort and trim according to which k we want sk = sort_inds(lk, method=which, sigma=sigma)[:k] lk = lk[sk] # also potentially sort into ascending order return np.sort(lk) if sort else lk