MINREAL
Minimal realization removes redundant dynamics while preserving the input-output behavior of a linear system.
For transfer-function models, this operation cancels pole-zero pairs that are numerically close within a tolerance, yielding an equivalent lower-order representation. For state-space models, it removes uncontrollable and unobservable states.
In transfer-function form,
G(s) = \frac{N(s)}{D(s)}
common factors of N(s) and D(s) are canceled to obtain a simplified model with the same external response.
Excel Usage
=MINREAL(sysdata, tolerance)
sysdata(list[list], required): Numerator and denominator of the system to simplify.tolerance(float, optional, default: null): Tolerance for state elimination or pole-zero cancellation.
Returns (str): Stringified dictionary containing the numerator and denominator coefficients of the minimal transfer function.
Example 1: Pole-zero cancellation
Inputs:
| sysdata | tolerance | |
|---|---|---|
| 1 | 1 | |
| 1 | 2 |
Excel formula:
=MINREAL({1,1;1,2,1}, )
Expected output:
"{'num': [1.0], 'den': [1.0, 1.0]}"
Example 2: Exact cancellation to first-order model
Inputs:
| sysdata | tolerance | ||
|---|---|---|---|
| 1 | 3 | 2 | |
| 1 | 4 | 5 |
Excel formula:
=MINREAL({1,3,2;1,4,5,2}, )
Expected output:
"{'num': [1.0], 'den': [1.0, 0.9999999999999997]}"
Example 3: No cancellation keeps second-order dynamics
Inputs:
| sysdata | tolerance |
|---|---|
| 1 | |
| 1 |
Excel formula:
=MINREAL({1;1,2,2}, )
Expected output:
"{'num': [1.0], 'den': [1.0, 1.9999999999999996, 1.9999999999999991]}"
Example 4: Near cancellation with explicit tolerance
Inputs:
| sysdata | tolerance | ||
|---|---|---|---|
| 1 | 2.0001 | 1.0001 | 0.001 |
| 1 | 2 | 1 |
Excel formula:
=MINREAL({1,2.0001,1.0001;1,2,1}, 0.001)
Expected output:
"{'num': [1.0], 'den': [1.0]}"
Python Code
Show Code
import control as ct
import numpy as np
def minreal(sysdata, tolerance=None):
"""
Eliminate uncontrollable or unobservable states.
See: https://python-control.readthedocs.io/en/latest/generated/control.minreal.html
This example function is provided as-is without any representation of accuracy.
Args:
sysdata (list[list]): Numerator and denominator of the system to simplify.
tolerance (float, optional): Tolerance for state elimination or pole-zero cancellation. Default is None.
Returns:
str: Stringified dictionary containing the numerator and denominator coefficients of the minimal transfer function.
"""
try:
def clean_coefficients(values):
coefficients = np.atleast_1d(np.asarray(values, dtype=float)).flatten()
coefficients = np.real_if_close(coefficients, tol=1000)
coefficients = np.where(np.abs(coefficients) < 1e-12, 0.0, coefficients)
return np.asarray(coefficients, dtype=float).tolist()
def to_tf(data):
if not isinstance(data, list) or len(data) != 2:
return None
try:
num_row = data[0] if isinstance(data[0], list) else [data[0]]
den_row = data[1] if isinstance(data[1], list) else [data[1]]
num = [float(v) for v in num_row]
den = [float(v) for v in den_row]
except (TypeError, ValueError):
return None
if not num or not den:
return None
return ct.tf(num, den)
sys = to_tf(sysdata)
if sys is None:
return "Error: sysdata must contain numeric numerator and denominator rows"
tol = float(tolerance) if tolerance is not None else None
if tol is not None and tol < 0:
return "Error: tolerance must be non-negative"
res = ct.minreal(sys, tol=tol, verbose=False)
numerator = clean_coefficients(res.num[0][0])
denominator = clean_coefficients(res.den[0][0])
return str({"num": numerator, "den": denominator})
except Exception as e:
return f"Error: {str(e)}"