def test_tn_conj(dtype): np.random.seed(10) indices = [ Index(U1Charge.random(dimension=10, minval=-5, maxval=5), False) for _ in range(4) ] a = BlockSparseTensor.randn(indices, dtype=dtype) b = conj(a) np.testing.assert_allclose(b.data, np.conj(a.data))
def test_flat_flows(): 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 = [0, 3, 1, 2] a = a.transpose(order) np.testing.assert_allclose(a.flat_flows, [a._flows[o] for o in a.flat_order])
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_matmul(dtype, num_charges, chargetype): np.random.seed(10) Ds1 = [100, 200] is1 = [ Index(get_charge(chargetype, num_charges, Ds1[n]), False) for n in range(2) ] is2 = [ is1[1].copy().flip_flow(), Index(get_charge(chargetype, num_charges, 150), False) ] tensor1 = BlockSparseTensor.random(is1, dtype=dtype) tensor2 = BlockSparseTensor.random(is2, dtype=dtype) result = tensor1 @ tensor2 assert result.dtype == dtype dense_result = tensor1.todense() @ tensor2.todense() #pytype: disable=unsupported-operands np.testing.assert_allclose(dense_result, result.todense())
def eigh(matrix: BlockSparseTensor, UPLO: Optional[Text] = 'L') -> Tuple[ChargeArray, BlockSparseTensor]: """ Compute the eigen decomposition of a hermitian `M` by `M` matrix `matrix`. Args: matrix: A matrix (i.e. a rank-2 tensor) of type `BlockSparseTensor` Returns: (ChargeArray,BlockSparseTensor): The eigenvalues and eigenvectors """ if matrix.ndim != 2: raise NotImplementedError("eigh currently supports only rank-2 tensors.") flat_charges = matrix._charges flat_flows = matrix._flows flat_order = matrix.flat_order tr_partition = len(matrix._order[0]) blocks, charges, shapes = _find_transposed_diagonal_sparse_blocks( flat_charges, flat_flows, tr_partition, flat_order) eigvals = [] v_blocks = [] for n, block in enumerate(blocks): e, v = np.linalg.eigh(np.reshape(matrix.data[block], shapes[:, n]), UPLO) eigvals.append(e) v_blocks.append(v) tmp_labels = [ np.full(len(eigvals[n]), fill_value=n, dtype=np.int16) for n in range(len(eigvals)) ] if len(tmp_labels) > 0: eigvalscharge_labels = np.concatenate(tmp_labels) else: eigvalscharge_labels = np.empty(0, dtype=np.int16) eigvalscharge = charges[eigvalscharge_labels] if len(eigvals) > 0: all_eigvals = np.concatenate(eigvals) else: all_eigvals = np.empty(0, dtype=get_real_dtype(matrix.dtype)) E = ChargeArray(all_eigvals, [eigvalscharge], [False]) charges_v = [eigvalscharge] + [matrix._charges[o] for o in matrix._order[0]] order_v = [[0]] + [list(np.arange(1, len(matrix._order[0]) + 1))] flows_v = [True] + [matrix._flows[o] for o in matrix._order[0]] if len(v_blocks) > 0: all_v_blocks = np.concatenate([np.ravel(v.T) for v in v_blocks]) else: all_v_blocks = np.empty(0, dtype=matrix.dtype) V = BlockSparseTensor( all_v_blocks, charges=charges_v, flows=flows_v, order=order_v, check_consistency=False).transpose() return E, V #pytype: disable=bad-return-type
def test_truediv_raises(): np.random.seed(10) indices = [ Index(U1Charge.random(dimension=10, minval=-5, maxval=5), False) for _ in range(4) ] a = BlockSparseTensor.randn(indices) with pytest.raises(TypeError): _ = a / np.array([1, 2])
def test_herm(chargetype, dtype): np.random.seed(10) D = 10 rank = 2 charges = [get_charge(chargetype, 1, D) 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 = BlockSparseTensor.random(inds, dtype=dtype) TH = T.H np.testing.assert_allclose(TH.todense(), T.todense().T.conj())
def test_flat_charges(): 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 = [0, 3, 1, 2] a = a.transpose(order) for n, o in enumerate(a.flat_order): charge_equal(a.flat_charges[n], a._charges[o])
def convert_to_tensor(self, tensor: Tensor) -> Tensor: if numpy.isscalar(tensor): tensor = BlockSparseTensor( data=tensor, charges=[], flows=[], order=[], check_consistency=False) if not isinstance(tensor, BlockSparseTensor): raise TypeError( "cannot convert tensor of type `{}` to `BlockSparseTensor`".format( type(tensor))) return tensor
def test_sign(): np.random.seed(10) Ds = np.array([8, 9, 10, 11]) flows = [True, False, True, False] indices = [ Index(U1Charge.random(dimension=Ds[n], minval=-5, maxval=5), flows[n]) for n in range(4) ] arr = BlockSparseTensor.random(indices) np.testing.assert_allclose(sign(arr).data, np.sign(arr.data))
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_size(chargetype, num_charges): np.random.seed(10) Ds = np.array([8, 9, 10, 11]) flows = [True, False, True, False] indices = [ Index(get_charge(chargetype, num_charges, Ds[n]), flows[n]) for n in range(4) ] arr = BlockSparseTensor.random(indices) assert arr.size == np.prod(Ds)
def test_neg(chargetype, dtype): np.random.seed(10) D = 10 rank = 2 charges = [get_charge(chargetype, 1, D) 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 = BlockSparseTensor.random(inds, dtype=dtype) T2 = -T np.testing.assert_allclose(T.data, -T2.data)
def test_matmul(dtype, num_charges, chargetype, rank1, rank2): np.random.seed(10) Ds1 = [20] * rank1 Ds2 = [20] * (rank2 - 1) is1 = [ Index(get_charge(chargetype, num_charges, Ds1[n]), False) for n in range(rank1) ] is2 = [is1[-1].copy().flip_flow()] + [ Index(get_charge(chargetype, num_charges, Ds2[n]), False) for n in range(rank2 - 1) ] tensor1 = BlockSparseTensor.random(is1, dtype=dtype) tensor2 = BlockSparseTensor.random(is2, dtype=dtype) result = tensor1 @ tensor2 assert result.dtype == dtype #pylint:disable=line-too-long dense_result = tensor1.todense() @ tensor2.todense() #pytype: disable=unsupported-operands np.testing.assert_allclose(dense_result, result.todense())
def test_fromdense_raises(): np.random.seed(10) Ds = [8, 9, 10, 11] rank = len(Ds) flows = np.random.choice([True, False], size=rank, replace=True) charges = [U1Charge.random(Ds[n], -5, 5) for n in range(rank)] indices = [Index(charges[n], flows[n]) for n in range(rank)] dense = np.random.random_sample([8, 9, 9, 11]) with pytest.raises(ValueError): _ = BlockSparseTensor.fromdense(indices, dense)
def test_tn_transpose(): 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) order = [2, 1, 0, 3] arr2 = transpose(arr, order) np.testing.assert_allclose(Ds[order], arr2.shape) np.testing.assert_allclose(arr2._order, [[2], [1], [0], [3]]) np.testing.assert_allclose(arr2.flows, [[True], [False], [True], [False]])
def test_norm(dtype): np.random.seed(10) Ds = np.asarray([8, 9, 10, 11]) rank = Ds.shape[0] flows = np.random.choice([True, False], size=rank, replace=True) indices = [ Index(U1Charge.random(-5, 5, Ds[n]), flows[n]) for n in range(4) ] arr = BlockSparseTensor.random(indices, dtype=dtype) dense_norm = np.linalg.norm(arr.todense()) np.testing.assert_allclose(norm(arr), dense_norm)
def test_pinv_raises(): num_charges = 1 np.random.seed(10) R = 3 D = 10 charge = BaseCharge( np.random.randint(-5, 6, (num_charges, D), dtype=np.int16), charge_types=[U1Charge] * num_charges) A = BlockSparseTensor.random([Index(charge, False) for n in range(R)], (-0.5, 0.5)) with pytest.raises(ValueError): pinv(A)
def test_BlockSparseTensor_contiguous_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)] b = BlockSparseTensor.random(inds, dtype=np.float64) order = [0, 3, 2, 1] b = b.transpose(order) b_ = b.contiguous(inplace=False) np.testing.assert_allclose(b.flows, b_.flows) for n in range(4): assert charge_equal(b._charges[order[n]], b_._charges[n])
def test_trace_matrix(dtype, num_charges, D): np.random.seed(10) R = 2 charge = BaseCharge( np.random.randint(-5, 6, (num_charges, D), dtype=np.int16), charge_types=[U1Charge] * num_charges) flows = [True, False] matrix = BlockSparseTensor.random([Index(charge, flows[n]) for n in range(R)], dtype=dtype) res = trace(matrix) res_dense = np.trace(matrix.todense()) np.testing.assert_allclose(res.data, res_dense)
def zeros(indices: Sequence[Index], dtype: Optional[Type[np.number]] = None) -> BlockSparseTensor: """ Initialize a symmetric tensor with zeros. Args: indices: List of `Index` objecst, one for each leg. dtype: An optional numpy dtype. The dtype of the tensor Returns: BlockSparseTensor """ return BlockSparseTensor.zeros(indices, dtype)
def randn(indices: Sequence[Index], dtype: Optional[Type[np.number]] = None) -> BlockSparseTensor: """ Initialize a random symmetric tensor from random normal distribution. Args: indices: List of `Index` objecst, one for each leg. dtype: An optional numpy dtype. The dtype of the tensor Returns: BlockSparseTensor """ return BlockSparseTensor.randn(indices, dtype)
def test_add_sub_raises(op): np.random.seed(10) Ds1 = [3, 4, 5, 6] Ds2 = [4, 5, 6, 7] indices1 = [Index(U1Charge.random(-5, 5, Ds1[n]), False) for n in range(4)] indices2 = [Index(U1Charge.random(-5, 5, Ds2[n]), 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(-5, 5, Ds3[n]), False) for n in range(4)] indices4 = [Index(U1Charge.random(-5, 5, Ds4[n]), 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(-5, 5, Ds5[n]), False) for n in range(2)] indices6 = [Index(U1Charge.random(-5, 5, Ds6[n]), False) for n in range(2)] e = BlockSparseTensor.randn(indices5) f = BlockSparseTensor.randn(indices6) with pytest.raises(ValueError): op(e, f)
def test_tensordot_raises(): R1 = 3 R2 = 3 dtype = np.float64 np.random.seed(10) Ds1 = np.arange(2, 2 + R1) Ds2 = np.arange(2 + R1, 2 + R1 + R2) 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) ] A = BlockSparseTensor.random(is1, dtype=dtype) B = BlockSparseTensor.random(is2, dtype=dtype) with pytest.raises(ValueError): tensordot(A, B, ([0, 1, 2, 3], [1, 2])) with pytest.raises(ValueError): tensordot(A, B, ([0, 1], [0, 1, 2, 3])) with pytest.raises(ValueError): tensordot(A, B, ([0], [1, 2])) with pytest.raises(ValueError): tensordot(A, B, [0, [1, 2]]) with pytest.raises(ValueError): tensordot(A, B, ([0, 0], [1, 2])) with pytest.raises(ValueError): tensordot(A, B, ([0, 1], [1, 1])) with pytest.raises(ValueError): tensordot(A, B, ([0, 4], [1, 2])) 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]))
def test_get_empty_diag(dtype, num_charges, Ds): np.random.seed(10) indices = [ Index( BaseCharge(np.random.randint(-2, 3, (num_charges, Ds[n])), charge_types=[U1Charge] * num_charges), False) for n in range(2) ] arr = BlockSparseTensor.random(indices, dtype=dtype) diagonal = diag(arr) np.testing.assert_allclose([], diagonal.data) for c in diagonal.flat_charges: assert len(c) == 0
def test_qr_decomposition(dtype, R, R1): np.random.seed(10) D = 30 charges = [U1Charge.random(-5, 5, D) for n in range(R)] flows = [True] * R A = BlockSparseTensor.random( [Index(charges[n], flows[n]) for n in range(R)], dtype=dtype) q, r = decompositions.qr_decomposition(bs, A, R1) res = bs.tensordot(q, r, 1) q_dense, r_dense = np_decompositions.qr_decomposition(np, A.todense(), R1) res2 = np.tensordot(q_dense, r_dense, 1) np.testing.assert_almost_equal(res.todense(), res2)
def test_tensordot_single_arg(): R = 3 dtype = np.float64 np.random.seed(10) Ds = [10, 10, 10] inds = [ Index(U1Charge.random(dimension=Ds[n], minval=-5, maxval=5), False) for n in range(R) ] A = BlockSparseTensor.random(inds, dtype=dtype) res = tensordot(A, A.conj(), ([0])) dense_res = np.tensordot(A.todense(), A.conj().todense(), ([0], [0])) np.testing.assert_allclose(dense_res, res.todense())
def test_BlockSparseTensor_transpose_data(): np.random.seed(10) Ds = np.array([8, 9, 10, 11]) order = [2, 0, 1, 3] flows = [True, False, True, False] indices = [ Index(U1Charge.random(-5, 5, Ds[n]), flows[n]) for n in range(4) ] arr = BlockSparseTensor.random(indices) data1 = np.ascontiguousarray(np.transpose(arr.todense(), order)) data2 = arr.transpose(order).transpose_data().todense() np.testing.assert_allclose(data1.strides, data2.strides) np.testing.assert_allclose(data1, data2)
def test_rmul(dtype, num_charges, chargetype): np.random.seed(10) indices = [ Index(get_charge(chargetype, num_charges, 20), False) for _ in range(4) ] indices = [ Index(U1Charge.random(dimension=10, minval=-5, maxval=5), False) for _ in range(4) ] a = BlockSparseTensor.randn(indices, dtype=dtype) b = a * 5 np.testing.assert_allclose(b.data, a.data * 5)
def random(indices: Sequence[Index], boundaries: Optional[Tuple[float, float]] = (0.0, 1.0), dtype: Optional[Type[np.number]] = None) -> BlockSparseTensor: """ Initialize a random symmetric tensor from random uniform distribution. Args: indices: List of `Index` objecst, one for each leg. boundaries: Tuple of interval boundaries for the random uniform distribution. dtype: An optional numpy dtype. The dtype of the tensor Returns: BlockSparseTensor """ return BlockSparseTensor.random(indices, boundaries, dtype)