ellipse314
ellipse314

Reputation: 47

Unable to invert a function in python

I am trying to solve the following expression for x in python:

y = 1 / f * ln(1+c*x) / x

where c and f are numerical constants. Also f = ln(1+c) - c/(1+c)

Below is my code:

import sympy as sp
import math

y, x, y_LHS = sp.symbols("y x y_LHS", positive=True)
c = 10
f = math.log(1+c) - c/(1+c)
y = 1 / f * sp.log(1+c*x) / x
eqn = sp.Eq(y_LHS, y)
sol = sp.solve(eqn, x)
print(sol)

I am expecting an expression in terms of y_LHS to be printed out. However, after 13 minutes of run time, python gives me a MemoryError saying that Output exceeds the size limit. Is the expression too difficult for sympy to solve? Or am I doing something wrong?

Upvotes: 1

Views: 94

Answers (2)

Oscar Benjamin
Oscar Benjamin

Reputation: 14480

Don't use math.log and use S(10) to get an exact SymPy rational number:

In [25]: import sympy as sp
    ...: 
    ...: y, x, y_LHS = sp.symbols("y x y_LHS", positive=True)
    ...: c = sp.S(10)
    ...: f = sp.log(1+c) - c/(1+c)
    ...: y = 1 / f * sp.log(1+c*x) / x
    ...: eqn = sp.Eq(y_LHS, y)

In [26]: eqn
Out[26]: 
          log(10⋅x + 1)   
y_LHS = ──────────────────
          ⎛  10          ⎞
        x⋅⎜- ── + log(11)⎟
          ⎝  11          ⎠

This has a large number of complex solutions and simplifying those is slow so disable simplification and checking:

In [27]: sol = solve(eqn, x, simplify=False, check=False)

In [28]: len(sol)
Out[28]: 110

We can extract the solutions that don't have complex numbers:

In [29]: r1, r2 = [r for r in result if not r.has(sp.I)]

In [30]: r1
Out[30]: 
           ⎛                           y_LHS  -y_LHS⋅log(11)  ⎞
           ⎜                           ─────  ─────────────── ⎟
           ⎜                             11          10       ⎟
           ⎜-y_LHS⋅(-10 + 11⋅log(11))⋅ℯ     ⋅ℯ                ⎟
       11⋅W⎜──────────────────────────────────────────────────⎟
  1        ⎝                       110                        ⎠
- ── - ────────────────────────────────────────────────────────
  10                   y_LHS⋅(-10 + 11⋅log(11))                

In [31]: r2
Out[31]: 
           ⎛                          y_LHS  -y_LHS⋅log(11) ⎞
           ⎜                          ─────  ───────────────⎟
           ⎜                            11          10      ⎟
           ⎜y_LHS⋅(-10 + 11⋅log(11))⋅ℯ     ⋅ℯ               ⎟
       11⋅W⎜────────────────────────────────────────────────⎟
  1        ⎝                      110                       ⎠
- ── - ──────────────────────────────────────────────────────
  10                  y_LHS⋅(-10 + 11⋅log(11)) 

I think these two solutions are for the two real branches of the Lambert W function.

Upvotes: 1

Prins
Prins

Reputation: 1051

The following will give you an answer expressed in terms of x which is unknown:

from sympy import log
from sympy.abc import c, f, x, y, z

f = log(1 + c) - (c / (1 + c))
expr = 1 / f * log(1 + (c * x)) / x
sol = expr.evalf(subs={c:10})

print(sol)

Upvotes: 0

Related Questions