JuliaSymbolics / Symbolics.jl

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

Document Symbolics <-> SymPy roundtripping #1223

Open ChrisRackauckas opened 3 months ago

ChrisRackauckas commented 3 months 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 months 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 2 months 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)?