Lecture 5 - Bifurcations

Published

January 27, 2026

Based on notes created by Sam Coogan and Murat Arcak. Licensed under a “Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License”

Motivation

“Qualitative behavior of a second-order system is determined by the pattern of its equilibrium points and periodic behavior, as well as their stability properties” – Khalil

However, how do we know whether or not the system maintains qualitative behavior under infinitesimally small perturbations?

Definition: Structurally Stable. A system is said to be structurally stable when stability is maintained under small perturbations.

Definition: Birfucation. The complement of structural stability is when small perturbations change the equilibrium points or periodic orbits. This phenomenon is known as a birfucation.

Birfucations

A birfucation is an abrupt change in qualitative behavior as a parameter is varied. Examples include equilibria or limit cycles appearing/disappearing, or becoming stable/unstable.

Fold Birfucation

Also known as “saddle node” or “blue sky” bifurcation

Example:

\dot{x} = \mu - x^2

If \mu > 0, two equilibria: x = \pm \sqrt{\mu}. If \mu < 0, no equilibria.

This can be visualized using a Bifurcation diagram1:

1 Bifurcation diagrams sketch the amplitude of the equilibrium points as a function of the bifurcation parameter. Solid lines represent stable nodes/foci/limit cycles. Dashed lines represent unstable nodes/foci/limit cycles.

Fold Bifurcation
Show code
import numpy as np
import matplotlib.pyplot as plt

# x grid
x = np.linspace(-3, 3, 300)

# Two representative μ values
mu_neg = -1.0
mu_pos = 1.0

# Compute nullclines
nullcline_neg = mu_neg - x**2
nullcline_pos = mu_pos - x**2

# Plot
plt.figure(figsize=(6,5))

# Nullclines
plt.plot(x, nullcline_neg, 'r--', label=rf'$\mu = {mu_neg}$')
plt.plot(x, nullcline_pos, 'b--', label=rf'$\mu = {mu_pos}$')

# Horizontal axis (x-axis for \dot{x}=0)
plt.axhline(0, color='k', linestyle='--', linewidth=1)

# Phase line arrows along \dot{x}=0
for xi in np.linspace(-2, 2, 3):
    # Choose μ > 0 for phase line
    xdot = mu_pos - xi**2
    dx = 0.1 * np.sign(xdot)  # arrow points right if xdot>0, left if xdot<0
    plt.arrow(xi, 0, dx, 0, head_width=0.5, head_length=0.1, color='blue')


plt.xlabel(r'$x$')
plt.ylabel(r'$\dot{x}$')
plt.title(r'Phase portrait for $\dot{x} = \mu - x^2$')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

Transcritical Bifurcation

Example:

\dot{x} = \mu x - x^2

Equilibria: x = 0 and x = \mu

Linearization \mu < 0 \mu > 0
\left.\frac{\partial f}{\partial x}\right|_{x = 0} = \mu stable unstable
\left.\frac{\partial f}{\partial x}\right|_{x = \mu} = -\mu unstable stable

Transcritical Bifurcation
Show code
import numpy as np
import matplotlib.pyplot as plt

# x grid
x = np.linspace(-3, 3, 300)

# Two representative μ values
mu_neg = -1.0
mu_pos = 1.0

# Compute nullclines
nullcline_neg = mu_neg * x - x**2
nullcline_pos = mu_pos * x - x**2

# Plot
plt.figure(figsize=(6,5))

# Nullclines
plt.plot(x, nullcline_neg, 'r--', label=rf'$\mu = {mu_neg}$')
plt.plot(x, nullcline_pos, 'b--', label=rf'$\mu = {mu_pos}$')

# Horizontal axis (x-axis for \dot{x}=0)
plt.axhline(0, color='k', linestyle='--', linewidth=1)

plt.xlabel(r'$x$')
plt.ylabel(r'$\dot{x}$')
plt.title(r'Phase portrait for $\dot{x} = \mu x - x^2$')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

Pitchfork Bifurcation

Example:

\dot{x} = \mu x - x^3

Equilibria: x = 0 for all \mu, and x = \pm \sqrt{\mu} if \mu > 0

Linearization \mu < 0 \mu > 0
\left.\frac{\partial f}{\partial x}\right|_{x = 0} = \mu stable unstable
\left.\frac{\partial f}{\partial x}\right|_{x = \pm \sqrt{\mu}} = -2\mu N/A stable

Supercritical Pitchfork

Example:

\dot{x} = \mu x + x^3

Equilibria: x = 0 for all \mu, and x = \pm \sqrt{-\mu} if \mu < 0

Linearization \mu < 0 \mu > 0
\left.\frac{\partial f}{\partial x}\right|_{x = 0} = \mu stable unstable
\left.\frac{\partial f}{\partial x}\right|_{x = \pm \sqrt{-\mu}} = -2\mu unstable N/A

Subcritical Pitchfork

Example:

\dot{x} = \mu x + x^3 - x^5

Figure 1: Hysteresis arising from a subcritical pitchfork bifurcation

Examples of bifurcations and hysteresis can also be found in perception2.

2 Bistable perception example Observe the transition from a man’s face to a sitting woman as you trace the figures from left to right, starting with the top row. When does the opposite transition happen as you trace back from the end to the beginning? [Fisher, 1967]

Higher Order Systems

Fold, transcritical, and pitchfork bifurcations are all one-dimensional bifurcations, as evident from the first order examples above. They occur in higher order systems too, but are restricted to a one-dimensional manifold.

\textrm{1D subspace: } c_1^Tx = \cdots = c_{n-1}^Tx = 0 \\ \textrm{1D manifold: } g_1(x) = \cdots = g_{n-1}(x) = 0

Example 1:

\begin{align*} \dot{x}_1 &= \mu - x_1^2 \\ \dot{x}_2 &= -x_2 \end{align*}

A fold bifurcation occurs on the invariant x_2=0 subspace:

two-dimensional fold bifurcation
Show code
import numpy as np
import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 3, figsize=(6, 3), sharex=True, sharey=True)

mu_values = [-1.0, 0.0, 1.0]
titles = [r'$\mu < 0$', r'$\mu = 0$', r'$\mu > 0$']

# Grid for streamplot
x1 = np.linspace(-2.5, 2.5, 200)
x2 = np.linspace(-2.5, 2.5, 200)
X1, X2 = np.meshgrid(x1, x2)

for ax, mu, title in zip(axes, mu_values, titles):

    # Vector field
    dX1 = mu - X1**2
    dX2 = -X2

    ax.streamplot(X1, X2, dX1, dX2, density=1.0, linewidth=0.8, arrowsize=1)

    # Equilibria
    if mu > 0:
        # Stable equilibrium (filled)
        ax.plot(np.sqrt(mu), 0, 'ko', markersize=7)

        # Unstable equilibrium (open)
        ax.plot(-np.sqrt(mu), 0, marker='o', markersize=7,
                markerfacecolor='white', markeredgecolor='black')

    elif mu == 0:
        # Saddle-node (semistable)
        ax.plot(0, 0, marker='o', markersize=7,
                markerfacecolor='white', markeredgecolor='black')

    # Axes styling
    ax.set_title(title)
    ax.axhline(0, color='k', linewidth=0.8)
    ax.set_xlim(-2.5, 2.5)
    ax.set_ylim(-2.5, 2.5)
    ax.set_aspect('equal')
    ax.set_xticks([])
    ax.set_yticks([])

axes[0].set_ylabel(r'$x_2$')
axes[1].set_xlabel(r'$x_1$')

plt.tight_layout()
plt.show()

Example 2:

Let’s revisit the bistable switch example from Lecture 1:

\begin{align*} \dot{x}_1 = -a x_1 + x_2 \\ \dot{x}_2 = \frac{x_1^2}{1 + x_1^2} - b x_2 \end{align*}

For this example, we had seen that there was a bistable switch when ab > 0.5. What we hadn’t talked about yet is that this system has a fold bifurcation at \mu = ab = 0.5.

Fold Bifurcation for Bistable Switch Example
NoteCharacteristic of one-dimensional bifurcations

\left.\frac{\partial f}{\partial x}\right|_{\mu = \mu^c, x=x^*(\mu^c)} \textrm{ has an eigenvalue at zero} where x^*(\mu) is the equilibrium point undergoing bifurcation and \mu^c is the critical value at which the bifurcation occurs.

Example 1 above:

\left.\frac{\partial f}{\partial x}\right|_{\mu=0,x=0} = \begin{bmatrix} 0 & 0 \\ 0 & -1 \end{bmatrix} \to \lambda_{1,2} = 0, -1

Example 2 above:

\left.\frac{\partial f}{\partial x}\right|_{\mu=1/2,x_1 = 1, x_2 = a} = \begin{bmatrix} -a & 1 \\ \frac{1}{2} & -b \end{bmatrix} \to \lambda_{1,2} = 0, -(a+b)

Hopf Bifurcation

A Hopf bifurcation is a two-dimensional bifurcation, unlike the one-dimensional types above.

Example: Supercritical Hopf bifurcation

\begin{align*} \dot{x}_1 &= x_1(\mu - x_1^2 - x_2^2) - x_2 \\ \dot{x}_2 &= x_2(\mu - x_1^2 - x_2^2) + x_1 \end{align*}

In polar coordinates: \begin{align*} \dot{r} &= \mu r - r^3 \\ \dot{\theta} &= 1 \end{align*}

Note that a positive equilibrium for the r subsystem means a limit cycle in the (x_1, x_2) plane.

\begin{align*} \mu < 0 &: \textrm{ stable equilibrium at } r = 0 \\ \mu > 0 &: \textrm{ unstable equilibrium at } r = 0 \textrm{ and stable limit cycle at } r = \sqrt{\mu} \end{align*}

The origin loses stability at \mu = 0 and a stable limit cycle emerges.

Supercritical Hopf bifurcation

Example: Subcritical Hopf bifurcation

\begin{align*} \dot{r} &= \mu r + r^3 - r^5 \\ \dot{\theta} &= 1 \end{align*}

Subcritical Hopf bifurcation
NoteCharacteristic of the Hopf bifurcations

\left.\frac{\partial f}{\partial x}\right|_{\mu = \mu^c, x=x^*(\mu^c)} \textrm{ has eigenvalues $\pm \beta i$} where again x^*(\mu) is the equilibrium point undergoing bifurcation and \mu^c is the critical value at which the bifurcation occurs.