JuliaSymbolics / Symbolics.jl

Symbolic programming for the next generation of numerical software
https://docs.sciml.ai/Symbolics/stable/
Other
1.35k stars 151 forks source link

Document Symbolics <-> SymPy roundtripping #1223

Open ChrisRackauckas opened 3 weeks ago

ChrisRackauckas commented 3 weeks ago

@jverzani IIUC the conversions work between them now right? Do you have a script that shows the round tripping that I can use to write some docs from?

jverzani commented 3 weeks ago

There is an extension in SymPyPythonCall that does this through PythonCall's pyconvert method (which I don't have tests setup for), but I think this TermInterface approach might be better. (It is certainly more straightforward). The only fussy part is the handling of symbolic numbers, as SymPy and SymPyPythonCall keep these on the Python side. This is not really tested and relies on the operation value to have a Julia counterpart, which might not be the case for some SymPy output, especially around cases and special functions.

# convert term to term
using TermInterface

using Symbolics, SymPyPythonCall
import SymPyCore: Sym

_N(ex::Sym) = N(ex)
_N(ex) = ex

function exchange(ex, as::Pair...)
    _exchange(Val(iscall(ex)), ex, as...)
end

function _exchange(::Val{true}, ex, as...)
    op, args = operation(ex), arguments(ex)
    args′ = replace(args, as...)
    op((exchange(aᵢ, as...) for aᵢ ∈ args′)...)
end

function _exchange(::Val{false}, ex, as...)
    for (k,v) ∈ as
        isequal(ex, k) && return v
    end
    _N(ex)
end

SymPyPythonCall.@syms 𝑥 𝑦
Symbolics.@syms x y

𝑒𝑥 = sin(𝑥^2 + y + π) / (2 + cos(𝑦) + 𝑥^2)
ex = sin(x^2 + y + π) / (2 + cos(y) + x^2)

exchange(𝑒𝑥, 𝑥 => x, 𝑦 => y)
exchange(ex, x => 𝑥, y => 𝑦)
ChrisRackauckas commented 1 week ago

Should this exchange function be added to SymPyPythonCall? Is there some issue with having symbolics_to_sympy(ex) find the variables and do such a conversion automatically without requiring the named symbols (and vice versa)?