Chapter 18: Jordan Canonical Form and General Modal Decomposition

Lesson 5: Interpretation of Jordan Form in Control Applications

This lesson interprets Jordan canonical form as a control-theoretic coordinate system. We connect Jordan chains to polynomial-times-exponential motion, repeated-pole behavior, controllability and observability along generalized eigenvector chains, and the limitations imposed by defective state matrices.

1. Why Jordan Form Matters in Control

For a continuous-time LTI system \( \dot{\mathbf{x} }=\mathbf{A}\mathbf{x}+\mathbf{B}\mathbf{u} \), Jordan form gives a coordinate system in which the internal modes of \( \mathbf{A} \) are exposed explicitly. If \( \mathbf{T} \) is nonsingular and \( \mathbf{x}=\mathbf{T}\mathbf{z} \), then

\[ \dot{\mathbf{z} }=\mathbf{J}\mathbf{z}+\tilde{\mathbf{B} }\mathbf{u}, \quad \mathbf{y}=\tilde{\mathbf{C} }\mathbf{z}+\mathbf{D}\mathbf{u}, \quad \mathbf{J}=\mathbf{T}^{-1}\mathbf{A}\mathbf{T}, \quad \tilde{\mathbf{B} }=\mathbf{T}^{-1}\mathbf{B}, \quad \tilde{\mathbf{C} }=\mathbf{C}\mathbf{T}. \]

Thus Jordan coordinates do not change the system; they reveal how the system stores, propagates, controls, and observes modal information. Diagonal modal form is possible only when there are enough independent eigenvectors. Jordan form handles the general case by supplementing eigenvectors with generalized eigenvectors.

flowchart TD
  A["Physical coordinates: x"] --> B["Similarity transform: x = T z"]
  B --> C["Jordan coordinates: z"]
  C --> D["Eigenvalue blocks"]
  D --> E["Jordan chains"]
  E --> F["Polynomial times exponential terms"]
  F --> G["Control interpretation: repeated poles, chain actuation, chain sensing"]
        

2. One Jordan Block as a Chain of Coupled Modal Coordinates

A Jordan block of size \( m \) associated with eigenvalue \( \lambda \) is

\[ \mathbf{J}_m(\lambda)= \lambda\mathbf{I}_m+\mathbf{N}_m, \quad \mathbf{N}_m= \begin{bmatrix} 0 & 1 & 0 & \cdots & 0\\ 0 & 0 & 1 & \cdots & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots\\ 0 & 0 & 0 & \cdots & 1\\ 0 & 0 & 0 & \cdots & 0 \end{bmatrix}, \quad \mathbf{N}_m^m=\mathbf{0}. \]

The nilpotent matrix \( \mathbf{N}_m \) couples the generalized eigenvector coordinates. The homogeneous Jordan-chain dynamics are

\[ \begin{aligned} \dot{z}_1 &= \lambda z_1 + z_2,\\ \dot{z}_2 &= \lambda z_2 + z_3,\\ &\vdots\\ \dot{z}_{m-1} &= \lambda z_{m-1}+z_m,\\ \dot{z}_m &= \lambda z_m. \end{aligned} \]

The final coordinate \( z_m \) drives \( z_{m-1} \), which drives \( z_{m-2} \), and so on. A Jordan block is therefore not a set of independent modes; it is a modal chain.

3. Matrix Exponential and Polynomial Growth Factors

Since \( \lambda\mathbf{I}_m \) and \( \mathbf{N}_m \) commute,

\[ e^{\mathbf{J}_m(\lambda)t} = e^{\lambda t}e^{\mathbf{N}_m t} = e^{\lambda t} \sum_{k=0}^{m-1}\frac{(\mathbf{N}_m t)^k}{k!}. \]

Therefore the entries above the diagonal contain powers of \( t \):

\[ e^{\mathbf{J}_m(\lambda)t} = e^{\lambda t} \begin{bmatrix} 1 & t & \frac{t^2}{2!} & \cdots & \frac{t^{m-1} }{(m-1)!}\\ 0 & 1 & t & \cdots & \frac{t^{m-2} }{(m-2)!}\\ \vdots & \vdots & \vdots & \ddots & \vdots\\ 0 & 0 & 0 & \cdots & t\\ 0 & 0 & 0 & \cdots & 1 \end{bmatrix}. \]

In control applications, this explains why repeated defective poles produce terms such as \( t e^{\lambda t} \), \( t^2e^{\lambda t} \), and higher powers. Even if \( \operatorname{Re}(\lambda)<0 \), transient amplification can occur before exponential decay dominates.

4. Stability Interpretation

The Jordan form sharpens the eigenvalue stability criterion. For continuous-time LTI systems, asymptotic stability requires every eigenvalue to satisfy \( \operatorname{Re}(\lambda_i)<0 \). However, marginal stability depends not only on eigenvalue locations but also on Jordan block sizes.

\[ \mathbf{A}\text{ is Lyapunov stable} \quad\Longleftrightarrow\quad \begin{cases} \operatorname{Re}(\lambda_i)\le 0 \text{ for all } i,\\ \begin{array}{l} \text{every eigenvalue with } \operatorname{Re}(\lambda_i)=0\\ \text{has only size-one Jordan blocks.} \end{array} \end{cases} \]

The reason is direct: if \( \lambda=j\omega \) and a Jordan block has size \( m>1 \), then \( e^{\mathbf{J}t} \) contains nondecaying polynomial factors multiplied by \( e^{j\omega t} \). This causes unbounded growth even though the eigenvalue lies on the imaginary axis.

5. Controllability Along a Jordan Chain

Consider the Jordan-coordinate system \( \dot{\mathbf{z} }=\mathbf{J}\mathbf{z}+\tilde{\mathbf{B} }\mathbf{u} \). For one single-input Jordan block, controllability depends on whether the input reaches the correct location in the chain. Let

\[ \mathbf{J}= \begin{bmatrix} \lambda & 1 & 0\\ 0 & \lambda & 1\\ 0 & 0 & \lambda \end{bmatrix}. \]

If \( \tilde{\mathbf{b} }=[0,0,1]^T \), then the input enters the tail of the chain and can propagate upward through \( \mathbf{J} \). The controllability matrix becomes

\[ \mathcal{C} = \begin{bmatrix} \tilde{\mathbf{b} } & \mathbf{J}\tilde{\mathbf{b} } & \mathbf{J}^2\tilde{\mathbf{b} } \end{bmatrix}, \quad \operatorname{rank}(\mathcal{C})=3. \]

But if \( \tilde{\mathbf{b} }=[1,0,0]^T \), the input enters only the head of the chain and cannot excite the generalized directions below it; the rank is one. Hence Jordan form gives a geometric explanation of actuator placement: it is not enough for an actuator to touch an eigenvalue; it must excite the correct generalized eigenvector directions.

flowchart TD
  B1["Input at chain tail"] --> Z3["z3"]
  Z3 --> Z2["z2"]
  Z2 --> Z1["z1"]
  Z1 --> C1["full chain controllable"]

  H1["Input only at chain head"] --> H2["z1 only"]
  H2 --> H3["generalized directions not reached"]
  H3 --> H4["rank deficient"]
        

6. Observability Along a Jordan Chain

Observability is dual. In Jordan coordinates, \( \mathbf{y}=\tilde{\mathbf{C} }\mathbf{z} \). For the same block, measuring the chain head can reveal the lower chain coordinates through output derivatives:

\[ \mathcal{O} = \begin{bmatrix} \tilde{\mathbf{C} }\\ \tilde{\mathbf{C} }\mathbf{J}\\ \tilde{\mathbf{C} }\mathbf{J}^2 \end{bmatrix}. \]

With \( \tilde{\mathbf{C} }=[1,0,0] \), the output directly senses the head of the chain and successive derivatives expose deeper generalized coordinates. With \( \tilde{\mathbf{C} }=[0,0,1] \), only the tail is sensed, and the rank is deficient. Thus sensor placement must be interpreted relative to the Jordan chain, not merely relative to the physical coordinates.

7. Repeated Poles, Defectiveness, and Pole Assignment

State feedback changes the closed-loop matrix: \( \mathbf{A}_{cl}=\mathbf{A}-\mathbf{B}\mathbf{K} \). When the pair \( (\mathbf{A},\mathbf{B}) \) is controllable, pole placement can assign the closed-loop eigenvalues. However, assigning repeated poles is numerically delicate because the closed-loop eigenvector structure also matters.

A repeated closed-loop eigenvalue may correspond to either several independent eigenvectors or one or more Jordan chains. In theory, controllable systems allow arbitrary characteristic polynomial assignment. In practice, intentionally creating large Jordan blocks is rarely desirable because the response contains polynomial transient factors:

\[ x(t) = c_0 e^{\lambda t} + c_1 t e^{\lambda t} + c_2 t^2 e^{\lambda t} + \cdots . \]

Therefore, a repeated eigenvalue with poor eigenvector conditioning can produce large transient responses even when the eigenvalue itself is stable.

8. Modal Participation and Physical Interpretation

If \( \mathbf{x}=\mathbf{T}\mathbf{z} \), the columns of \( \mathbf{T} \) are eigenvectors and generalized eigenvectors. A physical state may contain several modal coordinates:

\[ \mathbf{x}(t) = \mathbf{T}e^{\mathbf{J}t}\mathbf{z}(0) = \sum_{\ell} \mathbf{T}_{\ell}e^{\mathbf{J}_{\ell}t}\mathbf{z}_{\ell}(0). \]

The transformed input matrix \( \tilde{\mathbf{B} }=\mathbf{T}^{-1}\mathbf{B} \) describes actuator participation in each modal chain, and \( \tilde{\mathbf{C} }=\mathbf{C}\mathbf{T} \) describes sensor participation. This is the basis for interpreting why some modes are easy to control or observe while others are weakly actuated or weakly measured.

9. Python Implementation

Chapter18_Lesson5.py


import math
import numpy as np
from scipy.linalg import expm

def jordan_block(lam, n):
    J = lam * np.eye(n)
    for i in range(n - 1):
        J[i, i + 1] = 1.0
    return J

def jordan_exp(lam, n, t):
    E = np.zeros((n, n))
    scale = math.exp(lam * t)
    for i in range(n):
        for j in range(i, n):
            k = j - i
            E[i, j] = scale * (t ** k) / math.factorial(k)
    return E

def ctrb(A, B):
    n = A.shape[0]
    blocks = []
    Ak = np.eye(n)
    for _ in range(n):
        blocks.append(Ak @ B)
        Ak = A @ Ak
    return np.hstack(blocks)

def obsv(A, C):
    n = A.shape[0]
    blocks = []
    Ak = np.eye(n)
    for _ in range(n):
        blocks.append(C @ Ak)
        Ak = Ak @ A
    return np.vstack(blocks)

A = jordan_block(-1.0, 3)
print("A:")
print(A)

print("closed-form exp(A t), t=2:")
print(jordan_exp(-1.0, 3, 2.0))

print("scipy expm(A t), t=2:")
print(expm(A * 2.0))

B_good = np.array([[0.0], [0.0], [1.0]])
B_bad = np.array([[1.0], [0.0], [0.0]])

print("rank ctrb good:", np.linalg.matrix_rank(ctrb(A, B_good)))
print("rank ctrb bad:", np.linalg.matrix_rank(ctrb(A, B_bad)))

C_good = np.array([[1.0, 0.0, 0.0]])
C_bad = np.array([[0.0, 0.0, 1.0]])

print("rank obsv good:", np.linalg.matrix_rank(obsv(A, C_good)))
print("rank obsv bad:", np.linalg.matrix_rank(obsv(A, C_bad)))
      

10. C++ Implementation

Chapter18_Lesson5.cpp


#include <Eigen/Dense>
#include <cmath>
#include <iostream>

using Eigen::MatrixXd;

MatrixXd jordanBlock(double lambda, int n) {
    MatrixXd J = lambda * MatrixXd::Identity(n, n);
    for (int i = 0; i < n - 1; ++i) {
        J(i, i + 1) = 1.0;
    }
    return J;
}

double factorial(int k) {
    double f = 1.0;
    for (int i = 2; i <= k; ++i) f *= i;
    return f;
}

MatrixXd jordanExp(double lambda, int n, double t) {
    MatrixXd E = MatrixXd::Zero(n, n);
    double scale = std::exp(lambda * t);
    for (int i = 0; i < n; ++i) {
        for (int j = i; j < n; ++j) {
            int k = j - i;
            E(i, j) = scale * std::pow(t, k) / factorial(k);
        }
    }
    return E;
}

MatrixXd ctrb(const MatrixXd& A, const MatrixXd& B) {
    int n = A.rows();
    int m = B.cols();
    MatrixXd W(n, n * m);
    MatrixXd Ak = MatrixXd::Identity(n, n);
    for (int k = 0; k < n; ++k) {
        W.block(0, k * m, n, m) = Ak * B;
        Ak = A * Ak;
    }
    return W;
}

MatrixXd obsv(const MatrixXd& A, const MatrixXd& C) {
    int n = A.rows();
    int p = C.rows();
    MatrixXd W(n * p, n);
    MatrixXd Ak = MatrixXd::Identity(n, n);
    for (int k = 0; k < n; ++k) {
        W.block(k * p, 0, p, n) = C * Ak;
        Ak = Ak * A;
    }
    return W;
}

int main() {
    MatrixXd A = jordanBlock(-1.0, 3);
    MatrixXd Bgood(3, 1), Bbad(3, 1);
    Bgood << 0, 0, 1;
    Bbad << 1, 0, 0;

    MatrixXd Cgood(1, 3), Cbad(1, 3);
    Cgood << 1, 0, 0;
    Cbad << 0, 0, 1;

    std::cout << "A:\\n" << A << "\\n\\n";
    std::cout << "exp(A*2) closed form:\\n" << jordanExp(-1.0, 3, 2.0) << "\\n\\n";
    std::cout << "rank ctrb good = " << Eigen::FullPivLU<MatrixXd>(ctrb(A, Bgood)).rank() << "\\n";
    std::cout << "rank ctrb bad = " << Eigen::FullPivLU<MatrixXd>(ctrb(A, Bbad)).rank() << "\\n";
    std::cout << "rank obsv good = " << Eigen::FullPivLU<MatrixXd>(obsv(A, Cgood)).rank() << "\\n";
    std::cout << "rank obsv bad = " << Eigen::FullPivLU<MatrixXd>(obsv(A, Cbad)).rank() << "\\n";
    return 0;
}
      

11. Java Implementation

Chapter18_Lesson5.java


public class Chapter18_Lesson5 {
    static double[][] eye(int n) {
        double[][] I = new double[n][n];
        for (int i = 0; i < n; i++) I[i][i] = 1.0;
        return I;
    }

    static double[][] jordanBlock(double lambda, int n) {
        double[][] J = eye(n);
        for (int i = 0; i < n; i++) J[i][i] = lambda;
        for (int i = 0; i < n - 1; i++) J[i][i + 1] = 1.0;
        return J;
    }

    static double factorial(int k) {
        double f = 1.0;
        for (int i = 2; i <= k; i++) f *= i;
        return f;
    }

    static double[][] jordanExp(double lambda, int n, double t) {
        double[][] E = new double[n][n];
        double scale = Math.exp(lambda * t);
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                int k = j - i;
                E[i][j] = scale * Math.pow(t, k) / factorial(k);
            }
        }
        return E;
    }

    static void printMatrix(String name, double[][] M) {
        System.out.println(name + " =");
        for (double[] row : M) {
            for (double v : row) System.out.printf("%12.6f", v);
            System.out.println();
        }
    }

    public static void main(String[] args) {
        double[][] A = jordanBlock(-1.0, 3);
        double[][] E = jordanExp(-1.0, 3, 2.0);
        printMatrix("A", A);
        printMatrix("closed form exp(A*2)", E);

        System.out.println("For full rank tests and matrix products, use the downloadable file.");
    }
}
      

12. MATLAB and Simulink Implementation

Chapter18_Lesson5.m


clear; clc; close all;

lambda = -1;
A = [lambda 1 0;
     0 lambda 1;
     0 0 lambda];

t = 2;
E_closed = exp(lambda*t) * [1 t t^2/factorial(2);
                            0 1 t;
                            0 0 1];

disp('A ='); disp(A);
disp('closed-form exp(A t) ='); disp(E_closed);
disp('MATLAB expm(A t) ='); disp(expm(A*t));

B_good = [0; 0; 1];
B_bad = [1; 0; 0];

C_good = [1 0 0];
C_bad = [0 0 1];

disp('rank ctrb good:'); disp(rank(ctrb(A, B_good)));
disp('rank ctrb bad:'); disp(rank(ctrb(A, B_bad)));
disp('rank obsv good:'); disp(rank(obsv(A, C_good)));
disp('rank obsv bad:'); disp(rank(obsv(A, C_bad)));

x0 = [0; 0; 1];
time = linspace(0, 6, 121);
X = zeros(numel(time), 3);

for k = 1:numel(time)
    X(k,:) = (expm(A*time(k))*x0).';
end

figure;
plot(time, X, 'LineWidth', 1.5);
grid on;
xlabel('time');
ylabel('state components');
legend('x_1','x_2','x_3');
title('Jordan-chain response');

if license('test','Simulink')
    mdl = 'Chapter18_Lesson5_Simulink';
    new_system(mdl);
    open_system(mdl);
    add_block('simulink/Continuous/State-Space', [mdl '/Jordan_Chain_State_Space']);
    set_param([mdl '/Jordan_Chain_State_Space'], ...
        'A', mat2str(A), 'B', mat2str(B_good), ...
        'C', mat2str(C_good), 'D', '0', 'X0', mat2str(x0));
    add_block('simulink/Sinks/Scope', [mdl '/Scope']);
    add_line(mdl, 'Jordan_Chain_State_Space/1', 'Scope/1');
    save_system(mdl);
end
      

13. Wolfram Mathematica Implementation

Chapter18_Lesson5.nb


ClearAll["Global`*"]

A = { {-1, 1, 0}, {0, -1, 1}, {0, 0, -1} };
MatrixForm[A]

MatrixExp[A t] // MatrixForm

JordanDecomposition[A]

ControllabilityMatrix[aa_, bb_] :=
  ArrayFlatten[{Table[MatrixPower[aa, k].bb, {k, 0, Length[aa] - 1}]}]

ObservabilityMatrix[aa_, cc_] :=
  Join @@ Table[cc.MatrixPower[aa, k], {k, 0, Length[aa] - 1}]

BGood = { {0}, {0}, {1} };
BBad = { {1}, {0}, {0} };

{MatrixRank[ControllabilityMatrix[A, BGood]],
 MatrixRank[ControllabilityMatrix[A, BBad]]}

CGood = { {1, 0, 0} };
CBad = { {0, 0, 1} };

{MatrixRank[ObservabilityMatrix[A, CGood]],
 MatrixRank[ObservabilityMatrix[A, CBad]]}

Plot[
 Evaluate[MatrixExp[A t].{0, 0, 1}],
 {t, 0, 6},
 PlotLegends -> {"x1", "x2", "x3"},
 AxesLabel -> {"t", "state"}
]
      

14. Problems and Solutions

Problem 1: Let \( \mathbf{J}=\begin{bmatrix}\lambda&1\\0&\lambda\end{bmatrix} \). Derive \( e^{\mathbf{J}t} \).

Solution: Write \( \mathbf{J}=\lambda\mathbf{I}+\mathbf{N} \), where \( \mathbf{N}=\begin{bmatrix}0&1\\0&0\end{bmatrix} \) and \( \mathbf{N}^2=\mathbf{0} \). Hence

\[ e^{\mathbf{J}t} = e^{\lambda t} \left(\mathbf{I}+\mathbf{N}t\right) = e^{\lambda t} \begin{bmatrix} 1 & t\\ 0 & 1 \end{bmatrix}. \]

Problem 2: For \( \mathbf{J}=\begin{bmatrix}\lambda&1&0\\0&\lambda&1\\0&0&\lambda\end{bmatrix} \), determine whether \( \tilde{\mathbf{b} }=[0,0,1]^T \) gives a controllable single-input pair.

Solution: The controllability matrix is

\[ \mathcal{C} = \begin{bmatrix} 0 & 0 & 1\\ 0 & 1 & 2\lambda\\ 1 & \lambda & \lambda^2 \end{bmatrix} \]

up to column ordering. Its determinant is nonzero, so the rank is three. Therefore the chain is controllable.

Problem 3: Explain why an imaginary-axis eigenvalue with a size-two Jordan block is not Lyapunov stable.

Solution: If \( \lambda=j\omega \), then \( e^{\mathbf{J}t}=e^{j\omega t}(\mathbf{I}+\mathbf{N}t) \). The magnitude of \( e^{j\omega t} \) is bounded, but the term \( t\mathbf{N} \) grows without bound. Therefore some initial states generate unbounded trajectories.

Problem 4: Show that observability of \( (\mathbf{J},\tilde{\mathbf{C} }) \) with \( \tilde{\mathbf{C} }=[1,0,0] \) holds for the length-three Jordan block above.

Solution: The observability matrix is

\[ \mathcal{O} = \begin{bmatrix} 1 & 0 & 0\\ \lambda & 1 & 0\\ \lambda^2 & 2\lambda & 1 \end{bmatrix}. \]

This matrix is lower triangular with diagonal entries equal to one, so its determinant is one and its rank is three.

Problem 5: Suppose \( \mathbf{A} \) has eigenvalues \( -1,-1,-1 \). Does this alone determine whether \( e^{\mathbf{A}t} \) contains \( t e^{-t} \) or \( t^2e^{-t} \) terms?

Solution: No. The eigenvalues determine the exponential factors, but the Jordan block sizes determine the polynomial factors. If \( \mathbf{A} \) is diagonalizable, only \( e^{-t} \) terms appear. A size-two block gives \( t e^{-t} \). A size-three block gives both \( t e^{-t} \) and \( t^2e^{-t} \) terms.

15. Summary

Jordan form is not merely an algebraic normal form. In control, it explains repeated-mode dynamics, polynomial transient factors, marginal-stability exceptions, controllability along generalized eigenvector chains, observability through output derivatives, and the practical sensitivity of repeated-pole assignment. Although numerical software often avoids explicit Jordan decomposition because it can be ill-conditioned, Jordan form remains essential for theoretical interpretation of internal dynamics.

16. References

  1. Jordan, C. (1870). Traité des substitutions et des équations algébriques. Gauthier-Villars.
  2. Kalman, R.E. (1960). On the general theory of control systems. Proceedings of the First International Congress on Automatic Control, 481–492.
  3. Gilbert, E.G. (1963). Controllability and observability in multivariable control systems. SIAM Journal on Control, 1(2), 128–151.
  4. Hautus, M.L.J. (1969). Controllability and observability conditions of linear autonomous systems. Nederl. Akad. Wetensch. Proc. Ser. A, 72, 443–448.
  5. Luenberger, D.G. (1967). Canonical forms for linear multivariable systems. IEEE Transactions on Automatic Control, 12(3), 290–293.
  6. Brunovsky, P. (1970). A classification of linear controllable systems. Kybernetika, 6(3), 173–188.
  7. Wonham, W.M. (1967). On pole assignment in multi-input controllable linear systems. IEEE Transactions on Automatic Control, 12(6), 660–665.
  8. Kato, T. (1966). Perturbation Theory for Linear Operators. Springer.