@@ -642,10 +642,10 @@ using ChainRules
642642using ForwardDiffChainRules
643643@ForwardDiff_frule LinearAlgebra. exp! (x1:: AbstractMatrix{<:ForwardDiff.Dual} ) true
644644
645- function inner_constructor (p, constructor, Ts)
645+ function inner_constructor (p, constructor, Ts, method )
646646 sys = constructor (p)
647647 if iscontinuous (sys)
648- return c2d (sys, Ts, :zoh ), p. K, p. x0
648+ return c2d (sys, Ts, method ), p. K, p. x0
649649 end
650650 return sys, p. K, p. x0
651651end
@@ -710,6 +710,7 @@ function structured_pem(
710710 # alphaguess = LineSearches.InitialStatic(alpha = 0.95),
711711 linesearch = LineSearches. BackTracking (),
712712 ),
713+ method = :zoh ,
713714 store_trace = true ,
714715 show_trace = true ,
715716 show_every = 50 ,
@@ -742,22 +743,34 @@ function structured_pem(
742743 end
743744 p0ca = ComponentArray (p = p0, K = T .(K0), x0 = x0i)
744745 function predloss (p)
745- sysi, Ki, x0 = inner_constructor (p, constructor, d. Ts)
746+ sysi, Ki, x0 = inner_constructor (p, constructor, d. Ts, method )
746747 syso = PredictionStateSpace (sysi, Ki, 0 , 0 )
747748 Pyh = ControlSystemsBase. observer_predictor (syso; h)
748749 simres = lsim (Pyh, pd; x0= Vector (x0))
749- yh = simres. y
750+ yh = simres. y
750751 yh .= metric .(yh .- d. y)
751752 c1 = sum (yh)
752753 c1 + inner_regularizer (regularizer, p, syso, simres)
753754 end
754755 function simloss (p)
755- syssim, _, x0 = inner_constructor (p, constructor, d. Ts)
756+ syssim, _, x0 = inner_constructor (p, constructor, d. Ts, method )
756757 simres = lsim (syssim, d; x0)
757- y = simres. y
758+ y = simres. y
758759 y .= metric .(y .- d. y)
759760 sum (y) + inner_regularizer (regularizer, p, syssim, simres)
760761 end
762+ function simresiduals (p)
763+ syssim, _, x0 = inner_constructor (p, constructor, d. Ts, method)
764+ simres = lsim (syssim, d; x0)
765+ vec (simres. y .- d. y)
766+ end
767+ function predresiduals (p)
768+ sysi, Ki, x0 = inner_constructor (p, constructor, d. Ts, method)
769+ syso = PredictionStateSpace (sysi, Ki, 0 , 0 )
770+ Pyh = ControlSystemsBase. observer_predictor (syso; h)
771+ simres = lsim (Pyh, pd; x0= Vector (x0))
772+ vec (simres. y .- d. y[:, 1 : size (simres. y, 2 )])
773+ end
761774 res = Optim. optimize (
762775 pred ? predloss : simloss,
763776 p0ca,
@@ -767,7 +780,7 @@ function structured_pem(
767780 time_limit, x_abstol, f_abstol, g_tol, f_calls_limit, g_calls_limit);
768781 autodiff = AutoForwardDiff (),
769782 )
770- sys_opt, K_opt, x0_opt = inner_constructor (res. minimizer, constructor, d. Ts)
783+ sys_opt, K_opt, x0_opt = inner_constructor (res. minimizer, constructor, d. Ts, method )
771784 sysp_opt = PredictionStateSpace (
772785 sys_opt,
773786 pred ? K_opt : zeros (T, nx, ny),
@@ -776,5 +789,20 @@ function structured_pem(
776789 zeros (T, nx, ny),
777790 )
778791 pred && ! isstable (observer_predictor (sysp_opt)) && @warn (" Estimated predictor dynamics A-KC is unstable" )
779- (; sys= sysp_opt, x0= x0_opt, res)
792+ function Λ ()
793+ residuals = pred ? predresiduals : simresiduals
794+ resid = residuals (res. minimizer)
795+ J = ForwardDiff. jacobian (residuals, res. minimizer)
796+ Tn = length (resid) ÷ ny
797+ npar = length (res. minimizer)
798+ Σout = vec (sum (abs2, reshape (resid, ny, Tn), dims= 2 )) ./ (Tn - npar)
799+ inds = range (1 , step= ny, length= Tn)
800+ for i = 1 : ny
801+ @views J[inds, :] ./= sqrt (Σout[i])
802+ inds = inds .+ 1
803+ end
804+ Symmetric (J' * J)
805+ end
806+ ax = ComponentArrays. getaxes (res. minimizer)
807+ (; sys= sysp_opt, x0= x0_opt, res, Λ, constructor= p-> inner_constructor (ComponentArray (p, ax), constructor, d. Ts, method))
780808end
0 commit comments