Skip to content

ltv_disc_io

MATLAB equivalent: sidLTVdiscIO

ltv_disc_io

Discrete-time LTV state-space identification from partial observations.

ltv_disc_io

ltv_disc_io(Y: ndarray | list, U: ndarray | list, H: ndarray, *, lambda_: float | ndarray, R: ndarray | None = None, max_iter: int = 50, tolerance: float = 1e-06, covariance_mode: str = 'diagonal', trust_region: float | str = 'off', trust_region_tol: float = 1e-06, uncertainty: bool = True) -> LTVIOResult

Identify a discrete-time LTV system from partial observations.

Identifies time-varying system matrices A(k), B(k) and estimates state trajectories from input-output data when only partial state observations are available:

.. math::

x(k+1) = A(k)\,x(k) + B(k)\,u(k), \quad k = 0, \ldots, N-1

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

Uses the Output-COSMIC algorithm: alternating minimisation between a COSMIC step (dynamics estimation) and an RTS smoother (state estimation), initialised via LTI realization from the I/O transfer function (:func:sid.lti_freq_io).

When rank(H) == n (full state observation), this reduces to the standard COSMIC algorithm with no EM iterations.

This is the Python port of sidLTVdiscIO.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
  • [Y_1, Y_2, ...] -- list of arrays (N_l+1, py)
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
lambda_ float or ndarray, shape ``(N-1,)``

Regularization strength. Scalar (uniform) or per-step vector. Must be positive.

required
R ndarray, shape ``(py, py)`` or None

Measurement noise covariance (SPD). Default: eye(py).

None
max_iter int

Maximum alternating iterations. Default: 50.

50
tolerance float

Convergence tolerance on relative cost change. Default: 1e-6.

1e-06
covariance_mode str

Noise covariance estimation mode: 'diagonal', 'full', or 'isotropic'. Default: 'diagonal'.

'diagonal'
trust_region float or ``'off'``

Trust-region parameter mu_0 in [0, 1], or 'off'. Default: 'off'.

'off'
trust_region_tol float

Minimum mu before final pass. Default: 1e-6.

1e-06
uncertainty bool

Compute Bayesian posterior uncertainty for A(k), B(k). Default: True. Uncertainty is always computed in Output-COSMIC; this parameter is accepted for API consistency.

True

Returns:

Type Description
LTVIOResult

Frozen dataclass with fields:

  • a (ndarray, shape (n, n, N)) -- Time-varying dynamics.
  • b (ndarray, shape (n, q, N)) -- Time-varying input.
  • x (ndarray or list) -- Estimated state trajectories.
  • h (ndarray, shape (py, n)) -- Observation matrix (copy).
  • r (ndarray, shape (py, py)) -- Noise covariance used.
  • cost (ndarray, shape (n_iter,)) -- Cost at each iteration.
  • iterations (int) -- Number of alternating iterations.
  • lambda_ (ndarray, shape (N-1,)) -- Lambda vector used.
  • data_length (int) -- N.
  • state_dim (int) -- n.
  • output_dim (int) -- py.
  • input_dim (int) -- q.
  • num_trajectories (int) -- L.
  • a_std (ndarray or None) -- Std dev of a.
  • b_std (ndarray or None) -- Std dev of b.
  • p_cov (ndarray or None) -- Row covariance blocks.
  • noise_cov (ndarray or None) -- Noise covariance.
  • noise_cov_estimated (bool or None) -- Whether estimated.
  • noise_variance (float or None) -- trace(Sigma)/n.
  • degrees_of_freedom (float or None) -- Effective DOF.
  • algorithm (str) -- 'cosmic'.
  • method (str) -- 'ltv_disc_io'.

Raises:

Type Description
SidError

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

SidError

If lambda is invalid (code: 'bad_lambda').

SidError

If covariance_mode is invalid (code: 'bad_cov_mode').

Examples:

Basic usage:

>>> import numpy as np
>>> import sid
>>> H = np.array([[1, 0]])
>>> result = sid.ltv_disc_io(Y, U, H, lambda_=1e5)

With known measurement noise:

>>> result = sid.ltv_disc_io(
...     Y, U, H, lambda_=1e5, R=R_meas
... )

With trust-region for difficult convergence:

>>> result = sid.ltv_disc_io(
...     Y, U, H, lambda_=1e5, trust_region=1.0
... )
Notes

Algorithm (Output-COSMIC):

  1. LTI initialisation: estimate A0, B0 via Ho-Kalman realization of the I/O transfer function (:func:sid.lti_freq_io).
  2. State step: fix dynamics, RTS smoother for states.
  3. COSMIC step: fix states, solve for A(k), B(k).
  4. Repeat steps 2-3 until convergence.

Complexity: O(T * (LNn^3 + N*(n+q)^3)) where T is iterations.

Specification: SPEC.md section 8.12 -- Output-COSMIC

References

.. [1] Carvalho, Soares, Lourenco, Ventura. "COSMIC: fast closed-form identification from large-scale data for LTV systems." arXiv:2112.04355, 2022.

See Also

sid.lti_freq_io : LTI initializer used internally. sid.ltv_disc : LTV identification with full state observation. sid.ltv_state_est : State estimation via RTS smoother.

Changelog

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