Python scipy.optimize: Using fsolve with multiple first guesses
Doing this might make you miss something important, but, to silence the warning message you could use warnings.filterwarnings
:
import warnings
warnings.filterwarnings('ignore', 'The iteration is not making good progress')
import math
from scipy.optimize import fsolve
import numpy as np
def p(s, l, k, q):
p = q * np.maximum(s - k, 0.0)
return (p + math.copysign(l, -q)) * math.fabs(q) * 100.0
x0 = fsolve(p, np.arange(33.86, 50.86, 1.0),
args=(1.42, 41.0, -1.0), xtol=1e-06, maxfev=500)
print(x0)
In fact, p(x0, 1.42, 41.0, -1)
is not close to zero, so fsolve
is correctly warning you that it failed to find a solution.
PS. When you say
fsolve(p, np.arange(33.86, 50.86, 1.0),...)
you are telling fsolve
that your initial guess for s
is the numpy array np.arange(33.86, 50.86, 1.0)
. The whole array is being passed in to p
at once.
Notice that np.arange(33.86, 50.86, 1.0)
has length 17 and so does x0
. That is because fsolve
thinks it is looking for an array of length 17 that solves p
.
I think perhaps you meant s
to be a float? In that case, you can only pass in one float value for your initial guess:
fsolve(p, 41.0, args = (1.42, 41.0, -1.0), xtol=1e-06, maxfev=500)
For example,
import math
import scipy.optimize as optimize
import numpy as np
def p(s, l, k, q):
p = q * np.maximum(s - k, 0.0)
return (p + math.copysign(l, -q)) * math.fabs(q) * 100.0
args = (1.42, 41.0, -1.0)
result = optimize.fsolve(p, 41.0, args=args, xtol=1e-06, maxfev=500)
print(result)
yields
[ 42.42]
fsolve
does a decent job of zeroing-in on the root if the initial guess is >= 41.0 (the value of k
) but fails when the initial guess is < 41.0.
My guess is that this is due to np.maximum
not changing for many guesses for s
. So fsolve
does not know whether to increase or decrease s
and is apt to guess wrong and move s
farther and farther from the root.