Reputation: 13
I want to solve the following equation in python.
It can be implemented in Matlab by fzero function as follows:
K=5;
H=6;
u=100;
fun=@(x) -(K*(-H+log(1+H/x)*(x+H)))/(log(2)*x^2*(log2((x+H)/x))^2*(x+H))+u;
xx=fzero(fun,[1e-3,1])
However, I can't find a suitable function in python. scipy.optimize.fsolve
needs the initial value. Moreover, it is always with unexplained errors. Could you please tell me how to implement it in python?
The python code is as follows:
import math
from scipy.optimize import fsolve
K=5
H=6
u=100
def func(x,K,H,u):
return (-(K*(-H+math.log(1+H/x)*(x+H)))/(math.log(2)*(x**2)*(math.log((x+H)/x,2))**2*(x+H))+u)
print(fsolve(func,0.5,args=(K,H,u)))
The error is as follows: return (-(K*(-H+math.log(1+H/x)(x+H)))/(math.log(2)(x**2)*(math.log((x+H)/x,2))*2(x+H))+u) ValueError: math domain error
Upvotes: 1
Views: 8360
Reputation: 4547
The problem you have is linked to the initial guess of your root and how it affects the stability of the implementation of the algortihm. For example, if you swap 0.5 by 1e-3, fsolve converges. I propose below an alternative script which makes use of a bracket algorithm and which converges without problems, provided that the root lies within the bracket and that the images of each end of the bracket are of opposite sign. If any of the latter conditions are not enforced, then the algorithm will let you know about it.
from numpy import log, log2
from scipy.optimize import root_scalar
def func(x, K, H, u):
return (u - K * (log(1 + H / x) * (x + H) - H)
/ log(2) / x ** 2 / log2((x + H) / x) ** 2 / (x + H))
sol = root_scalar(func, args=(5, 6, 100), method='toms748', bracket=[1e-3, 1])
print(sol.root, func(sol.root, 5, 6, 100))
# 0.0784837307625566 4.263256414560601e-14
Upvotes: 4