コード例 #1
0
def test_split_node_qr_unitarity(dtype, num_charges):
    np.random.seed(10)
    a = tn.Node(get_square_matrix(50, num_charges, dtype=dtype),
                backend='symmetric')
    q, r = tn.split_node_qr(a, [a[0]], [a[1]])
    r[0] | q[1]
    qbar = tn.linalg.node_linalg.conj(q)
    q[1] ^ qbar[1]
    u1 = q @ qbar
    qbar[0] ^ q[0]
    u2 = qbar @ q
    blocks, _, shapes = _find_diagonal_sparse_blocks(u1.tensor.flat_charges,
                                                     u1.tensor.flat_flows,
                                                     len(u1.tensor._order[0]))
    for n, block in enumerate(blocks):
        np.testing.assert_almost_equal(
            np.reshape(u1.tensor.data[block], shapes[:, n]),
            np.eye(N=shapes[0, n], M=shapes[1, n]))

    blocks, _, shapes = _find_diagonal_sparse_blocks(u2.tensor.flat_charges,
                                                     u2.tensor.flat_flows,
                                                     len(u2.tensor._order[0]))
    for n, block in enumerate(blocks):
        np.testing.assert_almost_equal(
            np.reshape(u2.tensor.data[block], shapes[:, n]),
            np.eye(N=shapes[0, n], M=shapes[1, n]))
コード例 #2
0
def test_pinv(dtype, num_charges):
    np.random.seed(10)
    R = 2
    D = 10
    charge = BaseCharge(np.random.randint(-5,
                                          6, (D, num_charges),
                                          dtype=np.int16),
                        charge_types=[U1Charge] * num_charges)
    flows = [True, False]
    A = BlockSparseTensor.random([Index(charge, flows[n]) for n in range(R)],
                                 (-0.5, 0.5),
                                 dtype=dtype)
    invA = pinv(A)
    left_eye = invA @ A

    blocks, _, shapes = _find_diagonal_sparse_blocks(left_eye.flat_charges,
                                                     left_eye.flat_flows, 1)
    for n, block in enumerate(blocks):
        t = np.reshape(left_eye.data[block], shapes[:, n])
        assert np.linalg.norm(t - np.eye(t.shape[0], t.shape[1])) < 1E-12

    right_eye = A @ invA
    blocks, _, shapes = _find_diagonal_sparse_blocks(right_eye.flat_charges,
                                                     right_eye.flat_flows, 1)
    for n, block in enumerate(blocks):
        t = np.reshape(right_eye.data[block], shapes[:, n])
        assert np.linalg.norm(t - np.eye(t.shape[0], t.shape[1])) < 1E-12
コード例 #3
0
def test_get_diag(dtype, num_charges, Ds, flow):
    np.random.seed(10)
    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 = diag(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)
コード例 #4
0
    def contiguous(self,
                   permutation: Optional[Union[Tuple, List,
                                               np.ndarray]] = None,
                   inplace: Optional[bool] = False) -> Any:
        """
    Transpose the tensor data in place such that the linear order 
    of the elements in `BlockSparseTensor.data` corresponds to the 
    current order of tensor indices. 
    Consider a tensor with current order given by `_order=[[1,2],[3],[0]]`,
    i.e. `data` was initialized according to order [0,1,2,3], and the tensor
    has since been reshaped and transposed. The linear oder of `data` does not
    match the desired order [1,2,3,0] of the tensor. `contiguous` fixes this
    by permuting `data` into this order, transposing `_charges` and `_flows`,
    and changing `_order` to `[[0,1],[2],[3]]`.
    Args:
      permutation: An optional alternative order to be used to transposed the 
        tensor. If `None` defaults to `BlockSparseTensor.permutation`.
    """
        flat_charges = self._charges
        flat_flows = self._flows
        if permutation is None:
            permutation = self.flat_order

        if np.array_equal(permutation, np.arange(len(permutation))):
            return self
        tr_partition = _find_best_partition(
            [flat_charges[n].dim for n in permutation])

        tr_sparse_blocks, tr_charges, _ = _find_transposed_diagonal_sparse_blocks(
            flat_charges, flat_flows, tr_partition, permutation)

        sparse_blocks, charges, _ = _find_diagonal_sparse_blocks(
            [flat_charges[n] for n in permutation],
            [flat_flows[n] for n in permutation], tr_partition)
        data = np.empty(len(self.data), dtype=self.dtype)
        for n, sparse_block in enumerate(sparse_blocks):
            ind = np.nonzero(tr_charges == charges[n])[0][0]
            perm = tr_sparse_blocks[ind]
            data[sparse_block] = self.data[perm]

        _, inds = np.unique(permutation, return_index=True)
        new_flat_order = inds[self.flat_order]
        tmp = np.append(0, np.cumsum([len(o) for o in self._order]))
        order = [
            list(new_flat_order[tmp[n]:tmp[n + 1]])
            for n in range(len(tmp) - 1)
        ]
        charges = [self._charges[o] for o in permutation]
        flows = [self._flows[o] for o in permutation]
        if not inplace:
            return BlockSparseTensor(data,
                                     charges=charges,
                                     flows=flows,
                                     order=order,
                                     check_consistency=False)
        self.data = data
        self._order = order
        self._charges = charges
        self._flows = flows
        return self
コード例 #5
0
def test_find_diagonal_sparse_blocks(num_legs, num_charges):
  np.random.seed(10)
  np_charges = [
      np.random.randint(-5, 5, (60, num_charges), dtype=np.int16)
      for _ in range(num_legs)
  ]
  fused = np.stack([
      fuse_ndarrays([np_charges[n][:, c]
                     for n in range(num_legs)])
      for c in range(num_charges)
  ],
                   axis=1)

  left_charges = np.stack([
      fuse_ndarrays([np_charges[n][:, c]
                     for n in range(num_legs // 2)])
      for c in range(num_charges)
  ],
                          axis=1)
  right_charges = np.stack([
      fuse_ndarrays(
          [np_charges[n][:, c]
           for n in range(num_legs // 2, num_legs)])
      for c in range(num_charges)
  ],
                           axis=1)
  #pylint: disable=no-member
  nz = np.nonzero(
      np.logical_and.reduce(fused == np.zeros((1, num_charges)), axis=1))[0]
  linear_locs = np.arange(len(nz))
  # pylint: disable=no-member
  left_inds, _ = np.divmod(nz, right_charges.shape[0])
  left = left_charges[left_inds, :]
  unique_left = np.unique(left, axis=0)
  blocks = []
  for n in range(unique_left.shape[0]):
    ul = unique_left[n, :][None, :]
    #pylint: disable=no-member
    blocks.append(linear_locs[np.nonzero(
        np.logical_and.reduce(left == ul, axis=1))[0]])

  charges = [
      BaseCharge(left_charges, charge_types=[U1Charge] * num_charges),
      BaseCharge(right_charges, charge_types=[U1Charge] * num_charges)
  ]
  bs, cs, ss = _find_diagonal_sparse_blocks(charges, [False, False], 1)
  np.testing.assert_allclose(cs.charges, unique_left)
  for b1, b2 in zip(blocks, bs):
    assert np.all(b1 == b2)

  assert np.sum(np.prod(ss, axis=0)) == np.sum([len(b) for b in bs])
  np.testing.assert_allclose(unique_left, cs.charges)
コード例 #6
0
def test_eye(dtype, num_charges, D):
    charge = BaseCharge(np.random.randint(-5,
                                          6, (D, num_charges),
                                          dtype=np.int16),
                        charge_types=[U1Charge] * num_charges)
    flow = False
    index = Index(charge, flow)
    A = eye(index, dtype=dtype)
    blocks, _, shapes = _find_diagonal_sparse_blocks(A.flat_charges,
                                                     A.flat_flows, 1)
    for n, block in enumerate(blocks):
        t = np.reshape(A.data[block], shapes[:, n])
        np.testing.assert_almost_equal(t, np.eye(t.shape[0], t.shape[1]))
コード例 #7
0
def test_create_diag(dtype, num_charges, flow):
    np.random.seed(10)
    D = 200
    index = Index(
        BaseCharge(np.random.randint(-2, 3, (D, num_charges)),
                   charge_types=[U1Charge] * num_charges), flow)

    arr = ChargeArray.random([index], dtype=dtype)
    diagarr = diag(arr)
    dense = np.ravel(diagarr.todense())
    np.testing.assert_allclose(np.sort(dense[dense != 0.0]),
                               np.sort(diagarr.data[diagarr.data != 0.0]))

    sparse_blocks, charges, block_shapes = _find_diagonal_sparse_blocks(
        diagarr.flat_charges, diagarr.flat_flows, 1)

    for n, block in enumerate(sparse_blocks):
        shape = block_shapes[:, n]
        block_diag = np.diag(np.reshape(diagarr.data[block], shape))
        np.testing.assert_allclose(
            arr.data[np.squeeze((index._charges[0] * flow) == charges[n])],
            block_diag)
コード例 #8
0
def outerproduct(tensor1: BlockSparseTensor,
                 tensor2: BlockSparseTensor) -> BlockSparseTensor:
    """
  Compute the outer product of two `BlockSparseTensor`.
  The first `tensor1.ndim` indices of the resulting tensor are the 
  indices of `tensor1`, the last `tensor2.ndim` indices are those
  of `tensor2`.
  Args:
    tensor1: A tensor.
    tensor2: A tensor.
  Returns:
    BlockSparseTensor: The result of taking the outer product.
  """

    final_charges = tensor1._charges + tensor2._charges
    final_flows = list(tensor1._flows) + list(tensor2._flows)
    order2 = [
        list(np.asarray(s) + len(tensor1._charges)) for s in tensor2._order
    ]

    data = np.zeros(compute_num_nonzero(final_charges, final_flows),
                    dtype=tensor1.dtype)
    if ((len(tensor1.data) > 0) and
        (len(tensor2.data) > 0)) and (len(data) > 0):
        # find the location of the zero block in the output
        final_block_maps, final_block_charges, _ = _find_diagonal_sparse_blocks(
            final_charges, final_flows, len(tensor1._charges))
        index = np.nonzero(
            final_block_charges == final_block_charges.identity_charges(
                dim=1))[0][0]
        data[final_block_maps[index].ravel()] = np.outer(
            tensor1.data, tensor2.data).ravel()

    return BlockSparseTensor(data,
                             charges=final_charges,
                             flows=final_flows,
                             order=tensor1._order + order2,
                             check_consistency=False)
コード例 #9
0
ファイル: linalg.py プロジェクト: mikechen66/TensorNetwork
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)