Chapter 1: Introduction to System Dynamics

Lesson 2: Dynamic vs. Static, Linear vs. Nonlinear, Time-Invariant vs. Time-Varying

This lesson introduces three fundamental classification axes for engineering systems: memory (dynamic vs. static), linearity (linear vs. nonlinear), and time dependence (time-invariant vs. time-varying). We formulate these notions in an operator-theoretic way, relate them to differential and difference equations, and provide small computational experiments in Python, C++, Java, MATLAB/Simulink, and Mathematica. These classifications will be used throughout the rest of the course.

1. System as an Operator and Classification Axes

We model a single-input single-output (SISO) system as an operator acting on signals. Let \( u(t) \) denote the input and \( y(t) \) the output, with both defined on some time domain (continuous or discrete). Abstractly, a system is an operator

\[ \mathcal{T} : u(\cdot) \mapsto y(\cdot), \qquad y(t) = \mathcal{T}[u](t). \]

Using this operator viewpoint, we classify systems along three axes:

  • Dynamic vs. static (memoryless): does the output at time \( t \) depend only on the input at \( t \), or on the past history?
  • Linear vs. nonlinear: does the operator satisfy superposition and homogeneity?
  • Time-invariant vs. time-varying: are the system properties unchanged under a shift of the time origin?

These properties are independent; a system can be, for example, dynamic, nonlinear, and time-invariant, or static, linear, and time-varying.

flowchart LR
  SYS["Physical system"] --> OP["Operator T: \nu(.) → y(.)"]
  OP --> M["Memory?"]
  M -->|No| ST["Static (memoryless)"]
  M -->|Yes| DY["Dynamic (with memory)"]

  OP --> LTEST["Test superposition"]
  LTEST --> LIN["Linear"]
  LTEST --> NLIN["Nonlinear"]

  OP --> TTEST["Coefficients depend \non time?"]
  TTEST --> TI["Time-invariant"]
  TTEST --> TV["Time-varying"]
        

2. Dynamic vs. Static (Memoryless) Systems

Intuitively, a system has memory if its present output depends on past values of the input. Formally, for a continuous-time system, let \( u_{(-\infty,t]} \) denote the restriction of \( u \) to the interval \( (-\infty,t] \).

A system is called static (memoryless) if there exists a function \( f \) such that for all input signals

\[ y(t) = \mathcal{T}[u](t) = f\big(u(t)\big), \]

i.e., the output at time \( t \) depends only on the input at the same time. No derivatives, integrals, or delays appear.

A system is called dynamic if the output at time \( t \) cannot be written solely as a function of \( u(t) \), but depends on past behavior. Often, dynamic systems are represented by differential or difference equations with internal state \( x(t) \):

\[ \dot{x}(t) = f\big(x(t),u(t),t\big), \qquad y(t) = g\big(x(t),u(t),t\big). \]

Here \( x(t) \) encodes the accumulated effect of past inputs. For discrete-time systems with sampling period \( T_s \), we similarly write

\[ x[k+1] = f\big(x[k],u[k],k\big), \qquad y[k] = g\big(x[k],u[k],k\big), \]

where \( k \) indexes the sampling instants.

Examples.

  • Static: \( y(t) = 2u(t) \), \( y(t) = \sin(u(t)) \), \( y(t) = u^3(t) \).
  • Dynamic: \( \dot{y}(t) + y(t) = u(t) \), \( y(t) = \displaystyle \int_{0}^{t} u(\lambda)\,\mathrm{d}\lambda \), \( y[k] = 0.5\,y[k-1] + u[k] \).

Note that dynamics can arise from integrators, derivatives, or explicit delays (e.g. output at time \( t \) depending on \( u(t-\tau) \)).

3. Linear vs. Nonlinear Systems

Let \( \mathcal{U} \) be a vector space of input signals (for example, square-integrable functions or finite-energy discrete-time sequences) and \( \mathcal{Y} \) a vector space of outputs. A system operator \( \mathcal{T} : \mathcal{U} \to \mathcal{Y} \) is linear if for all inputs \( u_1,u_2 \in \mathcal{U} \) and scalars \( \alpha,\beta \in \mathbb{R} \) (or \( \mathbb{C} \))

\[ \mathcal{T}[\alpha u_1 + \beta u_2] = \alpha\,\mathcal{T}[u_1] + \beta\,\mathcal{T}[u_2]. \]

This implies both additivity and homogeneity. If this condition fails, the system is called nonlinear.

Static systems. For a static system \( y(t) = f(u(t)) \), linearity requires that for every pair of scalars \( a_1,a_2 \) and inputs \( u_1,u_2 \):

\[ f\big(a_1 u_1(t) + a_2 u_2(t)\big) = a_1 f\big(u_1(t)\big) + a_2 f\big(u_2(t)\big), \quad \forall t. \]

It can be shown (using functional equations) that the only continuous solutions are \( f(u) = k u \) with constant \( k \). Thus, a static linear system is necessarily a pure gain.

Dynamic systems. A common representation of a linear dynamic system is an ODE (continuous-time) or difference equation (discrete-time) that is linear in both the input and the output (and its derivatives or shifts). For continuous-time:

\[ a_n(t)\frac{\mathrm{d}^n y(t)}{\mathrm{d}t^n} + \dots + a_1(t)\frac{\mathrm{d}y(t)}{\mathrm{d}t} + a_0(t)\,y(t) = b_m(t)\frac{\mathrm{d}^m u(t)}{\mathrm{d}t^m} + \dots + b_0(t)\,u(t), \]

where the coefficients \( a_i(t) \), \( b_j(t) \) are scalar functions of time. The system is linear in the signals \( y(\cdot) \) and \( u(\cdot) \) because no products like \( y^2(t) \), \( y(t)u(t) \), or \( \sin(y(t)) \) occur.

In state-space form, a linear dynamic system can be written as

\[ \dot{x}(t) = A(t)\,x(t) + B(t)\,u(t), \qquad y(t) = C(t)\,x(t) + D(t)\,u(t), \]

where \( A(t),B(t),C(t),D(t) \) are matrices with suitable dimensions. Nonlinear systems violate this structure, for example: \( \dot{x}(t) = x^2(t) + u(t) \) or \( y(t) = x^3(t) \).

Examples.

  • Linear dynamic: \( \dot{y}(t) + 3y(t) = 2u(t) \).
  • Nonlinear static: \( y(t) = u^2(t) \), \( y(t) = \sin\big(u(t)\big) \).
  • Nonlinear dynamic: \( \dot{y}(t) + y^2(t) = u(t) \), \( \dot{y}(t) = y(t)\,u(t) \).

4. Time-Invariant vs. Time-Varying Systems

Time invariance formalizes the idea that the system laws do not explicitly depend on the absolute time origin. Consider the time-shift operator \( (\mathcal{S}_{t_0}u)(t) = u(t-t_0) \).

A system \( \mathcal{T} \) is called time-invariant if for every input \( u \) and every shift \( t_0 \) we have

\[ \mathcal{T}[\mathcal{S}_{t_0} u](t) = \mathcal{S}_{t_0}\big(\mathcal{T}[u]\big)(t) \quad\text{for all } t. \]

Equivalently, shifting the input by \( t_0 \) shifts the output by the same amount, without changing its shape. If this property fails, the system is time-varying.

Examples.

  • Time-invariant: \( y(t) = 3u(t) \), \( \dot{y}(t) + 2y(t) = u(t) \), \( y(t) = \displaystyle\int_{0}^{\infty} k(\tau)\,u(t-\tau)\,\mathrm{d}\tau \) with fixed kernel \( k(\tau) \).
  • Time-varying: \( y(t) = t\,u(t) \), \( \dot{y}(t) + t\,y(t) = u(t) \), \( y(t) = u(2t) \).

For ODEs of the form shown in Section 3, the system is time-invariant precisely when the coefficients are constant:

\[ a_i(t) = a_i,\quad b_j(t) = b_j \quad\text{(constants)}. \]

In state-space form, time invariance corresponds to constant matrices \( A,B,C,D \):

\[ \dot{x}(t) = A\,x(t) + B\,u(t), \qquad y(t) = C\,x(t) + D\,u(t). \]

5. Unified Operator View and Classification Flow

For system-level reasoning in control engineering, it is useful to summarize these properties in a unified framework. Consider an operator \( \mathcal{T} \) acting on signals; to classify it:

  1. Memory test: does \( y(t) \) depend only on \( u(t) \)?
  2. Linearity test: does superposition hold for all admissible inputs?
  3. Time-invariance test: is the operator commutative with time shifts?

This conceptual procedure is sketched below.

flowchart LR
  START["Given input-output \ndescription"] --> STEP1["Check dependence \non history"]
  STEP1 -->|"Only u(t)"| S1["Static"]
  STEP1 -->|"Past states/inputs"| S2["Dynamic"]

  STEP2["Test superposition \nT[alpha u1 + beta u2] = \nalpha T[u1] + beta T[u2]"] --> L1["Linear"]
  STEP2 --> L2["Nonlinear"]

  STEP3["Apply time shift to input"] --> T1["Output only shifts → Time-invariant"]
  STEP3 --> T2["Output shape changes → Time-varying"]
        

In later chapters we will see that linear time-invariant (LTI) systems are especially important: they admit powerful analytic tools (e.g. eigenvalue analysis, transfer functions, and frequency response). However, many real systems are nonlinear and/or time-varying, so modeling often involves approximation and linearization.

6. Python Lab — Discrete-Time Classification Experiments

To build intuition, we approximate continuous-time signals by discrete-time sequences and implement small numerical tests for linearity and time invariance. We use numpy for vector operations. More specialized libraries (such as scipy.signal or the Python control toolbox) will be used in later chapters when we discuss transfer functions and state-space models.


import numpy as np

# Discrete-time signals: vectors u of length N
N = 100
n = np.arange(N, dtype=float)

# Example inputs
u1 = np.sin(0.1 * n)        # signal 1
u2 = np.cos(0.07 * n)       # signal 2

# 1) Static linear system: y[k] = 2 * u[k]
def sys_static_linear(u):
    return 2.0 * u

# 2) Static nonlinear system: y[k] = u[k]^2
def sys_static_nonlinear(u):
    return u**2

# 3) Dynamic linear system: first-order difference
#    y[k+1] = a * y[k] + b * u[k], with y[0] = 0
def sys_dynamic_linear(u, a=0.8, b=0.2):
    y = np.zeros_like(u)
    for k in range(N - 1):
        y[k + 1] = a * y[k] + b * u[k]
    return y

# Helper: approximate test of linearity by sampling a1,a2
def check_linearity(sys_fun, u1, u2, alpha=1.3, beta=-0.7):
    y1 = sys_fun(u1)
    y2 = sys_fun(u2)
    lhs = sys_fun(alpha * u1 + beta * u2)
    rhs = alpha * y1 + beta * y2
    error = np.linalg.norm(lhs - rhs) / max(1e-12, np.linalg.norm(rhs))
    return error

# Helper: approximate test of time invariance for shift d
def check_time_invariance(sys_fun, u, d=5):
    # zero-pad left shift (circular effects avoided by padding)
    u_shifted = np.zeros_like(u)
    if d < N:
        u_shifted[d:] = u[:N - d]

    y = sys_fun(u)
    y_shifted_input = sys_fun(u_shifted)

    y_time_shifted = np.zeros_like(y)
    if d < N:
        y_time_shifted[d:] = y[:N - d]

    error = np.linalg.norm(y_shifted_input - y_time_shifted) / max(1e-12, np.linalg.norm(y_time_shifted))
    return error

# Run tests
for name, sys_fun in [
    ("static_linear", sys_static_linear),
    ("static_nonlinear", sys_static_nonlinear),
    ("dynamic_linear", sys_dynamic_linear),
]:
    lin_err = check_linearity(sys_fun, u1, u2)
    ti_err = check_time_invariance(sys_fun, u1)
    print("System:", name)
    print("  linearity error ~", lin_err)
    print("  time-invariance error ~", ti_err)
      

For the static linear and dynamic linear systems, the linearity and time-invariance errors should be close to zero (up to numerical effects). For the static nonlinear system the linearity error will be large, although it remains time-invariant.

7. C++ and Java — Simple Interfaces for Dynamic Systems

In compiled languages, we often encapsulate system laws in classes or functors. Below, we show minimal abstractions for a discrete-time system in C++ and Java. Later, more sophisticated libraries (Eigen in C++, Apache Commons Math in Java) can be used for vector-matrix operations and numerical integration.

7.1 C++ example


#include <vector>
#include <cmath>

// Abstract base for SISO discrete-time systems
class DiscreteSystem {
public:
    virtual ~DiscreteSystem() {}
    // takes full input trajectory u and returns output y
    virtual std::vector<double> apply(const std::vector<double>& u) const = 0;
};

// Static linear system: y[k] = k_gain * u[k]
class StaticLinear : public DiscreteSystem {
public:
    explicit StaticLinear(double k_gain) : k_gain_(k_gain) {}
    std::vector<double> apply(const std::vector<double>& u) const override {
        std::vector<double> y(u.size());
        for (std::size_t k = 0; k < u.size(); ++k) {
            y[k] = k_gain_ * u[k];
        }
        return y;
    }
private:
    double k_gain_;
};

// Dynamic linear system: y[k+1] = a*y[k] + b*u[k], y[0] = 0
class FirstOrderDynamic : public DiscreteSystem {
public:
    FirstOrderDynamic(double a, double b) : a_(a), b_(b) {}
    std::vector<double> apply(const std::vector<double>& u) const override {
        std::size_t N = u.size();
        std::vector<double> y(N, 0.0);
        for (std::size_t k = 0; k + 1 < N; ++k) {
            y[k + 1] = a_ * y[k] + b_ * u[k];
        }
        return y;
    }
private:
    double a_, b_;
};
      

7.2 Java example


public interface DiscreteSystem {
    double[] apply(double[] u);
}

// Static nonlinear system: y[k] = u[k]^2
public class StaticNonlinear implements DiscreteSystem {
    @Override
    public double[] apply(double[] u) {
        double[] y = new double[u.length];
        for (int k = 0; k < u.length; ++k) {
            y[k] = u[k] * u[k];
        }
        return y;
    }
}

// Dynamic linear system: y[k+1] = a*y[k] + b*u[k], y[0] = 0
public class FirstOrderDynamic implements DiscreteSystem {
    private final double a;
    private final double b;

    public FirstOrderDynamic(double a, double b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public double[] apply(double[] u) {
        int N = u.length;
        double[] y = new double[N];
        y[0] = 0.0;
        for (int k = 0; k + 1 < N; ++k) {
            y[k + 1] = a * y[k] + b * u[k];
        }
        return y;
    }
}
      

In both languages, static vs. dynamic is reflected in whether the class maintains or updates internal state (here, y[k] depends on past values for dynamic systems).

8. MATLAB/Simulink and Mathematica Implementations

8.1 MATLAB scripts for static and dynamic systems

In MATLAB, we can treat discrete-time signals as vectors. Below we implement the same static and dynamic systems as in Python and C++.


N = 100;
n = 0:N-1;

u = sin(0.1 * n);   % example input

% Static linear system: y[k] = 2 * u[k]
y_static_linear = 2 * u;

% Static nonlinear system: y[k] = u[k]^2
y_static_nonlinear = u.^2;

% Dynamic linear system: y[k+1] = a*y[k] + b*u[k]
a = 0.8;
b = 0.2;
y_dynamic = zeros(size(u));
for k = 1:(N-1)
    y_dynamic(k+1) = a * y_dynamic(k) + b * u(k);
end

% Plot to visualize dynamic memory
figure;
plot(n, u, 'DisplayName', 'u[k]');
hold on;
plot(n, y_dynamic, 'DisplayName', 'y[k]');
xlabel('k');
ylabel('Amplitude');
legend('show');
grid on;
      

In Simulink, a static gain block implements a static linear system, while an integrator or unit delay block introduces dynamics. A time-varying gain can be implemented by using a block whose gain parameter is driven by another signal (for example, by feeding a time-dependent parameter via a block mask or a lookup table).

8.2 Mathematica: symbolic representation and tests

Mathematica is well suited for symbolic manipulations and functional definitions of systems. Below we define a static linear and a static nonlinear operator and test linearity symbolically.


ClearAll[TstaticLinear, TstaticNonlinear]

(* Static linear system: y(t) = k * u(t) *)
k = Symbol["k"];
TstaticLinear[u_] := k * u;

(* Static nonlinear system: y(t) = u(t)^2 *)
TstaticNonlinear[u_] := u^2;

(* Symbolic test of linearity for TstaticLinear *)
ClearAll[u1, u2, a1, a2];
lhsLinear = TstaticLinear[a1*u1 + a2*u2];
rhsLinear = a1*TstaticLinear[u1] + a2*TstaticLinear[u2];
Simplify[lhsLinear - rhsLinear]

(* For TstaticNonlinear *)
lhsNonlinear = TstaticNonlinear[a1*u1 + a2*u2];
rhsNonlinear = a1*TstaticNonlinear[u1] + a2*TstaticNonlinear[u2];
Expand[lhsNonlinear - rhsNonlinear]
      

The first difference simplifies to zero, confirming linearity. The second difference is generally nonzero, demonstrating nonlinearity of the quadratic static system.

9. Problems and Solutions

Problem 1 (Classification of a static affine system).
Consider the system \( y(t) = 3u(t) + 1 \). Classify it as dynamic or static, linear or nonlinear, and time-invariant or time-varying.

Solution.

  • Static vs. dynamic: The output at time \( t \) depends only on the value \( u(t) \), with no derivatives, integrals, or delays. Hence the system is static (memoryless).
  • Linearity: For linearity we require \( y(t) = k u(t) \) with no constant offset. Here, \( y(t) = 3u(t) + 1 \) does not satisfy homogeneity:

\[ \mathcal{T}[\alpha u](t) = 3\,\alpha u(t) + 1 \neq \alpha\,(3u(t) + 1) \quad\text{for general } \alpha. \]

Thus the system is nonlinear (more precisely, affine).

  • Time invariance: There is no explicit dependence on time; replacing \( u(t) \) by \( u(t-t_0) \) yields \( y(t) = 3u(t-t_0)+1 \), which is just a shifted version of the original output. Therefore, the system is time-invariant.

Problem 2 (Integral system).
Consider the system \( y(t) = \displaystyle\int_{0}^{t} e^{-(t-\lambda)} u(\lambda)\,\mathrm{d}\lambda \). Classify it.

Solution.

  • The output at time \( t \) depends on all past values \( u(\lambda) \) for \( 0 \le \lambda \le t \), so the system has memory and is dynamic.
  • The mapping is linear in \( u \) because the integral is linear:

\[ \mathcal{T}[\alpha u_1 + \beta u_2](t) = \int_{0}^{t} e^{-(t-\lambda)}\big(\alpha u_1(\lambda) + \beta u_2(\lambda)\big)\,\mathrm{d}\lambda = \alpha\,\mathcal{T}[u_1](t) + \beta\,\mathcal{T}[u_2](t). \]

  • The kernel \( e^{-(t-\lambda)} \) depends only on the time difference \( t-\lambda \). Shifting the input by \( t_0 \) shifts the output by the same amount, so the system is time-invariant.

Overall, the system is dynamic, linear, and time-invariant.

Problem 3 (Time-varying linear ODE).
Consider the ODE \( \dot{y}(t) + t\,y(t) = u(t) \). Classify the system.

Solution.

  • The equation involves \( \dot{y}(t) \), so the system has memory: it is dynamic.
  • The ODE is linear in both \( y \) and \( u \); there are no products such as \( y^2 \) or \( yu \). Therefore, the system is linear.
  • The coefficient of \( y(t) \) explicitly depends on time (\( t \)), so shifting the input does not just shift the output; the system is time-varying.

Problem 4 (Delayed nonlinear discrete-time system).
Consider the discrete-time system \( y[k] = u^2[k-1] \). Classify it.

Solution.

  • The output at time index \( k \) depends on the past input \( u[k-1] \), so the system has memory and is dynamic.
  • The relation is quadratic in \( u \). Superposition fails:

\[ (a_1 u_1[k-1] + a_2 u_2[k-1])^2 \neq a_1 u_1^2[k-1] + a_2 u_2^2[k-1] \quad\text{in general}. \]

Hence the system is nonlinear.

  • There is no explicit dependence on \( k \) in the equation; shifting the input by one step shifts the output by one step with the same rule, hence the system is time-invariant.

Problem 5 (Flow for classification).
Outline a step-by-step procedure to classify a given input–output relation into the categories discussed in this lesson.

Solution. One possible procedure is illustrated below.

flowchart TD
  S["Start from input-output equation"] --> M["Does y depend only on u(t) or u[k]?"]
  M -->|Yes| STAT["Static"]
  M -->|No| DYN["Dynamic"]

  DYN --> L["Test linearity (superposition)"]
  STAT --> L
  L -->|Holds| LIN["Linear"]
  L -->|Fails| NLIN["Nonlinear"]

  LIN --> TI["Apply time shift to input"]
  NLIN --> TI
  TI -->|Only shift in output| TINV["Time-invariant"]
  TI -->|Output shape changes| TVAR["Time-varying"]
        

For each step, the key is to apply the definitions: check whether the mapping can be written as \( y(t) = f(u(t)) \) (static), whether the superposition property holds (linear), and whether time shifts commute with the system operator (time-invariant).

10. Summary

In this lesson, we introduced three central classification axes for systems used in control engineering:

  • Dynamic vs. static: dynamic systems possess memory (typically captured by state variables), whereas static systems are memoryless mappings \( y(t) = f(u(t)) \).
  • Linear vs. nonlinear: linear systems satisfy superposition and are described by equations linear in the signals; nonlinear systems violate at least one of these properties.
  • Time-invariant vs. time-varying: time-invariant systems commute with time shifts and are often characterized by constant coefficients; time-varying systems involve explicit time dependence in their laws.

We also implemented simple classification experiments in Python, C++, Java, MATLAB, and Mathematica, emphasizing that the same conceptual properties can be explored in both theoretical and computational settings. In subsequent lessons and chapters, we will systematically exploit the special structure of linear time-invariant systems while keeping in mind that many physical systems are inherently nonlinear and sometimes time-varying.

11. References

  1. Zadeh, L.A., & Desoer, C.A. (1963). Linear System Theory: The State Space Approach. McGraw-Hill, New York.
  2. Kalman, R.E. (1960). Contributions to the theory of optimal control. Boletín de la Sociedad Matemática Mexicana, 5(2), 102–119.
  3. Rugh, W.J. (1972). Nonlinear system theory: the Volterra/Wiener approach. SIAM Journal on Control, 10(2), 268–285.
  4. Desoer, C.A., & Kuh, E.S. (1969). Basic Circuit Theory. McGraw-Hill, New York. (Foundational chapters on linearity and time invariance.)
  5. Willems, J.C. (1972). Dissipative dynamical systems. Archive for Rational Mechanics and Analysis, 45(5), 321–393.
  6. Vidyasagar, M. (1978). Nonlinear systems analysis: a Lyapunov-based approach. SIAM Journal on Control and Optimization, various articles.
  7. Brockett, R.W. (1970). Finite dimensional linear systems. Wiley Series in Probability and Mathematical Statistics.
  8. Sontag, E.D. (1979). Polynomial response maps. Springer Lecture Notes in Control and Information Sciences, 13.
  9. Hahn, W. (1967). Stability of Motion. Springer. (Chapters on linear vs. nonlinear systems.)
  10. Triggiani, R. (1975). Invariance and time-variance in linear systems. Journal of Mathematical Analysis and Applications, 49(2), 347–364.