Example #1
0
    def __init__(self,
                 data: np.ndarray,
                 charges: List[BaseCharge],
                 flows: Union[np.ndarray, List[bool]],
                 order: Optional[List[Union[List, np.ndarray]]] = None,
                 check_consistency: Optional[bool] = False) -> None:
        """
    Args: 
      data: An np.ndarray containing the actual data. 
      charges: A list of `BaseCharge` objects.
      flows: The flows of the tensor indices, `False` for inflowing, `True`
        for outflowing.
      order: An optional order argument, determining the shape and order of the
        tensor.
      check_consistency: If `True`, check if `len(data)` is consistent with 
        number of non-zero elements given by the charges. This usually causes
        significant overhead, so use only for debugging.
    """
        super().__init__(data=data,
                         charges=charges,
                         flows=flows,
                         order=order,
                         check_consistency=check_consistency)

        if check_consistency and (len(self._charges) > 0):
            num_non_zero_elements = compute_num_nonzero(
                self._charges, self._flows)
            if num_non_zero_elements != len(data.flat):
                raise ValueError("number of tensor elements {} defined "
                                 "by `charges` is different from"
                                 " len(data)={}".format(
                                     num_non_zero_elements, len(data.flat)))
Example #2
0
def test_compute_num_nonzero(num_charges):
  np.random.seed(12)
  D = 40
  qs = [np.random.randint(-3, 3, (D, num_charges)) for _ in range(3)]
  charges = [BaseCharge(q, charge_types=[U1Charge] * num_charges) for q in qs]
  flows = [False, True, False]
  np_flows = [1, -1, 1]
  fused = fuse_many_ndarray_charges([qs[n] * np_flows[n] for n in range(3)],
                                    [U1Charge] * num_charges)
  nz1 = compute_num_nonzero(charges, flows)
  #pylint: disable=no-member
  nz2 = len(
      np.nonzero(
          np.logical_and.reduce(
              fused == np.zeros((1, num_charges), dtype=np.int16), axis=1))[0])
  assert nz1 == nz2
Example #3
0
  def zeros(cls,
            indices: Sequence[Index],
            dtype: Optional[Type[np.number]] = None) -> "BlockSparseTensor":
    """
    Initialize a symmetric tensor with zeros.
    Args:
      indices: List of `Index` objects, one for each leg. 
      dtype: An optional numpy dtype. The dtype of the tensor
    Returns:
      BlockSparseTensor
    """
    charges, flows = get_flat_meta_data(indices)
    num_non_zero_elements = compute_num_nonzero(charges, flows)
    tmp = np.append(0, np.cumsum([len(i.flat_charges) for i in indices]))
    order = [list(np.arange(tmp[n], tmp[n + 1])) for n in range(len(tmp) - 1)]

    return cls(
        data=np.zeros((num_non_zero_elements,), dtype=dtype),
        charges=charges,
        flows=flows,
        order=order,
        check_consistency=False)
Example #4
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)