Contour Plots

Contour plots are useful for visualizing the functional space and iteration history for 2D optimization problems. Optimization isn’t really necessary for 2D problems (you can just plot it and see the optimum), but studying 2D optimization problems is helpful for our learning because they can be easily visualized.

We will create contour plots for the simple function:

\[z = 3(x - 2)^2 + (y+1)^2\]

In both Python and Matlab this can be solved inline without any loops, but to represent what you would need to do with more complicated functions, we will make the computation of z a separate method.

Matlab

First we create a method for computing z in a separate file called func.m.

function [z] = func(x, y)
z = 3*(x-2)^2 + (y+1)^2;
end

Next, we can create a contour plot across some chosen bounds and resolution


clear; close all;

% --- setup grid ---
nx = 200;  % number of points in x-direction
ny = 150;  % number of points in y-direction
x = linspace(-5, 5, nx);  % nx points equally spaced between -5...5
y = linspace(-6, 6, ny);  % ny points equally spaced between -6...6
[X, Y] = ndgrid(x, y);  % 2D array (matrix) of points across x and y
Z = zeros(nx, ny);  % initialize output of size (nx, ny)

% --- evaluate across grid ---
for i = 1:nx
    for j = 1:ny
        Z(i, j) = func(X(i, j), Y(i, j));
    end
end

% --- contour plot ---
figure();  % start a new figure
contour(X, Y, Z, 50);  % using 50 contour lines.  
colorbar();  % add a colorbar
xlabel('x');  % labels for axes
ylabel('y');

Notes:

Python

The corresponding Python looks very similar. The main changes are:

import numpy as np
import matplotlib.pyplot as plt

def func(x, y):
    return 3*(x-2)**2 + (y+1)**2

# --- setup grid ---
nx = 200  # number of points in x-direction
ny = 150  # number of points in y-direction
x = np.linspace(-5, 5, nx)  # nx points equally spaced between -5...5
y = np.linspace(-6, 6, ny)  # ny points equally spaced between -6...6
X, Y = np.meshgrid(x, y, indexing='ij')  # 2D array (matrix) of points across x and y
Z = np.zeros((nx, ny))  # initialize output of size (nx, ny)

# --- evaluate across grid ---
for i in range(nx):
    for j in range(ny):
        Z[i, j] = func(X[i, j], Y[i, j])

# --- contour plot ---
plt.figure()  # start a new figure
plt.contour(X, Y, Z, 50)  # using 50 contour lines.
plt.colorbar()  # add a colorbar
plt.xlabel('x')  # labels for axes
plt.ylabel('y')
plt.show()  # show plot

Notes: