How to take element-wise logarithm of a matrix in sympy?
Asked Answered
S

2

7

Working with a sympy Matrix or numpy array of sympy symbols, how does one take the element-wise logarithm?

For example, if I have:

m=sympy.Matrix(sympy.symbols('a b c d'))

Then np.abs(m) works fine, but np.log(m) does not work ("AttributeError: log").

Any solutions?

Sarthe answered 16/1, 2014 at 16:53 Comment(8)
Please post the exact traceback.Sphere
@AshwiniChaudhary that is the exact traceback I get.Sarthe
Python's tracebacks are usually 4-5 lines long.Sphere
@Sarthe See this issue on github. Apparently, you can't use numpy.log on object arrays (e.g. sympy arrays).Diminished
@Diminished thanks. So this means that there is no way to take the logarithm of a sympy array/matrix?Sarthe
@Sarthe Are we talking about an actual matrix logarithm (inverse of the matrix exponential) or an element-wise logarithm? I ask because the matrix m you've defined is not square (it's 1-by-4), so it doesn't have a matrix log.Diminished
@Diminished element-wise, like I wrote in the question.Sarthe
@Sarthe Oops, sorry, reading comprehension failure.Diminished
K
8

Use Matrix.applyfunc:

In [6]: M = sympy.Matrix(sympy.symbols('a b c d'))

In [7]: M.applyfunc(sympy.log)
Out[7]:
⎡log(a)⎤
⎢      ⎥
⎢log(b)⎥
⎢      ⎥
⎢log(c)⎥
⎢      ⎥
⎣log(d)⎦

You can't use np.log because that does a numeric log, but you want the symbolic version, i.e., sympy.log.

Koonce answered 17/1, 2014 at 1:5 Comment(5)
Hey, just saw you are the lead developer of sympy - respect! Good job. It would be great if the matrix vectorization was more streamlined similar to Matlab symbolic toolbox.Sarthe
Well, I didn't write most of the code, though. There have been a ton of contributors.Koonce
If you have any suggestion to make it better, let us know.Koonce
is there a way to pass in the base for log?Hibben
The base is given as a second argument to log, but for now, it just divides by log(base), so log(x, y) just gives log(x)/log(y). So in this case you could use M.applyfunc(sympy.log)/sympy.log(base).Koonce
D
1

If you want an elementwise logarithm, and your matrices are all going to be single-column, you should just be able to use a list comprehension:

>>> m = sympy.Matrix(sympy.symbols('a b c d'))
>>> logm = sympy.Matrix([sympy.log(x) for x in m])
>>> logm
Matrix([
[log(a)],
[log(b)],
[log(c)],
[log(d)]])

This is kind of ugly, but you could wrap it in a function for ease, e.g.:

>>> def sp_log(m):
    return sympy.Matrix([sympy.log(x) for x in m])

>>> sp_log(m)
Matrix([
[log(a)],
[log(b)],
[log(c)],
[log(d)]])
Diminished answered 16/1, 2014 at 19:8 Comment(1)
Thanks - so no vectorized solution I guess. I hoped sympy would be a good replacement for Matlab symbolic stuff but I see sympy isn't there yet in terms of handling matrices.Sarthe

© 2022 - 2024 — McMap. All rights reserved.