dynare/tests/riccatiupdate.m

141 lines
3.5 KiB
Matlab

debug = true;
if debug
[top_test_dir, ~, ~] = fileparts(mfilename('fullpath'));
else
top_test_dir = getenv('TOP_TEST_DIR');
end
addpath([top_test_dir filesep '..' filesep 'matlab']);
if ~debug
% Test Dynare Version
if ~strcmp(dynare_version(), getenv('DYNARE_VERSION'))
error('Incorrect version of Dynare is being tested')
end
end
dynare_config;
NumberOfTests = 0;
testFailed = 0;
if ~debug
skipline()
disp('*** TESTING: riccatiupdate.m ***');
end
if isoctave
addpath([top_test_dir filesep '..' filesep 'mex' filesep 'octave']);
else
addpath([top_test_dir filesep '..' filesep 'mex' filesep 'matlab']);
end
t0 = clock;
% Set the number of experiments for time measurement
N = 5000;
% Set the dimension of the problem to be solved.
r = 50;
n = 100;
tol = 1e-15;
% Set the input arguments
% P, Q: use the fact that for any real matrix A, A'*A is positive semidefinite
P = rand(n,r);
P = P'*P;
Q = rand(n,r);
Q = Q'*Q;
K = rand(r,n);
Z = rand(n,r);
T = rand(r,r);
% Computing an upperbound for the norm the updated variance-covariance matrix
ub = norm(T,1)^2*norm(P,1)*(1+norm(K*Z,1))+norm(Q,1);
% Weighting the P and Q matrices to keep the norm of the variance-covariance matrix below 1
P = 0.5*P/ub;
Q = 0.5*Q/ub;
% 1. Update the state vairance-covariance matrix with Matlab
tElapsed1 = 0.;
tic;
for i=1:N
Ptmp_matlab = T*(P-K*Z*P)*transpose(T)+Q;
end
tElapsed1 = toc;
disp(['Elapsed time for the Matlab Riccati update is: ' num2str(tElapsed1) ' (N=' int2str(N) ').'])
% 2. Update the state varance-covariance matrix with the mex routine
NumberOfTests = NumberOfTests+1;
tElapsed2 = 0.;
Ptmp_fortran = P;
try
tic;
for i=1:N
Ptmp_fortran = riccati_update(P, T, K, Z, Q);
end
tElapsed2 = toc;
disp(['Elapsed time for the Fortran Riccati update is: ' num2str(tElapsed2) ' (N=' int2str(N) ').'])
R = norm(Ptmp_fortran-Ptmp_matlab,1);
if (R > tol)
testFailed = testFailed+1;
if debug
dprintf('The Fortran Riccati update is wrong')
end
end
catch
testFailed = testFailed+1;
if debug
dprintf('Fortran Riccati update failed')
end
end
% Compare the Fortran and Matlab execution time
if debug
if tElapsed1<tElapsed2
skipline()
dprintf('Matlab Riccati update is %5.2f times faster than its Fortran counterpart.', tElapsed2/tElapsed1)
skipline()
else
skipline()
dprintf('Fortran Riccati update is %5.2f times faster than its Matlab counterpart.', tElapsed1/tElapsed2)
skipline()
end
end
% Compare results after multiple calls
N = 50;
disp(['After 1 update using the Riccati formula, the norm-1 discrepancy is ' num2str(norm(Ptmp_fortran-Ptmp_matlab,1)) '.']);
for i=2:N
Ptmp_matlab = T*(Ptmp_matlab-K*Z*Ptmp_matlab)*transpose(T)+Q;
Ptmp_fortran = riccati_update(Ptmp_fortran, T, K, Z, Q);
disp(['After ' int2str(i) ' updates using the Riccati formula, the norm-1 discrepancy is ' num2str(norm(Ptmp_fortran-Ptmp_matlab,1)) '.'])
end
t1 = clock;
if ~debug
cd(getenv('TOP_TEST_DIR'));
else
dprintf('FAILED tests: %i', testFailed)
end
if isoctave
fid = fopen('riccatiupdate.o.trs', 'w+');
else
fid = fopen('riccatiupdate.m.trs', 'w+');
end
if testFailed
fprintf(fid,':test-result: FAIL\n');
fprintf(fid,':list-of-failed-tests: riccatiupdate.m\n');
else
fprintf(fid,':test-result: PASS\n');
end
fprintf(fid,':number-tests: %i\n', NumberOfTests);
fprintf(fid,':number-failed-tests: %i\n', testFailed);
fprintf(fid,':elapsed-time: %f\n', etime(t1, t0));
fclose(fid);
if ~debug
exit;
end