简体   繁体   中英

How to rearrange a complicated equation by Python

I want to rearrange the below equation for the variable r by using Python.

P = C * ((1-(1+r)**(-n)))/r + fv*(1+r)**(-n)
to
r = blabla...

I understood that sympy is related to a rearranging task like this. So, I wrote the below codes.

# Solve the equation for r
import sympy
from sympy import symbols

P, C, r, n, fv = sympy.symbols('P C r n fv')
eq = sympy.Eq(P, C * ((1-1/(1+r)**n))/r + fv/(1+r)**n)
sympy.solve(eq, r)

However, I got the error like this.

NotImplementedError                       Traceback (most recent call last)
<ipython-input-47-a183add313da> in <module>
      3 P, C, r, n, fv = sympy.symbols('P C r n fv')
      4 eq = sympy.Eq(P, C * ((1-1/(1+r)**n))/r + fv/(1+r)**n)
----> 5 sympy.solve(eq, r)

~\Anaconda3\lib\site-packages\sympy\solvers\solvers.py in solve(f, *symbols, **flags)
   1169     ###########################################################################
   1170     if bare_f:
-> 1171         solution = _solve(f[0], *symbols, **flags)
   1172     else:
   1173         solution = _solve_system(f, symbols, **flags)

~\Anaconda3\lib\site-packages\sympy\solvers\solvers.py in _solve(f, *symbols, **flags)
   1740 
   1741     if result is False:
-> 1742         raise NotImplementedError('\n'.join([msg, not_impl_msg % f]))
   1743 
   1744     if flags.get('simplify', True):

NotImplementedError: multiple generators [r, (r + 1)**n]
No algorithms are implemented to solve equation -C*(1 - (r + 1)**(-n))/r + P - fv*(r + 1)**(-n)

I guess the calculation for power is not available as to sympy. Do you know how to execute this kind of complicated rearrangement for a equation? I am using Python==3.7, sympy==1.4.

This is not a trivial equation to solve. It doesn't have to do with the calculation for power though, it's just that the equation is too complicated for sympy to solve for r.

However, if there are specific values for the other variables and you need to solve for r (ie find a zero for a nontrivial equation), you can use the numerical solver: nsolve

# Solve the equation for r
from sympy import var, Eq, solve

var('C, r, n, fv, P', positive = True)

# this throws an error: no algorithms are implemented to solve equation
equation = Eq(P, C * ((1-1/(1+r)**n))/r + fv/(1+r)**n)

# a simple calculation for power works fine
equation = Eq(P, (1+r)**n)
solve(equation, r)

The equation you are trying to solve is:

In [23]: eq                                                                                                                       
Out[23]: 
      ⎛           -n⎞               
    C⋅⎝1 - (r + 1)  ⎠             -n
P = ───────────────── + fv⋅(r + 1)  
            r 

We can rearrange this into a polynomial like so

In [24]: eq2 = Eq(eq.lhs * (1+r)**n * r, eq.rhs * (1+r)**n * r).expand()                                                          

In [25]: eq2                                                                                                                      
Out[25]: 
           n            n           
P⋅r⋅(r + 1)  = C⋅(r + 1)  - C + fv⋅r

Now we see that this is a polynomial except that the exponent n is symbolic. In general this kind of equation will not have a solution expressible in closed form - that is why sympy has no algorithms for this particular case (it is not a limitation of sympy itself).

It is possible to solve this equation numerically but numerical solution only works if we have numerical values for each of the parameters. If we substitute numbers for the parameters then nsolve can find the solution numerically:

In [26]: eq3 = eq.subs({P:1, C:2, fv:1, n:100})                                                                                   

In [27]: eq3                                                                                                                      
Out[27]: 
                   ⎛        1     ⎞
                 2⋅⎜1 - ──────────⎟
                   ⎜           100⎟
        1          ⎝    (r + 1)   ⎠
1 = ────────── + ──────────────────
           100           r         
    (r + 1)                        

In [28]: nsolve(eq3, r, 1)                                                                                                        
Out[28]: 2.00000000000000

But note that the solutions to this equation are not unique for example -2 is also a solution here:

In [52]: nsolve(eq3, r, -1.9)                                                                                                     
Out[52]: -2.00000000000000

This particular equation has something like 100 roots although not necessarily all real.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM