/* nag_opt_nlp1_sparse_solve (e04ugc) Example Program.
*
* Copyright 2023 Numerical Algorithms Group.
*
* NAG C Library
*
* Mark 29.1, 2023.
*
*/
#include <math.h>
#include <nag.h>
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
static void NAG_CALL confun(Integer ncnln, Integer njnln, Integer nnzjac,
const double x[], double conf[], double conjac[],
Nag_Comm *comm);
static void NAG_CALL objfun(Integer nonln, const double x[], double *objf,
double objgrad[], Nag_Comm *comm);
#ifdef __cplusplus
}
#endif
#define NAMES(I, J) names[(I)*9 + J]
int main(void) {
const char *optionsfile = "e04ugce.opt";
Integer exit_status = 0, *ha = 0, i, icol, iobj, j, jcol, *ka = 0, m, n,
ncnln;
Integer ninf, njnln, nnz, nonln;
Nag_E04_Opt options;
char **crnames = 0, *names = 0;
double *a = 0, *bl = 0, *bu = 0, obj, sinf, *xs = 0;
Integer verbose_output;
Nag_Comm comm;
NagError fail;
INIT_FAIL(fail);
printf("nag_opt_nlp1_sparse_solve (e04ugc) Example Program Results\n");
fflush(stdout);
/* Skip heading in data file */
scanf(" %*[^\n]");
/* Read the problem dimensions */
scanf(" %*[^\n]");
scanf("%" NAG_IFMT "%" NAG_IFMT "", &n, &m);
/* Read NCNLN, NONLN and NJNLN from data file. */
scanf(" %*[^\n]");
scanf("%" NAG_IFMT "%" NAG_IFMT "%" NAG_IFMT "", &ncnln, &nonln, &njnln);
/* Read NNZ, IOBJ */
scanf(" %*[^\n]");
scanf("%" NAG_IFMT "%" NAG_IFMT "", &nnz, &iobj);
if (!(a = NAG_ALLOC(nnz, double)) || !(bl = NAG_ALLOC(n + m, double)) ||
!(bu = NAG_ALLOC(n + m, double)) || !(xs = NAG_ALLOC(n + m, double)) ||
!(ha = NAG_ALLOC(nnz, Integer)) || !(ka = NAG_ALLOC(n + 1, Integer)) ||
!(crnames = NAG_ALLOC(n + m, char *)) ||
!(names = NAG_ALLOC((n + m) * 9, char))) {
printf("Allocation failure\n");
exit_status = 1;
goto END;
}
/* Read the column and row names */
scanf(" %*[^\n]");
scanf(" %*[^']");
for (i = 0; i < n + m; ++i) {
scanf(" '%8c'", &NAMES(i, 0));
NAMES(i, 8) = '\0';
crnames[i] = &NAMES(i, 0);
}
/* read the matrix and set up ka. */
jcol = 1;
ka[jcol - 1] = 0;
scanf(" %*[^\n]");
for (i = 0; i < nnz; ++i) {
/* a[i] stores (ha[i], icol) element of matrix */
scanf("%lf%" NAG_IFMT "%" NAG_IFMT "", &a[i], &ha[i], &icol);
if (icol < jcol) {
/* Elements not ordered by increasing column index. */
printf("Element in column%5" NAG_IFMT " found after element in"
" column%5" NAG_IFMT ". Problem abandoned.\n",
icol, jcol);
exit_status = 1;
goto END;
} else if (icol == jcol + 1) {
/* Index in a of the start of the icol-th column equals i. */
ka[icol - 1] = i;
jcol = icol;
} else if (icol > jcol + 1) {
/* Index in a of the start of the icol-th column equals i,
* but columns jcol+1,jcol+2,...,icol-1 are empty. Set the
* corresponding elements of ka to i.
*/
for (j = jcol + 1; j <= icol - 1; ++j)
ka[j - 1] = i;
ka[icol - 1] = i;
jcol = icol;
}
}
ka[n] = nnz;
if (n > icol) {
/* Columns N,N-1,...,ICOL+1 are empty. Set the
* corresponding elements of ka accordingly. */
for (j = icol; j <= n - 1; ++j)
ka[j] = nnz;
}
/* Read the bounds */
scanf(" %*[^\n]");
for (i = 0; i < n + m; ++i)
scanf("%lf", &bl[i]);
scanf(" %*[^\n]");
for (i = 0; i < n + m; ++i)
scanf("%lf", &bu[i]);
/* Read the initial estimate of x */
scanf(" %*[^\n]");
for (i = 0; i < n; ++i)
scanf("%lf", &xs[i]);
/* Initialize the options structure */
/* nag_opt_init (e04xxc).
* Initialization function for option setting
*/
nag_opt_init(&options);
/* Set this to 1 to cause e04ugc to produce intermediate
progress output */
verbose_output = 0;
/* Read some option values from standard input */
/* nag_opt_read (e04xyc).
* Read options from a text file
*/
nag_opt_read("e04ugc", optionsfile, &options,
(Nag_Boolean)(verbose_output == 1), "stdout", &fail);
/* Set some other options directly */
options.major_iter_lim = 100;
options.crnames = crnames;
if (verbose_output == 0) {
options.list = Nag_FALSE;
options.print_level = Nag_NoPrint;
options.print_deriv = Nag_D_NoPrint;
}
/* Solve the problem. */
/* nag_opt_nlp1_sparse_solve (e04ugc), see above. */
nag_opt_nlp1_sparse_solve(confun, objfun, n, m, ncnln, nonln, njnln, iobj,
nnz, a, ha, ka, bl, bu, xs, &ninf, &sinf, &obj,
&comm, &options, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_nlp1_sparse_solve (e04ugc).\n%s\n",
fail.message);
exit_status = 1;
goto END;
}
if (verbose_output == 0) {
printf("\n");
printf("Final objective value = %12.3f\n", obj);
printf("Optimal X = ");
for (i = 1; i <= n; ++i) {
printf("%9.3f%s", xs[i - 1], i % 7 == 0 || i == n ? "\n" : " ");
}
}
/* We perturb the solution and solve the
* same problem again using a warm start.
*/
printf("\nA run of the same example with a warm start:\n");
printf("--------------------------------------------\n");
options.start = Nag_Warm;
/* Modify some printing options */
options.print_deriv = Nag_D_NoPrint;
if (verbose_output == 1)
options.print_level = Nag_Iter;
else
options.print_level = Nag_NoPrint;
/* Perturb xs */
for (i = 0; i < n + m; i++)
xs[i] += 0.2;
/* Reset multiplier estimates to 0.0 */
if (ncnln > 0) {
for (i = 0; i < ncnln; i++)
options.lambda[n + i] = 0.0;
}
/* Solve the problem again. */
/* nag_opt_nlp1_sparse_solve (e04ugc), see above. */
fflush(stdout);
nag_opt_nlp1_sparse_solve(confun, objfun, n, m, ncnln, nonln, njnln, iobj,
nnz, a, ha, ka, bl, bu, xs, &ninf, &sinf, &obj,
&comm, &options, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_nlp1_sparse_solve (e04ugc).\n%s\n",
fail.message);
exit_status = 1;
}
if (verbose_output == 0) {
printf("Final objective value = %12.3f\n", obj);
printf("Optimal X = ");
for (i = 1; i <= n; ++i) {
printf("%9.3f%s", xs[i - 1], i % 7 == 0 || i == n ? "\n" : " ");
}
}
/* Free memory allocated by nag_opt_nlp1_sparse_solve (e04ugc) to pointers in
* options
*/
/* nag_opt_free (e04xzc).
* Memory freeing function for use with option setting
*/
nag_opt_free(&options, "all", &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_free (e04xzc).\n%s\n", fail.message);
exit_status = 1;
goto END;
}
END:
NAG_FREE(a);
NAG_FREE(bl);
NAG_FREE(bu);
NAG_FREE(xs);
NAG_FREE(ha);
NAG_FREE(ka);
NAG_FREE(crnames);
NAG_FREE(names);
return exit_status;
}
/* Subroutine */
static void NAG_CALL confun(Integer ncnln, Integer njnln, Integer nnzjac,
const double x[], double conf[], double conjac[],
Nag_Comm *comm) {
#define CONJAC(I) conjac[(I)-1]
#define CONF(I) conf[(I)-1]
#define X(I) x[(I)-1]
/* Compute the nonlinear constraint functions and their Jacobian. */
if (comm->flag == 0 || comm->flag == 2) {
CONF(1) = sin(-X(1) - 0.25) * 1e3 + sin(-X(2) - 0.25) * 1e3;
CONF(2) = sin(X(1) - 0.25) * 1e3 + sin(X(1) - X(2) - 0.25) * 1e3;
CONF(3) = sin(X(2) - X(1) - 0.25) * 1e3 + sin(X(2) - 0.25) * 1e3;
}
if (comm->flag == 1 || comm->flag == 2) {
/* Nonlinear Jacobian elements for column 1.0 */
CONJAC(1) = cos(-X(1) - 0.25) * -1e3;
CONJAC(2) = cos(X(1) - 0.25) * 1e3 + cos(X(1) - X(2) - 0.25) * 1e3;
CONJAC(3) = cos(X(2) - X(1) - 0.25) * -1e3;
/* Nonlinear Jacobian elements for column 2.0 */
CONJAC(4) = cos(-X(2) - 0.25) * -1e3;
CONJAC(5) = cos(X(1) - X(2) - 0.25) * -1e3;
CONJAC(6) = cos(X(2) - X(1) - 0.25) * 1e3 + cos(X(2) - 0.25) * 1e3;
}
}
static void NAG_CALL objfun(Integer nonln, const double x[], double *objf,
double objgrad[], Nag_Comm *comm) {
#define OBJGRAD(I) objgrad[(I)-1]
#define X(I) x[(I)-1]
/* Compute the nonlinear part of the objective function and its grad */
if (comm->flag == 0 || comm->flag == 2)
*objf = X(3) * X(3) * X(3) * 1e-6 + X(4) * X(4) * X(4) * 2e-6 / 3.0;
if (comm->flag == 1 || comm->flag == 2) {
OBJGRAD(1) = 0.0;
OBJGRAD(2) = 0.0;
OBJGRAD(3) = X(3) * X(3) * 3e-6;
OBJGRAD(4) = X(4) * X(4) * 2e-6;
}
}