Методы дихотомии
Материал из MachineLearning.
(Новая: == Введение == '''Метод дихотомии''' - достаточно широко используемый метод поиска, известный также как '''...) |
|||
Строка 1: | Строка 1: | ||
== Введение == | == Введение == | ||
+ | Существует довольно очевидная теорема: ''"Если непрерывная функция на концах некоторого интервала имеет значения разных знаков, то внутри этого интервала у нее есть корень (как минимум, один, но м.б. и несколько)"''. На базе этой теоремы построено численное нахождение приближенного значения корня функции. Обобщенно этот метод называется '''дихотомией''', т.е. '''делением отрезка на две части'''. Обобщенный алгоритм выглядит так: | ||
- | + | #Задать начальный интервал <tex>[X_{left}..X_{right}]</tex>; | |
- | # | + | #Убедиться, что на концах функция имеет разный знак; |
- | # | + | #Повторять |
+ | #*выбрать внутри интервала точку <tex>X</tex>; | ||
+ | #*сравнить знак функции в точке <tex>X</tex> со знаком функции в одном из концов; | ||
+ | #**если совпадает, то переместить этот конец интервала в точку <tex>X</tex>, | ||
+ | #**иначе переместить в точку <tex>X</tex> другой конец интервала; | ||
+ | :пока не будет достигнута нужная точность. | ||
- | == Метод | + | Варианты метода дихотомии различаются выбором точки деления. Рассмотрим варианты дихотомии: '''метод половинного деления''' и '''метод хорд'''. |
- | === Изложение метода === | + | == Метод половинного деления== |
- | Перед применением метода | + | |
+ | '''Метод половинного деления''' известен также как '''метод бисекции'''. В данном методе интервал делится ровно пополам. | ||
+ | |||
+ | Такой подход обеспечивает гарантированную сходимость метода независимо от сложности функции - и это весьма важное свойство. Недостатком метода является то же самое - метод никогда не сойдется быстрее, т.е. сходимость метода всегда равна сходимости в наихудшем случае. | ||
+ | |||
+ | Метод половинного деления: | ||
+ | #Один из простых способов поиска ''корней функции одного аргумента''. | ||
+ | #Применяется для нахождения ''значений действительно-значной функции'', определяемому по какому-либо критерию (это может быть сравнение на ''минимум'', ''максимум'' или конкретное число). | ||
+ | |||
+ | === Метод половинного деления как метод поиска корней функции === | ||
+ | ==== Изложение метода ==== | ||
+ | Перед применением метода для поиска корней функции необходимо отделить корни одним из известных способов, например, графическим методом. Отделение корней необходимо в случае, если неизвестно на каком отрезке нужно искать корень. | ||
- | Будем считать, что корень <tex>t</tex> функции <tex>f(x)=0</tex> отделён на отрезке <tex>[a,b]</tex>. Задача заключается в том, чтобы найти и уточнить этот корень методом половинного деления | + | Будем считать, что корень <tex>t</tex> функции <tex>f(x)=0</tex> отделён на отрезке <tex>[a,b]</tex>. Задача заключается в том, чтобы найти и уточнить этот корень методом половинного деления. Другими словами, требуется найти приближённое значение корня с заданной точностью <tex>\eps</tex>. |
Пусть функция <tex>f</tex> непрерывна на отрезке <tex>[a,b]</tex>, | Пусть функция <tex>f</tex> непрерывна на отрезке <tex>[a,b]</tex>, | ||
Строка 25: | Строка 42: | ||
Для того, чтобы найти приближённое значение корня с точностью до <tex> \eps >0</tex>, необходимо остановить процесс половинного деления на таком шаге <tex>n</tex>, на котором <tex>|b_n-c_n|<\eps</tex> и вычислить <tex>x=\frac {a_n+b_n}{2}</tex>. Тогда можно взять <tex>t\approx x</tex>. | Для того, чтобы найти приближённое значение корня с точностью до <tex> \eps >0</tex>, необходимо остановить процесс половинного деления на таком шаге <tex>n</tex>, на котором <tex>|b_n-c_n|<\eps</tex> и вычислить <tex>x=\frac {a_n+b_n}{2}</tex>. Тогда можно взять <tex>t\approx x</tex>. | ||
- | === Реализация метода на С++ и числовой пример === | + | ==== Реализация метода на С++ и числовой пример ==== |
- | Решим уравнение <tex>4-e^x-2x^2=0</tex> методом | + | Решим уравнение <tex>4-e^x-2x^2=0</tex> методом половинного деления. Графическим методом находим отрезок <tex>[0; \,1]</tex>, которому принадлежит искомый корень. Так как <tex>f(0)\cdot f(1)<0</tex>, то принимаем <tex>a=0, \; b=1</tex>. |
Ниже приведен пример программы на [[C++|Си++]], которая решает поставленную задачу. | Ниже приведен пример программы на [[C++|Си++]], которая решает поставленную задачу. | ||
Строка 113: | Строка 130: | ||
</center> | </center> | ||
- | == Метод | + | === Метод половинного деления как метод оптимизации === |
- | [[Изображение:09 01.gif|frame|Рис. 1. Поиск экстремума функции <tex>F(x)</tex> методом | + | [[Изображение:09 01.gif|frame|Рис. 1. Поиск экстремума функции <tex>F(x)</tex> методом половинного деления]] |
- | [[Изображение:09 02.gif|frame|Рис. 2. Схема алгоритма метода | + | [[Изображение:09 02.gif|frame|Рис. 2. Схема алгоритма метода половинного деления]] |
'''''Однопараметрическая оптимизация''''' (поиск экстремумов функций одной переменной) является самостоятельной и часто встречаемой задачей. Кроме того, к ней сводится гораздо более сложная задача - поиск экстремума функции многих переменных. | '''''Однопараметрическая оптимизация''''' (поиск экстремумов функций одной переменной) является самостоятельной и часто встречаемой задачей. Кроме того, к ней сводится гораздо более сложная задача - поиск экстремума функции многих переменных. | ||
- | Рассмотрим метод | + | Рассмотрим метод половинного деления как простейший однопараметрический метод безусловной оптимизации. Данный метод является ''методом прямого поиска''. В нем при поиске экстремума целевой функции используются только вычисленные значения целевой функции. |
Дана функция <tex>F(x)</tex>. Необходимо найти <tex>\overline{x}</tex>, доставляющий минимум (или максимум) функции <tex>F(x)</tex> на интервале <tex>[a,b]</tex> с заданной точностью <tex>\varepsilon</tex>, т.е. найти | Дана функция <tex>F(x)</tex>. Необходимо найти <tex>\overline{x}</tex>, доставляющий минимум (или максимум) функции <tex>F(x)</tex> на интервале <tex>[a,b]</tex> с заданной точностью <tex>\varepsilon</tex>, т.е. найти | ||
Строка 139: | Строка 156: | ||
- | Схема алгоритма метода | + | Схема алгоритма метода представлена на рис 2. |
На рис 2: | На рис 2: | ||
Строка 146: | Строка 163: | ||
При выводе <tex>x</tex> – координата точки, в которой функция <tex>F(x)</tex> имеет минимум (или максимум), <tex>F_M</tex> – значение функции <tex>F(x)</tex> в этой точке. | При выводе <tex>x</tex> – координата точки, в которой функция <tex>F(x)</tex> имеет минимум (или максимум), <tex>F_M</tex> – значение функции <tex>F(x)</tex> в этой точке. | ||
+ | |||
+ | == Метод хорд== | ||
+ | Недостаток деления отрезка строго пополам проистекает от того, что он использует лишь знак функции, игноририруя отклонение (абсолютную величину). Но очевидно, что чем меньше (по абсолютной величине) значение функции, тем ближе мы находимся к корню. '''Метод хорд''' предлагает делить отрезок в точке, отстоящей от краев отрезка пропорционально абсолютному значению функции на краях. (Название "метод хорд" происходит от того, что точка деления является пересечением отрезка <tex>[(X_{left},\; F(X_{left})), \; (X_{right},\; F(X_{right}))] </tex> - хорды - с осью абцисс.) | ||
+ | |||
+ | === Изложение метода === | ||
+ | Метод основан на замене функции <tex>f(x)</tex> на каждом шаге поиска хордой, пересечение которой с осью <tex>X</tex> дает приближение корня. | ||
+ | |||
+ | [[Изображение:04-10.jpg|frame|Рис. 3. Метод хорд]] | ||
+ | |||
+ | При этом в процессе поиска семейство хорд может строиться: | ||
+ | #при фиксированном левом конце хорд, т.е. <tex>z=a</tex>, тогда начальная точка <tex>x_0=b</tex> (рис. 3а); | ||
+ | #при фиксированном правом конце хорд, т.е. <tex>z=b</tex>, тогда начальная точка <tex>x_0=a</tex> (рис. 3б); | ||
+ | |||
+ | В результате итерационный процесс схождения к корню реализуется рекуррентной формулой: | ||
+ | *для случая а): | ||
+ | ::<tex>x_{n+1}=x_n - \frac{f(x_n)}{f(x_n)-f(a)} (x_n - a);</tex> | ||
+ | *для случая б): | ||
+ | ::<tex>x_{n+1}=x_n - \frac{f(x_n)}{f(x_n)-f(b)} (x_n - b);</tex> | ||
+ | |||
+ | [[Изображение:04-11sm.jpg|frame|Рис. 4. Схема алгоритма уточнения корня методом хорд]] | ||
+ | Процесс поиска продолжается до тех пор, пока не выполнится условие | ||
+ | <tex>|x_{n+1}-x_n| \le \varepsilon </tex> или <tex>| h| \le \varepsilon </tex>. | ||
+ | |||
+ | Метод обеспечивает быструю сходимость, если <tex>f(z)\cdot f''(z) > 0</tex>, т.е. хорды фиксируются в том конце интервала <tex>[a,b]</tex>, где знаки функции <tex>f(z)</tex> и ее кривизны <tex>f"(z)</tex> совпадают. | ||
+ | |||
+ | Схема алгоритма уточнения корня методом хорд представлена на рис. 4. | ||
+ | |||
+ | == Комбинация метода хорд и метода половинного деления == | ||
+ | Метод хорд можно применить в качестве "последнего штриха" после того, как метод половинного деления гарантирует требуемую точность - это не улучшит существенно гарантируемой точности, но, скорее всего, на несколько порядков повысит точность решения. | ||
+ | |||
+ | Если применять аналогичное уточнение к интервалу, полученному методом хорд, то эффект будет значительно слабее. Это ещё раз иллюстрирует тот факт, что метод хорд очень хорошо работает в условиях малого интервала (близости обеих границ интервала к корню), но неспособен сам создать себе эти условия (приблизить обе границы к корню). | ||
+ | |||
+ | На вопрос о том, стоит ли использовать попеременное применение метода половинного деления и метода хорд, ответ отрицателен. После того, как метод хорд приближает одну из границ почти вплотную к корню, методу половинного деления придётся долго работать, чтобы гарантировать заданную точность, т.к. метод хорд ее гарантировать не может. | ||
+ | |||
+ | Поэтому лучше использовать в качестве точки деления что-то среднее: если метод половинного деления предлагает использовать <tex>X_{halfdiv}</tex>, а метод хорд - <tex>X_{chord}</tex>, то возьмем <tex>X_{halfdiv}*K+X_{chord}*(1-K)</tex>. Коэффициент <tex>K \in [0..1]</tex>. | ||
+ | |||
+ | Чему должен быть равен коэффициент <tex>K</tex>? Его следует не задавать, а вычислять по ходу работы: если при очередной операции интервал уменьшился более чем в два раза (это то, что гарантирует метод половинного деления), то значит, нужно больше доверять методу хорд (уменьшить <tex>K</tex>), и наоборот. | ||
+ | |||
+ | Может показаться, что при большом доверии к методу хорд этот комбинированный метод работает так же, как метод хорд. На самом деле, это не так: метод хорд передвигает по направлению к корню только одну границу, а комбинированный метод даже при высоком доверии к методу хорд передвигает и вторую границу, обеспечивая лучшие условия для работы метода хорд, а значит - для ещё большего доверия к нему. | ||
== Список литературы == | == Список литературы == | ||
- | * | + | * http://dmitrykarpov.nm.ru/misc/dihotomy.htm |
- | * http://www. | + | * http://mathfunc.narod.ru/met_dih.html |
- | * http://www.intuit.ru/department/calculate/ | + | * http://www.intuit.ru/department/mathematics/mathprog/9/ |
+ | * http://www.intuit.ru/department/calculate/intromathmodel/4/3.html | ||
+ | * http://calc-x.com/chm/dich.php | ||
+ | * http://elib.ispu.ru/library/math/sem1/kiselev1/node84.html | ||
== См. также == | == См. также == |
Текущая версия
Содержание |
Введение
Существует довольно очевидная теорема: "Если непрерывная функция на концах некоторого интервала имеет значения разных знаков, то внутри этого интервала у нее есть корень (как минимум, один, но м.б. и несколько)". На базе этой теоремы построено численное нахождение приближенного значения корня функции. Обобщенно этот метод называется дихотомией, т.е. делением отрезка на две части. Обобщенный алгоритм выглядит так:
- Задать начальный интервал ;
- Убедиться, что на концах функция имеет разный знак;
- Повторять
- выбрать внутри интервала точку ;
- сравнить знак функции в точке со знаком функции в одном из концов;
- если совпадает, то переместить этот конец интервала в точку ,
- иначе переместить в точку другой конец интервала;
- пока не будет достигнута нужная точность.
Варианты метода дихотомии различаются выбором точки деления. Рассмотрим варианты дихотомии: метод половинного деления и метод хорд.
Метод половинного деления
Метод половинного деления известен также как метод бисекции. В данном методе интервал делится ровно пополам.
Такой подход обеспечивает гарантированную сходимость метода независимо от сложности функции - и это весьма важное свойство. Недостатком метода является то же самое - метод никогда не сойдется быстрее, т.е. сходимость метода всегда равна сходимости в наихудшем случае.
Метод половинного деления:
- Один из простых способов поиска корней функции одного аргумента.
- Применяется для нахождения значений действительно-значной функции, определяемому по какому-либо критерию (это может быть сравнение на минимум, максимум или конкретное число).
Метод половинного деления как метод поиска корней функции
Изложение метода
Перед применением метода для поиска корней функции необходимо отделить корни одним из известных способов, например, графическим методом. Отделение корней необходимо в случае, если неизвестно на каком отрезке нужно искать корень.
Будем считать, что корень функции отделён на отрезке . Задача заключается в том, чтобы найти и уточнить этот корень методом половинного деления. Другими словами, требуется найти приближённое значение корня с заданной точностью .
Пусть функция непрерывна на отрезке ,
- и - единственный корень уравнения .
(Мы не рассматриваем случай, когда корней на отрезке несколько, то есть более одного. В качестве можно взять и другое достаточно малое положительное число, например, .)
Поделим отрезок пополам. Получим точку и два отрезка .
- Если , то корень найден ().
- Если нет, то из двух полученных отрезков и надо выбрать один такой, что , то есть
- , если или
- , если .
- Новый отрезок делим пополам. Получаем середину этого отрезка и так далее.
Для того, чтобы найти приближённое значение корня с точностью до , необходимо остановить процесс половинного деления на таком шаге , на котором и вычислить . Тогда можно взять .
Реализация метода на С++ и числовой пример
Решим уравнение методом половинного деления. Графическим методом находим отрезок , которому принадлежит искомый корень. Так как , то принимаем .
Ниже приведен пример программы на Си++, которая решает поставленную задачу.
Программа 1. Корень уравнения
#include <iostream> #include <cmath> using namespace std; const double epsilon = 1e-2; double f(double x) { return 4- exp(x) - 2*x^2; } int main() { double a, b, c; a = 0; b = 2; while (b - a > epsilon){ c = (a + b) / 2; if(f(b) * f(c) < 0) a = c; else b = c; } cout << (a + b) / 2 << endl; return 0; }
Искомый корень . Вычисления проводились с точностью .
Промежуточные вычисления представлены в таблице ниже.
n | an | bn | cn | bn-cn |
---|---|---|---|---|
1 | 0 | 1 | 0.5 | 0.5 |
2 | 0.5 | 1 | 0.75 | 0.25 |
3 | 0.75 | 1 | 0.875 | 0.125 |
4 | 0.875 | 1 | 0.9375 | 0.0625 |
5 | 0.875 | 0.9375 | 0.90625 | 0.03125 |
6 | 0.875 | 0.90625 | 0.890625 | 0.015625 |
7 | 0.875 | 0.890625 | 0.8828125 | 0.0078125 |
Метод половинного деления как метод оптимизации
Однопараметрическая оптимизация (поиск экстремумов функций одной переменной) является самостоятельной и часто встречаемой задачей. Кроме того, к ней сводится гораздо более сложная задача - поиск экстремума функции многих переменных.
Рассмотрим метод половинного деления как простейший однопараметрический метод безусловной оптимизации. Данный метод является методом прямого поиска. В нем при поиске экстремума целевой функции используются только вычисленные значения целевой функции.
Дана функция . Необходимо найти , доставляющий минимум (или максимум) функции на интервале с заданной точностью , т.е. найти
- .
Запишем словесный алгоритм метода.
- На каждом шаге процесса поиска делим отрезок пополам, - координата середины отрезка .
- Вычисляем значение функции в окрестности вычисленной точки , т.е.
. - Сравниваем и и отбрасываем одну из половинок отрезка (рис. 1).
- При поиске минимума:
- Если , то отбрасываем отрезок , тогда . (рис. 1.а)
- Иначе отбрасываем отрезок , тогда . (рис. 1.б)
- При поиске максимума:
- Если , то отбрасываем отрезок , тогда .
- Иначе отбрасываем отрезок , тогда .
- При поиске минимума:
- Деление отрезка продолжается, пока его длина не станет меньше заданной точности , т.е. .
Схема алгоритма метода представлена на рис 2.
На рис 2:
- - константа,
При выводе – координата точки, в которой функция имеет минимум (или максимум), – значение функции в этой точке.
Метод хорд
Недостаток деления отрезка строго пополам проистекает от того, что он использует лишь знак функции, игноририруя отклонение (абсолютную величину). Но очевидно, что чем меньше (по абсолютной величине) значение функции, тем ближе мы находимся к корню. Метод хорд предлагает делить отрезок в точке, отстоящей от краев отрезка пропорционально абсолютному значению функции на краях. (Название "метод хорд" происходит от того, что точка деления является пересечением отрезка - хорды - с осью абцисс.)
Изложение метода
Метод основан на замене функции на каждом шаге поиска хордой, пересечение которой с осью дает приближение корня.
При этом в процессе поиска семейство хорд может строиться:
- при фиксированном левом конце хорд, т.е. , тогда начальная точка (рис. 3а);
- при фиксированном правом конце хорд, т.е. , тогда начальная точка (рис. 3б);
В результате итерационный процесс схождения к корню реализуется рекуррентной формулой:
- для случая а):
- для случая б):
Процесс поиска продолжается до тех пор, пока не выполнится условие или .
Метод обеспечивает быструю сходимость, если , т.е. хорды фиксируются в том конце интервала , где знаки функции и ее кривизны совпадают.
Схема алгоритма уточнения корня методом хорд представлена на рис. 4.
Комбинация метода хорд и метода половинного деления
Метод хорд можно применить в качестве "последнего штриха" после того, как метод половинного деления гарантирует требуемую точность - это не улучшит существенно гарантируемой точности, но, скорее всего, на несколько порядков повысит точность решения.
Если применять аналогичное уточнение к интервалу, полученному методом хорд, то эффект будет значительно слабее. Это ещё раз иллюстрирует тот факт, что метод хорд очень хорошо работает в условиях малого интервала (близости обеих границ интервала к корню), но неспособен сам создать себе эти условия (приблизить обе границы к корню).
На вопрос о том, стоит ли использовать попеременное применение метода половинного деления и метода хорд, ответ отрицателен. После того, как метод хорд приближает одну из границ почти вплотную к корню, методу половинного деления придётся долго работать, чтобы гарантировать заданную точность, т.к. метод хорд ее гарантировать не может.
Поэтому лучше использовать в качестве точки деления что-то среднее: если метод половинного деления предлагает использовать , а метод хорд - , то возьмем . Коэффициент .
Чему должен быть равен коэффициент ? Его следует не задавать, а вычислять по ходу работы: если при очередной операции интервал уменьшился более чем в два раза (это то, что гарантирует метод половинного деления), то значит, нужно больше доверять методу хорд (уменьшить ), и наоборот.
Может показаться, что при большом доверии к методу хорд этот комбинированный метод работает так же, как метод хорд. На самом деле, это не так: метод хорд передвигает по направлению к корню только одну границу, а комбинированный метод даже при высоком доверии к методу хорд передвигает и вторую границу, обеспечивая лучшие условия для работы метода хорд, а значит - для ещё большего доверия к нему.
Список литературы
- http://dmitrykarpov.nm.ru/misc/dihotomy.htm
- http://mathfunc.narod.ru/met_dih.html
- http://www.intuit.ru/department/mathematics/mathprog/9/
- http://www.intuit.ru/department/calculate/intromathmodel/4/3.html
- http://calc-x.com/chm/dich.php
- http://elib.ispu.ru/library/math/sem1/kiselev1/node84.html