使numpy fsolve在分段常数函数上工作

时间:2016-12-09 09:47:19

标签: python numpy numerical-methods

我正在尝试使用fsolve来查找各种参数分段定义函数的交点:

max_price = 20.0
b = 0.5
consumption_func = lambda x,b : max_price if x <= b else max_price - (x-b)
func = lambda x: consumption_func(x,b)

bid_start, _, ier, msg = fsolve(lambda x: func(x) - 5.0, 0.0, xtol=0.0001, full_output=True)

但是,如果起点位于函数恒定的范围内,求解器即使对于这个非常简单的函数也找不到交点:

bid_start, _, ier, msg = fsolve(lambda x: func(x) - 5.0, b-0.1, full_output=True)

Out: array([0.4]) #starting point
msg='The iteration is not making good progress, as measured by the 
  improvement from the last ten iterations.'

并且如果它处于非恒定范围内则成功:

bid_start, _, ier, msg = fsolve(lambda x: func(x) - 5.0, b-0.1, full_output=True)

Out: array([15.5]) #correct answer

我猜这与fsolve使用的MINPACK算法有关(可能基于梯度)。在这个简单的例子中,我设法通过传递b作为参数来绕过它,但是在将来我计划使用更复杂的函数;关于如何让fsolve在这里工作的任何想法?

1 个答案:

答案 0 :(得分:1)

通过在等式中添加随机线性函数,可以使fsolve无法卡住。使用随机方程的解作为原始方程的起点。随机方程的解有时接近实方程的原始,这将导致收敛。如果它没有;再试一次随机。

请参阅下面的while循环,该循环一直运行,直到ier的标记fsolve等于原始等式的1,表示成功。

from scipy.optimize import fsolve
import random
max_price = 20.0
b = 0.5
consumption_func = lambda x,b : max_price if x <= b else max_price - (x-b)
func = lambda x: consumption_func(x,b)

ier = 0
while ier != 1:
    k = random.uniform(-0.01, 0.01)
    func_random = lambda x: func(x) + k*x
    x_prelim = fsolve(lambda x: func_random(x) - 5.0, 0.0, xtol=0.01)
    bid_start, _, ier, msg = fsolve(lambda x: func(x) - 5.0, x_prelim, xtol=0.0001, full_output=True)

print(bid_start)