Тернарний пошук

Метод в інформатиці для пошуків максимумів та мінімумів функції, яка спочатку строго зростає, потім строго убуває (або навпаки)

Постановка задачі ред.

Нехай дана функція  , унімодальна на деякому відрізку  . Під унімодальна розуміється один з двох варіантів. Перший: функція спочатку строго зростає, потім досягає максимуму (в одній точці або цілому відрізку), потім строго спадає. Другий варіант, симетричний: функція спочатку спадає, досягає мінімуму, зростає. Надалі ми будемо розглядати перший варіант, другий буде абсолютно симетричний йому. Потрібно знайти максимум функції   на відрізку  .

Алгоритм ред.

Візьмемо будь-які дві точки   і   в цьому відрізку:  . Порахуємо значення функції   і  .Далі у нас виходить три варіанти:

  • Якщо виявиться, що  , то шуканий максимум не може перебувати в лівій частині, тобто в частині  . У цьому легко переконатися: якщо в лівій точці функція менше, ніж в правій, то або ці дві точки знаходяться в області «підйому» функції, або тільки ліва точка знаходиться там. У будь-якому випадку, це означає, що максимум далі є сенс шукати тільки в відрізку  .
  • Якщо, навпаки,  , то ситуація аналогічна попередній з точністю до симетрії. Тепер шуканий максимум не може перебувати в правій частині, тобто в частині  , тому переходимо до відрізка  .
  • Якщо  , то або обидві ці точки знаходяться в області максимуму, або ліва точка знаходиться в області зростання, а права — в області спадання (тут істотно використовується те, що зростання / спадання суворі). Таким чином, в подальшому пошук має сенс на відрізку  , але (з метою спрощення коду) цей випадок можна віднести до будь-якого з двох попередніх.

Таким чином, за результатом порівняння значень функції в двох внутрішніх точках ми замість поточного відрізка пошуку   знаходимо новий відрізок  . Повторимо тепер всі дії для цього нового відрізка, знову отримаємо новий, суворо менший, відрізок, і так далі.

 
 

Втім, при іншому виборі, коли   і   ближче один до одного, швидкість збіжності збільшиться.

Випадок цілочисельного аргументу ред.

Якщо аргумент функції   цілочисельний, то відрізок   теж стає дискретним, але, оскільки ми не накладали ніяких обмежень на вибір точок   і  , то на коректність алгоритму це ніяк не впливає. Можна як і раніше вибирати   і   так, щоб вони ділили відрізок   на 3 частини, але вже тільки приблизно рівні.

Другий відмінний момент — критерій зупинки алгоритму. В даному випадку тернарний пошук треба буде зупиняти, коли стане  , адже в такому випадку вже неможливо буде вибрати точки   і   так, щоб були різними і відрізнялися від   і  , і це може привести до зациклення. Після того, як алгоритм тернарного пошуку зупиниться і стане  , з решти декількох точок   треба вибрати точку з максимальним значенням функції.

Реалізація ред.

Реалізація для безперервного випадку (тобто коли функція   має вигляд: double f(double x)):

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;
}

Тут EPS — фактично, абсолютна похибка відповіді (не враховуючи похибок, пов'язаних з неточним обчисленням функції).

Замість критерію «while (r - l > EPS)» можна вибрати і такий критерій:

for (int it = 0; it < iterations; ++it)

З одного боку, доведеться підібрати константу  , щоб забезпечити необхідну точність (зазвичай досить декількох сотень, щоб досягти максимальної точності). Зате, з іншого боку, число ітерацій перестає залежати від абсолютних величин   і  , тобто ми фактично за допомогою   задаємо необхідну відносну похибку.