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.
Jason Strimpel
Passionate technologist and experienced leader. My super power is found at the intersection of engineering, sales and leadership.
Updated on September 17, 2020Comments
-
Jason Strimpel over 3 years
Scipy version 0.10.0
Consider the following:
>>> 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) Warning (from warnings module): File "C:\Python27\lib\site-packages\scipy\optimize\minpack.py", line 152 warnings.warn(msg, RuntimeWarning) RuntimeWarning: The iteration is not making good progress, as measured by the improvement from the last ten iterations. >>> print x0 [ -4.87169392e+05 -4.87168392e+05 -4.87167392e+05 -4.87166392e+05 -4.87165392e+05 -4.87164392e+05 -4.87163392e+05 -4.87162392e+05 4.24200000e+01 4.24200000e+01 4.24200000e+01 4.24200000e+01 4.24200000e+01 4.24200000e+01 4.24200000e+01 4.24200000e+01 4.24200000e+01]
First question is how one might suppress the warning message that's being returned?
Second, why might this error be generated in the first place (other than the obvious, that the iteration is not making good progress :) )?
Finally, the root of this function is 42.42 (which is found). Why is
fzero
returning-4.87e+05
as well?