/* nag_opt_nlp2_option_file (e04wec) Example Program.
*
* Copyright 2024 Numerical Algorithms Group.
*
* Mark 30.2, 2024.
*/
#include <nag.h>
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
static void NAG_CALL confun(Integer *mode, Integer ncnln, Integer n,
Integer ldcj, const Integer needc[],
const double x[], double ccon[], double cjac[],
Integer nstate, Nag_Comm *comm);
static void NAG_CALL objfun(Integer *mode, Integer n, const double x[],
double *objf, double grad[], Integer nstate,
Nag_Comm *comm);
#ifdef __cplusplus
}
#endif
int main(void) {
const char *optionsfile = "e04wece.opt";
/* Scalars */
double bndinf, featol, objf;
Integer elmode, exit_status, i, j, majits, n, nclin, ncnln, nctotal, pda;
Integer pdcj, pdh;
/* Arrays */
static double ruser[2] = {-1.0, -1.0};
double *a = 0, *bl = 0, *bu = 0, *ccon = 0, *cjac = 0, *clamda = 0;
double *grad = 0, *hess = 0, *x = 0;
Integer *istate = 0, *iuser = 0;
/* Nag Types */
Nag_E04State state;
NagError fail;
Nag_Comm comm;
Nag_FileID fileidin;
Nag_FileID fileidout;
#define A(I, J) a[(I - 1) * pda + J - 1]
exit_status = 0;
INIT_FAIL(fail);
printf("%s", "nag_opt_nlp2_option_file (e04wec) Example Program"
" Results");
printf("\n");
/* For communication with user-supplied functions: */
comm.user = ruser;
fflush(stdout);
/* This program demonstrates the use of routines to set and get values of
* optional parameters associated with nag_opt_nlp2_solve (e04wdc).
*/
/* Skip heading in data file */
scanf("%*[^\n] ");
scanf("%" NAG_IFMT " %" NAG_IFMT " %" NAG_IFMT " ", &n, &nclin, &ncnln);
scanf("%*[^\n] ");
pda = n;
pdcj = n;
pdh = n;
nctotal = n + nclin + ncnln;
if (!(a = NAG_ALLOC(ncnln * n, double)) ||
!(bl = NAG_ALLOC(nctotal, double)) ||
!(bu = NAG_ALLOC(nctotal, double)) ||
!(ccon = NAG_ALLOC(ncnln, double)) ||
!(cjac = NAG_ALLOC(ncnln * n, double)) ||
!(clamda = NAG_ALLOC(nctotal, double)) ||
!(grad = NAG_ALLOC(n, double)) || !(hess = NAG_ALLOC(n * n, double)) ||
!(x = NAG_ALLOC(n, double)) || !(istate = NAG_ALLOC(nctotal, Integer)) ||
!(iuser = NAG_ALLOC(1, Integer))) {
printf("Allocation failure\n");
exit_status = -1;
goto END;
}
/* Read A, BL, BU and X from data file */
if (nclin > 0) {
for (i = 1; i <= nclin; ++i) {
for (j = 1; j <= n; ++j) {
scanf("%lf", &A(i, j));
}
}
scanf("%*[^\n] ");
}
for (i = 1; i <= n + nclin + ncnln; ++i) {
scanf("%lf", &bl[i - 1]);
}
scanf("%*[^\n] ");
for (i = 1; i <= n + nclin + ncnln; ++i) {
scanf("%lf", &bu[i - 1]);
}
scanf("%*[^\n] ");
for (i = 1; i <= n; ++i) {
scanf("%lf", &x[i - 1]);
}
scanf("%*[^\n] ");
/* Call nag_opt_nlp2_init (e04wcc) to initialize nag_opt_nlp2_solve (e04wdc).
*/
/* nag_opt_nlp2_init (e04wcc).
* Initialization function for nag_opt_nlp2_solve (e04wdc)
*/
nag_opt_nlp2_init(&state, &fail);
if (fail.code != NE_NOERROR) {
printf("Initialization of nag_opt_nlp2_init (e04wcc) failed.\n%s\n",
fail.message);
exit_status = 1;
goto END;
}
/* By default nag_opt_nlp2_solve (e04wdc) does not print monitoring
* information. Call nag_file_open (x04acc) to set the print file fileid.
*/
/* nag_file_open (x04acc).
* Open unit number for reading, writing or appending, and
* associate unit with named file
*/
nag_file_open("", 2, &fileidout, &fail);
if (fail.code != NE_NOERROR) {
printf("Fileidout could not be obtained.\n");
exit_status = 1;
goto END;
}
/* Use nag_opt_nlp2_option_integer_set (e04wgc) to set the Integer-valued
* option 'Print file' */
/* nag_opt_nlp2_option_integer_set (e04wgc).
* Set a single option for nag_opt_nlp2_solve (e04wdc) from
* an integer argument
*/
nag_opt_nlp2_option_integer_set("Print file", fileidout, &state, &fail);
if (fail.code != NE_NOERROR) {
printf("nag_opt_nlp2_option_integer_set (e04wgc) failed to set Print"
" File\n");
exit_status = 1;
goto END;
}
/* Use nag_opt_nlp2_option_file (e04wec) to read some options from
* the options file. Firsr call nag_file_open (x04acc) to set the options file
* fileid.
*/
nag_file_open(optionsfile, 0, &fileidin, &fail);
if (fail.code != NE_NOERROR) {
printf("Fileidin could not be obtained.\n");
exit_status = 1;
goto END;
}
/* nag_opt_nlp2_option_file (e04wec).
* Supply optional parameter values for nag_opt_nlp2_solve
* (e04wdc) from external file
*/
nag_opt_nlp2_option_file(fileidin, &state, &fail);
if (fail.code != NE_NOERROR) {
printf("nag_opt_nlp2_option_file (e04wec) could not read input"
" File\n");
exit_status = 1;
goto END;
}
/* Use nag_opt_nlp2_option_integer_get (e04wkc) to find the value of
* Integer-valued option 'Elastic mode'.
*/
/* nag_opt_nlp2_option_integer_get (e04wkc).
* Get the setting of an integer valued option of
* nag_opt_nlp2_solve (e04wdc)
*/
nag_opt_nlp2_option_integer_get("Elastic mode", &elmode, &state, &fail);
if (fail.code != NE_NOERROR) {
printf("nag_opt_nlp2_option_integer_get (e04wkc) failed to find the value"
" of Elastic Mode\n");
exit_status = 1;
goto END;
}
printf("Option 'Elastic mode' has the value ");
printf("%3" NAG_IFMT ".\n", elmode);
/* Use nag_opt_nlp2_option_double_set (e04whc) to set the value of real-valued
* option 'Infinite bound size'.
*/
bndinf = 1e10;
/* nag_opt_nlp2_option_double_set (e04whc).
* Set a single option for nag_opt_nlp2_solve (e04wdc) from a
* double argument
*/
nag_opt_nlp2_option_double_set("Infinite bound size", bndinf, &state, &fail);
if (fail.code != NE_NOERROR) {
printf("nag_opt_nlp2_option_double_set (e04whc) failed to set Infinite"
" bound size\n");
exit_status = 1;
goto END;
}
/* Use nag_opt_nlp2_option_double_get (e04wlc) to find the value of
* real-valued option 'Feasibility tolerance'.
*/
/* nag_opt_nlp2_option_double_get (e04wlc).
* Get the setting of a double valued option of
* nag_opt_nlp2_solve (e04wdc)
*/
nag_opt_nlp2_option_double_get("Feasibility tolerance", &featol, &state,
&fail);
if (fail.code != NE_NOERROR) {
printf("nag_opt_nlp2_option_double_get (e04wlc) failed to find the value"
" of a real-valued option\n");
exit_status = 1;
goto END;
}
printf("Option 'Feasibility tolerance' has the value %14.5e.\n", featol);
/* Use nag_opt_nlp2_option_string (e04wfc) to set the option 'Major
* iterations limit'.
*/
/* nag_opt_nlp2_option_string (e04wfc).
* Set a single option for nag_opt_nlp2_solve (e04wdc) from a
* character string
*/
nag_opt_nlp2_option_string("Major iterations limit 50", &state, &fail);
if (fail.code != NE_NOERROR) {
printf("nag_opt_nlp2_option_string (e04wfc) failed to set Major"
" iterations limit\n");
exit_status = 1;
goto END;
}
fflush(stdout);
/* Solve the problem. */
/* nag_opt_nlp2_solve (e04wdc).
* Solves the nonlinear programming (NP) problem
*/
nag_file_open("", 2, &fileidout, &fail); /* Open library output */
nag_opt_nlp2_option_integer_set("Print file", fileidout, &state, &fail);
fflush(stdout);
nag_opt_nlp2_solve(n, nclin, ncnln, pda, pdcj, pdh, a, bl, bu, confun, objfun,
&majits, istate, ccon, cjac, clamda, &objf, grad, hess, x,
&state, &comm, &fail);
if (fail.code == NE_NOERROR) {
printf("\nFinal objective value = %11.3f\n", objf);
printf("Optimal X = ");
for (i = 1; i <= n; ++i) {
printf("%9.2f%s", x[i - 1], i % 7 == 0 || i == n ? "\n" : " ");
}
} else {
printf("Error message from nag_opt_nlp2_solve (e04wdc).\no%s\n",
fail.message);
}
END:
NAG_FREE(a);
NAG_FREE(bl);
NAG_FREE(bu);
NAG_FREE(ccon);
NAG_FREE(cjac);
NAG_FREE(clamda);
NAG_FREE(grad);
NAG_FREE(hess);
NAG_FREE(x);
NAG_FREE(istate);
NAG_FREE(iuser);
return exit_status;
}
static void NAG_CALL objfun(Integer *mode, Integer n, const double x[],
double *objf, double grad[], Integer nstate,
Nag_Comm *comm) {
/* Routine to evaluate objective function and its 1st derivatives. */
/* Function Body */
if (comm->user[0] == -1.0) {
fflush(stdout);
printf("(User-supplied callback objfun, first invocation.)\n");
comm->user[0] = 0.0;
fflush(stdout);
}
if (*mode == 0 || *mode == 2) {
*objf = x[0] * x[3] * (x[0] + x[1] + x[2]) + x[2];
}
if (*mode == 1 || *mode == 2) {
grad[0] = x[3] * (x[0] * 2. + x[1] + x[2]);
grad[1] = x[0] * x[3];
grad[2] = x[0] * x[3] + 1.;
grad[3] = x[0] * (x[0] + x[1] + x[2]);
}
return;
} /* objfun */
static void NAG_CALL confun(Integer *mode, Integer ncnln, Integer n,
Integer ldcj, const Integer needc[],
const double x[], double ccon[], double cjac[],
Integer nstate, Nag_Comm *comm) {
/* Scalars */
Integer i, j;
#define CJAC(I, J) cjac[(I - 1) * ldcj + J - 1]
/* Routine to evaluate the nonlinear constraints and their 1st */
/* derivatives. */
/* Function Body */
if (comm->user[1] == -1.0) {
fflush(stdout);
printf("(User-supplied callback confun, first invocation.)\n");
comm->user[1] = 0.0;
fflush(stdout);
}
if (nstate == 1) {
/* First call to CONFUN. Set all Jacobian elements to zero. */
/* Note that this will only work when 'Derivative Level = 3' */
/* (the default; see Section 11.2). */
for (j = 1; j <= n; ++j) {
for (i = 1; i <= ncnln; ++i) {
CJAC(i, j) = 0.;
}
}
}
if (needc[0] > 0) {
if (*mode == 0 || *mode == 2) {
ccon[0] = x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3];
}
if (*mode == 1 || *mode == 2) {
CJAC(1, 1) = x[0] * 2.;
CJAC(1, 2) = x[1] * 2.;
CJAC(1, 3) = x[2] * 2.;
CJAC(1, 4) = x[3] * 2.;
}
}
if (needc[1] > 0) {
if (*mode == 0 || *mode == 2) {
ccon[1] = x[0] * x[1] * x[2] * x[3];
}
if (*mode == 1 || *mode == 2) {
CJAC(2, 1) = x[1] * x[2] * x[3];
CJAC(2, 2) = x[0] * x[2] * x[3];
CJAC(2, 3) = x[0] * x[1] * x[3];
CJAC(2, 4) = x[0] * x[1] * x[2];
}
}
return;
} /* confun */