def _multiply_operators( hilbert, support_A: Tuple, A: Array, support_B: Tuple, B: Array, *, dtype ) -> Tuple[Tuple, Array]: """ Returns the `Tuple[acting_on, Matrix]` representing the operator obtained by multiplying the two input operators A and B. """ support_A = np.asarray(support_A) support_B = np.asarray(support_B) inters = np.intersect1d(support_A, support_B, return_indices=False) if support_A.size == support_B.size and np.array_equal(support_A, support_B): return tuple(support_A), A @ B elif inters.size == 0: # disjoint supports support = tuple(np.concatenate([support_A, support_B])) operator = np.kron(A, B) operator, support = _reorder_kronecker_product(hilbert, operator, support) return tuple(support), operator else: _support_A = list(support_A) _support_B = list(support_B) _A = A.copy() _B = B.copy() # expand _act to match _act_i supp_B_min = min(support_B) for site in support_A: if site not in support_B: I = np.eye(hilbert.shape[site], dtype=dtype) if site < supp_B_min: _support_B = [site] + _support_B _B = np.kron(I, _B) else: # site > actmax _support_B = _support_B + [site] _B = np.kron(_B, I) supp_A_min = min(support_A) for site in support_B: if site not in support_A: I = np.eye(hilbert.shape[site], dtype=dtype) if site < supp_A_min: _support_A = [site] + _support_A _A = np.kron(I, _A) else: # site > actmax _support_A = _support_A + [site] _A = np.kron(_A, I) # reorder _A, _support_A = _reorder_kronecker_product(hilbert, _A, _support_A) _B, _support_B = _reorder_kronecker_product(hilbert, _B, _support_B) if len(_support_A) == len(_support_B) and np.array_equal( _support_A, _support_B ): # back to the case of non-interesecting with same support return tuple(_support_A), _A @ _B else: raise ValueError("Something failed")
def _to_int_vector(v: Array) -> str: try: v = __to_int_vector(v) return f"[{v[0]},{v[1]},{v[2]}]" except ValueError: # in hexagonal symmetry, you often get a √3 in the x/y coordinate try: w = v.copy() w[1] /= 3**0.5 w = __to_int_vector(w) return f"[{w[0]},{w[1]}√3,{w[2]}]" except ValueError: # just return a normalised v v = v / np.linalg.norm(v) return f"[{v[0]:.3f},{v[1]:.3f},{v[2]:.3f}]"