// The easiest way to pull in all necessary definitions is to include oct.h #include // Overwrite type names duplicated in Octave and NAG header files #define Complex NagComplex #define MatrixType NagMatrixType // and include the appropriate NAG header files #include #include extern "C" { static void objfun(Integer n, double x[], double *objf, double objgrd[], Nag_Comm *comm); static void confun(Integer n, Integer ncnlin, Integer needc[], double x[], double conf[], double conjac[], Nag_Comm *comm); } /* The third parameter (nargout) is not used, so it is omitted from the list of arguments to DEFUN_DLD in order to avoid the warning from gcc about an unused function parameter. */ DEFUN_DLD (nag_opt, args, , "Calls nag_opt_nlp (e04ucc), which minimizes an arbitrary smooth function \n\ subject to constraints using a sequential quadratic programming (SQP) method.\n\ As many first derivatives as possible should be supplied by you; \n\ any unspecified derivatives are approximated by finite differences. \n\ It is not intended for large sparse problems.\n\ nag_opt_nlp (e04ucc) may also be used for unconstrained, bound-constrained \n\ and linearly constrained optimization.\n") { // Variable to store function output values octave_value_list retval; int nargin = args.length (); if (nargin != 8) { error ("Insufficient input arguments."); } else { // Retrieve input arguments from args Integer n = args(0).int_value(); Integer nclin = args(1).int_value(); Integer ncnlin = args(2).int_value(); Matrix a(args(3).matrix_value()); Integer tda = args(4).int_value(); NDArray bl(args(5).array_value()); NDArray bu(args(6).array_value()); NDArray x(args(7).array_value()); dim_vector dv (1); dv(0) = n; NDArray objgrd(dv); if (! error_state) { // Declare local variables double objf; Nag_Comm comm; NagError fail; INIT_FAIL(fail); // Call NAG routine /* nag_opt_nlp (e04ucc). * Minimization with nonlinear constraints using a * sequential QP method */ nag_opt_nlp(n, nclin, ncnlin, a.fortran_vec(), tda, bl.fortran_vec(), bu.fortran_vec(), objfun, confun, x.fortran_vec(), &objf, objgrd.fortran_vec(), E04_DEFAULT, &comm, &fail); /* T* fortran_vec (void) method returns a pointer to the underlying data of the matrix or a array so that it can be manipulated directly by an external library. */ if (fail.code != NE_NOERROR) { error ("Error from nag_opt_nlp (e04ucc).\n%s\n", fail.message); goto END; } // Assign output arguments to retval retval(0) = objf; retval(1) = objgrd; retval(2) = fail.code; } } END: return retval; } static void objfun(Integer n, double x[], double *objf, double objgrd[], Nag_Comm *comm) { /* Routine to evaluate objective function and its 1st derivatives. */ if (comm->flag == 0 || comm->flag == 2) *objf = x[0] * x[3] * (x[0] + x[1] + x[2]) + x[2]; if (comm->flag == 2) { objgrd[0] = x[3] * (2.0*x[0] + x[1] + x[2]); objgrd[1] = x[0] * x[3]; objgrd[2] = x[0] * x[3] + 1.0; objgrd[3] = x[0] * (x[0] + x[1] + x[2]); } } /* objfun */ static void confun(Integer n, Integer ncnlin, Integer needc[], double x[], double conf[], double conjac[], Nag_Comm *comm) { /* Routine to evaluate the nonlinear constraints and * their 1st derivatives. */ #define CONJAC(I,J) conjac[(I-1)*n + J - 1] Integer i, j; if (comm->first) { /* First call to confun. Set all Jacobian elements to zero. * Note that this will only work when con_deriv = TRUE * (the default; see Section 4 (confun) and 8.2 (con_deriv)). */ for (j = 1; j <= n; ++j) for (i = 1; i <= ncnlin; ++i) CONJAC(i,j) = 0.0; } if (needc[0] > 0) { if (comm->flag == 0 || comm->flag == 2) conf[0] = x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3]; if (comm->flag == 2) { CONJAC(1,1) = x[0] * 2.0; CONJAC(1,2) = x[1] * 2.0; CONJAC(1,3) = x[2] * 2.0; CONJAC(1,4) = x[3] * 2.0; } } if (needc[1] > 0) { if (comm->flag == 0 || comm->flag == 2) conf[1] = x[0] * x[1] * x[2] * x[3]; if (comm->flag == 2) { CONJAC(2,1) = x[1] * x[2] * x[3]; CONJAC(2,2) = x[0] * x[2] * x[3]; CONJAC(2,3) = x[0] * x[1] * x[3]; CONJAC(2,4) = x[0] * x[1] * x[2]; } } } /* confun */