def compute_fused_charge_degeneracies( charges: List[BaseCharge], flows: List[bool]) -> Tuple[BaseCharge, np.ndarray]: """ For a list of charges, computes all possible fused charges resulting from fusing `charges` and their respective degeneracies Args: charges: List of `BaseCharge`, one for each leg of a tensor. flows: A list of bool, one for each leg of a tensor. with values `False` or `True` denoting inflowing and outflowing charge direction, respectively. Returns: BaseCharge: The unique fused charges. np.ndarray: The degeneracies of each unqiue fused charge. """ if len(charges) == 1: return (charges[0] * flows[0]).unique(return_counts=True, sort=False) # get unique charges and their degeneracies on the first leg. # We are fusing from "left" to "right". accumulated_charges, accumulated_degeneracies = (charges[0] * flows[0]).unique( return_counts=True, sort=False) for n in range(1, len(charges)): leg_charges, leg_degeneracies = charges[n].unique(return_counts=True, sort=False) fused_charges = accumulated_charges + leg_charges * flows[n] fused_degeneracies = fuse_degeneracies(accumulated_degeneracies, leg_degeneracies) accumulated_charges = fused_charges.unique(sort=False) accumulated_degeneracies = np.empty(len(accumulated_charges), dtype=SIZE_T) accumulated_degeneracies = np.array([ np.sum(fused_degeneracies[fused_charges.charge_labels == accumulated_charges.charge_labels[m]]) for m in range(len(accumulated_charges)) ]) return accumulated_charges, accumulated_degeneracies
def test_fuse_degeneracies(): d1 = np.asarray([0, 1]) d2 = np.asarray([2, 3, 4]) fused_degeneracies = fuse_degeneracies(d1, d2) np.testing.assert_allclose(fused_degeneracies, np.kron(d1, d2))