Demo of the ident package

1 Installation

The software is hosted in GitHub. You can download it as a single zip file, or install it in a sub-directory \(\mathtt{slra}\) to your current directory by pasting the following commands into MATLAB:

%% Installation
unzip('https://github.com/slra/slra/zipball/master')
addpath(fullfile(cd, 'slra-slra-3e77deb'))

.

2 Usage

The package has two main functions:

[sys, info, wh] = ident(w, m, ell, opt); % identification 
[M, wh] = misfit(w, sys, opt);           % validation
  • data \(\mathtt{w}\) — set of time series \(\{\, w^1, \ldots, w^N \,\}\), \(w^k(t) \in \mathbb{R}^q\) specified by
    • \(T\times q\) matrix — \(q\)-variate time series with \(T\) samples
    • \(T\times q \times N\) array — \(N\), \(q\)-variate time series with \(T\) samples
    • cell array of \(T_k\times q\) matrices — vector time series with different number of samples
    • missing data — \(\mathtt{NaN}\) elements of \(\mathtt{w}\)
  • model \(\mathtt{sys}\) — LTI system in \(\mathtt{ss}\) object format
  • model class — \(\mathcal{L}_{m,\ell}\) is LTI systems with at most \(\mathtt{m}\) inputs and lag at most \(\mathtt{ell}\)
  • identification criterion — misfit \(\mathtt{M}\), defined as \begin{equation*} M(w,\mathcal{B}) := \min_{\hat w^1,\ldots,\hat w^N\in\mathcal{B}} \sqrt{\textstyle\sum_{k=1}^N \|w^k - \hat w^k\|^2_2 } \end{equation*}
  • identification problem, solved by \(\mathtt{ident}\) — \(\min_{\mathcal{B}\in\mathcal{L}_{m,\ell}} M(w,\mathcal{B})\)
  • extra options \(\mathtt{opt}\)
    • \(\mathtt{exct}\) — exact/fixed variables (e.g., output error setup)
    • \(\mathtt{wini}\) — fixed initial conditions (e.g., step response data)
    • \(\mathtt{sys0}\), \(\mathtt{maxiter}\) — initial model and maximum # of iterations for the optimization method
  • online help — \(\mathtt{help ident}\)

3 Equivalence with PEM in the OE case

%% simulation parameters
clear all, randn('seed', 0), rand('seed', 0), warning off
m = 1; p = 1; ell = 2; T = 300; s = 0.1;     
opt_oe.exct = 1:m; % fixed inputs = output error identification
opt_eiv.exct = []; % errors-in-variables setup 

%% generate data
n = ell * p; q = m + p; sys0 = drss(n, p, m); % random "true" system
u0 = rand(T, m); xini0 = rand(n, 1);          % random "true" trajectory
y0 = lsim(sys0, u0, [], xini0); u = u0;       
yt = randn(T, p); y = y0 + s * norm(y0) * yt / norm(yt); % output error
w0 = [u0 y0]; w = [u y];

%% compare ident and pem
tic, sysh_ident = ident(w, m, ell, opt_oe); t_ident = toc;
tic, sysh_pem = pem(iddata(y, u), n); t_pem = toc;
[Yh, M] = compare(iddata(y, u), idss(sysh_ident), sysh_pem); 
ans = [[mean(M{1}); mean(M{2})] [t_ident; t_pem]]
86.831 0.39396
86.806 6.2899

4 Permutation of variables

%% the model for [y u] is the inverse of the model for [u y]
sysh1 = ident(w, m, ell, opt_eiv);
sysh2 = ident(fliplr(w), m, ell, opt_eiv);
ans = [eig(sysh1) eig(inv(sysh2))]
0.01129 0.011284
0.69769 0.69767

5 Unstable system

  • noisy data
    %% the model for the reversed time data has reciprocal poles
    sysh3 = ident(flipud(w), m, ell, opt_eiv); 
    ans = [sort(1 ./ (eig(sysh1))) eig(sysh3)]
    
    1.433 1.433
    88.573 88.566
  • exact data
    %% pem fails to identify unstable model
    sysh_ident = ident(flipud(w0), m, ell, opt_oe); % note that now we use the true data w0
    opt_pem = ssestOptions; opt_pem.Advanced.StabilityThreshold.z = inf; % disable the stability constraint
    try 
      sysh_pem = pem(iddata(flipud(y0), flipud(u0)), n, opt_pem, 'dist', 'none');
    catch
      sysh_pem = zeros(n); % zero indicates failure 
    end
    ans = [sort(1 ./ eig(sys0)) eig(sysh_ident) sort(eig(sysh_pem))]
    
    1.510 1.510 0
    25.751 25.751 0

6 Trajectory of minimal length

%% pem needs more data to identify a model
Tmin = ell + q * (ell + 1) - 1; TT = (Tmin - 1):15; np = length(TT);
work_ident = zeros(1, np); correct_ident = zeros(1, np); 
work_pem   = zeros(1, np); correct_pem   = zeros(1, np);
for i = 1:np
  try 
    sysh_ident = ident(w0(1:TT(i), :), m, ell, opt_oe); work_ident(i) = 1; 
    correct_ident(i) = norm(sys0 - sysh_ident) < 1e-5; 
  end
  try 
    sysh_pem = pem(iddata(y0(1:TT(i), :), u0(1:TT(i), :)), n, 'dist', 'none'); work_pem(i) = 1; 
    correct_pem(i) = norm(sys0 - sysh_pem) < 1e-5; 
  end
end 
ans = [TT; work_ident; correct_ident; work_pem; correct_pem]
6 7 8 9 10 11 12 13 14 15
0 0 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 0 1 1 1

7 Multiple short trajectories

%% N short trajectories equivalent to one long trajectory (N * Tshort = T)
Tshort = 13; N = round(T / Tshort); 
u_mult = {}; y_mult = {}; w_mult = []; 
for k = 1:N,
  u0 = rand(Tshort, m); xini0 = rand(n, 1); 
  y0 = lsim(sys0, u0, [], xini0); 
  yt = randn(Tshort, p); y_mult{k} = y0 + s * norm(y0) * yt / norm(yt); 
  u_mult{k} = u0; w_mult(:, :, k) = [u0 y_mult{k}]; 
end
tic, sysh = ident(w_mult, m, ell, opt_oe); t_ident = toc;
tic, sysh_pem = pem(iddata(y_mult, u_mult), n, 'dist', 'none'); t_pem = toc;
[Yh, M] = compare(iddata(y_mult, u_mult), idss(sysh), sysh_pem); 
ans = [[mean(M{1}); mean(M{2})] [t_ident; t_pem]]
88.303 0.0083
88.462 1.1033

8 Missing data

%% randomly distributed missing data in time and variables
Tp = 100; Im = randperm(q * Tp); Tm = round(0.2 * q * Tp); 
wm = w(1:Tp, :); wm(Im(1:Tm)) = NaN; um = wm(:, 1:m); ym = wm(:, m + 1:end);

%% use misdata for the comparison
tic, sysh_n4sid = ss(n4sid(misdata(iddata(ym, um), 10), n, 'dist', 'none')); t_n4sid = toc;
tic, opt_oe.sys0 = sysh_n4sid; sysh_ident = ident(wm, m, ell, opt_oe); t_ident = toc; opt_oe.sys0 = []; 
tic, sysh_pem = pem(misdata(iddata(ym, um), 10), sysh_n4sid, 'dist', 'none'); t_pem = toc;
[Yh, M] = compare(iddata(y0, u0), sysh_n4sid, idss(sysh_ident), sysh_pem); 
ans = [[mean(M{1}); mean(M{2}); mean(M{3})] [t_n4sid; t_ident; t_pem]]
58.51 6.8132
83.93 0.0726
60.36 7.3597

9 Step response identification

%% simulate step response data
ys0 = step(sys0); Ts = length(ys0); us = ones(Ts, m);
yt = randn(Ts, p); ys = ys0 + s * norm(ys0) * yt / norm(yt); 
opt_oe.w0 = 0; opt_oe.sys0 = sys0; [sysh, info, wh] = ident([us ys], m, ell, opt_oe);
figure('visible', 'off');
plot(1:Ts, ys0, '-r', 1:Ts, ys, ':k', 1:Ts, wh(:, end), '--b')
legend('true', 'noisy', 'approx.   .')
plot2svg demo_f.svg, set(gca, 'fontsize', 25), print -dpdf demo_f.pdf;
 

10 References

  • I. Markovsky and K. Usevich. Software for weighted structured low-rank approximation. J. Comput. Appl. Math., 256:278-292, 2014. [ bib | DOI | pdf | .html | Abstract ]
  • I. Markovsky. A software package for system identification in the behavioral setting. Control Engineering Practice, 21:1422-1436, 2013. [ bib | DOI | pdf | .html | Abstract ]