def __mul__(self, l): if type(l) == expr: lhs = gpt.apply_expr_unary(self) rhs = gpt.apply_expr_unary(l) # Attempt to close before product to avoid exponential growth of terms. # This does not work for sub-expressions without lattice fields, so # lhs and rhs may still contain multiple terms. if len(lhs.val) > 1: lhs = expr(gpt.eval(lhs)) if len(rhs.val) > 1: rhs = expr(gpt.eval(rhs)) return expr([(a[0] * b[0], a[1] + b[1]) for a in lhs.val for b in rhs.val]) elif type(l) == gpt.tensor and self.is_single(gpt.tensor): ue, uf, to = self.get_single() if ue == 0 and uf & factor_unary.BIT_TRANS != 0: tag = l.otype.__name__ assert tag in to.otype.itab mt = to.otype.itab[tag] lhs = to.array if uf & gpt.factor_unary.BIT_CONJ != 0: lhs = lhs.conj() res = gpt.tensor(np.tensordot(lhs, l.array, axes=mt[1]), mt[0]()) if res.otype == gpt.ot_singlet: res = complex(res.array) return res assert 0 else: return self.__mul__(expr(l))
def __mul__(self, l): if type(l) == expr: lhs = gpt.apply_expr_unary(self) rhs = gpt.apply_expr_unary(l) # close before product to avoid exponential growth of terms if len(lhs.val) > 1: lhs = expr(gpt.eval(lhs)) if len(rhs.val) > 1: rhs = expr(gpt.eval(rhs)) assert (len(lhs.val) == 1 or len(rhs.val) == 1) return expr([(a[0] * b[0], a[1] + b[1]) for a in lhs.val for b in rhs.val]) elif type(l) == gpt.tensor and self.is_single(gpt.tensor): ue, uf, to = self.get_single() if ue == 0 and uf & factor_unary.BIT_TRANS != 0: tag = (to.otype, l.otype) assert (tag in gpt.otype.itab) mt = gpt.otype.itab[tag] lhs = to.array if uf & gpt.factor_unary.BIT_CONJ != 0: lhs = lhs.conj() res = gpt.tensor(np.tensordot(lhs, l.array, axes=mt[1]), mt[0]) if res.otype == gpt.ot_complex: res = complex(res.array) return res assert (0) else: return self.__mul__(expr(l))
def __add__(self, l): if type(l) == expr: if self.unary == l.unary: return expr(self.val + l.val, self.unary) else: return expr( gpt.apply_expr_unary(self).val + gpt.apply_expr_unary(l).val ) else: return self.__add__(expr(l))