def test_eigsh_caching(): def matvec(mps, A, B, C): return ncon([A, mps, B, C], [[3, 1, -1], [1, 2, 4], [3, 5, -2, 2], [5, 4, -3]], backend='symmetric') backend = symmetric_backend.SymmetricBackend() D = 100 M = 5 mpsinds = [ Index(U1Charge(np.random.randint(5, 15, D, dtype=np.int16)), False), Index(U1Charge(np.array([0, 1, 2, 3], dtype=np.int16)), False), Index(U1Charge(np.random.randint(5, 18, D, dtype=np.int16)), True) ] mpoinds = [ Index(U1Charge(np.random.randint(0, 5, M)), False), Index(U1Charge(np.random.randint(0, 10, M)), True), mpsinds[1], mpsinds[1].flip_flow() ] Linds = [mpoinds[0].flip_flow(), mpsinds[0].flip_flow(), mpsinds[0]] Rinds = [mpoinds[1].flip_flow(), mpsinds[2].flip_flow(), mpsinds[2]] mps = BlockSparseTensor.random(mpsinds) mpo = BlockSparseTensor.random(mpoinds) L = BlockSparseTensor.random(Linds) R = BlockSparseTensor.random(Rinds) ncv = 20 backend.eigsh_lanczos(matvec, [L, mpo, R], initial_state=mps, num_krylov_vecs=ncv) assert get_cacher().cache == {}
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_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 get_contractable_tensors(R1, R2, cont, dtype, num_charges): DsA = np.random.randint(5, 10, R1) DsB = np.random.randint(5, 10, R2) assert R1 >= cont assert R2 >= cont chargesA = [ BaseCharge( np.random.randint(-5, 6, (num_charges, DsA[n])), charge_types=[U1Charge] * num_charges) for n in range(R1 - cont) ] commoncharges = [ BaseCharge( np.random.randint(-5, 6, (num_charges, DsA[n + R1 - cont])), charge_types=[U1Charge] * num_charges) for n in range(cont) ] chargesB = [ BaseCharge( np.random.randint(-5, 6, (num_charges, DsB[n])), charge_types=[U1Charge] * num_charges) for n in range(R2 - cont) ] #contracted indices indsA = np.random.choice(np.arange(R1), cont, replace=False) indsB = np.random.choice(np.arange(R2), cont, replace=False) flowsA = np.full(R1, False, dtype=np.bool) flowsB = np.full(R2, False, dtype=np.bool) flowsB[indsB] = True indicesA = [None for _ in range(R1)] indicesB = [None for _ in range(R2)] for n, iA in enumerate(indsA): indicesA[iA] = Index(commoncharges[n], flowsA[iA]) indicesB[indsB[n]] = Index(commoncharges[n], flowsB[indsB[n]]) compA = list(set(np.arange(R1)) - set(indsA)) compB = list(set(np.arange(R2)) - set(indsB)) for n, cA in enumerate(compA): indicesA[cA] = Index(chargesA[n], flowsA[cA]) for n, cB in enumerate(compB): indicesB[cB] = Index(chargesB[n], flowsB[cB]) indices_final = [] for n in sorted(compA): indices_final.append(indicesA[n]) for n in sorted(compB): indices_final.append(indicesB[n]) A = BlockSparseTensor.random(indices=indicesA, dtype=dtype) B = BlockSparseTensor.random(indices=indicesB, dtype=dtype) return A, B, indsA, indsB
def test_diagonal(Ds, dtype, num_charges, flow): np.random.seed(10) backend = symmetric_backend.SymmetricBackend() np_flow = -np.int((np.int(flow) - 0.5) * 2) indices = [ Index( BaseCharge(np.random.randint(-2, 3, (Ds[n], num_charges)), charge_types=[U1Charge] * num_charges), flow) for n in range(2) ] arr = BlockSparseTensor.random(indices, dtype=dtype) fused = fuse_charges(arr.flat_charges, arr.flat_flows) inds = np.nonzero(fused == np.zeros((1, num_charges), dtype=np.int16))[0] # pylint: disable=no-member left, _ = np.divmod(inds, Ds[1]) unique = np.unique(np_flow * (indices[0]._charges[0].charges[left, :]), axis=0) diagonal = backend.diagonal(arr) sparse_blocks, _, block_shapes = _find_diagonal_sparse_blocks( arr.flat_charges, arr.flat_flows, 1) data = np.concatenate([ np.diag(np.reshape(arr.data[sparse_blocks[n]], block_shapes[:, n])) for n in range(len(sparse_blocks)) ]) np.testing.assert_allclose(data, diagonal.data) np.testing.assert_allclose(unique, diagonal.flat_charges[0].unique_charges) with pytest.raises(NotImplementedError): diagonal = backend.diagonal(arr, axis1=0) with pytest.raises(NotImplementedError): diagonal = backend.diagonal(arr, axis2=1) with pytest.raises(NotImplementedError): diagonal = backend.diagonal(arr, offset=1)
def get_square_matrix(shape, num_charges, dtype=np.float64): charge = BaseCharge( np.random.randint(-5, 5, (shape, num_charges)), charge_types=[U1Charge] * num_charges) flows = [True, False] indices = [Index(charge, flows[n]) for n in range(2)] return BlockSparseTensor.random(indices=indices, dtype=dtype)
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_addition(R, dtype, num_charges): np.random.seed(10) backend = symmetric_backend.SymmetricBackend() a = get_tensor(R, num_charges, dtype) b = BlockSparseTensor.random(a.sparse_shape) res = backend.addition(a, b) np.testing.assert_allclose(res.data, a.data + b.data)
def get_square_matrix(num_charges, dtype=np.float64): D = np.random.randint(40, 60) charges = BaseCharge(np.random.randint(-5, 6, (num_charges, D)), charge_types=[U1Charge] * num_charges) flows = [False, True] indices = [Index(charges, flows[n]) for n in range(2)] return BlockSparseTensor.random(indices=indices, dtype=dtype)
def get_random_symmetric(shape, flows, num_charges, seed=10, dtype=np.float64): assert np.all(np.asarray(shape) == shape[0]) np.random.seed(seed) R = len(shape) charge = BaseCharge(np.random.randint(-5, 5, (shape[0], num_charges)), charge_types=[U1Charge] * num_charges) indices = [Index(charge, flows[n]) for n in range(R)] return BlockSparseTensor.random(indices=indices, dtype=dtype)
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 get_tensor(R, num_charges, dtype=np.float64): Ds = np.random.randint(8, 12, R) charges = [ BaseCharge(np.random.randint(-5, 6, (num_charges, Ds[n])), charge_types=[U1Charge] * num_charges) for n in range(R) ] flows = list(np.full(R, fill_value=False, dtype=np.bool)) indices = [Index(charges[n], flows[n]) for n in range(R)] return BlockSparseTensor.random(indices=indices, dtype=dtype)
def get_hermitian_matrix(num_charges, dtype=np.float64): D = np.random.randint(40, 60) charges = BaseCharge(np.random.randint(-5, 6, (D, num_charges)), charge_types=[U1Charge] * num_charges) flows = [False, True] indices = [Index(charges, flows[n]) for n in range(2)] A = BlockSparseTensor.random(indices=indices, dtype=dtype) return A + A.conj().T
def get_random(shape, num_charges, dtype=np.float64): R = len(shape) charges = [ BaseCharge(np.random.randint(-5, 5, (num_charges, shape[n])), charge_types=[U1Charge] * num_charges) for n in range(R) ] flows = list(np.full(R, fill_value=False, dtype=np.bool)) indices = [Index(charges[n], flows[n]) for n in range(R)] return BlockSparseTensor.random(indices=indices, dtype=dtype)
def test_subbtraction_raises(R, dtype, num_charges): np.random.seed(10) backend = symmetric_backend.SymmetricBackend() a = get_tensor(R, num_charges, dtype) b = get_tensor(R + 1, num_charges, dtype) with pytest.raises(ValueError): backend.subtraction(a, b) shape = b.sparse_shape c = BlockSparseTensor.random([shape[n] for n in reversed(range(len(shape)))]) with pytest.raises(ValueError): backend.subtraction(a, c)
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 test_sparse_shape(dtype, num_charges): np.random.seed(10) Ds = [11, 12, 13] R = len(Ds) charges = [ BaseCharge(np.random.randint(-5, 6, (num_charges, Ds[n])), charge_types=[U1Charge] * num_charges) for n in range(R) ] flows = list(np.full(R, fill_value=False, dtype=np.bool)) indices = [Index(charges[n], flows[n]) for n in range(R)] a = BlockSparseTensor.random(indices=indices, dtype=dtype) backend = symmetric_backend.SymmetricBackend() for s1, s2 in zip(a.sparse_shape, backend.sparse_shape(a)): assert s1 == s2
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)
def test_sparse_shape(num_charges): np.random.seed(10) dtype = np.float64 shape = [10, 11, 12, 13] R = len(shape) charges = [ BaseCharge(np.random.randint(-5, 5, (shape[n], num_charges)), charge_types=[U1Charge] * num_charges) for n in range(R) ] flows = list(np.full(R, fill_value=False, dtype=np.bool)) indices = [Index(charges[n], flows[n]) for n in range(R)] a = BlockSparseTensor.random(indices=indices, dtype=dtype) node = tn.Node(a, backend='symmetric') for s1, s2 in zip(node.sparse_shape, indices): assert s1 == s2
def test_decomps_raise(): np.random.seed(10) dtype = np.float64 backend = symmetric_backend.SymmetricBackend() D = 16 R = 3 indices = [Index(U1Charge.random(D, -5, 5), True) for _ in range(R)] H = BlockSparseTensor.random(indices, dtype=dtype) with pytest.raises( NotImplementedError, match="Can't specify non_negative_diagonal with BlockSparse."): backend.qr(H, non_negative_diagonal=True) with pytest.raises( NotImplementedError, match="Can't specify non_negative_diagonal with BlockSparse."): backend.rq(H, non_negative_diagonal=True)
def test_eigs_cache_exception(): dtype = np.float64 np.random.seed(10) backend = symmetric_backend.SymmetricBackend() D = 16 index = Index(U1Charge.random(D, 0, 0), True) def mv(vec): raise ValueError() init = BlockSparseTensor.random([index], dtype=dtype) with pytest.raises(ValueError): backend.eigs(mv, [], init) cacher = get_cacher() assert not cacher.do_caching assert not get_caching_status() assert cacher.cache == {}