/* nag_opt_lp_solve (e04mfc) Example Program.
*
* Copyright 2024 Numerical Algorithms Group.
*
* Mark 30.1, 2024.
*/
/* This sample linear program (LP) is a portfolio investment problem
* (see Chapter 7, pp 258--262 of ``Numerical Linear Algebra and
* Optimization'', by Gill, Murray and Wright, Addison Wesley, 1991).
* The problem involves the rearrangement of a portfolio of three
* stocks, Glitter, Risky and Trusty, so that the net worth of the
* investor is maximized.
* The problem is characterized by the following data:
* Glitter Risky Trusty
* 1990 Holdings 75 1000 25
* 1990 Priceshare($) 20 2 100
* 2099 Priceshare($) 18 3 102
* 2099 Dividend 5 0 2
*
* The variables x[0], x[1] and x[2] represent the change in each of
* the three stocks.
*/
#include <nag.h>
#include <stdio.h>
#define A(I, J) a[(I)*tda + J]
int main(void) {
const char *optionsfile = "e04mfce.opt";
Integer exit_status = 0;
Nag_Boolean print;
Integer n, nbnd, nclin, tda;
Nag_E04_Opt options;
double *a = 0, bigbnd, *bl = 0, *bu = 0, *cvec = 0, objf, *x = 0;
Nag_Comm comm;
NagError fail;
INIT_FAIL(fail);
printf("nag_opt_lp_solve (e04mfc) Example Program Results\n");
/* Set the actual problem dimensions.
* n = the number of variables.
* nclin = the number of general linear constraints (may be 0).
*/
n = 3;
nclin = 5;
nbnd = n + nclin;
if (n >= 1 && nclin >= 0) {
if (!(x = NAG_ALLOC(n, double)) || !(cvec = NAG_ALLOC(n, double)) ||
!(a = NAG_ALLOC(nclin * n, double)) ||
!(bl = NAG_ALLOC(nbnd, double)) || !(bu = NAG_ALLOC(nbnd, double))) {
printf("Allocation failure\n");
exit_status = -1;
goto END;
}
tda = n;
} else {
printf("Invalid n or nclin.\n");
exit_status = 1;
return exit_status;
}
/* Define the value used to denote ``infinite'' bounds. */
bigbnd = 1e+25;
/* Objective function: maximize 5*X[0] + 2*X[2], or equivalently,
* minimize -5*X[0] - 2*X[2].
*/
cvec[0] = -5.0;
cvec[1] = 0.0;
cvec[2] = -2.0;
/* a = the general constraint matrix.
* bl = the lower bounds on x and A*x.
* bu = the upper bounds on x and A*x.
* x = the initial estimate of the solution.
*
* A nonnegative amount of stock must be present after rearrangement.
* For Glitter: x[0] + 75 >= 0.
*/
bl[0] = -75.0;
bu[0] = bigbnd;
/* For Risky: x[1] + 1000 >= 0.0 */
bl[1] = -1000.0;
bu[1] = bigbnd;
/* For Trusty: x[2] + 25 >= 0.0 */
bl[2] = -25.0;
bu[2] = bigbnd;
/* The current value of the portfolio must be the same after
* rearrangement, i.e.,
* 20*(75+x[0]) + 2*(1000+x[1]) + 100*(25+x[2]) = 6000, or
* 20*x[0] + 2*x[1] + 100*x[2] = 0.
*/
A(0, 0) = 20.0;
A(0, 1) = 2.0;
A(0, 2) = 100.0;
bl[n] = 0.0;
bu[n] = 0.0;
/* The value of the portfolio must increase by at least 5 per cent
* at the end of the year, i.e.,
* 18*(75+x[0]) + 3*(1000+x[1]) + 102*(25+x[2]) >= 6300, or
* 18*x[0] + 3*x[1] + 102*x[2] >= -600.
*/
A(1, 0) = 18.0;
A(1, 1) = 3.0;
A(1, 2) = 102.0;
bl[n + 1] = -600.0;
bu[n + 1] = bigbnd;
/* There are three ``balanced portfolio'' constraints. The value of
* a stock must constitute at least a quarter of the total final
* value of the portfolio. After rearrangement, the value of the
* portfolio after is 20*(75+x[0]) + 2*(1000+x[1]) + 100*(25+x[2]).
*
* If Glitter is to constitute at least a quarter of the final
* portfolio, then 15*x[0] - 0.5*x[1] - 25*x[2] >= 0.
*/
A(2, 0) = 15.0;
A(2, 1) = -0.5;
A(2, 2) = -25.0;
bl[n + 2] = 0.0;
bu[n + 2] = bigbnd;
/* If Risky is to constitute at least a quarter of the final
* portfolio, then -5*x[0] + 1.5*x[1] - 25*x[2] >= -500.
*/
A(3, 0) = -5.0;
A(3, 1) = 1.5;
A(3, 2) = -25.0;
bl[n + 3] = -500.0;
bu[n + 3] = bigbnd;
/* If Trusty is to constitute at least a quarter of the final
* portfolio, then -5*x[0] - 0.5*x[1] + 75*x[2] >= -1000.
*/
A(4, 0) = -5.0;
A(4, 1) = -0.5;
A(4, 2) = 75.0;
bl[n + 4] = -1000.0;
bu[n + 4] = bigbnd;
/* Set the initial estimate of the solution.
* This portfolio is infeasible.
*/
x[0] = 10.0;
x[1] = 20.0;
x[2] = 100.0;
/* Initialize options structure to null values. */
/* nag_opt_init (e04xxc).
* Initialization function for option setting
*/
nag_opt_init(&options);
options.inf_bound = bigbnd;
/* Solve the problem. */
/* nag_opt_lp_solve (e04mfc), see above. */
fflush(stdout);
nag_opt_lp_solve(n, nclin, a, tda, bl, bu, cvec, x, &objf, &options, &comm,
&fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_lp_solve (e04mfc).\n%s\n", fail.message);
exit_status = 1;
goto END;
}
/* Re-solve the problem with some additonal options. */
printf("Re-solve problem with output of iteration results");
printf(" suppressed and ftol = 1.0e-10.\n");
/* Read additional options from a file. */
print = Nag_TRUE;
/* nag_opt_read (e04xyc).
* Read options from a text file
*/
fflush(stdout);
nag_opt_read("e04mfc", optionsfile, &options, print, "stdout", &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_read (e04xyc).\n%s\n", fail.message);
exit_status = 1;
goto END;
}
/* Reset starting point */
x[0] = 0.0;
x[1] = 0.0;
x[2] = 0.0;
/* Solve the problem again. */
/* nag_opt_lp_solve (e04mfc), see above. */
nag_opt_lp_solve(n, nclin, a, tda, bl, bu, cvec, x, &objf, &options, &comm,
&fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_lp_solve (e04mfc).\n%s\n", fail.message);
exit_status = 1;
goto END;
}
/* Free memory allocated by nag_opt_lp_solve (e04mfc) 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(x);
NAG_FREE(cvec);
NAG_FREE(a);
NAG_FREE(bl);
NAG_FREE(bu);
return exit_status;
}