derivtst.gms : How to test derivatives of functions

Description

This model demonstrates how to tests the first and second order derivatives
of a given function by comparing the (exact/analytical) derivatives with
derivatives calculated by finite differences.

GAMS provides through the function suffix .grad/.hess the (exact) derivatives
and the finite difference derivatives through function suffix gradn/.hessn.
These facilities work for intrinisc and extrinsic functions.

Keywords: GAMS language features, accuracy test, analytical derivatives,
          finite difference


Small Model of Type : GAMS


Category : GAMS Model library


Main file : derivtst.gms

$title How to test Derivatives of Functions (DERIVTST,SEQ=406)

$onText
This model demonstrates how to tests the first and second order derivatives
of a given function by comparing the (exact/analytical) derivatives with
derivatives calculated by finite differences.

GAMS provides through the function suffix .grad/.hess the (exact) derivatives
and the finite difference derivatives through function suffix gradn/.hessn.
These facilities work for intrinisc and extrinsic functions.

Keywords: GAMS language features, accuracy test, analytical derivatives,
          finite difference
$offText

$if not set sampleSize $set sampleSize 100
$if not set tol        $set tol        1e-6
$if not set func       $set func       power

Set
   s  'sample'        / s1*s%sampleSize%  /
   ai 'argument info' / lo, up, int, endo /;

* Function data
$ifThenI %func%==pdfnormal
$  funcLibIn mylib stodclib
   function %func% / mylib.%func% /;
$  set args sp(s,'a1'),sp(s,'a2'),sp(s,'a3')
   Set a 'function arguments' / a1*a3 /;

   Table fi(a,ai) 'function argument information'
            lo  up  int  endo
      a1   -10  10          1
      a2    -5   5
      a3   0.5   1;
$elseIfI %func%==power
$  set args sp(s,'a1'),sp(s,'a2')
   Set a 'function arguments' / a1*a2 /;

   Table fi(a,ai) 'function argument information'
            lo   up  int  endo
      a1  -100  100          1
      a2    -5    5    1;
$else
$  abort 'no function data for %func%
$endIf

Parameter
   sp(s,a)      'sample points for argument'
   grad(s,a)    'exact gradient'
   gradn(s,a)   'numerical gradient'
   hess(s,a,a)  'exact gradient'
   hessn(s,a,a) 'numerical gradient';

Set
   ae(a)    'endogenos arguments'
   badsp(s) 'sample points that trigger an execerror';

Alias (ae,aep);

ae(a)   = fi(a,'endo');
sp(s,a) = uniformInt(fi(a,'lo'),fi(a,'up'))$(fi(a,'int'))
        + uniform(fi(a,'lo'),fi(a,'up'))$(not fi(a,'int'));

loop(s,
   grad (s,ae)     = %func%.grad (ae.pos:%args%);
   gradn(s,ae)     = %func%.gradn(ae.pos:%args%);
   hess (s,ae,aep) = %func%.hess (ae.pos:aep.pos:%args%);
   hessn(s,ae,aep) = %func%.hessn(ae.pos:aep.pos:%args%);
   if(execError,
      badsp(s)  = yes;
      execError = 0;
   );
);

* Compare gradient and hessian
Set csp(s) 'sample points to compare';

Parameter
   badargs(s,a)     'sample points that triggered an execution error'
   gradError(s,a)   'error in gradient calculation'
   HessError(s,a,a) 'error in hessian  calculation';

csp(s) = not badsp(s);
badargs(badsp,a) = sp(badsp,a);
$macro Error(a,b) abs(a-b)/abs(a+1)
gradError(csp,ae)     = Error(grad(csp,ae),gradn(csp,ae));
hessError(csp,ae,aep) = Error(hess(csp,ae,aep),hessn(csp,ae,aep));
gradError(csp,ae    )$(gradError(csp,ae)     < %tol%) = 0;
hessError(csp,ae,aep)$(hessError(csp,ae,aep) < %tol%) = 0;

abort$(card(badsp) + card(gradError) + card(hessError)) badargs, gradError, hessError;