fsolve всегда возвращает предположение / оценку

Я впервые использую функцию scipy optimize.fsolve, чтобы найти корни уравнения. Проблема в том, что любое число, которое я использую в качестве значения предположения / оценки, - это то, что я получаю в качестве своего ответа (с точностью до 8 знаков после запятой). При использовании full_output = True я получаю флаг выхода равным «1», что должно означать, что «Решение сошлось», что, насколько я понимаю, должно означать, что результат действительно является корнем уравнения.

Я знаю, что существует конечное число различных корней (которые разнесены друг на друга), поскольку, когда я рисую уравнение, я могу их видеть. Кроме того, fsolve не работает (выдает ошибки выхода), когда я ввожу начальную точку в диапазон, который должен возвращать неопределенные значения (деление на ноль, квадратный корень из отрицательного значения). Но помимо этого он всегда возвращает начальную точку как корень.

Я тестировал fsolve с очень простым уравнением, и он работал нормально, поэтому я знаю, что импортирую все, что мне нужно, и должен правильно использовать fsolve. Я также пробовал возиться с некоторыми входными аргументами, но я их не очень хорошо понимаю и, похоже, ничего не изменилось).

Ниже приведен соответствующий код (E - единственная переменная, все остальное имеет ненулевое значение):

def func(E):
    s = sqrt(c_sqr * (1 - E / V_0))
    f = s / tan(s) + sqrt(c_sqr - s**2)
    return f

guess = 3
fsolve(func, guess)

который просто выводит «3» и говорит: «Решение конвергировано.», хотя самые близкие решения должны быть примерно на уровне 2,8 и 4,7.

Кто-нибудь знает, как это исправить и получить правильный ответ (с помощью fsolve)?


person scaevity    schedule 19.12.2011    source источник
comment
Возможно, вы просто очень хорошо разбираетесь в догадках.   -  person Michael J. Barber    schedule 19.12.2011
comment
Можете ли вы указать значения для V_0 и c_sqr? Пробовал ставить c_sqr = 100 и V_0 = 10, и он правильно сходится в корень 2.90496355.   -  person Paolo Capriotti    schedule 19.12.2011


Ответы (2)


Я думаю, что ваше уравнение не делает того, что вы думаете. Во-первых, когда я пробую его, это не дает никаких результатов; он возвращает число, близкое к предположению. Это очень нестабильно, и это, кажется, сбивает с толку fsolve. Например:

>>> V_0 = 100
>>> c_sqr = 3e8 ** 2
>>> guess = 5
>>> fsolve(func, guess)
array([ 5.00000079])

Это не 5. Это даже не 5 в пределах машинной точности. Это также не корень уравнения:

>>> func(5.00000079)
2114979.3239706755

Но поведение уравнения в любом случае довольно непредсказуемо:

>>> func(5.0000008)
6821403.0196130127
>>> func(5.0000006)
-96874198.203683496

Очевидно, где-то там есть нулевой переход. Я бы посоветовал хорошенько взглянуть на свое уравнение. Убедитесь, что вы указываете аргумент tan в радианах, например.

person ptomato    schedule 19.12.2011

Вы пытались изменить свою функцию на что-то действительно тривиальное? Нравится:

#!/usr/bin/python
from scipy.optimize import fsolve

def func(E):
#    s = sqrt(c_sqr * (1 - E / V_0))
#    f = s / tan(s) + sqrt(c_sqr - s**2)
    f = E**2 -3.
    return f

guess = 9

sol=fsolve(func, guess)
print sol, func(sol)

Для меня приведенный выше код сходится там, где он должен.

Кроме того, в предоставленном вами коде --- что такое c_str и V_0? Если на самом деле ваша функция зависит от нескольких переменных, и вы обрабатываете все из них, кроме одной, как постоянные параметры, используйте аргумент args функции fsolve, например:

#!/usr/bin/python
from scipy.optimize import fsolve
from numpy import sqrt

def func(E,V_0):
    #s = sqrt(c_sqr * (1 - E / V_0))
    #f = s / tan(s) + sqrt(c_sqr - s**2)
    f = E**2 -V_0
    return f

VV=4.
guess = 9
sol=fsolve(func, guess, args=(VV))

print sol, func(sol,VV) 
person ev-br    schedule 19.12.2011