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.