JuliaPy / SymPy.jl

Julia interface to SymPy via PyCall
http://juliapy.github.io/SymPy.jl/
MIT License
268 stars 62 forks source link

MethodError: no method matching degree(::Vector{Sym}, ::Vector{Sym}) #480

Closed xiang-yu closed 10 months ago

xiang-yu commented 1 year ago

I try to derive the degree of polynomials in a vector, but got the following error,
using SymPy x = [symbols("x$i") for i in 1:3] y = [symbols("y$i") for i in 1:3] y[1] = x[1]^2 y[2] = x[2]^2 y[3] = x[2]*x[1] degree(y, x) ERROR: MethodError: no method matching degree(::Vector{Sym}, ::Vector{Sym})

Any idea about this? Thanks in advance.

jverzani commented 1 year ago

I'm pretty sure degree is meant to find the degree of a variable within a term. I'm not sure what you have in mind, but note in this example how the degree of x_1 in x_1*x_2 is 1:

julia> @syms x[1:3]
(Sym[x₁, x₂, x₃],)

julia> y = [x[1]^2, x[2]^2, x[2]*x[1]]
3-element Vector{Sym}:
  x₁^2
  x₂^2
 x₁⋅x₂

julia> degree(y[1].as_poly(x), x[1])
2

julia> degree(y[2].as_poly(x), x[1])
0

julia> degree(y[3].as_poly(x), x[1])
1

What exactly are you hoping to get out? Maybe I can help sort out some pattern for what you want.

xiang-yu commented 1 year ago

I'm pretty sure degree is meant to find the degree of a variable within a term. I'm not sure what you have in mind, but note in this example how the degree of x_1 in x_1*x_2 is 1:


julia> @syms x[1:3]

(Sym[x₁, x₂, x₃],)

julia> y = [x[1]^2, x[2]^2, x[2]*x[1]]

3-element Vector{Sym}:

  x₁^2

  x₂^2

 x₁⋅x₂

julia> degree(y[1].as_poly(x), x[1])

2

julia> degree(y[2].as_poly(x), x[1])

0

julia> degree(y[3].as_poly(x), x[1])

1

What exactly are you hoping to get out? Maybe I can help sort out some pattern for what you want.

Thanks a lot. I want to find the highest degrees of y regarding x (e.g., x1^2, x2^3, ...), where my y is a vector with polynomials,

y[1] = x[1]^2 + x[2]^2 + x[1]*x[2] y[2] = x[2]^2 y[3] = 1 degree(y, x)

The closest I can find in Sympy.py is degree_list(x*2 + yx + 1), but I couldn't find "degree_list" in Sympy.jl.

I did it using Symbolics.jl but I have to switch to Sympy.jl for now because Symbolics cannot substitute a*b term correctly.

jverzani commented 1 year ago

This works for the toy example:

[findmax(degree.(yᵢ, x)) for yᵢ ∈ y]
xiang-yu commented 1 year ago

Thanks. The degree of x1*x2 is supposed to be 2, but when I consider a simpler case,

julia> @syms x[1:3] julia> y = x[1]*x[2] julia> degree.(y,x) 3-element Vector{Sym}: 1 1 0

The highest degree is 1. In general, how to determine the degree multivariable polynomials in SymPy.jl? For example, in my case, y = x1*x2, "degree(y, x)"should just return 2. Any thoughts on this?

jverzani commented 1 year ago

The broadcast degree.(y,x) isn't quite what you want. Often you might see degree.(y,x') when graphing to get the cartesian broadcast, but here you would want something like either of these two:

 m = [degree(yᵢ, xⱼ) for yᵢ ∈ y, xⱼ ∈ x] # also degree.(y, permutedims(x));

This returns a matrix with each row indicating the degree of the x variables. You can sum over these to get the degree you want:

[sum(r) for r ∈ eachrow(m)] # or sum.(eachrow(m))

It isn't fast! In a test with 200 random polynomials over 500 variables it took about 1 minute.

xiang-yu commented 1 year ago

Thanks. I used the sum method as well, but as you also found, it is quite slow. Nevertheless, It can solve the problem for now.