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_item(): t1 = BlockSparseTensor( data=np.array(1.0), charges=[], flows=[], order=[], check_consistency=False) assert t1.item() == 1 Ds = [10, 11, 12, 13] charges = [U1Charge.random(Ds[n], -5, 5) for n in range(4)] flows = [True, False, True, False] inds = [Index(c, flows[n]) for n, c in enumerate(charges)] t2 = BlockSparseTensor.random(inds, dtype=np.float64) with pytest.raises( ValueError, match="can only convert an array of" " size 1 to a Python scalar"): t2.item()
def test_BlockSparseTensor_contiguous_3(): Ds = [10, 11, 12, 13] charges = [U1Charge.random(Ds[n], -5, 5) for n in range(4)] flows = [True, False, True, False] inds = [Index(c, flows[n]) for n, c in enumerate(charges)] a = BlockSparseTensor.random(inds, dtype=np.float64) order_a = [0, 3, 1, 2] a = a.transpose(order_a) adense = a.todense() order_b = [0, 2, 1, 3] b = BlockSparseTensor.random([inds[n] for n in order_b], dtype=np.float64) b = b.transpose([0, 3, 2, 1]) b.contiguous([0, 2, 1, 3], inplace=True) bdense = b.todense() c = a + b cdense = c.todense() np.testing.assert_allclose(a.flows, b.flows) np.testing.assert_allclose(a.flows, b.flows) np.testing.assert_allclose(adense + bdense, cdense)
def test_add_sub_raises(op): np.random.seed(10) Ds1 = [3, 4, 5, 6] Ds2 = [4, 5, 6, 7] indices1 = [ Index(U1Charge.random(dimension=Ds1[n], minval=-5, maxval=5), False) for n in range(4) ] indices2 = [ Index(U1Charge.random(dimension=Ds2[n], minval=-5, maxval=5), False) for n in range(4) ] a = BlockSparseTensor.randn(indices1) b = BlockSparseTensor.randn(indices2) with pytest.raises(TypeError): op(a, np.array([1, 2, 3])) with pytest.raises(ValueError): op(a, b) Ds3 = [3, 3, 3, 3] Ds4 = [9, 9] indices3 = [ Index(U1Charge.random(dimension=Ds3[n], minval=-5, maxval=5), False) for n in range(4) ] indices4 = [ Index(U1Charge.random(dimension=Ds4[n], minval=-5, maxval=5), False) for n in range(2) ] c = BlockSparseTensor.randn(indices3).reshape([9, 9]) d = BlockSparseTensor.randn(indices4) with pytest.raises(ValueError): op(c, d) Ds5 = [200, 200] Ds6 = [200, 200] indices5 = [ Index(U1Charge.random(dimension=Ds5[n], minval=-5, maxval=5), False) for n in range(2) ] indices6 = [ Index(U1Charge.random(dimension=Ds6[n], minval=-5, maxval=5), False) for n in range(2) ] e = BlockSparseTensor.randn(indices5) f = BlockSparseTensor.randn(indices6) with pytest.raises(ValueError): op(e, f)
def test_ChargeArray_arithmetic_raises(): np.random.seed(10) dtype = np.float64 D = 10 rank = 3 charges = [U1Charge.random(D, -2, 2) for _ in range(rank)] flows = np.random.choice([True, False], size=rank, replace=True) inds = [Index(c, f) for c, f in zip(charges, flows)] T = ChargeArray.random(inds, dtype=dtype) with pytest.raises(NotImplementedError): T - T with pytest.raises(NotImplementedError): T + T with pytest.raises(NotImplementedError): -T with pytest.raises(NotImplementedError): T * 5 with pytest.raises(NotImplementedError): 5 * T with pytest.raises(NotImplementedError): T / 5
def test_tn_reshape(dtype): np.random.seed(10) Ds = [8, 9, 10, 11] indices = [Index(U1Charge.random(-5, 5, Ds[n]), False) for n in range(4)] arr = BlockSparseTensor.random(indices, dtype=dtype) arr2 = reshape(arr, [72, 110]) for n in range(2): for m in range(2): assert charge_equal(arr2.charges[n][m], indices[n * 2 + m].charges) np.testing.assert_allclose(arr2.shape, [72, 110]) np.testing.assert_allclose(arr2._order, [[0, 1], [2, 3]]) np.testing.assert_allclose(arr2.flows, [[False, False], [False, False]]) assert arr2.ndim == 2 arr3 = reshape(arr, Ds) for n in range(4): assert charge_equal(arr3.charges[n][0], indices[n].charges) np.testing.assert_allclose(arr3.shape, Ds) np.testing.assert_allclose(arr3._order, [[0], [1], [2], [3]]) np.testing.assert_allclose(arr3.flows, [[False], [False], [False], [False]]) assert arr3.ndim == 4
def test_tn_transpose_reshape(): np.random.seed(10) Ds = np.array([8, 9, 10, 11]) flows = [True, False, True, False] indices = [Index(U1Charge.random(-5, 5, Ds[n]), flows[n]) for n in range(4)] arr = BlockSparseTensor.random(indices) arr2 = transpose(arr, [2, 0, 1, 3]) arr3 = reshape(arr2, [80, 99]) np.testing.assert_allclose(arr3.shape, [80, 99]) np.testing.assert_allclose(arr3._order, [[2, 0], [1, 3]]) np.testing.assert_allclose(arr3.flows, [[True, True], [False, False]]) arr4 = transpose(arr3, [1, 0]) np.testing.assert_allclose(arr4.shape, [99, 80]) np.testing.assert_allclose(arr4._order, [[1, 3], [2, 0]]) np.testing.assert_allclose(arr4.flows, [[False, False], [True, True]]) arr5 = reshape(arr4, [9, 11, 10, 8]) np.testing.assert_allclose(arr5.shape, [9, 11, 10, 8]) np.testing.assert_allclose(arr5._order, [[1], [3], [2], [0]]) np.testing.assert_allclose(arr5.flows, [[False], [False], [True], [True]])
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_ChargeArray_transpose_reshape(): Ds = np.array([8, 9, 10, 11]) flows = [True, False, True, False] indices = [ Index(U1Charge.random(-5, 5, Ds[n]), flows[n]) for n in range(4) ] arr = ChargeArray.random(indices) arr2 = arr.transpose([2, 0, 1, 3]) arr3 = arr2.reshape([80, 99]) np.testing.assert_allclose(arr3.shape, [80, 99]) np.testing.assert_allclose(arr3._order, [[2, 0], [1, 3]]) np.testing.assert_allclose(arr3.flows, [[True, True], [False, False]]) arr4 = arr3.transpose([1, 0]) np.testing.assert_allclose(arr4.shape, [99, 80]) np.testing.assert_allclose(arr4._order, [[1, 3], [2, 0]]) np.testing.assert_allclose(arr4.flows, [[False, False], [True, True]]) arr5 = arr4.reshape([9, 11, 10, 8]) np.testing.assert_allclose(arr5.shape, [9, 11, 10, 8]) np.testing.assert_allclose(arr5._order, [[1], [3], [2], [0]]) np.testing.assert_allclose(arr5.flows, [[False], [False], [True], [True]])
def test_BlockSparseTensor_init(): np.random.seed(10) D = 10 rank = 4 flows = np.random.choice([True, False], size=rank, replace=True) charges = [ U1Charge.random(dimension=D, minval=-5, maxval=5) for _ in range(rank) ] fused = fuse_charges(charges, flows) data = np.random.uniform( 0, 1, size=len(np.nonzero(fused == np.zeros((1, 1)))[0])) order = [[n] for n in range(rank)] arr = BlockSparseTensor(data, charges, flows, order=order) np.testing.assert_allclose(data, arr.data) for c1, c2 in zip(charges, arr.charges): assert charge_equal(c1, c2[0]) for c1, c2 in zip(charges, arr._charges): assert charge_equal(c1, c2) data = np.random.uniform( 0, 1, size=len(np.nonzero(fused == np.zeros((1, 1)))[0]) + 1) with pytest.raises(ValueError): arr = BlockSparseTensor( data, charges, flows, order=order, check_consistency=True)
def test_repr(): np.random.seed(10) dtype = np.float64 D = 10 rank = 3 charges = [U1Charge.random(D, -2, 2) for _ in range(rank)] flows = np.random.choice([True, False], size=rank, replace=True) inds = [Index(c, f) for c, f in zip(charges, flows)] T = ChargeArray.random(inds, dtype=dtype) actual = T.__repr__() expected = "ChargeArray\n shape: (10, 10, 10)\n " +\ " charge types: ['U1Charge']\n dtype: " +\ repr(T.dtype.name) + "\n flat flows: " + \ repr(list(flows)) + "\n order: " + repr(T._order) assert actual == expected res = tensordot(T, T.conj(), ([0, 1, 2], [0, 1, 2])) actual = res.__repr__() expected = "BlockSparseTensor\n shape: ()\n " +\ " charge types: no charge types (scalar)\n dtype: " +\ repr(res.dtype.name) + "\n flat flows: " + \ repr(list(res.flat_flows)) + "\n order: " + repr(res._order) assert actual == expected
def test_ChargeArray_reshape(dtype, Ds): flat_Ds = sum(Ds, []) R = len(flat_Ds) indices = [ Index(U1Charge.random(-5, 5, flat_Ds[n]), False) for n in range(R) ] arr = ChargeArray.random(indices, dtype=dtype) ds = [np.prod(D) for D in Ds] arr2 = arr.reshape(ds) cnt = 0 for n in range(arr2.ndim): for m in range(len(arr2.charges[n])): assert charge_equal(arr2.charges[n][m], indices[cnt].charges) cnt += 1 order = [] flows = [] start = 0 for D in Ds: order.append(list(range(start, start + len(D)))) start += len(D) flows.append([False] * len(D)) np.testing.assert_allclose(arr2.shape, ds) for n in range(len(arr2._order)): np.testing.assert_allclose(arr2._order[n], order[n]) np.testing.assert_allclose(arr2.flows[n], flows[n]) assert arr2.ndim == len(Ds) arr3 = arr.reshape(flat_Ds) for n in range(len(Ds)): assert charge_equal(arr3.charges[n][0], indices[n].charges) np.testing.assert_allclose(arr3.shape, flat_Ds) np.testing.assert_allclose(arr3._order, [[n] for n in range(len(flat_Ds))]) np.testing.assert_allclose(arr3.flows, [[False] for n in range(len(flat_Ds))]) assert arr3.ndim == len(flat_Ds)
def test_eigsh_lanczos_sanity_check_1(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 init = BlockSparseTensor.random([index], dtype=dtype) def mv(x, mat): return mat @ x eta1, U1 = backend.eigsh_lanczos(mv, [H], init) 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_transpose_reshape_transpose_data(): Ds = np.array([8, 9, 10, 11]) flows = [True, False, True, False] indices = [ Index(U1Charge.random(-5, 5, Ds[n]), flows[n]) for n in range(4) ] arr = ChargeArray.random(indices) nparr = np.reshape(arr.data, Ds) arr2 = arr.transpose([2, 0, 1, 3]) nparr2 = nparr.transpose([2, 0, 1, 3]) arr3 = arr2.reshape([80, 99]) nparr3 = nparr2.reshape([80, 99]) arr4 = arr3.transpose([1, 0]) nparr4 = nparr3.transpose([1, 0]) arr5 = arr4.reshape([9, 11, 10, 8]) nparr5 = nparr4.reshape([9, 11, 10, 8]) np.testing.assert_allclose(arr3.transpose_data().data, np.ascontiguousarray(nparr3).flat) np.testing.assert_allclose(arr4.transpose_data().data, np.ascontiguousarray(nparr4).flat) np.testing.assert_allclose(arr5.transpose_data().data, np.ascontiguousarray(nparr5).flat)
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)
# set simulation parameters chi_b = 4 chi = 4 chi_p = 4 chi_m = 12 n_levels = 3 n_iterations = 2000 n_sites = 3 * (2**(n_levels + 1)) left_on = 1 right_on = 1 center_on = 1 initialize_on = 1 # define quantum numbers q_chi_b = U1Charge([-1, 0, 0, 1]) q_chi_p = U1Charge([-1, 0, 0, 1]) q_chi = U1Charge([-1, 0, 0, 1]) # create 2 versions of each index (incoming/outgoing flows) # --- Martin: is there a way of avoiding defining both flows separately? ind_chib0 = Index(charges=q_chi_b, flow=True) ind_chib1 = Index(charges=q_chi_b, flow=False) ind_chip0 = Index(charges=q_chi_p, flow=True) ind_chip1 = Index(charges=q_chi_p, flow=False) ind_chi0 = Index(charges=q_chi, flow=True) ind_chi1 = Index(charges=q_chi, flow=False) ind_1 = Index(charges=U1Charge([0]), flow=False) # ----------------- # define hamiltonian and do 2-to-1 blocking
def test_ChargeArray_todense(dtype): Ds = [8, 9, 10, 11] indices = [Index(U1Charge.random(-5, 5, Ds[n]), False) for n in range(4)] arr = ChargeArray.random(indices, dtype=dtype) np.testing.assert_allclose(arr.todense(), np.reshape(arr.data, Ds))
def test_truediv(dtype): np.random.seed(10) indices = [Index(U1Charge.random(-5, 5, 10), False) for _ in range(4)] a = BlockSparseTensor.randn(indices, dtype=dtype) b = a / 5 np.testing.assert_allclose(b.data, a.data / 5)
# set simulation parameters chi_b = 4 chi = 4 chi_p = 4 chi_m = 16 n_levels = 3 n_iterations = 1000 n_sites = 3 * (2**(n_levels + 1)) left_on = 1 right_on = 1 center_on = 1 initialize_on = 1 # define quantum numbers q_chi_b = U1Charge([-2, 0, 0, 2]) q_chi_p = U1Charge([-2, 0, 0, 2]) q_chi = U1Charge([-2, 0, 0, 2]) # create 2 versions of each index (incoming/outgoing flows) # --- Martin: is there a way of avoiding defining both flows separately? ind_chib0 = Index(charges=q_chi_b, flow=True) ind_chib1 = Index(charges=q_chi_b, flow=False) ind_chip0 = Index(charges=q_chi_p, flow=True) ind_chip1 = Index(charges=q_chi_p, flow=False) ind_chi0 = Index(charges=q_chi, flow=True) ind_chi1 = Index(charges=q_chi, flow=False) ind_1 = Index(charges=U1Charge([0]), flow=False) # ----------------- # define hamiltonian and do 2-to-1 blocking
def test_truediv_raises(): np.random.seed(10) indices = [Index(U1Charge.random(-5, 5, 10), False) for _ in range(4)] a = BlockSparseTensor.randn(indices) with pytest.raises(TypeError): _ = a / np.array([1, 2])
def get_shape_hermitian(backend, shape): if backend == 'symmetric': flows = [True, False] c = U1Charge.random(shape[0], -1, 1) return [Index(c, flow) for flow in flows] return shape
def test_tensordot_raises(): R1 = 3 R2 = 3 R3 = 3 dtype = np.float64 np.random.seed(10) Ds1 = np.arange(2, 2 + R1) Ds2 = np.arange(2 + R1, 2 + R1 + R2) Ds3 = np.arange(2 + R1, 2 + R1 + R3) is1 = [ Index(U1Charge.random(dimension=Ds1[n], minval=-5, maxval=5), False) for n in range(R1) ] is2 = [ Index(U1Charge.random(dimension=Ds2[n], minval=-5, maxval=5), False) for n in range(R2) ] is3 = [ Index(U1Charge.random(dimension=Ds3[n], minval=-5, maxval=5), False) for n in range(R3) ] A = BlockSparseTensor.random(is1, dtype=dtype) B = BlockSparseTensor.random(is2, dtype=dtype) C = BlockSparseTensor.random(is3, dtype=dtype) with pytest.raises(ValueError, match="same length"): tensordot(A, B, ([0, 1, 2, 3], [1, 2])) with pytest.raises(ValueError, match="same length"): tensordot(A, B, ([0, 1], [0, 1, 2, 3])) with pytest.raises(ValueError, match="same length"): tensordot(A, B, ([0], [1, 2])) with pytest.raises(ValueError, match='invalid input'): tensordot(A, B, [0, [1, 2]]) with pytest.raises(ValueError, match="incompatible elementary flows"): tensordot(A, B, ([0, 0], [1, 2])) with pytest.raises(ValueError): tensordot(A, B, ([0, 1], [1, 1])) with pytest.raises(ValueError, match="rank of `tensor1` is smaller than "): tensordot(A, B, ([0, 4], [1, 2])) with pytest.raises(ValueError, match="rank of `tensor2` is smaller than "): tensordot(A, B, ([0, 1], [0, 4])) with pytest.raises(ValueError): tensordot(A, B, ([0, 4], [1, 4])) with pytest.raises(ValueError): tensordot(A, B, ([0, 1], [0, 1])) with pytest.raises(ValueError): tensordot(A, A, ([0, 1], [0, 1])) with pytest.raises(ValueError): tensordot(A, A.conj(), ([0, 1], [1, 0])) with pytest.raises(ValueError, match="is incompatible with `tensor1.shape"): tensordot(A, A.conj(), ([0, 1, 2, 3], [0, 1, 2, 3])) with pytest.raises(ValueError, match="is incompatible with `tensor1.shape"): tensordot(A, C, ([0, 1, 2, 3], [0, 1, 2, 3])) Ds1 = np.array([8, 9, 10, 11]) Ds2 = np.array([8, 9]) flows1 = [False] * len(Ds1) flows2 = [False] * len(Ds2) indices1 = [ Index(U1Charge.random(D, -2, 2), f) for D, f in zip(Ds1, flows1) ] indices2 = [ Index(U1Charge.random(D, -2, 2), f) for D, f in zip(Ds2, flows2) ] arr1 = BlockSparseTensor.random(indices1) arr2 = BlockSparseTensor.random(indices2) with pytest.raises(ValueError, match="axes2 = "): tensordot(arr1, arr2, ([0, 1, 2], [0, 1, 2])) Ds2 = np.array([8, 9, 2, 5, 11]) flows2 = [False] * len(Ds2) indices1 = [ Index(U1Charge.random(D, -2, 2), f) for D, f in zip(Ds1, flows1) ] indices2 = [ Index(U1Charge.random(D, -2, 2), f) for D, f in zip(Ds2, flows2) ] arr1 = BlockSparseTensor.random(indices1) arr2 = BlockSparseTensor.random(indices2).reshape(Ds1) with pytest.raises(ValueError, match="incompatible elementary shapes "): tensordot(arr1, arr2.conj(), ([2, 3], [2, 3]))
def test_tn_conj(dtype): np.random.seed(10) indices = [Index(U1Charge.random(-5, 5, 10), False) for _ in range(4)] a = BlockSparseTensor.randn(indices, dtype=dtype) b = conj(a) np.testing.assert_allclose(b.data, np.conj(a.data))
# tensornetwork and block_sparse modules from binaryMERA import binaryMERA from eigh import eigh tn.set_default_backend('symmetric') # set simulation parameters chib = 4 chim = 4 chi = 4 n_levels = 3 n_iterations = 200 n_sites = 3 * (2**(n_levels + 1)) # define quantum numbers q_chib = U1Charge([-2, 0, 0, 2]) q_chim = U1Charge([-2, 0, 0, 2]) q_chi = U1Charge([-2, 0, 0, 2]) # q_chib = Z2Charge([0, 1, 1, 0]) # q_chim = Z2Charge([0] * (chim // 2) + [1] * (chim // 2)) # q_chi = Z2Charge([0] * (chi // 2) + [1] * (chi // 2)) # create 2 versions of each index (incoming/outgoing flows) # --- Martin: is there a way of avoiding defining both flows separately? ind_chib0 = Index(charges=q_chib, flow=True) ind_chib1 = Index(charges=q_chib, flow=False) ind_chim0 = Index(charges=q_chim, flow=True) ind_chim1 = Index(charges=q_chim, flow=False) ind_chi0 = Index(charges=q_chi, flow=True) ind_chi1 = Index(charges=q_chi, flow=False) # -----------------
initialize_on = 0 prelim_sweeps = 20 link_sweep_gap = 4 # set simulation parameters chi = 12 n_levels = 3 n_iterations = 100 n_sites = 3 * (2**(n_levels + 1)) # ------------------------------------------------------------ # initialization # define quantum numbers q_chi_b = U1Charge([-2, 0, 0, 2]) ind_chib0 = Index(charges=q_chi_b, flow=True) ind_chib1 = Index(charges=q_chi_b, flow=False) # define hamiltonian and do 2-to-1 blocking chi_b = 4 sX = np.array([[0, 1], [1, 0]]) sY = np.array([[0, -1j], [1j, 0]]) sZ = np.array([[1, 0], [0, -1]]) ham_s = np.real(np.kron(sX, sX) + np.kron(sY, sY)) ham_temp = (0.5 * np.kron(np.eye(8), np.kron(ham_s, np.eye(2))) + np.kron(np.eye(4), np.kron(ham_s, np.eye(4))) + 0.5 * np.kron(np.eye(2), np.kron(ham_s, np.eye(8)))) bias_shift = max(LA.eigvalsh(ham_temp)) - min(LA.eigvalsh(ham_temp)) ham_init = BT.fromdense([ind_chib1] * 3 + [ind_chib0] * 3, ham_temp.reshape([chi_b] * 6))
def test_BaseCharge_intersect_3(): c1 = U1Charge(np.array([1, 0, -1]), charge_labels=np.array([2, 0, 1])) c2 = np.array([-1, 0, 1], dtype=np.int16) res = c1.intersect(c2) np.testing.assert_allclose(res.charges, [[-1], [0], [1]])
def get_shape(backend, shape): if backend == 'symmetric': return [Index(U1Charge.random(s,-1,1), False) for s in shape] return shape