#python #numerical-methods #nonlinear-optimization
#python #численные методы #нелинейная оптимизация
Вопрос:
У меня есть гиперболическая функция, и мне нужно найти ее 0. Я пробовал различные классические методы (деление пополам, Ньютон и так далее).
Вторые производные непрерывны, но недоступны аналитически, поэтому я должен исключить методы, использующие их.
Для целей моего приложения метод Newton является единственным, обеспечивающим достаточную скорость, но он относительно нестабилен, если я недостаточно близок к фактическому нулю. Вот простой скриншот:
Нуль находится где-то около 0,05. и поскольку функция расходится на 0, если я беру начальное значение предположения, превышающее минимальное местоположение определенной степени, то у меня, очевидно, проблемы с асимптотой.
Существует ли в этом случае более стабильный метод, который в конечном итоге предлагал бы скорости, сравнимые с Newton?
Я также думал о преобразовании функции в эквивалентную лучшую функцию с тем же нулем и только затем применял Newton, но я действительно не знаю, какие преобразования я могу выполнить.
Любая помощь будет оценена.
Комментарии:
1. Хотите показать нам уравнение?
2. Привет @YvesDaoust, к сожалению, функция на самом деле не является явной и не имеет замкнутой формы, которую я могу просто опубликовать, более того, вычисляется и собирается в различных модулях. Это просто похоже на гиперболическую функцию, вот почему я использовал этот пример. Однако это scheleton должно быть что-то вроде y = A / x ^ 2 B / x с константами A и B. График, который я опубликовал, просто y = (1 / x) -20
Ответ №1:
Метод Деккера или Брента должен быть почти таким же быстрым, как Ньютон. Если вы хотите что-то простое для самостоятельной реализации, иллинойский вариант метода regula-falsi также достаточно быстр. Все это методы брекетинга, поэтому не должны покидать домен, если начальный интервал находится внутри домена.
def illinois(f,a,b,tol=1e-8):
'''regula falsi resp. false postion method with
the Illinois anti-stalling variation'''
fa = f(a)
fb = f(b)
if abs(fa)<abs(fb): a,fa,b,fb = b,fb,a,fa
while(np.abs(b-a)>tol):
c = (a*fb-b*fa)/(fb-fa)
fc = f(c)
if fa*fc < 0:
fa *= 0.5
else:
a, fa = b, fb
b, fb = c, fc
return b, fb
Комментарии:
1. спасибо, regula-falsi, на самом деле хорошо справляется с моей проблемой. Теперь я буду тестировать на разных прогонах
Ответ №2:
Как насчет использования log(x) вместо x?
Комментарии:
1. Это создает разрыв при x = 1. Также я не думаю, что он сохраняет позицию 0
2. функция это что-то в виде 1 / x
3. Это не так …
log(1) = 0
, но оно непрерывное. Затем, когда вы нашлиx
, конечно, вы беретеexp(x)
, чтобы получить оригиналx
.4. тогда я не понял, вы предлагаете построить функцию 1 / log (x), скажем, найти 0 с помощью newton или эквивалента, а затем exp (x), чтобы получить исходный результат?
5. Вы оставляете значения функции такими, какие они есть (я предполагаю, что это не просто ваша актуальная проблема
1/x - 20
, потому что тогдаx=1/20
и весь вопрос тривиален), но изобретаетеz = log(x)
и рассматриваете новую функциюy = f(z)
. Если вы построите это, это может быть более линейным и может быть решено Newton без проблем.
Ответ №3:
В вашем случае ответ @sams-studio может сработать, и я бы попробовал это в первую очередь. В аналогичной ситуации — также в многовариантном контексте — я использовал гомотопические методы Ньютона.
По сути, вы ограничиваете шаг Ньютона до тех пор, пока абсолютное значение y
не уменьшится. Самый дешевый способ реализации — это половина шага Ньютона, если y
увеличивается с последнего шага. После нескольких шагов вы возвращаетесь к Newton с полной сходимостью второго порядка.
Disclamer: Если вы можете связать свое решение (вы знаете максимум x
), ответ от @Lutz Lehmann также был бы моим первым выбором.
Комментарии:
1. На самом деле у меня нет верхней границы, но поскольку мой ‘x’ — это толщина, он не может идти до бесконечности, но я не знаю верхнего значения априори. Я всегда могу вставить искусственную верхнюю границу, которая достаточно велика. Я посмотрю на гомотопические методы Ньютона. спасибо за предложение