Nathan
Nathan

Reputation: 3648

How to pass args to sympy.lambdify

This is a more precise version of this question where the comments said my minimal reproducible code was too minimal, so with more information:

I want to evaluate an Expression without having to pass the symbols along separately. My current workaround is this:

from sympy import Symbol, lambdify


def evaluate_expr(expr):
    lambdified = lambdify(tuple(expr.free_symbols), expr)
    return lambdified(*[i.value for i in expr.free_symbols])


class symbol_x(Symbol):
    def __new__(cls, symbol, value):
        obj = Symbol.__new__(cls, symbol)
        obj.value = value
        return obj

x = symbol_x('x', 2)
y = symbol_x('y', 3)

value = evaluate_expr(x / y)
print(value)

This works. My problem is that expr.free_symbols is a set (which doesn't maintain order), so casting it to a tuple might create unexpected bugs. What would be the correct way of evaluating this expression?

Upvotes: 0

Views: 225

Answers (1)

Davide_sd
Davide_sd

Reputation: 13185

You need to sort the free symbols according to some reproducible logic, like sorting by name:

def evaluate_expr(expr):
    fs = sorted(expr.free_symbols, key=lambda t: t.name)
    lambdified = lambdify(fs, expr)
    return lambdified(*[i.value for i in fs])

Edit for explanation:

The problem is that expr.free_symbols returns a set. lambdify requires a list. In Python, the conversion from a set to a list is non-deterministic. For example, say you have a set {a, b}. When you convert it to a list you can either have [a, b] or [b, a].

To fix this behavior, we can use sorted to sort the free symbols alphabetically.

Upvotes: 1

Related Questions