Find the Minimum and Maximum of a Function in R

The function optimize (also spelled optimise) in R returns the minimum or maximum of a function f(x) within a specified interval.

It takes as inputs:

  • f: a function.
  • interval: a vector containing the lower and upper bounds of the domain where we want to search for the minimum or maximum.
  • maximum: a logical, where TRUE tells optimize that we want to find the maximum, and FALSE the minimum, of f (the default is FALSE).

The function optimize outputs the x and y values of the minimum/maximum.

Here are some examples:

Finding the minimum of: \(f(x) = x^2 + 1\)

# code the function
f = function(x) {
  x^2 + 1
}

# find the minimum of f(x) within the interval [-1, 1]
ans = optimize(f, interval = c(-1,1))

# optimize returns a list of 2 values:
# "minimum" is the x value where the minimum occurs
# and "objective" is the y value, i.e. f(minimum)
x_min = ans$minimum
y_min = ans$objective

# plot f(x)
x = seq(-1, 1, length.out = 100) # generates 100 numbers between -1 and 1
plot(x, f(x), type = 'l')

# plot the minimum point
points(x_min, y_min, pch = 15)

# annotation
text(x = x_min, y = y_min, labels = 'Minimum',
     pos = 3, col = 'blue')

Output:

Plot showing the minimum of a quadratic function f(x)

Finding the maximum of: \(f(x) = x^5-5x^4+5x^2-x+1\)

f = function(x) {
  x^5 - 5*x^4 + 5*x^2 - x + 1
}

# find the maximum of f(x) within the interval [-1, 1]
ans = optimize(f, interval = c(-1,1), maximum = TRUE)

# extract the coordinates of the maximum
x_max = ans$maximum
y_max = ans$objective

# plot f(x)
x = seq(-1, 1, length.out = 100)
plot(x, f(x), type = 'l')

# plot the maximum
points(x_max, y_max, pch = 15)
text(x = x_max, y = y_max, labels = 'Maximum',
     pos = 4, col = 'blue')

Output:

plot showing the maximum of a polynomial function f(x)

Finding the maximum of: \(f(x) = cos x\)

f = function(x) {
  cos(x)
}

# find the maximum of f(x) within the interval [-10, 10]
ans = optimize(f, interval = c(-10,10), maximum = TRUE)

# extract the coordinates of the maximum
x_max = ans$maximum
y_max = ans$objective

# plot f(x)
x = seq(-10, 10, length.out = 100)
plot(x, f(x), type = 'l')

# plot the maximum
points(x_max, y_max, pch = 15)
text(x = x_max, y = y_max, labels = 'Maximum',
     pos = 4, col = 'blue')

Output:

plot showing the maximum of the cosine function

So why did optimize chose this particular point as maximum?

To investigate at which x values the function is being evaluated, you can use a print statement inside f(x):

f = function(x) {
  print(x) # prints the value of x whenever f(x) is called
  cos(x)
}
optimize(f, interval = c(-10, 10), maximum = TRUE)

Output:

[1] -2.36068
[1] 2.36068
[1] 5.27864
[1] 7.082039
[1] 6.804159
[1] 6.2776
[1] 6.25876
[1] 6.283509
[1] 6.283185
[1] 6.283145
[1] 6.283226
[1] 6.283185
$maximum
[1] 6.283185

$objective
[1] 1

Next, let’s plot these points to see what’s happening:

xs = c(-2.36068,
       2.36068,
       5.27864,
       7.082039,
       6.804159,
       6.2776,
       6.25876,
       6.283509,
       6.283185,
       6.283145,
       6.283226,
       6.283185)

plot(x, cos(x), type = 'l')
points(xs, cos(xs), col = 'red', pch = 15)
text(x = xs, y = cos(xs), labels = c(1:5, '6-12', rep('', 6)),
     pos = 4, col = 'red')

Output:

step-by-step description of finding the maximum of the cosine function

This plot shows that optimize did not detect a change in the y value between points 1 and 2, and perhaps thought that the function was constant between these 2 points and missed the peak at x = 0.

Note: I tried changing the interval from [-10, 10] to [-7, 10], and optimize had no problem detecting a maximum at (0, 1).

Finding the minimum of \(f(x) = 3\)

f = function(x) {
  3
}

# find the minimum of f(x) within the interval [-1, 1]
ans = optimize(f, interval = c(-1,1))

x_min = ans$minimum
y_min = ans$objective

# create empty plot
plot(1, type = "n", xlab = "x", ylab = "f(x)",
     xlim = c(-1.1, 1.1), ylim = c(0, 5))

# plot f(x)
abline(h = 3)

# plot the minimum point on f(x)
points(x_min, y_min, pch = 15)
text(x = x_min, y = y_min, labels = 'Minimum',
     pos = 3, col = 'blue')

Output:

plot showing the minimum of a constant function

Even though \(f(x) = 3\) is constant, optimize managed to find a minimum at x = 1!

Further reading