MAXimal | |
добавлено: 23 Jul 2009 12:53 Содержание [скрыть] Тернарный поискПостановка задачиПусть дана функция , унимодальная на некотором отрезке . Под унимодальностью понимается один из двух вариантов. Первый: функция сначала строго возрастает, потом достигает максимума (в одной точке или целом отрезке), потом строго убывает. Второй вариант, симметричный: функция сначала убывает убывает, достигает минимума, возрастает. В дальнейшем мы будем рассматривать первый вариант, второй будет абсолютно симметричен ему. Требуется найти максимум функции на отрезке . АлгоритмВозьмём любые две точки и в этом отрезке: . Посчитаем значения функции и . Дальше у нас получается три варианта:
Таким образом, по результату сравнения значений функции в двух внутренних точках мы вместо текущего отрезка поиска находим новый отрезок . Повторим теперь все действия для этого нового отрезка, снова получим новый, строго меньший, отрезок, и т.д. Рано или поздно длина отрезка станет маленькой, меньшей заранее определённой константы-точности, и процесс можно останавливать. Этот метод численный, поэтому после остановки алгоритма можно приближённо считать, что во всех точках отрезка достигается максимум; в качестве ответа можно взять, например, точку . Осталось заметить, что мы не накладывали никаких ограничений на выбор точек и . От этого способа, понятно, будет зависеть скорость сходимости (но и возникающая погрешность). Наиболее распространённый способ — выбирать точки так, чтобы отрезок делился ими на 3 равные части: Впрочем, при другом выборе, когда и ближе друг к другу, скорость сходимости несколько увеличится. Случай целочисленного аргументаЕсли аргумент функции целочисленный, то отрезок тоже становится дискретным, однако, поскольку мы не накладывали никаких ограничений на выбор точек и , то на корректность алгоритма это никак не влияет. Можно по-прежнему выбирать и так, чтобы они делили отрезок на 3 части, но уже равные только приблизительно. Второй отличающийся момент — критерий остановки алгоритма. В данном случае тернарный поиск надо будет останавливать, когда станет , ведь в таком случае уже невозможно будет выбрать точки и так, чтобы были различными и отличались от и , и это может привести к зацикливанию. После того, как алгоритм тернарного поиска остановится и станет , из оставшихся нескольких точек-кандидатов надо выбрать точку с максимальным значением функции. РеализацияРеализация для непрерывного случая (т.е. функция имеет вид: ): double l = ..., r = ..., EPS = ...; // входные данные while (r - l > EPS) { double m1 = l + (r - l) / 3, m2 = r - (r - l) / 3; if (f (m1) < f (m2)) l = m1; else r = m2; } Здесь — фактически, абсолютная погрешность ответа (не считая погрешностей, связанных с неточным вычислением функции). Вместо критерия "while (r - l > EPS)" можно выбрать и такой критерий останова: for (int it=0; it<iterations; ++it) С одной стороны, придётся подобрать константу , чтобы обеспечить требуемую точность (обычно достаточно нескольких сотен, чтобы достичь максимальной точности). Но зато, с другой стороны, число итераций перестаёт зависеть от абсолютных величин и , т.е. мы фактически с помощью задаём требуемую относительную погрешность.
|