Skip to content

lti_freq_io

MATLAB equivalent: sidLTIfreqIO

lti_freq_io

LTI state-space realization from input-output data via Ho-Kalman.

lti_freq_io

lti_freq_io(Y: ndarray | list, U: ndarray | list, H: ndarray, *, horizon: int | None = None, max_stabilize: float = 0.999) -> tuple[ndarray, ndarray]

Identify an LTI state-space model from input-output data.

Estimates a constant (LTI) state-space realization from input-output data, given a known observation matrix H:

.. math::

x(k+1) = A_0\,x(k) + B_0\,u(k)

y(k)   = H\,x(k)

Uses the Ho-Kalman realization algorithm applied to the frequency response estimated via :func:sid.freq_bt. The realization is transformed to the H-basis so that the observation equation y = H x holds exactly with the returned (A0, B0).

This is the Python port of sidLTIfreqIO.m.

Parameters:

Name Type Description Default
Y ndarray or list of ndarray

Output data. Accepted formats:

  • (N+1, py) -- single trajectory
  • (N+1, py, L) -- L trajectories, same horizon N
  • [Y_1, Y_2, ...] -- list of arrays (N_l+1, py). Trajectories shorter than ceil(2/3 * max_horizon) are discarded; the rest are trimmed to a common length.
required
U ndarray or list of ndarray

Input data, matching format of Y:

  • (N, q) -- single trajectory
  • (N, q, L) -- L trajectories
  • [U_1, U_2, ...] -- list of arrays (N_l, q)
required
H ndarray, shape ``(py, n)``

Observation matrix.

required
horizon int or None

Hankel matrix depth r. Default is min(N_imp // 3, 50) where N_imp is the number of impulse response coefficients.

None
max_stabilize float

Maximum eigenvalue magnitude after stabilization. Unstable eigenvalues are reflected inside the unit circle, then clamped to this radius. Default is 0.999.

0.999

Returns:

Name Type Description
A0 ndarray, shape ``(n, n)``

Estimated LTI dynamics matrix.

B0 ndarray, shape ``(n, q)``

Estimated LTI input matrix.

Raises:

Type Description
SidError

If data is too short for Hankel construction (code: 'too_short').

SidError

If data dimensions are inconsistent (code: 'dim_mismatch').

Examples:

>>> import numpy as np
>>> import sid
>>> H = np.array([[1, 0]])
>>> A0, B0 = sid.lti_freq_io(Y, U, H)
Notes

Algorithm:

  1. Estimate transfer function G(e^{jw}) via :func:sid.freq_bt.
  2. Compute Markov parameters g(k) = H A^{k-1} B via IFFT.
  3. Build block Hankel matrices H_0 and H_1 (shifted).
  4. SVD of H_0, truncate to order n (Ho-Kalman realization).
  5. Transform realization to H-basis: find T s.t. C_r T^{-1} = H.
  6. Stabilize eigenvalues if needed.

Specification: SPEC.md section 8.12 -- Output-COSMIC (LTI initialization)

References

.. [1] Ho, B.L. and Kalman, R.E. "Effective construction of linear state-variable models from input/output functions." Regelungstechnik, 14(12):545-548, 1966.

See Also

sid.freq_bt : Frequency response estimation used in step 1. sid.ltv_disc_io : Output-COSMIC identification that uses this as initializer.

Changelog

2026-04-09 : First version (Python port) by Pedro Lourenco.