Метод Бренца - Brents method - Wikipedia
В числовой анализ, Метод Брента это алгоритм поиска корней объединение метод деления пополам, то секущий метод и обратная квадратичная интерполяция. Он надежен на деление пополам, но может быть таким же быстрым, как и некоторые из менее надежных методов. Алгоритм пытается использовать потенциально быстро сходящийся метод секущей или обратную квадратичную интерполяцию, если это возможно, но при необходимости возвращается к более надежному методу деления пополам. Метод Брента обусловлен Ричард Брент[1] и основан на более раннем алгоритме Теодорус Деккер.[2] Следовательно, метод также известен как Метод Брента – Деккера.
Метод Чандрупатлы - это вариант, который проще и быстрее сходится для функций, которые имеют плоскую форму вокруг своих корней (что означает, что они имеют несколько корней или близко расположенные корни).[3][4]
Метод Деккера
Идея объединить метод деления пополам с методом секущей восходит к Деккер (1969).
Предположим, что мы хотим решить уравнение ж(Икс) = 0. Как и в случае с методом деления пополам, нам нужно инициализировать метод Деккера двумя точками, скажем а0 и б0, так что ж(а0) и ж(б0) имеют противоположные знаки. Если ж непрерывно на [а0, б0], теорема о промежуточном значении гарантирует существование решения между а0 и б0.
В каждой итерации участвуют три момента:
- бk это текущая итерация, то есть текущее предположение для корня ж.
- аk является «контрапунктом», т. е. такой точкой, что ж(аk) и ж(бk) имеют противоположные знаки, поэтому интервал [аk, бk] содержит решение. Кроме того, |ж(бk) | должно быть меньше или равно |ж(аk) |, так что бk это лучшее предположение для неизвестного решения, чем аk.
- бk−1 это предыдущая итерация (для первой итерации мы устанавливаем бk−1 = а0).
Вычисляются два предварительных значения для следующей итерации. Первый задается линейной интерполяцией, также известной как метод секущей:
а второй - методом деления пополам
Если результат метода секущих, s, лежит строго между бk и м, то следующая итерация (бk+1 = s), в противном случае используется средняя точка (бk+1 = м).
Затем значение нового контрапункта выбирается так, чтобы ж(аk+1) и ж(бk+1) имеют противоположные знаки. Если ж(аk) и ж(бk+1) имеют противоположные знаки, то контрапункт остается прежним: аk+1 = аk. Иначе, ж(бk+1) и ж(бk) имеют противоположные знаки, поэтому новый контрапункт становится аk+1 = бk.
Наконец, если |ж(аk+1)| < |ж(бk+1) |, то аk+1 вероятно лучшее предположение для решения, чем бk+1, а значит, и значения аk+1 и бk+1 обмениваются.
На этом заканчивается описание единственной итерации метода Деккера.
Метод Деккера работает хорошо, если функция ж ведет себя достаточно хорошо. Однако есть обстоятельства, при которых каждая итерация использует метод секущей, но итерация повторяет бk сходятся очень медленно (в частности, |бk − бk−1| может быть сколь угодно малым). В этом случае метод Деккера требует гораздо большего количества итераций, чем метод деления пополам.
Метод Брента
Брент (1973) предложила небольшую модификацию, чтобы избежать этой проблемы. Он вставил дополнительный тест, который должен быть удовлетворен, прежде чем результат метода секущей будет принят в качестве следующей итерации. Одновременно должны выполняться два неравенства: с учетом определенного числового допуска , если на предыдущем шаге использовался метод деления пополам, неравенство
должен удерживаться для выполнения интерполяции, в противном случае выполняется метод деления пополам и его результат используется для следующей итерации.
Если на предыдущем шаге выполнялась интерполяция, то выполняется неравенство
вместо этого используется для выполнения следующего действия (для выбора) интерполяции (когда неравенство истинно) или метода деления пополам (когда неравенство не верно).
Кроме того, если на предыдущем шаге использовался метод деления пополам, неравенство
должен выполняться, иначе будет выполнен метод деления пополам, и его результат будет использоваться для следующей итерации. Если на предыдущем шаге выполнялась интерполяция, то выполняется неравенство
вместо этого используется.
Эта модификация гарантирует, что на k-й итерации шаг деления пополам будет выполнен не более чем за дополнительных итераций, потому что вышеуказанные условия вынуждают размеры последовательных шагов интерполяции уменьшаться вдвое каждые две итерации, и не более чем после итераций размер шага будет меньше чем , который вызывает шаг пополам. Брент доказал, что его метод требует не более N2 итераций, где N обозначает количество итераций для метода деления пополам. Если функция ж хорошо себя ведет, то метод Брента обычно использует либо обратную квадратичную, либо линейную интерполяцию, и в этом случае он сходится сверхлинейно.
Кроме того, метод Брента использует обратная квадратичная интерполяция вместо линейная интерполяция (как используется секущим методом). Если ж(бk), ж(аk) и ж(бk−1) отчетливы, это немного увеличивает эффективность. Как следствие, условие принятия s (значение, предложенное либо линейной интерполяцией, либо обратной квадратичной интерполяцией) необходимо изменить: s должен находиться между (3аk + бk) / 4 и бk.
Алгоритм
Эта секция возможно содержит оригинальные исследования.Февраль 2019 г.) (Узнайте, как и когда удалить этот шаблон сообщения) ( |
Вход а, б, и (указатель на) функцию для жвычислить ж(а) вычислить ж(б)если ж(а)ж(б) ≥ 0 тогда функция выхода, потому что корень не заключен в квадратные скобки.конец, еслиесли |ж(а)| < |ж(б)| тогда замена (а,б)конец, еслиc := анабор mflagповторять, пока ж(б или же s) = 0 или же |б − а| является достаточно мал (конвергенция) если ж(а) ≠ ж(c) и ж(б) ≠ ж(c) тогда (обратная квадратичная интерполяция ) еще (секущий метод ) конец, если если (условие 1) s не является между и б или же (условие 2) (mflag является набор и |s−б| ≥ |б−c|/2) или же (условие 3) (mflag является очищен и |s−б| ≥ |c−d|/2) или же (условие 4) (mflag является набор и |б−c| < |δ|) или же (условие 5) (mflag является очищен и |c−d| < |δ|) тогда (метод деления пополам ) набор mflag еще Чисто mflag конец, если вычислить ж(s) d := c (d здесь назначается впервые; он не будет использоваться выше на первой итерации, поскольку установлен mflag) c := б если ж(а)ж(s) < 0 тогда б := s еще а := s конец, если если |ж(а)| < |ж(б)| тогда замена (а,б) конец, есликонец повторениявыход б или s (вернуть корень)
Пример
Предположим, что мы ищем нуль функции, определенной формулой ж(Икс) = (Икс + 3)(Икс − 1)2.
Мы принимаем [а0, б0] = [−4, 4/3] как наш начальный интервал.
У нас есть ж(а0) = −25 и ж(б0) = 0,48148 (все числа в этом разделе округлены), поэтому условия ж(а0) ж(б0) <0 и |ж(б0)| ≤ |ж(а0) | довольны.
- В первой итерации мы используем линейную интерполяцию между (б−1, ж(б−1)) = (а0, ж(а0)) = (−4, −25) и (б0, ж(б0)) = (1,33333, 0,48148), что дает s = 1,23256. Это находится между (3а0 + б0) / 4 и б0, поэтому это значение принято. Более того, ж(1.23256) = 0.22891, поэтому мы полагаем а1 = а0 и б1 = s = 1.23256.
- Во второй итерации мы используем обратную квадратичную интерполяцию между (а1, ж(а1)) = (−4, −25) и (б0, ж(б0)) = (1,33333, 0,48148) и (б1, ж(б1)) = (1,23256, 0,22891). Это дает 1,14205, что находится между (3а1 + б1) / 4 и б1. Кроме того, неравенство | 1.14205 - б1| ≤ |б0 − б−1| / 2 удовлетворяется, поэтому это значение принято. Более того, ж(1,14205) = 0,083582, поэтому мы полагаем а2 = а1 и б2 = 1.14205.
- В третьей итерации мы используем обратную квадратичную интерполяцию между (а2, ж(а2)) = (−4, −25) и (б1, ж(б1)) = (1,23256, 0,22891) и (б2, ж(б2)) = (1,14205, 0,083582). Это дает 1,09032, что находится между (3а2 + б2) / 4 и б2. Но здесь вступает в действие дополнительное условие Брента: неравенство | 1.09032 - б2| ≤ |б1 − б0| / 2 не выполняется, поэтому это значение отклоняется. Вместо этого середина м = −1,42897 интервала [а2, б2] вычисляется. У нас есть ж(м) = 9.26891, поэтому положим а3 = а2 и б3 = −1.42897.
- В четвертой итерации мы используем обратную квадратичную интерполяцию между (а3, ж(а3)) = (−4, −25) и (б2, ж(б2)) = (1,14205, 0,083582) и (б3, ж(б3)) = (-1,42897, 9,26891). Это дает 1,15448, что не находится в интервале между (3а3 + б3) / 4 и б3). Следовательно, он заменяется средней точкой м = −2,71449. У нас есть ж(м) = 3.93934, поэтому положим а4 = а3 и б4 = −2.71449.
- На пятой итерации обратная квадратичная интерполяция дает −3,45500, что лежит в требуемом интервале. Однако предыдущая итерация была делением пополам, поэтому неравенство | −3.45500 - б4| ≤ |б4 − б3| / 2 должны быть удовлетворены. Это неравенство неверно, поэтому мы используем среднюю точку м = -3,35724. У нас есть ж(м) = −6.78239, поэтому м становится новым контрапунктом (а5 = −3,35724) и итерация остается прежней (б5 = б4).
- На шестой итерации мы не можем использовать обратную квадратичную интерполяцию, потому что б5 = б4. Следовательно, мы используем линейную интерполяцию между (а5, ж(а5)) = (−3,35724, −6,78239) и (б5, ж(б5)) = (-2,71449, 3,93934). Результат s = −2.95064, что удовлетворяет всем условиям. Но поскольку итерация не изменилась на предыдущем шаге, мы отклоняем этот результат и возвращаемся к делению пополам. Мы обновляем s = -3,03587, и ж(s) = -0.58418.
- В седьмой итерации мы снова можем использовать обратную квадратичную интерполяцию. Результат s = −3.00219, что удовлетворяет всем условиям. Сейчас же, ж(s) = −0,03515, поэтому положим а7 = б6 и б7 = −3.00219 (а7 и б7 меняются местами, так что условие |ж(б7)| ≤ |ж(а7) | доволен). (Правильный : линейная интерполяция )
- На восьмой итерации мы не можем использовать обратную квадратичную интерполяцию, потому что а7 = б6. Линейная интерполяция дает s = −2,99994, что принято. (Правильный : )
- В следующих итерациях корень Икс = −3 приближается быстро: б9 = −3 + 6·10−8 и б10 = −3 − 3·10−15. (Правильный : Iter 9: ж(s) = −1.4 × 10−7, Iter 10: ж(s) = 6.96 × 10−12)
Реализации
- Брент (1973) опубликовал Алгол 60 выполнение.
- Netlib содержит перевод этой реализации на Фортран с небольшими изменениями.
- В PARI / GP метод
решать
реализует метод. - Другие реализации алгоритма (на C ++, C и Fortran) можно найти в Числовые рецепты книги.
- В Apache Commons Математическая библиотека реализует алгоритм в Ява.
- В SciPy Модуль optimize реализует алгоритм в Python (язык программирования)
- Стандартная библиотека Modelica реализует алгоритм в Modelica.
- В
униор
функция реализует алгоритм в R (программное обеспечение). - В
fzero
функция реализует алгоритм в MATLAB. - В Boost (библиотеки C ++) реализует два алгоритма на основе метода Брента в C ++ в инструментарии Math:
- Минимизация функции при minima.hpp с примером минимумы функции определения местоположения.
- В поиске корней реализован новый TOMS748, более современный и эффективный алгоритм, чем оригинал Брента, на TOMS748, и Поиск корней Boost.Math который использует TOMS748 внутри с Примеры.
- В Optim.jl пакет реализует алгоритм в Юля (язык программирования)
Рекомендации
- ^ Брент 1973
- ^ Деккер 1969
- ^ Чандрупатла, Тирупати Р. (1997). «Новый гибридный квадратичный алгоритм / алгоритм деления пополам для нахождения нуля нелинейной функции без использования производных». Достижения в инженерном программном обеспечении. 28 (3): 145–149. Дои:10.1016 / S0965-9978 (96) 00051-8.
- ^ "Десять маленьких алгоритмов, часть 5: квадратичная интерполяция экстремума и метод Чандрупатлы - Джейсон Сакс".
- Брент, Р. П. (1973), "Глава 4: Алгоритм с гарантированной сходимостью для нахождения нуля функции", Алгоритмы минимизации без производных, Энглвуд Клиффс, Нью-Джерси: Прентис-Холл, ISBN 0-13-022335-2
- Деккер, Т. Дж. (1969), «Нахождение нуля с помощью последовательной линейной интерполяции», у Dejon, B .; Хенрици, П. (ред.), Конструктивные аспекты основной теоремы алгебры, Лондон: Wiley-Interscience, ISBN 978-0-471-20300-1
дальнейшее чтение
- Аткинсон, Кендалл Э. (1989). «Раздел 2.8.». Введение в численный анализ (2-е изд.). Джон Уайли и сыновья. ISBN 0-471-50023-2.
- Press, W. H .; Теукольский, С. А .; Vetterling, W. T .; Фланнери, Б. П. (2007). «Раздел 9.3. Метод Ван Вейнгаардена – Деккера – Брента». Числовые рецепты: искусство научных вычислений (3-е изд.). Нью-Йорк: Издательство Кембриджского университета. ISBN 978-0-521-88068-8.
- Алефельд, Г. Э .; Potra, F.A .; Ши Исюнь (сентябрь 1995 г.). «Алгоритм 748: заключительные нули непрерывных функций». Транзакции ACM на математическом ПО. 21 (3): 327–344. Дои:10.1145/210089.210111.
внешняя ссылка
- zeroin.f в Netlib.
- модуль brent в C ++ (также C, Fortran, Matlab) Джон Буркардт
- GSL выполнение.
- Boost C ++ выполнение.
- Python (Scipy) выполнение