Search code examples
pythonsympy

Sympy mapping defined functions


I have a userdefined language containing mathematical expressions in python syntax but with wrapper special mathematical functions, e.g. instead of sqrt(y) - x I have _math.foo(y) - x

I want to be able to use sympy.parse_expr on these strings and handle them the same way. I tried two different things with not yet the correct result:


import sympy
import math

import sympy.utilities
from sympy.utilities.lambdify import implemented_function

class Math:
    foo = math.sqrt
    bar = implemented_function("sqrt", math.sqrt)

input = "sqrt(y) - x"
input = "_math.bar(y) - x"
input = "_math.foo(y) - x"
expr = sympy.parse_expr(input, {"_math" : Math})
print(expr)
print(sympy.solveset(expr, sympy.Symbol("y")))
print(sympy.solveset(expr, sympy.Symbol("x")))

With input = "sqrt(y) - x" I do get the result:

-x + sqrt(y)
{x**2}
{sqrt(y)}

which is the result I want. The approach input = "_math.bar(y) - x" gives me the output:

-x + sqrt(y)
ConditionSet(y, Eq(-x + sqrt(y), 0), Complexes)
{sqrt(y)}

which I do not fully understand, but is not th same as the one above and the last approach input = "_math.foo(y) - x" gives me TypeError("Cannot convert expression to float") inside eval.

Note that the string representation of the first two approaches is the same.


Solution

  • Copilot for the win. SymPy actually has math functions available (just not a very good documentation) that can directly be used for symbols. Other methods that are not directly available can be composed.

    class Math:
        foo = sympy.sqrt
    
        @staticmethod
        def mydiv(a: Any, b: Any) -> Any:
            """sympy division operation"""
            return sympy.Mul(a, sympy.Pow(b, -1))