LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
infer_lqn_ekf.m
1function [ahat, info] = infer_lqn_ekf(hfun, a0, P0, Z, Q, R, options)
2% INFER_LQN_EKF Extended Kalman Filter for LQN parameter identification.
3%
4% [AHAT, INFO] = INFER_LQN_EKF(HFUN, A0, P0, Z, Q, R, OPTIONS) tracks a
5% hidden parameter vector across the measurement sequence Z using an Extended
6% Kalman Filter, following Zheng, Yang, Woodside, Litoiu, Iszlai, "Tracking
7% Time-Varying Parameters in Software Systems with Extended Kalman Filters",
8% CASCON 2005 (equations 1-9). The parameter is modelled as a zero-mean
9% random walk a_k = a_{k-1} + w and the measurement as z_k = h(a_k) + v,
10% where h is the (nonlinear) LQN performance model supplied as HFUN.
11%
12% Inputs:
13% HFUN : handle mapping a parameter vector to a predicted observation
14% vector z = h(a) (evaluates the LQN model).
15% A0 : (np x 1) initial parameter estimate.
16% P0 : (np x np) initial estimation-error covariance.
17% Z : (no x nsteps) measurement matrix, one column per step.
18% Q : (np x np) parameter-drift (process-noise) covariance.
19% R : (no x no) measurement-error covariance.
20% OPTIONS : struct with optional fields:
21% fdStep (1e-3), fdFloor (1e-6) - finite-difference steps
22% clampPositive (true) - clamp estimates to > fdFloor
23% aTrue ([]) - ground truth for Ea metric
24% verbose (false)
25%
26% Outputs:
27% AHAT : (np x nsteps) parameter estimate trajectory.
28% INFO : struct with fields P (final covariance), Phist (per-step
29% covariances), e (no x nsteps prediction errors), zpred (predicted
30% measurements), Er (prediction RMS), Ea (parameter tracking RMS vs
31% aTrue when supplied, else []).
32%
33% Copyright (c) 2012-2026, Imperial College London
34% All rights reserved.
35
36if nargin < 7, options = struct(); end
37fdStep = infer_lqn_optget(options, 'fdStep', 1e-3);
38fdFloor = infer_lqn_optget(options, 'fdFloor', 1e-6);
39clampPositive = infer_lqn_optget(options, 'clampPositive', true);
40aTrue = infer_lqn_optget(options, 'aTrue', []);
41verbose = infer_lqn_optget(options, 'verbose', false);
42
43a0 = a0(:);
44np = numel(a0);
45no = size(Z, 1);
46nsteps = size(Z, 2);
47
48ahat = zeros(np, nsteps);
49info.e = zeros(no, nsteps);
50info.zpred = zeros(no, nsteps);
51info.Phist = cell(1, nsteps);
52
53a = a0;
54P = P0;
55I_np = eye(np);
56for k = 1:nsteps
57 % (1) predict: zero-mean drift keeps a_pred = a; project covariance (eq 5)
58 aPred = a;
59 Ppred = P + Q;
60
61 % (2,4) predicted measurement and sensitivity matrix H = dh/da at a_pred
62 [H, zpred] = infer_lqn_jacobian(hfun, aPred, fdStep, fdFloor);
63
64 % (3) prediction error
65 zk = Z(:, k);
66 e = zk - zpred;
67
68 % (6) Kalman gain (suboptimal because h is nonlinear)
69 S = H * Ppred * H' + R;
70 K = (Ppred * H') / S;
71
72 % (4-update) improved parameter estimate
73 a = aPred + K * e;
74 if clampPositive
75 a = max(a, fdFloor);
76 end
77
78 % (7) covariance update; symmetrize for numerical stability
79 P = (I_np - K * H) * Ppred;
80 P = 0.5 * (P + P');
81
82 ahat(:, k) = a;
83 info.e(:, k) = e;
84 info.zpred(:, k) = zpred;
85 info.Phist{k} = P;
86
87 if verbose
88 line_printf('[infer_lqn_ekf] step %d/%d ||e||=%.4g\n', k, nsteps, norm(e));
89 end
90end
91info.P = P;
92
93% RMS tracking (Ea) and prediction (Er) errors (paper Section 4)
94info.Er = sqrt(mean(info.e(:).^2));
95if ~isempty(aTrue)
96 aTrue = aTrue(:);
97 D = ahat - repmat(aTrue, 1, nsteps);
98 info.Ea = sqrt(mean(D(:).^2));
99else
100 info.Ea = [];
101end
102end
Definition Station.m:245