File: gradcd.m

package info (click to toggle)
dynare 4.5.7-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 49,408 kB
  • sloc: cpp: 84,998; ansic: 29,058; pascal: 13,843; sh: 4,833; objc: 4,236; yacc: 3,622; makefile: 2,278; lex: 1,541; python: 236; lisp: 69; xml: 8
file content (83 lines) | stat: -rw-r--r-- 2,631 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
function grdd = gradcd(fcn,x0,grdh,P1,P2,P3,P4,P5,P6,P7,P8,P9,...
                   P10,P11,P12,P13,P14,P15,P16,P17,P18,P19,P20)
%function grdd = gradcd(fcn,x0,grdh,P1,P2,P3,P4,P5,P6,P7,P8,P9,...
%             P10,P11,P12,P13,P14,P15,P16,P17,P18,P19,P20)
% computes numerical gradient of a single-valued function or Jacobian
%   matrix of a vector-valued function using a central difference with
%                    function grdd = gradcd(fcn,x0,grdh)
%
%   fcn: a string naming a vector-valued function (f:n*1 -> k*1).
%   x0: a column vector n*1, at which point the hessian is evaluated.
%   grdh: step size, n*1. Set as follows
%              step = eps^(1/3);
%              %step = 1e-04;
%              grdh = step * (max([abs(x) ones(length(x),1)]'))' .* (abs(x) ./ x);
%   grdd: Jacobian matrix, k*n.
%
% Copyright (C) 1997-2012 Tao Zha
%
% This free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% It is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% If you did not received a copy of the GNU General Public License
% with this software, see <http://www.gnu.org/licenses/>.
%


stps = eps^(1/3);
% eps: floating point relative accuracy or machine precision: 2.22e-16
% stps: step size recommended by Dennis and Schnabel: 6.006e-6

x0 = x0(:);
tailstr = ')';
for i=nargin-3:-1:1
   tailstr=[ ',P' num2str(i)  tailstr];
end
f0 = eval([fcn '(x0' tailstr]);

% ** initializations
n = length(x0);
k = length(f0);   % dimension of "fcn"

% ** Computation of stepsize (dh)
if all(grdh)
    dh = grdh;
else
    ax0 = abs(x0);
    if all(x0)
        dax0 = x0 ./ ax0;
    else
        dax0 = 1;
    end
    dh = stps * (max([ax0 ones(n,1)]'))' .* dax0;
end

xdh = x0 + dh;
dh = xdh - x0;    % This increases precision slightly
%
argplus = x0(:,ones(n,1));
argminus = argplus;
dnum = 1:n+1:n^2;    % positions of diagonals in vec(argplus).
argplus(dnum) = xdh;     % replace the diagonals of "argplus" by "xdh".
argminus(dnum) = x0-dh;    % replace the diagonals of "argplus" by "xdh".

grdd = zeros(k,n);   % preallocate to speed the loop.
i = 0;
while i ~= n
    i = i+1;
    fp = eval([fcn '(argplus(:,i)' tailstr]);
    fm = eval([fcn '(argminus(:,i)' tailstr]);
    grdd(:,i) = fp - fm;
end
dhm = dh(:,ones(k,1));
dhm = dhm';      % k*n
grdd = grdd ./ (2*dhm);