Introduction

Ternary search is a search that finds a local minimum or maximum value in a function given an interval from A to B.

If there are multiple local minimum and maximum values, ternary search will only find one of them but it will not necessarily be the maximum or minimum.

Implementation

Suppose we have a function f(x) with only one max point between A and B. We want to find the point (M, f(M)) where f(M) is the maximum between A and B.

We split the range from A to B into three intervals. At every iteration of our algorithm, we can narrow down the range by 1/3 and we have a new interval. At every step, we can remove one of the intervals based on the following:

Let m1 by 1/3 of the way from A and B and let m2 be 2/3 of the way from B.

Case 1 : f(m1) < f(m2)

  • Case 1.1: m1 < m2 < M, so m1 < M

  • Case 1.2: m1 < M < m2, so m1 < M

  • Case 1.3: M < m1 < m2 is not possible.

Thus if f(m1) < f(m2), then m1 < M, so we only need to search from m1 to B.

Case 2: f(m1) >= f(m2)

  • Case 2.1: m1 < M < m2, so M < m2

  • Case 2.2: M < m1 < m2, so M < m2

  • Case 2.3: m1 < m2 < M is not possible

Thus, if f(m1) >= f(m2), then M < m2, so we only need to search from A to m2.

Therefore, based on the values of f(m1) and f(m2), we can always remove a third of the range. We can keep repeating this until the range is within a very small threshold such as 0.0001.


Example

Example of ternary search:

Suppose we have a function f(x) with a maximum point between A and B.

We find m1 (1/3) point and m2 (2/3) point between A and B.

Since f(m1) > f(m2), then we can reduce the range from A to m2. We find the new m1 and m2 points.

Since f(m1) < f(m2), then we can reduce the range from m1 to B. We find the new m1 and m2 points.

Since f(m1) < f(m2), then we can reduce the range from m1 to B. We find the new m1 and m2 points.

Since f(m1) < f(m2), then we can reduce the range from m1 to B. We find the new m1 and m2 points.

We keep repeating this until we narrow down the range to within a small threshold and we can find the point where f(x) is maximum.


Formalization

Let f(x) be the function.
Let (a, b) be interval of search.

Let tern(a,b) return M where f(M) is the maximum.

Let m1 = a + (b - a) / 3
Let m2 = a + (b - a) * 2 / 3

tern(a,b) = (a + b) / 2 if |f(a) - f(b)| < epsilon
tern(a,b) = tern(m1, b) if f(a) < f(b)
tern(a,b) = tern(a, m2) otherwise

Code

public double tern(double a,double b){
  if (Math.abs(f(a) - f(b)) < 0.0001) {
    return (a + b) / 2.0;
  }
  double m1 = a + (b - a) / 3.0;
  double m2 = a + (b - a) * 2.0 / 3.0;
  if (f(m1) < f(m2)) {
    return tern(m1, b);
  } else {
    return tern(a, m2);
  }
}