def _(expr, args): if all(i.is_commutative for i in args): _mulsort(args) _eval_numbers(expr, args) return expr.func(*args, evaluate=False) else: return expr._new_rawargs(*args)
def _abs(mul): from sympy.core.mul import _mulsort c, nc = mul.args_cnc() a = [] o = [] for i in c: if isinstance(i, Abs): a.append(i.args[0]) elif isinstance(i, Pow) and isinstance(i.base, Abs) and i.exp.is_real: a.append(i.base.args[0]**i.exp) else: o.append(i) if len(a) < 2 and not any(i.exp.is_negative for i in a if isinstance(i, Pow)): return mul absarg = Mul(*a) A = Abs(absarg) args = [A] args.extend(o) if not A.has(Abs): args.extend(nc) return Mul(*args) if not isinstance(A, Abs): # reevaluate and make it unevaluated A = Abs(absarg, evaluate=False) args[0] = A _mulsort(args) args.extend(nc) # nc always go last return Mul._from_args(args, is_commutative=not nc)
def __new__(cls, *args, **kwargs): # A Mul, being a DifferentiableOp, may not trigger evaluation upon # construction (e.g., when an EvalDerivative is present among its # arguments), so here we apply a small set of basic simplifications # to avoid generating functional, but also ugly, code # (a*b)*c -> a*b*c (flattening) nested, others = split(args, lambda e: isinstance(e, Mul)) args = flatten(e.args for e in nested) + list(others) # a*0 -> 0 if any(i == 0 for i in args): return sympy.S.Zero # a*1 -> a args = [i for i in args if i != 1] # a*-1*-1 -> a nminus = len([i for i in args if i == sympy.S.NegativeOne]) if nminus % 2 == 0: args = [i for i in args if i != sympy.S.NegativeOne] # Reorder for homogeneity with pure SymPy types _mulsort(args) return super().__new__(cls, *args, **kwargs)
def _(expr, args): if all(i.is_commutative for i in args): _mulsort(args) # In-place sorting return expr.func(*args, evaluate=False) else: return expr._new_rawargs(*args)