/* nag_opt_estimate_deriv (e04xac) Example Program.
*
* Copyright 2024 Numerical Algorithms Group.
*
* Mark 30.0, 2024.
*
*/
#include <nag.h>
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
static void NAG_CALL objfun(Integer n, const double x[], double *objf,
double g[], Nag_Comm *comm);
#ifdef __cplusplus
}
#endif
#define H(I, J) h[(I)*tdh + J]
int main(void) {
Integer exit_status = 0, i, j, n, tdh;
double *g = 0, *h = 0, *h_central = 0, *h_forward = 0, *hess_diag = 0, objf,
*x = 0;
Nag_Comm comm;
Nag_DerivInfo *deriv_info = 0;
Nag_E04_Opt options;
NagError fail;
INIT_FAIL(fail);
printf("nag_opt_estimate_deriv (e04xac) Example Program Results\n");
n = 4;
if (!(x = NAG_ALLOC(n, double)) || !(h_central = NAG_ALLOC(n, double)) ||
!(h_forward = NAG_ALLOC(n, double)) || !(g = NAG_ALLOC(n, double)) ||
!(h = NAG_ALLOC(n * n, double)) || !(hess_diag = NAG_ALLOC(n, double)) ||
!(deriv_info = NAG_ALLOC(n, Nag_DerivInfo))) {
printf("Allocation failure\n");
exit_status = -1;
goto END;
}
tdh = n;
x[0] = 3.0;
x[1] = -1.0;
x[2] = 0.0;
x[3] = 1.0;
/* nag_opt_init (e04xxc).
* Initialization function for option setting
*/
nag_opt_init(&options);
options.list = Nag_FALSE;
options.print_deriv = Nag_D_NoPrint;
options.deriv_want = Nag_Grad_HessDiag;
printf("\nEstimate gradient and Hessian diagonals given function only\n");
/* Note: it is acceptable to pass an array of length n (hess_diag)
* as the Hessian parameter in this case.
*/
/* nag_opt_estimate_deriv (e04xac), see above. */
nag_opt_estimate_deriv(n, x, objfun, &objf, g, h_forward, h_central,
hess_diag, tdh, deriv_info, &options, &comm, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_estimate_deriv (e04xac).\n%s\n", fail.message);
exit_status = 1;
goto END;
}
printf("\nFunction value: %13.4e\n", objf);
printf("Estimated gradient vector\n");
for (i = 0; i < n; ++i)
printf("%13.4e ", g[i]);
printf("\nEstimated Hessian matrix diagonal\n");
for (i = 0; i < n; ++i)
printf("%13.4e ", hess_diag[i]);
printf("\n");
options.deriv_want = Nag_HessFull;
printf("\nEstimate full Hessian given function and gradients\n");
/* nag_opt_estimate_deriv (e04xac), see above. */
nag_opt_estimate_deriv(n, x, objfun, &objf, g, h_forward, h_central, h, tdh,
deriv_info, &options, &comm, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_estimate_deriv (e04xac).\n%s\n", fail.message);
exit_status = 1;
goto END;
}
printf("\nFunction value: %13.4e\n", objf);
printf("Computed gradient vector\n");
for (i = 0; i < n; ++i)
printf("%13.4e ", g[i]);
printf("\nEstimated Hessian matrix\n");
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j)
printf("%13.4e ", H(i, j));
printf("\n");
}
END:
NAG_FREE(x);
NAG_FREE(h_central);
NAG_FREE(h_forward);
NAG_FREE(g);
NAG_FREE(h);
NAG_FREE(hess_diag);
NAG_FREE(deriv_info);
return exit_status;
}
static void NAG_CALL objfun(Integer n, const double x[], double *objf,
double g[], Nag_Comm *comm) {
double a, asq, b, bsq, c, csq, d, dsq;
a = x[0] + 10.0 * x[1];
b = x[2] - x[3];
c = x[1] - 2.0 * x[2];
d = x[0] - x[3];
asq = a * a;
bsq = b * b;
csq = c * c;
dsq = d * d;
*objf = asq + 5.0 * bsq + csq * csq + 10.0 * dsq * dsq;
if (comm->flag == 2) {
g[0] = 2.0 * a + 40.0 * d * dsq;
g[1] = 20.0 * a + 4.0 * c * csq;
g[2] = 10.0 * b - 8.0 * c * csq;
g[3] = -10.0 * b - 40.0 * d * dsq;
}
}
/* objfun */