You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When substituting expressions and defining function at the same time, the SympyBackend.substitute method fails with an AttributeError if sole substitution is enough to evaluate the expression to number.
How to Reproduce
The following code triggers an error:
backend=SympyBackend()
deff(x):
returnint(x) +1# The int here is crucialdefg(x):
returnxexpr=backend.as_expression("f(x)")
backend.substitute(expr, {"x": 10}, {"f": f, "g": g})
This is because after the substitution of x, the expression becomes constant, then this constant is converted to a native integer and the _define_function function fails for native integers (or floats). This, in turn, is caused by an incorrect usage of identity_for_numbers decorator which I didn't catch earlier.
Note that the problem is triggered only if the expression is not constant when entering substituteand becomes constant after defining one of the functions, before another attempt to define another function is made. So, for instance, the following code does not trigger an error:
backend.substitute(10, {"x": 10}, {"f": f, "g": g}) # We start with a constantbackend.substitute(expr, {"x": 10}, {"f": f}) # f evaluates to constant, but no function is is defined after f.
This is why we didn't spot the bug until now - its occurrence is rather rare.
Expected behavior
A constant resulting from variable substitution is returned.
Actual behavior
An AttributeError is raised:
AttributeError Traceback (most recent call last)
Cell In[10], line 1
----> 1 backend.substitute("x", {"x": 8}, {"f": f})
File ~/Projects/bartiq/src/bartiq/symbolics/sympy_backends.py:71, in identity_for_numbers.<locals>._inner(backend, expr, *args, **
kwargs)
70 def _inner(backend: SympyBackend, expr: TExpr[S], *args: P.args, **kwargs: P.kwargs) -> T | Number:
---> 71 return expr if isinstance(expr, Number) else func(backend, expr, *args, **kwargs)
File ~/Projects/bartiq/src/bartiq/symbolics/sympy_backends.py:176, in SympyBackend.substitute(self, expr, replacements, functions_
map)
167 @identity_for_numbers
168 def substitute(
169 self,
(...)
173 functions_map: Mapping[str, Callable[[TExpr[Expr]], TExpr[Expr]]] | None = None,
174 ) -> TExpr[Expr]:
--> 176 symbols_in_expr = self.free_symbols_in(expr)
177 restricted_replacements = [(symbols(old), new) for old, new in replacements.items() if old in symbols_in_expr]
178 expr = expr.subs(restricted_replacements)
File ~/Projects/bartiq/src/bartiq/symbolics/sympy_backends.py:64, in empty_for_numbers.<locals>._inner(backend, expr, *args, **kwa
rgs)
63 def _inner(backend: SympyBackend, expr: TExpr[S], *args: P.args, **kwargs: P.kwargs) -> Iterable[T]:
---> 64 return () if isinstance(expr, Number) else func(backend, expr, *args, **kwargs)
File ~/Projects/bartiq/src/bartiq/symbolics/sympy_backends.py:143, in SympyBackend.free_symbols_in(self, expr)
140 @empty_for_numbers
141 def free_symbols_in(self, expr: Expr) -> Iterable[str]:
142 """Return an iterable over free symbol names in given expression."""
--> 143 return tuple(map(str, expr.free_symbols))
AttributeError: 'str' object has no attribute 'free_symbols'
Environment:**
This bug is environment-independent.
Additional context
N/A
The text was updated successfully, but these errors were encountered:
…144)
* Add test triggering #143
* Fix typo in test
* Fix root cause of the issue - invalid usage of identity_for_numbers
* Add a warning to the docstring to avoid incorrect usage of
identity_for_numbers
* Add comment about the function g
Describe the bug
When substituting expressions and defining function at the same time, the
SympyBackend.substitute
method fails with anAttributeError
if sole substitution is enough to evaluate the expression to number.How to Reproduce
The following code triggers an error:
This is because after the substitution of
x
, the expression becomes constant, then this constant is converted to a native integer and the_define_function
function fails for native integers (or floats). This, in turn, is caused by an incorrect usage ofidentity_for_numbers
decorator which I didn't catch earlier.Note that the problem is triggered only if the expression is not constant when entering
substitute
and becomes constant after defining one of the functions, before another attempt to define another function is made. So, for instance, the following code does not trigger an error:This is why we didn't spot the bug until now - its occurrence is rather rare.
Expected behavior
A constant resulting from variable substitution is returned.
Actual behavior
An
AttributeError
is raised:Environment:**
This bug is environment-independent.
Additional context
N/A
The text was updated successfully, but these errors were encountered: