def test_eigsh_valid_init_operator_with_shape(dtype): np.random.seed(100) backend = symmetric_backend.SymmetricBackend() np_backend = numpy_backend.NumPyBackend() D = 16 index = Index(U1Charge.random(D, -1, 1), True) indices = [index, index.copy().flip_flow()] a = BlockSparseTensor.random(indices, dtype=dtype) H = a + a.T.conj() def mv(vec, mat): return mat @ vec init = BlockSparseTensor.random([index], dtype=dtype) # note: this will only find eigenvalues in the charge (0,0) # block of H because `init` only has non-zero values there. # To find eigen values in other sectors we need to support non-zero # divergence for block-sparse tensors eta1, U1 = backend.eigsh_lanczos(mv, [H], init) eta2, U2 = np_backend.eigsh_lanczos(mv, [H.todense()], init.todense()) v1 = np.reshape(U1[0].todense(), (D)) v1 = v1 / sum(v1) v1 /= np.linalg.norm(v1) v2 = np.reshape(U2[0], (D)) v2 = v2 / sum(v2) v2[np.abs(v2) < 1E-12] = 0.0 v2 /= np.linalg.norm(v2) np.testing.assert_allclose(eta1[0], min(eta2)) np.testing.assert_allclose(v1, v2)
def test_eigsh_lanczos_sanity_check_2(dtype): np.random.seed(10) D = 16 backend = symmetric_backend.SymmetricBackend() index = Index(U1Charge.random(D, 0, 0), True) indices = [index, index.copy().flip_flow()] H = BlockSparseTensor.random(indices, dtype=dtype) H = H + H.conj().T def mv(x, mat): return mat @ x eta1, U1 = backend.eigsh_lanczos(mv, [H], shape=(H.sparse_shape[1].flip_flow(), ), dtype=dtype) eta2, U2 = np.linalg.eigh(H.todense()) v1 = np.reshape(U1[0].todense(), (D)) v1 = v1 / sum(v1) v2 = U2[:, 0] v2 = v2 / sum(v2) np.testing.assert_allclose(eta1[0], min(eta2)) np.testing.assert_allclose(v1, v2)
def test_eigsh_lanczos_reorthogonalize_sanity_check(dtype, numeig): np.random.seed(10) D = 24 backend = symmetric_backend.SymmetricBackend() index = Index(U1Charge.random(D, 0, 0), True) indices = [index, index.copy().flip_flow()] H = BlockSparseTensor.random(indices, dtype=dtype) H = H + H.conj().T def mv(x, mat): return mat @ x eta1, U1 = backend.eigsh_lanczos(mv, [H], shape=(H.sparse_shape[1].flip_flow(), ), dtype=dtype, numeig=numeig, num_krylov_vecs=D, reorthogonalize=True, ndiag=1, tol=10**(-12), delta=10**(-12)) eta2, U2 = np.linalg.eigh(H.todense()) np.testing.assert_allclose(eta1[0:numeig], eta2[0:numeig]) for n in range(numeig): v2 = U2[:, n] v2 /= np.sum(v2) #fix phases v1 = np.reshape(U1[n].todense(), (D)) v1 /= np.sum(v1) np.testing.assert_allclose(v1, v2, rtol=10**(-5), atol=10**(-5))
def test_eigs_raises(): np.random.seed(10) dtype = np.float64 backend = symmetric_backend.SymmetricBackend() D = 16 index = Index(U1Charge.random(D, 0, 0), True) indices = [index, index.copy().flip_flow()] H = BlockSparseTensor.random(indices, dtype=dtype) init = BlockSparseTensor.random([index], dtype=dtype) with pytest.raises(ValueError, match='which = SI is currently not supported.'): backend.eigs(lambda x: x, [H], initial_state=init, which='SI') with pytest.raises(ValueError, match='which = LI is currently not supported.'): backend.eigs(lambda x: x, [H], initial_state=init, which='LI') with pytest.raises( ValueError, match="if no `initial_state` is passed, then `shape` and" "`dtype` have to be provided"): backend.eigs(lambda x: x, [H]) with pytest.raises(ValueError, match="`num_krylov_vecs`"): backend.eigs(lambda x: x, [H], numeig=3, num_krylov_vecs=3) with pytest.raises(TypeError, match="Expected a"): backend.eigs(lambda x: x, [H], initial_state=[])
def test_index_copy(): D = 10 B = 4 dtype = np.int16 np.random.seed(10) q1 = U1Charge(np.random.randint(-B // 2, B // 2 + 1, D).astype(dtype)) q2 = U1Charge(np.random.randint(-B // 2, B // 2 + 1, D).astype(dtype)) i = Index(charges=[q1, q2], flow=[False, True]) icopy = i.copy() assert not np.any([a is b for a, b in zip(i._charges, icopy._charges)]) assert i.flow is not icopy.flow
def test_eigsh_small_number_krylov_vectors_sanity_check(): np.random.seed(10) dtype = np.float64 backend = symmetric_backend.SymmetricBackend() index = Index(U1Charge.random(2, 0, 0), True) indices = [index, index.copy().flip_flow()] H = BlockSparseTensor.random(indices, dtype=dtype) H.data = np.array([1, 2, 3, 4], dtype=np.float64) init = BlockSparseTensor.random([index], dtype=dtype) init.data = np.array([1, 1], dtype=np.float64) def mv(x, mat): return mat @ x eta, _ = backend.eigsh_lanczos(mv, [H], init, num_krylov_vecs=1) np.testing.assert_allclose(eta[0], 5)
def test_eigs_valid_init_operator_with_shape_sanity_check(dtype): np.random.seed(10) backend = symmetric_backend.SymmetricBackend() D = 16 index = Index(U1Charge.random(D, 0, 0), True) indices = [index, index.copy().flip_flow()] H = BlockSparseTensor.random(indices, dtype=dtype) def mv(vec, mat): return mat @ vec init = BlockSparseTensor.random([index], dtype=dtype) eta1, U1 = backend.eigs(mv, [H], init) eta2, U2 = np.linalg.eig(H.todense()) compare_eigvals_and_eigvecs(np.stack([u.todense() for u in U1], axis=1), eta1, U2, eta2, thresh=1E-8)
def eye(column_index: Index, row_index: Optional[Index] = None, dtype: Optional[Type[np.number]] = None) -> BlockSparseTensor: """ Return an identity matrix. Args: column_index: The column index of the matrix. row_index: The row index of the matrix. dtype: The dtype of the matrix. Returns: BlockSparseTensor """ if row_index is None: row_index = column_index.copy().flip_flow() if dtype is None: dtype = np.float64 blocks, _, shapes = _find_diagonal_sparse_blocks( column_index.flat_charges + row_index.flat_charges, column_index.flat_flows + row_index.flat_flows, len(column_index.flat_charges)) data = np.empty(np.int64(np.sum(np.prod(shapes, axis=0))), dtype=dtype) for n, block in enumerate(blocks): data[block] = np.ravel(np.eye(shapes[0, n], shapes[1, n], dtype=dtype)) order = [list(np.arange(0, len(column_index.flat_charges)))] + [ list( np.arange( len(column_index.flat_charges), len(column_index.flat_charges) + len(row_index.flat_charges))) ] return BlockSparseTensor( data=data, charges=column_index.flat_charges + row_index.flat_charges, flows=column_index.flat_flows + row_index.flat_flows, order=order, check_consistency=False)
def test_eigsh_valid_init_operator_with_shape_sanity_check(dtype): np.random.seed(10) backend = symmetric_backend.SymmetricBackend() D = 16 index = Index(U1Charge.random(D, 0, 0), True) indices = [index, index.copy().flip_flow()] a = BlockSparseTensor.random(indices, dtype=dtype) H = a + a.T.conj() def mv(vec, mat): return mat @ vec init = BlockSparseTensor.random([index], dtype=dtype) eta1, U1 = backend.eigsh_lanczos(mv, [H], init) v1 = np.reshape(U1[0].todense(), (D)) v1 = v1 / sum(v1) eta2, U2 = np.linalg.eigh(H.todense()) v2 = U2[:, 0] v2 = v2 / sum(v2) np.testing.assert_allclose(eta1[0], min(eta2)) np.testing.assert_allclose(v1, v2)