/* nag_opt_lsq_no_deriv(e04fcc) Example Program * * Copyright 1991 Numerical Algorithms Group. * * Mark 2, 1991. * Mark 7 revised, 2001. * */ #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif static void lsqfun1(Integer m, Integer n, double x[], double fvec[], Nag_Comm *comm); static void lsqfun2(Integer m, Integer n, double x[], double fvec[], Nag_Comm *comm); #ifdef __cplusplus } #endif static void ex1(void); static void ex2(void); #define MMAX 15 #define NMAX 3 #define TMAX 3 /* Define a user structure template to store data in lsqfun. */ struct user { double y[MMAX]; double t[MMAX][TMAX]; }; int main(void) { /* Two examples are called, ex1() which uses the * default settings to solve the problem and * ex2() which solves the same problem with * some optional parameters set by the user. */ Vprintf("e04fcc Example Program Results.\n"); Vscanf(" %*[^\n]"); /* Skip heading in data file */ ex1(); ex2(); return EXIT_SUCCESS; } static void ex1(void) { double fjac[MMAX][NMAX], fvec[MMAX], x[NMAX]; Integer m, n, tdj; double fsumsq; static NagError fail; Vprintf("\ne04fcc example 1: no option setting.\n"); Vscanf(" %*[^\n]"); /* Skip heading in data file */ n = 3; m = 15; tdj = NMAX; /* Set up the starting point */ x[0] = 0.5; x[1] = 1.0; x[2] = 1.5; /* Call the optimization routine */ fail.print = TRUE; e04fcc(m, n, lsqfun1, x, &fsumsq, fvec, &fjac[0][0], tdj, E04_DEFAULT, NAGCOMM_NULL, &fail); if (fail.code != NE_NOERROR && fail.code != NW_COND_MIN) exit(EXIT_FAILURE); } /* ex1 */ static void lsqfun1(Integer m, Integer n, double x[], double fvec[], Nag_Comm *comm) { /* Function to evaluate the residuals for example 1. * * In this example a static variable is used to hold the * initial observations. The data is read into the structure * gs on the first call to lsqfun1(), it could alternatively * be read in from within int main(void). */ static struct user gs; Integer i, j, nt; if (comm->first) { /* First call to lsfun1(), read data into structure. * Observations t (j = 0, 1, 2) are held in gs.t[i][j] * (i = 0, 1, 2, . . . , 14) */ nt = 3; for (i = 0; i < m; ++i) { Vscanf("%lf", &gs.y[i]); for (j = 0; j < nt; ++j) Vscanf("%lf", &gs.t[i][j]); } } for (i = 0; i < m; ++i) fvec[i] = x[0] + gs.t[i][0] / (x[1]*gs.t[i][1] + x[2]*gs.t[i][2]) - gs.y[i]; } /* lsqfun1 */ static void ex2(void) { double fjac[MMAX][NMAX], fvec[MMAX], x[NMAX]; Integer i, j, m, n, nt, tdj; double fsumsq; Boolean print; Nag_E04_Opt options; Nag_Comm comm; static NagError fail, fail2; struct user s; Vprintf("\n\ne04fcc example 2: using option setting.\n"); Vscanf(" %*[^\n]"); /* Skip heading in data file */ n = 3; m = 15; tdj = NMAX; nt = 3; /* Read data into structure. * Observations t (j = 0, 1, 2) are held in s->t[i][j] * (i = 0, 1, 2, . . . , 14) */ nt = 3; for (i = 0; i < m; ++i) { Vscanf("%lf", &s.y[i]); for (j = 0; j < nt; ++j) Vscanf("%lf", &s.t[i][j]); } /* Set up the starting point */ x[0] = 0.5; x[1] = 1.0; x[2] = 1.5; e04xxc(&options); /* Initialise options structure */ /* Set one option directly. */ options.optim_tol = 10.0*sqrt(X02AJC); /* Read remaining option values from file */ fail.print = TRUE; print = FALSE; e04xyc("e04fcc", "stdin", &options, print, "", &fail); /* Assign address of user defined structure to * comm.p for communication to lsqfun2(). */ comm.p = (Pointer)&s; if (fail.code == NE_NOERROR) e04fcc(m, n, lsqfun2, x, &fsumsq, fvec, &fjac[0][0], tdj, &options, &comm, &fail); /* Free memory allocated to pointers s and v */ fail2.print = TRUE; e04xzc(&options, "all", &fail2); if ((fail.code != NE_NOERROR && fail.code != NW_COND_MIN) || fail2.code != NE_NOERROR) exit(EXIT_FAILURE); } /* ex2 */ static void lsqfun2(Integer m, Integer n, double x[], double fvec[], Nag_Comm *comm) { /* Function to evaluate the residuals for example 2. * * To avoid the use of a global varibale this example assigns the address * of a user defined structure to comm.p in the main program (where the * data was also read in). * The address of this structure is recovered in each call to lsqfun2() * from comm->p and the structure used in the calculation of the residuals. */ Integer i; struct user *s = (struct user *)comm->p; for (i = 0; i < m; ++i) fvec[i] = x[0] + s->t[i][0] / (x[1]*s->t[i][1] + x[2]*s->t[i][2]) - s->y[i]; } /* lsqfun2 */