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)}"

Online Calculator

Numerator and denominator of the system to simplify.
Tolerance for state elimination or pole-zero cancellation.