Created
January 9, 2021 05:29
-
-
Save erictleung/6672c647a6c706a28b1da70e4fa6d429 to your computer and use it in GitHub Desktop.
Apply expression on each side of SymPy expression
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Source: | |
# https://github.com/sympy/sympy/issues/5031#issuecomment-36996878 | |
def do(self, e, i=None, doit=False): | |
"""Return a new Eq using function given or a model | |
model expression in which a variable represents each | |
side of the expression. | |
Examples | |
======== | |
>>> from sympy import Eq | |
>>> from sympy.abc import i, x, y, z | |
>>> eq = Eq(x, y) | |
When the argument passed is an expression with one | |
free symbol that symbol is used to indicate a "side" | |
in the Eq and an Eq will be returned with the sides | |
from self replaced in that expression. For example, to | |
add 2 to both sides: | |
>>> eq.do(i + 2) | |
Eq(x + 2, y + 2) | |
To add x to both sides: | |
>>> eq.do(i + x) | |
Eq(2*x, x + y) | |
In the preceding it was actually ambiguous whether x or i | |
was to be added but the rule is that any symbol that are | |
already in the expression are not to be interpreted as the | |
dummy variable. If we try to add z to each side, however, an | |
error is raised because now it is unclear whether i or z is being | |
added: | |
>>> eq.do(i + z) | |
Traceback (most recent call last): | |
... | |
ValueError: not sure what symbol is being used to represent a side | |
The ambiguity must be resolved by indicating with another parameter | |
which is the dummy variable representing a side: | |
>>> eq.do(i + z, i) | |
Eq(x + z, y + z) | |
Alternatively, if only one Dummy symbol appears in the expression then | |
it will be automatically used to represent a side of the Eq. | |
>>> eq.do(2*Dummy() + z) | |
Eq(2*x + z, 2*y + z) | |
Operations like differentiation must be passed as a | |
lambda: | |
>>> Eq(x, y).do(lambda i: i.diff(x)) | |
Eq(1, 0) | |
Because doit=False by default, the result is not evaluated. to | |
evaluate it, either use the doit method or pass doit=True. | |
>>> _.doit == Eq(x, y).do(lambda i: i.diff(x), doit=True) | |
True | |
""" | |
if not isinstance(e, (FunctionClass, Lambda, type(lambda:1))): | |
e = S(e) | |
imaybe = e.free_symbols - self.free_symbols | |
if not imaybe: | |
raise ValueError('expecting a symbol') | |
if imaybe and i and i not in imaybe: | |
raise ValueError('indicated i not in given expression') | |
if len(imaybe) != 1 and not i: | |
d = [i for i in imaybe if isinstance(i, Dummy)] | |
if len(d) != 1: | |
raise ValueError( | |
'not sure what symbol is being used to represent a side') | |
i = set(d) | |
else: | |
i = imaybe | |
i = i.pop() | |
f = lambda side: e.subs(i, side) | |
else: | |
f = e | |
return self.func(*[f(side) for side in self.args], evaluate=doit) | |
from sympy.core.relational import Equality | |
Equality.do = do |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment