Sergey Dovgal
Sergey Dovgal

Reputation: 664

Sympy: how to simplify logarithm of product into sum of logarithms?

To motivate the question, sympy.concrete has some efficient tools to manipulate symbolic sums. In order to apply these tools to symbolic products, one has to take a logarithm. However, straightforward taking the logarithm doesn't automatically give the transformation:

import sympy as sp
sp.init_printing() # display math as latex
z = sp.Symbol('z')
j,k = sp.symbols('j,k')
Prod = sp.Product( (z + sp.sqrt(1-4*j*z**2))**(-1), (j,1,k) )
sp.log(Prod)

gives

\log{\left (\prod_{j=1}^{k} \frac{1}{z + \sqrt{- 4 j z^{2} + 1}} \right )}

in all possible variations:

sp.log(Prod)
sp.log(Prod).expand()
sp.log(Prod).simplify()
sp.expand_log(sp.log(Prod),force=True)

Question. How to convert it into sum of logarithms?

Related:

How to simplify logarithm of exponent in sympy?

Upvotes: 5

Views: 2067

Answers (1)

Sergey Dovgal
Sergey Dovgal

Reputation: 664

Assuming that there is no standard function with desired behaviour yet, I wrote my own, mimicking the behaviour of

sp.expand_log(expr, force=True)

This code recursively goes over expression trying to locate patterns log(product) and replaces them by sum(log). This also supports multi-index summation.

Code.

def concrete_expand_log(expr, first_call = True):
    import sympy as sp
    if first_call:
        expr = sp.expand_log(expr, force=True)
    func = expr.func
    args = expr.args
    if args == ():
        return expr
    if func == sp.log:
        if args[0].func == sp.concrete.products.Product:
            Prod = args[0]
            term = Prod.args[0]
            indices = Prod.args[1:]
            return sp.Sum(sp.log(term), *indices)
    return func(*map(lambda x:concrete_expand_log(x, False), args))

Example.

import sympy as sp
from IPython.display import display
sp.init_printing() # display math as latex
z = sp.Symbol('z')
j,k,n = sp.symbols('j,k,n')
Prod = sp.Product( (z + sp.sqrt(1-4*j*z**2))**(-1), (j,0,k))
expr = sp.log(z**(n-k) * (1 - sp.sqrt((1 - 4*(k+2)*z**2)/(1-4*(k+1)*z**2)) ) * Prod)
display(expr)

\log{\left (z^{- k + n} \left(- \sqrt{\frac{- z^{2} \left(4 k + 8\right) + 1}{- z^{2} \left(4 k + 4\right) + 1}} + 1\right) \prod_{j=0}^{k} \frac{1}{z + \sqrt{- 4 j z^{2} + 1}} \right )}

display(concrete_expand_log(expr))

\left(- k + n\right) \log{\left (z \right )} + \log{\left (- \sqrt{\frac{- z^{2} \left(4 k + 8\right) + 1}{- z^{2} \left(4 k + 4\right) + 1}} + 1 \right )} + \sum_{j=0}^{k} \log{\left (\frac{1}{z + \sqrt{- 4 j z^{2} + 1}} \right )}

Upvotes: 7

Related Questions