Well, it's not what I had hoped for, but I think the solution will necessarily involve going through the expression and forcing the applications. Applying such applications is like applying simplify
, so it's not too unexpected or onerous. The following is sufficient for my purposes, though more general expressions might require more special cases. The essential ideas are found here, in the tutorial, and involve recursing through the expression tree:
def gobbleExpr(expr):
if isinstance(expr, Gobbler):
return expr
if isinstance(expr, Mul):
args = list(o if o.is_Atom or isinstance(o, Gobbler)
else gobbleExpr(o)
for o in expr.args)
gobbler = prod(t for t in args if isinstance(t, Gobbler))
others = prod(o for o in args if not isinstance(o, Gobbler))
if gobbler==1:
return others
else:
return gobbler.__mul__(others)
if isinstance(expr, Add):
return sum(gobbleExpr(arg) for arg in expr.args)
return expr
So now I can do something like
>>> expand(b*(x+y)*a)
x*a*b + y*a*b
>>> gobbleExpr(_)
gob(gob(x*1)*a*b) + gob(gob(y*1)*a*b)
So the only remaining things are Gobbler
s added to each other, which I handle elsewhere.