Chapter 7: Block Diagrams and Signal Flow Graphs
Lesson 5: Practical Modeling Examples Using Block Diagrams and Signal Flow Graphs
This lesson consolidates the modeling workflow by constructing block diagrams and equivalent signal flow graphs for realistic interconnected dynamic systems. We derive closed-loop transfer functions for reference tracking, input disturbances, and measurement noise; verify results using Mason’s gain formula; and present implementable workflows in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica. Emphasis is placed on rigorous algebraic derivations and the graph-theoretic foundations that justify block-diagram reduction and signal-flow computations.
1. Learning Outcomes and Setup
By the end of this lesson, you should be able to:
- Translate a physical interconnection into a consistent block diagram with explicit summing junctions and signal definitions.
- Convert the same interconnection into a signal flow graph (SFG) with node equations and directed branch gains.
- Compute key closed-loop transfer functions (reference-to-output, disturbance-to-output, noise-to-output) by (i) block-diagram algebra and (ii) Mason’s gain formula.
- Relate Mason’s formula to linear algebra via \( (\mathbf{I}-\mathbf{A})^{-1} \), determinants, and cofactors.
- Implement the computations in multiple programming environments, including a from-scratch Mason solver for small graphs.
Throughout, we assume linear time-invariant (LTI) blocks represented by transfer functions in the Laplace domain. If a signal is \( x(t) \) in time, its Laplace transform is \( X(s) \). All interconnections are interpreted as algebraic relations among Laplace-domain variables (consistent with Chapter 6 and Chapter 7, Lessons 1–4).
2. Practical Example A — Feedback with Disturbance and Measurement Noise
Consider a standard feedback interconnection with the following LTI blocks: \( C(s) \) (controller or compensator), \( A(s) \) (actuator dynamics), \( G(s) \) (plant dynamics), \( H(s) \) (sensor/measurement dynamics). We include an additive input disturbance \( D(s) \) at the plant input and additive measurement noise \( N(s) \) at the sensor output.
Define signals (Laplace domain): \( R(s) \) reference, \( E(s) \) error, \( U(s) \) controller output, \( V(s) \) actuator/plant input, \( Y(s) \) plant output, \( M(s) \) measured output.
\[ \begin{aligned} E(s) &= R(s) - M(s), \\ U(s) &= C(s)\,E(s), \\ V(s) &= A(s)\,U(s) + D(s), \\ Y(s) &= G(s)\,V(s), \\ M(s) &= H(s)\,Y(s) + N(s). \end{aligned} \]
The loop transfer function is defined as \( L(s) := C(s)A(s)G(s)H(s) \). Solving algebraically for \( Y(s) \) yields the three fundamental closed-loop transfer functions.
2.1 Closed-loop derivation by block-diagram algebra
Substitute \( M(s)=H(s)Y(s)+N(s) \) into \( E(s)=R(s)-M(s) \), then propagate forward:
\[ \begin{aligned} Y(s) &= G(s)\big(A(s)C(s)\big(R(s)-H(s)Y(s)-N(s)\big)+D(s)\big) \\ &= G(s)A(s)C(s)R(s) - G(s)A(s)C(s)H(s)Y(s) - G(s)A(s)C(s)N(s) + G(s)D(s). \end{aligned} \]
Collect the \( Y(s) \) terms:
\[ \big(1 + C(s)A(s)G(s)H(s)\big)\,Y(s) = C(s)A(s)G(s)\,R(s) + G(s)\,D(s) - C(s)A(s)G(s)\,N(s). \]
Therefore:
\[ \boxed{ \frac{Y(s)}{R(s)} = \frac{C(s)A(s)G(s)}{1 + L(s)},\quad \frac{Y(s)}{D(s)} = \frac{G(s)}{1 + L(s)},\quad \frac{Y(s)}{N(s)} = -\frac{C(s)A(s)G(s)}{1 + L(s)}. } \]
Two frequently used closed-loop factors are the sensitivity and complementary sensitivity: \( S(s) := \frac{1}{1+L(s)} \) and \( T(s) := \frac{L(s)}{1+L(s)} \). Note that \( H(s)\frac{Y(s)}{R(s)} = T(s) \).
2.2 A concrete plant choice (from earlier chapters)
A typical translational mass–spring–damper plant (force input, position output) is: \( G(s) = \frac{1}{ms^2 + bs + k} \), where \( m > 0 \), \( b > 0 \), \( k > 0 \).
\[ G(s) = \frac{1}{ms^2 + bs + k},\quad L(s) = C(s)A(s)H(s)\frac{1}{ms^2 + bs + k}. \]
This example is “practical” because the same interconnection simultaneously quantifies: tracking (\( Y/R \)), disturbance rejection (\( Y/D \)), and noise injection (\( Y/N \))—all via the same denominator \( 1+L(s) \).
3. Block Diagram Representation (Example A)
The block diagram below explicitly shows the disturbance injected at the plant input and the measurement noise added after the sensor. (All labels are ASCII-friendly for diagram rendering.)
flowchart TD
R["R(s)"] --> SUME["sum: E = R - M"]
SUME --> C["C(s)"]
C --> A["A(s)"]
A --> SUMV["sum: V = A*U + D"]
D["D(s)"] --> SUMV
SUMV --> G["G(s)"]
G --> Y["Y(s)"]
Y --> H["H(s)"]
H --> SUMN["sum: M = H*Y + N"]
N["N(s)"] --> SUMN
SUMN --> M["M(s)"]
M -->|"-"| SUME
In reduction work, it is essential to keep summing junctions explicit until you have verified the sign conventions and injection points. A frequent modeling error is placing \( N(s) \) before \( H(s) \) (which changes the noise-to-output transfer).
4. Equivalent Signal Flow Graph and Mason Verification
The same interconnection can be represented as an SFG by making each signal a node and each block or summation contribution a directed branch. The key is to encode the node equations exactly as in Section 2.
flowchart LR
R["R"] -->|"+1"| E["E"]
M["M"] -->|"-1"| E
E -->|"C(s)"| U["U"]
U -->|"A(s)"| VA["A*U"]
D["D"] -->|"+1"| V["V"]
VA -->|"+1"| V
V -->|"G(s)"| Y["Y"]
Y -->|"H(s)"| HY["H*Y"]
HY -->|"+1"| M
N["N"] -->|"+1"| M
4.1 Mason’s gain formula check for \( Y/R \)
Identify the forward path from \( R \) to \( Y \): \( R \rightarrow E \rightarrow U \rightarrow V \rightarrow Y \) with path gain \( P_1(s)=C(s)A(s)G(s) \).
There is one feedback loop: \( E \rightarrow U \rightarrow V \rightarrow Y \rightarrow H\!Y \rightarrow M \rightarrow E \), whose gain is
\[ L_1(s) = \big(C(s)\big)\big(A(s)\big)\big(G(s)\big)\big(H(s)\big)\cdot(-1) = -L(s). \]
Hence Mason’s determinant is \( \Delta(s)=1-\sum L_i(s)=1-(-L(s))=1+L(s) \). Since the loop touches the forward path, the cofactor determinant for that path is \( \Delta_1(s)=1 \). Therefore:
\[ \frac{Y(s)}{R(s)} = \frac{P_1(s)\Delta_1(s)}{\Delta(s)} = \frac{C(s)A(s)G(s)}{1+L(s)}, \]
which matches the block-diagram algebra result.
4.2 Practical note: using Mason for disturbance and noise
Treat \( D \) and \( N \) as additional independent inputs and compute the forward paths \( D \rightarrow V \rightarrow Y \) and \( N \rightarrow M \rightarrow E \rightarrow U \rightarrow V \rightarrow Y \). The same \( \Delta(s)=1+L(s) \) denominator appears, because the loop set is unchanged—only the forward paths differ.
5. Linear-Algebra Foundation of Signal Flow Graphs
For an SFG with node variable vector \( \mathbf{x}(s)\in\mathbb{R}^n \), branch gains define a matrix \( \mathbf{A}(s)\in\mathbb{R}^{n\times n} \) such that each node equation is linear:
\[ \mathbf{x}(s) = \mathbf{A}(s)\mathbf{x}(s) + \mathbf{b}(s)\,R(s), \quad Y(s) = \mathbf{c}(s)^\top \mathbf{x}(s), \]
where \( \mathbf{b}(s) \) selects how the input enters the nodes, and \( \mathbf{c}(s) \) selects the output node. Assuming \( \det(\mathbf{I}-\mathbf{A}(s)) \neq 0 \), we obtain:
\[ \mathbf{x}(s) = (\mathbf{I}-\mathbf{A}(s))^{-1}\mathbf{b}(s)\,R(s), \quad \frac{Y(s)}{R(s)} = \mathbf{c}(s)^\top (\mathbf{I}-\mathbf{A}(s))^{-1}\mathbf{b}(s). \]
5.1 Theorem (Cramer/cofactor form of the transfer function)
Let \( \mathbf{M}(s) := \mathbf{I}-\mathbf{A}(s) \). If the input injects at node \( k \) and the output is node \( \ell \), then
\[ \boxed{ \frac{X_\ell(s)}{R(s)} = \frac{\operatorname{cof}\big(\mathbf{M}(s)\big)_{k\ell}}{\det(\mathbf{M}(s))} } \]
Proof: With a single input entering node \( k \), we have \( \mathbf{b}(s)=\mathbf{e}_k \) (standard basis vector), so
\[ \mathbf{x}(s) = \mathbf{M}(s)^{-1}\mathbf{e}_k\,R(s). \]
Therefore, \( X_\ell(s)/R(s) \) is the \( \ell \)-th component of \( \mathbf{M}(s)^{-1}\mathbf{e}_k \), i.e., the \( (\ell,k) \) entry of \( \mathbf{M}(s)^{-1} \). Using \( \mathbf{M}^{-1} = \operatorname{adj}(\mathbf{M})/\det(\mathbf{M}) \) and \( \operatorname{adj}(\mathbf{M})_{\ell k} = \operatorname{cof}(\mathbf{M})_{k\ell} \) completes the proof.
5.2 Why Mason’s formula matches this result (proof sketch)
Mason’s formula expresses \( Y/R \) as a ratio of two quantities built from (i) forward paths and (ii) loop/non-touching loop products. The determinant \( \det(\mathbf{I}-\mathbf{A}) \) expands into sums of products of matrix entries; combinatorially, these products correspond to disjoint directed cycles (loops). The cofactor \( \operatorname{cof}(\mathbf{I}-\mathbf{A}) \) similarly expands into sums of products of entries that correspond to a forward connection from input to output together with loop products that do not touch that forward connection.
In other words, Mason’s \( \Delta \) equals \( \det(\mathbf{I}-\mathbf{A}) \) (up to the sign convention already handled by branch signs), and Mason’s \( \Delta_k \) corresponds to the cofactor restrictions (“remove” nodes on the path so only non-touching loops remain). This is the rigorous bridge between graph rules and linear algebra.
6. Practical Example B — Nested Feedback (Two Loops)
Nested feedback is common in engineering systems (e.g., inner-loop actuator stabilization with an outer performance loop). Consider an inner feedback around the plant \( G(s) \) with feedback \( H_2(s) \), and an outer feedback around the entire “inner-closed” plant with feedback \( H_1(s) \) and forward block \( C(s)A(s) \).
Step 1 (inner loop reduction):
\[ G_{\text{inner}}(s) = \frac{G(s)}{1 + G(s)H_2(s)}. \]
Step 2 (outer loop reduction):
\[ \frac{Y(s)}{R(s)} = \frac{C(s)A(s)\,G_{\text{inner}}(s)}{1 + C(s)A(s)\,G_{\text{inner}}(s)\,H_1(s)} = \frac{C(s)A(s)G(s)}{1 + G(s)H_2(s) + C(s)A(s)G(s)H_1(s)}. \]
The final denominator has the practical interpretation “sum of loop effects”: one term for the inner loop \( G H_2 \), one for the outer loop \( CAGH_1 \), and the constant 1. If you build the SFG, you will find two loops that share nodes (touching loops), so there is no non-touching-loop product term.
7. Practical Example C — 2×2 MIMO Feedback Using Block-Matrix Algebra
In Chapter 7, Lesson 4, you learned to treat MIMO blocks as transfer matrices. Consider \( \mathbf{G}(s)\in\mathbb{R}^{2\times 2} \) and a static or dynamic feedback matrix \( \mathbf{K}(s)\in\mathbb{R}^{2\times 2} \) with the interconnection \( \mathbf{u}(s)=\mathbf{r}(s)-\mathbf{K}(s)\mathbf{y}(s) \) and \( \mathbf{y}(s)=\mathbf{G}(s)\mathbf{u}(s) \).
\[ \begin{aligned} \mathbf{y}(s) &= \mathbf{G}(s)\big(\mathbf{r}(s)-\mathbf{K}(s)\mathbf{y}(s)\big) \\ \big(\mathbf{I} + \mathbf{G}(s)\mathbf{K}(s)\big)\mathbf{y}(s) &= \mathbf{G}(s)\mathbf{r}(s) \\ \boxed{ \mathbf{y}(s) = \big(\mathbf{I} + \mathbf{G}(s)\mathbf{K}(s)\big)^{-1}\mathbf{G}(s)\mathbf{r}(s) } \end{aligned} \]
Invertibility condition: the closed-loop transfer matrix is well-defined if \( \det(\mathbf{I}+\mathbf{G}(s)\mathbf{K}(s)) \neq 0 \). This is the MIMO analogue of the scalar condition \( 1+L(s)\neq 0 \).
For a 2×2 matrix, you can write an explicit adjugate form. If \( \mathbf{M}(s)=\mathbf{I}+\mathbf{G}(s)\mathbf{K}(s)=\begin{bmatrix} a(s)&b(s)\\c(s)&d(s)\end{bmatrix} \), then
\[ \mathbf{M}(s)^{-1} = \frac{1}{a(s)d(s)-b(s)c(s)} \begin{bmatrix} d(s) & -b(s) \\ -c(s) & a(s) \end{bmatrix}, \quad \text{provided } a(s)d(s)-b(s)c(s)\neq 0. \]
This explicit formula is useful when you want to compute and simplify each closed-loop entry symbolically (e.g., in Mathematica), and it mirrors the cofactor logic used in SFG theory.
8. Implementations Across Tools
This section implements Example A in multiple environments. The numerical plant is chosen as: \( m=1 \), \( b=2 \), \( k=20 \), with \( A(s)=1 \), \( H(s)=1 \), and a simple proportional controller \( C(s)=K \). (We do not design \( K \) here; we only demonstrate modeling and computation.)
8.1 Python (control + from-scratch Mason for small graphs)
# pip install control sympy networkx numpy matplotlib
import numpy as np
import control as ct
# Example A parameters
m, b, k = 1.0, 2.0, 20.0
K = 5.0
s = ct.TransferFunction.s
G = 1 / (m*s**2 + b*s + k) # plant
A = 1 # actuator
H = 1 # sensor
C = K # controller (proportional)
L = C*A*G*H
S = 1 / (1 + L)
Gyr = (C*A*G) * S # Y/R
Gyd = (G) * S # Y/D (disturbance injected at plant input)
Gyn = -(C*A*G) * S # Y/N (measurement noise added after H)
print("Y/R =", Gyr)
print("Y/D =", Gyd)
print("Y/N =", Gyn)
# Step response from reference
t = np.linspace(0, 5, 800)
t1, y1 = ct.step_response(Gyr, T=t)
# Example: sinusoidal disturbance and noise
d = 0.2*np.sin(2*np.pi*1.0*t) # disturbance input
n = 0.05*np.sin(2*np.pi*10.0*t) # measurement noise
_, yd = ct.forced_response(Gyd, T=t, U=d)
_, yn = ct.forced_response(Gyn, T=t, U=n)
y_total = y1 + yd + yn
# Plotting is optional; if you plot, remember to not hardcode colors in your own workflow.
# import matplotlib.pyplot as plt
# plt.figure()
# plt.plot(t, y_total)
# plt.grid(True)
# plt.title("Output y(t) with reference + disturbance + noise")
# plt.show()
# --- From-scratch Mason for a small SFG (symbolic, single loop case demonstration) ---
# We implement Mason for a graph with symbolic branch gains using sympy.
import sympy as sp
# Define symbolic transfer functions as sympy expressions in s
ss = sp.Symbol('s')
Cs, As, Gs, Hs = sp.symbols('C A G H')
# Nodes: R, E, U, V, Y, M
# Branch list: (from, to, gain)
branches = [
("R","E", 1),
("M","E", -1),
("E","U", Cs),
("U","V", As),
("D","V", 1),
("V","Y", Gs),
("Y","M", Hs),
("N","M", 1),
]
# For Y/R: forward path R->E->U->V->Y has gain Cs*As*Gs.
P1 = Cs*As*Gs
# One loop: E->U->V->Y->M->E gain = Cs*As*Gs*Hs*(-1) = -Cs*As*Gs*Hs
L1 = -Cs*As*Gs*Hs
Delta = 1 - L1 # Mason: Delta = 1 - sum(loop gains) + ...
Tyr = sp.simplify(P1 / Delta)
print("Mason Y/R =", Tyr) # returns Cs*As*Gs / (1 + Cs*As*Gs*Hs)
In practice, full Mason implementations must enumerate (i) all forward paths, (ii) all loops, and (iii) all sets of non-touching loops. For many engineering interconnections, block-diagram algebra is simpler; Mason is most valuable for complex multi-loop graphs where reduction is error-prone.
8.2 C++ (frequency-response evaluation with a TransferFunction class)
A concise practical approach in C++ is to evaluate transfer functions at \( s=j\omega \) and compute closed-loop relationships numerically. This avoids heavy symbolic algebra while still validating modeling and interconnection logic.
#include <iostream>
#include <vector>
#include <complex>
#include <cmath>
// Minimal TransferFunction: numerator/denominator polynomials in descending powers of s.
struct TransferFunction {
std::vector<double> num; // e.g., {1} for constant 1
std::vector<double> den; // e.g., {m, b, k} for m s^2 + b s + k
std::complex<double> eval(const std::complex<double>& s) const {
auto poly_eval = [&](const std::vector<double>& p) {
std::complex<double> acc = 0.0;
for (size_t i = 0; i < p.size(); ++i) {
acc = acc * s + p[i];
}
return acc;
};
return poly_eval(num) / poly_eval(den);
}
};
int main() {
// Example A: m=1, b=2, k=20; C=K=5; A=1; H=1
double m = 1.0, b = 2.0, k = 20.0;
double K = 5.0;
TransferFunction G{ {1.0}, {m, b, k} }; // 1/(m s^2 + b s + k)
// Frequency grid
for (double w : {0.5, 1.0, 2.0, 5.0, 10.0}) {
std::complex<double> s(0.0, w);
std::complex<double> Gs = G.eval(s);
std::complex<double> L = (K) * (1.0) * Gs * (1.0); // K*G
std::complex<double> S = 1.0 / (1.0 + L);
std::complex<double> Tyr = (K * Gs) * S; // Y/R
std::complex<double> Tyd = (Gs) * S; // Y/D
std::complex<double> Tyn = -(K * Gs) * S; // Y/N
std::cout << "w=" << w
<< " |Y/R|=" << std::abs(Tyr)
<< " |Y/D|=" << std::abs(Tyd)
<< " |Y/N|=" << std::abs(Tyn)
<< std::endl;
}
return 0;
}
This C++ workflow is appropriate when you want to validate closed-loop interconnections numerically (e.g., against lab data), without requiring symbolic manipulation of rational functions.
8.3 Java (Apache Commons Math Complex)
import org.apache.commons.math3.complex.Complex;
public class ClosedLoopExampleA {
static class TransferFunction {
// numerator/denominator in descending powers
double[] num;
double[] den;
TransferFunction(double[] num, double[] den) {
this.num = num;
this.den = den;
}
Complex eval(Complex s) {
Complex n = polyEval(num, s);
Complex d = polyEval(den, s);
return n.divide(d);
}
private Complex polyEval(double[] p, Complex s) {
Complex acc = Complex.ZERO;
for (int i = 0; i < p.length; i++) {
acc = acc.multiply(s).add(p[i]);
}
return acc;
}
}
public static void main(String[] args) {
double m = 1.0, b = 2.0, k = 20.0;
double K = 5.0;
TransferFunction G = new TransferFunction(new double[]{1.0}, new double[]{m, b, k});
double[] wGrid = new double[]{0.5, 1.0, 2.0, 5.0, 10.0};
for (double w : wGrid) {
Complex s = new Complex(0.0, w);
Complex Gs = G.eval(s);
Complex L = Gs.multiply(K); // K*G
Complex S = Complex.ONE.divide(Complex.ONE.add(L));
Complex Tyr = Gs.multiply(K).multiply(S); // Y/R
Complex Tyd = Gs.multiply(S); // Y/D
Complex Tyn = Gs.multiply(K).negate().multiply(S); // Y/N
System.out.println(
"w=" + w
+ " |Y/R|=" + Tyr.abs()
+ " |Y/D|=" + Tyd.abs()
+ " |Y/N|=" + Tyn.abs()
);
}
}
}
Java is especially convenient for building robust validation tooling (unit tests for interconnections, regression checks), while relying on frequency-response computations for dynamic blocks.
8.4 MATLAB and Simulink (scripted construction)
% Example A in MATLAB (Control System Toolbox)
m = 1; b = 2; k = 20;
K = 5;
s = tf('s');
G = 1/(m*s^2 + b*s + k);
A = 1;
H = 1;
C = K;
L = C*A*G*H;
S = 1/(1+L);
Gyr = (C*A*G)*S; % Y/R
Gyd = (G)*S; % Y/D
Gyn = -(C*A*G)*S; % Y/N
disp('Y/R ='); Gyr
disp('Y/D ='); Gyd
disp('Y/N ='); Gyn
% Step response from reference
figure; step(Gyr); grid on; title('Reference-to-output step response');
% --- Programmatic Simulink model build (no image needed) ---
% This script builds the block connections corresponding to Section 3.
model = 'ExampleA_BlockInterconnection';
new_system(model); open_system(model);
% Blocks
add_block('simulink/Sources/Step', [model '/R']);
add_block('simulink/Sources/Sine Wave', [model '/D']);
add_block('simulink/Sources/Sine Wave', [model '/N']);
add_block('simulink/Math Operations/Sum', [model '/SumE'], 'Inputs', '+-');
add_block('simulink/Math Operations/Sum', [model '/SumV'], 'Inputs', '++');
add_block('simulink/Math Operations/Sum', [model '/SumM'], 'Inputs', '++');
add_block('simulink/Continuous/Transfer Fcn', [model '/C']);
add_block('simulink/Continuous/Transfer Fcn', [model '/G']);
add_block('simulink/Continuous/Transfer Fcn', [model '/H']);
% Parameters: C(s)=K, so TF is K/1
set_param([model '/C'], 'Numerator', mat2str(K), 'Denominator', mat2str(1));
% G(s)=1/(m s^2 + b s + k)
set_param([model '/G'], 'Numerator', mat2str(1), 'Denominator', mat2str([m b k]));
% H(s)=1
set_param([model '/H'], 'Numerator', mat2str(1), 'Denominator', mat2str(1));
% Scope
add_block('simulink/Sinks/Scope', [model '/ScopeY']);
% Wiring: R -> SumE(+) ; M -> SumE(-)
add_line(model, 'R/1', 'SumE/1');
add_line(model, 'SumM/1', 'SumE/2');
% SumE -> C -> (actuator is unity, omitted) -> SumV
add_line(model, 'SumE/1', 'C/1');
add_line(model, 'C/1', 'SumV/1');
% D -> SumV
add_line(model, 'D/1', 'SumV/2');
% SumV -> G -> Y
add_line(model, 'SumV/1', 'G/1');
% Y -> Scope and Y -> H -> SumM
add_line(model, 'G/1', 'ScopeY/1');
add_line(model, 'G/1', 'H/1');
add_line(model, 'H/1', 'SumM/1');
% N -> SumM
add_line(model, 'N/1', 'SumM/2');
save_system(model);
The scripted Simulink build is valuable in coursework because it forces explicit definition of summing signs and injection points, reducing “diagram-only” ambiguity.
8.5 Wolfram Mathematica (TransferFunctionModel + matrix/cofactor form)
(* Example A in Mathematica *)
m = 1; b = 2; k = 20; K = 5;
s =.; (* s is the Laplace variable in TransferFunctionModel *)
G = TransferFunctionModel[1/(m s^2 + b s + k), s];
C = TransferFunctionModel[K, s];
A = TransferFunctionModel[1, s];
H = TransferFunctionModel[1, s];
L = SystemsModelSeriesConnect[C, A, G, H];
S = 1/(1 + L);
Gyr = SystemsModelSeriesConnect[C, A, G, S]; (* Y/R *)
Gyd = SystemsModelSeriesConnect[G, S]; (* Y/D *)
Gyn = -SystemsModelSeriesConnect[C, A, G, S]; (* Y/N *)
Gyr // Simplify
Gyd // Simplify
Gyn // Simplify
(* Linear-algebra / cofactor representation for a small SFG:
x = A x + b r, y = c^T x => y/r = c^T (I - A)^(-1) b.
*)
Agraph = { {0, 0, 0},
{K, 0, 0},
{0, 1/(m s^2 + b s + k), 0} }; (* illustrative; you would build this from your SFG *)
M = IdentityMatrix[Length[Agraph]] - Agraph;
bvec = {1, 0, 0};
cvec = {0, 0, 1};
T = Simplify[cvec . Inverse[M] . bvec]; (* y/r *)
Tcof = Simplify[Det[ReplacePart[M, {3, 1} -> 1]]/Det[M]]; (* one way to express cofactor-like ratios *)
T
Mathematica is particularly strong for symbolic simplification and for demonstrating the determinant/cofactor structure underlying SFG computations.
9. Problems and Solutions
Problem 1 (Three closed-loop transfer functions): For Example A, using the equations \( E=R-M \), \( U=CE \), \( V=AU+D \), \( Y=GV \), \( M=HY+N \), derive \( Y/R \), \( Y/D \), and \( Y/N \).
Solution: Substitute forward and eliminate internal signals:
\[ \begin{aligned} Y &= G(A C(R-HY-N)+D) \\ (1+CAGH)Y &= CAG\,R + G\,D - CAG\,N \\ \frac{Y}{R} &= \frac{CAG}{1+CAGH},\quad \frac{Y}{D} = \frac{G}{1+CAGH},\quad \frac{Y}{N} = -\frac{CAG}{1+CAGH}. \end{aligned} \]
Problem 2 (Nested loop denominator): An inner loop is formed by \( G(s) \) with feedback \( H_2(s) \), then the resulting block is placed in an outer loop with forward block \( C(s)A(s) \) and feedback \( H_1(s) \). Derive \( Y/R \).
Solution: Reduce inner loop then outer loop:
\[ G_{\text{inner}} = \frac{G}{1+GH_2}, \quad \frac{Y}{R} = \frac{CAG_{\text{inner}}}{1+CAG_{\text{inner}}H_1} = \frac{CAG}{1+GH_2+CAGH_1}. \]
Problem 3 (Mason determinant with a single loop): For the SFG in Section 4, compute Mason’s \( \Delta \) and use it to obtain \( Y/R \).
Solution: One forward path \( P_1=CAG \). One loop gain \( L_1=-CAGH \). Thus:
\[ \Delta = 1-\sum L_i = 1-(-CAGH)=1+CAGH, \quad \frac{Y}{R}=\frac{P_1}{\Delta}=\frac{CAG}{1+CAGH}. \]
Problem 4 (Cofactor transfer formula): Let an SFG be written as \( \mathbf{x}=\mathbf{A}\mathbf{x}+\mathbf{e}_k R \). Prove \( X_\ell/R = \operatorname{cof}(\mathbf{I}-\mathbf{A})_{k\ell}/\det(\mathbf{I}-\mathbf{A}) \), assuming invertibility.
Solution: Let \( \mathbf{M}=\mathbf{I}-\mathbf{A} \). Then \( \mathbf{M}\mathbf{x}=\mathbf{e}_k R \). Hence \( \mathbf{x}=\mathbf{M}^{-1}\mathbf{e}_k R \). The ratio \( X_\ell/R \) equals the \( (\ell,k) \) entry of \( \mathbf{M}^{-1} \). Using \( \mathbf{M}^{-1}=\operatorname{adj}(\mathbf{M})/\det(\mathbf{M}) \) and the identity \( \operatorname{adj}(\mathbf{M})_{\ell k}=\operatorname{cof}(\mathbf{M})_{k\ell} \) proves the claim.
Problem 5 (2×2 MIMO closed-loop): Given \( \mathbf{y}=\mathbf{G}\mathbf{u} \) and \( \mathbf{u}=\mathbf{r}-\mathbf{K}\mathbf{y} \), derive the closed-loop transfer matrix \( \mathbf{y}/\mathbf{r} \).
Solution:
\[ \mathbf{y}=\mathbf{G}(\mathbf{r}-\mathbf{K}\mathbf{y}) \Rightarrow (\mathbf{I}+\mathbf{G}\mathbf{K})\mathbf{y}=\mathbf{G}\mathbf{r} \Rightarrow \mathbf{y}=(\mathbf{I}+\mathbf{G}\mathbf{K})^{-1}\mathbf{G}\mathbf{r}, \]
provided \( \det(\mathbf{I}+\mathbf{G}\mathbf{K})\neq 0 \).
10. Summary
This lesson demonstrated a rigorous, repeatable workflow for practical modeling with block diagrams and signal flow graphs. Using a disturbance-and-noise feedback interconnection, we derived \( Y/R \), \( Y/D \), and \( Y/N \) by direct algebra and verified the result using Mason’s gain formula on the equivalent SFG. We then connected SFG computations to linear algebra via \( (\mathbf{I}-\mathbf{A})^{-1} \) and cofactors, and extended the interconnection logic to nested loops and 2×2 MIMO feedback. Finally, we provided concrete implementations in Python, C++, Java, MATLAB/Simulink, and Mathematica to support reproducible analysis.
11. References
- Mason, S.J. (1953). Feedback theory—Some properties of signal flow graphs. Proceedings of the IRE, 41(9), 1144–1156.
- Mason, S.J. (1956). Feedback theory—Further properties of signal flow graphs. Proceedings of the IRE, 44(7), 920–926.
- Coates, C.L. (1959). Flow-graph solutions of linear algebraic equations. IRE Transactions on Circuit Theory, 6(2), 170–187.
- Shannon, C.E. (1941). Mathematical theory of the differential analyzer. Journal of Mathematics and Physics, 20, 337–354.
- Rugh, W.J. (1981). Linear system theory: A state space approach (early theoretical treatments of interconnections). Various journal contributions on interconnection theory.
- Rosenbrock, H.H. (1970). State-space and multivariable theory (foundational linear-algebraic interconnection arguments). Proceedings / journal contributions on multivariable control theory.