Reputation: 9901
I have two structurally identical expressions in SymPy, created in different ways:
import sympy as sp
f = sp.Symbol('f')
x = sp.Symbol('x')
by_hand = sp.Function(f)(x)
from_string = sp.sympify('f(x)')
Despite being identical expressions by construction, the two are not ==
:
by_hand == from_string
# False
Indeed, SymPy doesn't even know that they're equal symbolically:
sp.simplify(by_hand - from_string)
# 𝑓(𝑥)−𝑓(𝑥)
The two have identical srepr
s:
(sp.srepr(by_hand), sp.srepr(from_string))
# ("Function('f')(Symbol('x'))", "Function('f')(Symbol('x'))")
sp.srepr(by_hand) == sp.srepr(from_string)
# True
I know that round-tripping through strings isn't necessary reliable for maintaining identity in SymPy, but even using the locals
argument as a fix doesn't resolve this issue:
by_hand == sp.sympify('f(x)', locals={'f': f}) == by_hand
# False
Having to use locals
is already somewhat painful, because I am trying to do unit testing of a routine that constructs a bunch of symbolic expressions by constructing them independently.
Upvotes: 1
Views: 78
Reputation: 43083
There are a few ways to fix that.
Pass locals={'f': sp.Function(f)}
instead of locals={'f': f}
.
by_hand = sp.Function(f)(x)
from_string = sp.sympify('f(x)')
# by_hand == sp.sympify('f(x)', locals={'f': f}) # Change this
by_hand == sp.sympify('f(x)', locals={'f': sp.Function(f)}) # True # to this
You defined by_hand = sp.Function(f)(x)
, so Function('f')
in sp.srepr(by_hand)
is sp.Function(f)
, or sp.Function(sp.Symbol('f'))
.
On the other hand, Function('f')
in sp.srepr(from_string)
is sp.Function('f')
.
(This leads us to Fix 2.)
The difference is that sp.Function(sp.Symbol('f'))
inherits the default assumption {'commutative': True}
of sp.Symbol('f')
.
(This leads us to Fix 3.)
This is the clean fix and may be what you intended.
# f = sp.Symbol('f') # Change this
f = sp.Function('f') # to this
x = sp.Symbol('x')
# by_hand = sp.Function(f)(x) # Change this
by_hand = f(x) # to this
from_string = sp.sympify('f(x)')
by_hand == from_string # True
This hack demonstrates the inherited assumption {'commutative': True}
identified in Fix 1.
by_hand = sp.Function(f)(x)
del by_hand._kwargs['commutative'] # Add this
# del by_hand._assumptions['commutative'] # Add this, optional
from_string = sp.sympify('f(x)')
by_hand == from_string # True
Upvotes: 2