What to read to be good at rewriting expressions?

74 views
Skip to first unread message

Hugh

unread,
Nov 3, 2015, 3:47:20 PM11/3/15
to sympy
import sympy
sympy
.init_session()


x11
, x12, x13, x21, x22, x23, x31, x32, x33 = symbols('x_1:4(1:4)')

A
= Matrix(3,3,symbols('x_1:4(1:4)'))
expr1
= A.det()

expr2
= x11*(x22*x33 - x23*x32) - x12*(x21*x33 -x23*x31) + x13*(x21*x32 - x22*x31)

# How to get expr2 from expr1?

I would like to use sympy to rewrite expressions just like how people would commonly do when writing proofs or doing homework. What are the documentation that I must read so that I can be proficient at this?

I've read the tutorial and some of the modules in the module reference but feel that I have just barely touched the surface of sympy's capabilities. For example, in the above code snippet, I don't know how to manipulate expr1 to get expr2. I thought expr1.factor() would work but it didn't.

Please advise.

Aaron Meurer

unread,
Nov 3, 2015, 5:19:34 PM11/3/15
to sy...@googlegroups.com
A good start would be the simplification section of the tutorial
http://docs.sympy.org/latest/tutorial/index.html.

In this case, collect(expr1, [x11, x12, x13]) does what you want.
factor() only does complete factorizations (into products of terms).
This is explained in more depth in the tutorial.

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/9cbb1995-3987-44f1-8c72-6de11e6a4013%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Hugh

unread,
Nov 3, 2015, 5:21:21 PM11/3/15
to sympy
After reading some more documentation and browsing the internet, I found out that I can get expr2 from expr1 by doing this:

expr3 = expr1.collect(x11).collect(x12).collect(x13)


a
= Wild('a')
b
= Wild('b')


expr4
= expr3.replace(x12*a+b, Mul(-x12, -a, evaluate = False) + b, exact = True).collect(x11).collect(x13)

# Now, expr4 is in the same form as expr2


But is this the recommended approach?

Mateusz Paprocki

unread,
Nov 3, 2015, 6:35:45 PM11/3/15
to sympy
Hi,

On 3 November 2015 at 21:47, Hugh <714...@gmail.com> wrote:
> import sympy
> sympy.init_session()
>
>
> x11, x12, x13, x21, x22, x23, x31, x32, x33 = symbols('x_1:4(1:4)')
>
> A = Matrix(3,3,symbols('x_1:4(1:4)'))
> expr1 = A.det()
>
> expr2 = x11*(x22*x33 - x23*x32) - x12*(x21*x33 -x23*x31) + x13*(x21*x32 -
> x22*x31)
>
> # How to get expr2 from expr1?

In [1]: from sympy import *

In [2]: var('x_1:4(1:4)')
Out[2]: (x_11, x_12, x_13, x_21, x_22, x_23, x_31, x_32, x_33)

In [3]: A = Matrix(3, 3, _)

In [4]: expr1 = A.det()

In [5]: expr1
Out[5]: x_11*x_22*x_33 - x_11*x_23*x_32 - x_12*x_21*x_33 +
x_12*x_23*x_31 + x_13*x_21*x_32 - x_13*x_22*x_31

In [6]: from sympy.utilities.iterables import multiset_partitions

In [7]: min([ sum([ factor(sum(f)) for f in l ]) for l in
multiset_partitions(expr1.args) ], key=lambda e: e.count_ops())
Out[7]: x_11*(x_22*x_33 - x_23*x_32) - x_12*(x_21*x_33 - x_23*x_31) +
x_13*(x_21*x_32 - x_22*x_31)

> I would like to use sympy to rewrite expressions just like how people would
> commonly do when writing proofs or doing homework. What are the
> documentation that I must read so that I can be proficient at this?
>
> I've read the tutorial and some of the modules in the module reference but
> feel that I have just barely touched the surface of sympy's capabilities.
> For example, in the above code snippet, I don't know how to manipulate expr1
> to get expr2. I thought expr1.factor() would work but it didn't.

At this point SymPy doesn't have any built-in function that would do
out of the box what's requested here. factor() can't help (at least
directly), because it gives a complete factorization (it works over
entire expression). What you are looking for would be called, e.g.,
factorsum() (as in Maxima). Such functionality can be implemented in
SymPy as shown in _7, just it's very inefficient due to a large number
of partitions.

Mateusz

Aaron Meurer

unread,
Nov 3, 2015, 7:42:28 PM11/3/15
to sy...@googlegroups.com
Perhaps collect() should gain some kind of "auto" flag, which would
automatically collect things that appear in more than one term (using
some kind of greedy approach).

As for more general factorization, I'm not sure if it's valuable in
general, especially since the concept of a partial factorization is
not really well-defined (at least in terms of uniqueness). Probably
separating different variables like x**2 + 2*x + y**2 + 2*y + 2 -> (x
+ 1)**2 + (y + 1)**2 would be about the furthest you'd want to go (and
even in that example, you can see the real issue comes in how to
correctly "split" constants).

Aaron Meurer

>
>> Please advise.
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "sympy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to sympy+un...@googlegroups.com.
>> To post to this group, send email to sy...@googlegroups.com.
>> Visit this group at http://groups.google.com/group/sympy.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/sympy/9cbb1995-3987-44f1-8c72-6de11e6a4013%40googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAGBZUCarw_f-UbLkcCuOjxWPPM3_W7kWTVaVG4zPAobh6obzUA%40mail.gmail.com.

Hugh

unread,
Nov 4, 2015, 6:13:28 AM11/4/15
to sympy
Thanks Aaron for pointing out the simplification section of the tutorial.

 Actually, collect(expr1, [x11, x12, x13]) does almost what I wanted. I still need to factor a -1 from x12( -x21x33 + x23x31). How would you do it using replace() like what I did? I also tried putting (x12*a).factor() as the value for replace but that didn't work. I had to use Mul() with evaluate = False to get it to do what I wanted.

Hugh

unread,
Nov 4, 2015, 6:14:52 AM11/4/15
to sympy
Thanks Mateusz for sharing the code. I thought it was a clever solution to solve my problem. 

Aaron Meurer

unread,
Nov 4, 2015, 11:36:46 AM11/4/15
to sy...@googlegroups.com
Yes, for now, Mul automatically distributes constants, so you have to
use evaluate=False to factor out something like -1.

Aaron Meurer
> https://groups.google.com/d/msgid/sympy/438ac161-214e-497d-964c-87900be74dcb%40googlegroups.com.

Hugh

unread,
Nov 4, 2015, 12:00:17 PM11/4/15
to sympy
Okay. Thanks again for your help.
Reply all
Reply to author
Forward
0 new messages