SymPy coeff() different behavior depending on how it is called

I am trying to get the coefficients from several SymPy expressions. Since there are a lot of different combinations, I’d like to loop over them with a variable n. However that fails when n=-1. Here is an example, where the first two attempts are explicit and work fine, and the last with the exponent written as a variable fails:

julia> using SymPy

julia> @syms x

julia> p = 1/x

julia> p.coeff(1/x)  # Yay, this works!

julia> p.coeff(x^(-1))  # This also works!

julia> n = -1; p.coeff(x^n)  # Crash, bang, catastrophy.
ERROR: DomainError with -1:
Cannot raise an integer x to a negative power -1.
Convert input to float.
 [1] throw_domerr_powbysq(#unused#::Sym, p::Int64)
   @ Base ./intfuncs.jl:241
 [2] power_by_squaring(x_::Sym, p::Int64)
   @ Base ./intfuncs.jl:265
 [3] ^(x::Sym, p::Int64)
   @ Base ./intfuncs.jl:290
 [4] top-level scope
   @ REPL[6]:1

To me this smells like some compiler inference stuff… meaning I have no clue what I’m talking about. Even just an explanation of what is going on would be greatly appreciated!

I think x^(-1) gets replaced by the compiler with Base.literal_pow(^, x, Val(-1)) which is probably being overloaded by SymPy to have different behaviour from ^. This should probably be considered a bug.

The issue here is x^(-1) is treated by the parser first; x^n dispatches to a generic implementation that errors. You can see the same behavior with x=2, it isn’t SymPy related.

Using a symbolic power, as in x^Sym(n), would stay within SymPy, and works as desired.

1 Like