Заставить numy fsolve работать над кусочно-постоянными функциями
Я пытаюсь использовать 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
Я предполагаю, что это как-то связано с алгоритмом MINPACK, который использует fsolve (возможно, на основе градиента). В этом простом случае мне удается обойти это, передав b в качестве параметра, но в будущем я планирую работать с более сложными функциями; Любая идея о том, как я могу заставить fsolve работать здесь?
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)