Difference between replace and subs?

3,841 views
Skip to first unread message

Shriramana Sharma

unread,
Dec 3, 2012, 9:30:22 PM12/3/12
to sy...@googlegroups.com
Hello again. Here's another question:

The documentation says that replace replaces "matching subexpressions
of self with value" and subs does "substitution of subexpressions as
defined by the objects themselves".

Unfortunately I am not totally able to comprehend the difference
between the two. Can you please give an example for each where the
other will not work?

(BTW as an aside, in some places in the documentation like p 502 (508
of PDF) what is apparently a terminal transcript such as ">>> from
sympy.matrices import" etc are not properly formatted -- just thought
I'd mention.)

Thank you!

--
Shriramana Sharma

Aaron Meurer

unread,
Dec 3, 2012, 9:54:49 PM12/3/12
to sy...@googlegroups.com
subs finds all instances of an expression and tries to replace them.
It takes into account mathematical knowledge (e.g., (4*x).subs(2*x, y)
will work, even though strictly speaking, 2*x is not part of the
expression tree of 4*x).

replace uses several methods to let you do more advanced substitutions
based on patterns. It does not substitute objects directly:

In [7]: x.replace(x, y)
Out[7]: x

In [8]: x.subs(x, y)
Out[8]: y

Rather, you use either a function or an expression with a Wild to
replace general expressions. For example

In [10]: a = Wild('a')

In [11]: (sin(x) + sin(x**2)).replace(sin(a), cos(a))
Out[11]:
⎛ 2⎞
cos(x) + cos⎝x ⎠

To do this with subs, you would have to manually gather all the sin's
in the expression (using .atoms(sin)) and build a replacement
dictionary of corresponding cosines. replace lets you do this in one
step. You can achieve the same thing using the function forms (e.g.,
expr.replace(sin, cos)).

The third option is xreplace. This is like a very stripped down
version of subs. It does not do any mathematical reasoning. In order
for the expression to be replaced, it must appear exactly as given in
the dictionary in the expression tree (another way to say this is that
it will appear in expr.atoms(type(old))). Use this if you want to
avoid the mathematical reasoning of subs from messing with you too
much. If you got your replacement dictionary keys using atoms, you
should probably be using xreplace. A common example where subs and
xreplace act differently is in replacing powers such as exponentials.

In [15]: (exp(x) + exp(2*x)).subs(exp(x), y)
Out[15]:
2
y + y

In [16]: (exp(x) + exp(2*x)).xreplace({exp(x): y})
Out[16]:
2⋅x
y + ℯ

So I would say, if you find yourself building complex substitutions
dictionaries, see if you can do it easier with replace. Regarding
subs vs. xreplace, consider how smart you want the replacement to be.
Do you want the replacement to try to happen as much as possible,
mathematically, or do you only want to replace the exact thing that
you found (or suspect might be) in your expression? Depending on how
you answer that question, use subs or xreplace, respectively.
This particular instance it seems was already fixed, but if you notice
any others, let us know. It usually just means that we have a minor
formatting error in the docstring, such as no empty line after the
heading.

Aaron Meurer

>
> Thank you!
>
> --
> Shriramana Sharma
>
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To post to this group, send email to sy...@googlegroups.com.
> To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
>

Chris Smith

unread,
Dec 3, 2012, 10:19:55 PM12/3/12
to sy...@googlegroups.com
(BTW as an aside, in some places in the documentation like p 502 (508
of PDF) what is apparently a terminal transcript such as ">>> from
sympy.matrices import" etc are not properly formatted -- just thought
I'd mention.)


>>> eq=x+y+2
>>> eq.replace(x+1, z)
x + y + 2
>>> eq.subs(x+1, z)
y + z + 1
>>> eq.xreplace({x+1:z})
x + y + 2
>>> eq.xreplace({x+2:z})
x + y + 2
>>> eq.xreplace({x+2+y:z})
z

The subs method is able to call helper methods that request help in identifying how an expression might be replaced in an expression; I think replace (and definitely xreplace) are more literal and are looking for nodes in the expression tree.

Thanks for the note about formatting problems.

Shriramana Sharma

unread,
Dec 5, 2012, 3:56:51 AM12/5/12
to sy...@googlegroups.com
Hi and thanks both for your replies. xreplace doesn't look like
something I'd be interested in using, but as a very superficial
approximation, it looks like replace changes the expression
lexicographically but subs changes the expression mathematically. I
know I know that's *very* superficial but I'll be back if I have any
further problems later. The following error message which I got was
very useful to know as well:

>>> e=x**2
>>> e.replace(2,3)

TypeError: first argument to replace() must be a type, an expression
or a callable

--
Shriramana Sharma
Reply all
Reply to author
Forward
0 new messages