pythonsympy

Expanding algebraic powers in python (sympy)


I'm just wondering if there is an existing method of expanding algebraic powers such as x**2 out to their multiplicative forms (i.e. x**2 -> x*x) in python's Sympy module?

Thanks!


Solution

  • There's no direct support for this. SymPy automatically combines common terms in a multiplication to exponentiation. The only way to make this not happen is to use the evaluate=False mechanism. For example

    >>> Mul(x, x, evaluate=False)
    x*x
    

    There was a discussion on the SymPy mailing list a while back about this exact question (https://groups.google.com/d/topic/sympy/qaJGesRbX_0/discussion). I posted some code there that will do this. I'll repeat it here:

    def pow_to_mul(expr):
        """
        Convert integer powers in an expression to Muls, like a**2 => a*a.
        """
        pows = list(expr.atoms(Pow))
        if any(not e.is_Integer for b, e in (i.as_base_exp() for i in pows)):
    
            raise ValueError("A power contains a non-integer exponent")
        repl = zip(pows, (Mul(*[b]*e,evaluate=False) for b,e in (i.as_base_exp() for i in pows)))
        return expr.subs(repl)
    

    Here's how it works

    >>> a = Symbol('a')
    >>> exp = a**2
    >>> print(exp)
    a**2
    >>> print(pow_to_mul(exp))
    a*a
    

    I'll put the same caveat here as on the mailing list: "evaluate=False is somewhat of a hack, so be aware that it is fragile. Some functions will reevaluate the expression, converting it back to Pow. Other functions will break because some expected invariant will be broken by the evaluate=False expression (e.g., I doubt factor() would work correctly)."