コード例 #1
0
    def __init__(self,
                 data: np.ndarray,
                 charges: List[BaseCharge],
                 flows: 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)

        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)))
コード例 #2
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 = tensor1.flat_flows + tensor2.flat_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)[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)
コード例 #3
0
def test_compute_num_nonzero(num_charges):
    np.random.seed(12)
    D = 40
    qs = [np.random.randint(-3, 3, (num_charges, D)) 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.T == np.zeros((1, num_charges),
                                                      dtype=np.int16),
                                  axis=1))[0])
    assert nz1 == nz2
コード例 #4
0
  def zeros(cls,
            indices: Union[Tuple[Index], List[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)