Home > matpower7.1 > mp-opt-model > lib > nlps_knitro.m

nlps_knitro

PURPOSE ^

NLPS_KNITRO Nonlinear programming (NLP) Solver based on Artelys Knitro.

SYNOPSIS ^

function [x, f, eflag, output, lambda] = nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt)

DESCRIPTION ^

NLPS_KNITRO  Nonlinear programming (NLP) Solver based on Artelys Knitro.
   [X, F, EXITFLAG, OUTPUT, LAMBDA] = ...
       NLPS_KNITRO(F_FCN, X0, A, L, U, XMIN, XMAX, GH_FCN, HESS_FCN, OPT)
   [X, F, EXITFLAG, OUTPUT, LAMBDA] = NLPS_KNITRO(PROBLEM)
   A wrapper function providing a standardized interface for using
   Artelys Knitro to solve the following NLP (nonlinear programming) problem:

   Minimize a function F(X) beginning from a starting point X0, subject to
   optional linear and nonlinear constraints and variable bounds.

       min F(X)
        X

   subject to

       G(X) = 0            (nonlinear equalities)
       H(X) <= 0           (nonlinear inequalities)
       L <= A*X <= U       (linear constraints)
       XMIN <= X <= XMAX   (variable bounds)

   Inputs (all optional except F_FCN and X0):
       F_FCN : handle to function that evaluates the objective function,
           its gradients and Hessian for a given value of X. If there
           are nonlinear constraints, the Hessian information is
           provided by the HESS_FCN function passed in the 9th argument
           and is not required here. Calling syntax for this function:
               [F, DF, D2F] = F_FCN(X)
       X0 : starting value of optimization vector X
       A, L, U : define the optional linear constraints. Default
           values for the elements of L and U are -Inf and Inf,
           respectively.
       XMIN, XMAX : optional lower and upper bounds on the
           X variables, defaults are -Inf and Inf, respectively.
       GH_FCN : handle to function that evaluates the optional
           nonlinear constraints and their gradients for a given
           value of X. Calling syntax for this function is:
               [H, G, DH, DG] = GH_FCN(X)
           where the columns of DH and DG are the gradients of the
           corresponding elements of H and G, i.e. DH and DG are
           transposes of the Jacobians of H and G, respectively.
       HESS_FCN : handle to function that computes the Hessian of the
           Lagrangian for given values of X, lambda and mu, where
           lambda and mu are the multipliers on the equality and
           inequality constraints, g and h, respectively. The calling
           syntax for this function is:
               LXX = HESS_FCN(X, LAM)
           where lambda = LAM.eqnonlin and mu = LAM.ineqnonlin.
       OPT : optional options structure with the following fields,
           all of which are also optional (default values shown in
           parentheses)
           verbose (0) - controls level of progress output displayed
               0 = no progress output
               1 = some progress output
               2 = verbose progress output
           knitro_opt  - options struct for Artelys Knitro, value in verbose
                   overrides these options
               opts - struct of other values to be passed directly to
                   Aretelys Knitro via an options file
               tol_x - termination tol on x
               tol_f - termination tol on f
               maxit - maximum number of iterations
       PROBLEM : The inputs can alternatively be supplied in a single
           PROBLEM struct with fields corresponding to the input arguments
           described above: f_fcn, x0, A, l, u, xmin, xmax,
                            gh_fcn, hess_fcn, opt

   Outputs:
       X : solution vector
       F : final objective function value
       EXITFLAG : exit flag
           1 = converged
           negative values = Artelys Knitro specific failure codes
           (see KNITROMATLAB documentation for details)
             https://www.artelys.com/docs/knitro/3_referenceManual/knitromatlabReference.html#return-codes-exit-flags
       OUTPUT : KNITROMATLAB output struct
           (see KNITROMATLAB documentation for details)
             https://www.artelys.com/docs/knitro/3_referenceManual/knitromatlabReference.html#output-structure-fields
           iterations - number of iterations performed
           funcCount - number of function evaluations
           constrviolation - maximum of constraint violations
           firstorderopt - measure of first-order optimality
       LAMBDA : struct containing the Langrange and Kuhn-Tucker
           multipliers on the constraints, with fields:
           eqnonlin - nonlinear equality constraints
           ineqnonlin - nonlinear inequality constraints
           mu_l - lower (left-hand) limit on linear constraints
           mu_u - upper (right-hand) limit on linear constraints
           lower - lower bound on optimization variables
           upper - upper bound on optimization variables

   Note the calling syntax is almost identical to that of FMINCON
   from MathWorks' Optimization Toolbox. The main difference is that
   the linear constraints are specified with A, L, U instead of
   A, B, Aeq, Beq. The functions for evaluating the objective
   function, constraints and Hessian are identical.

   Calling syntax options:
       [x, f, exitflag, output, lambda] = ...
           nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt);

       x = nlps_knitro(f_fcn, x0);
       x = nlps_knitro(f_fcn, x0, A, l);
       x = nlps_knitro(f_fcn, x0, A, l, u);
       x = nlps_knitro(f_fcn, x0, A, l, u, xmin);
       x = nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax);
       x = nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn);
       x = nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn);
       x = nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt);
       x = nlps_knitro(problem);
               where problem is a struct with fields:
                   f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt
                   all fields except 'f_fcn' and 'x0' are optional
       x = nlps_knitro(...);
       [x, f] = nlps_knitro(...);
       [x, f, exitflag] = nlps_knitro(...);
       [x, f, exitflag, output] = nlps_knitro(...);
       [x, f, exitflag, output, lambda] = nlps_knitro(...);

   Example: (problem from https://en.wikipedia.org/wiki/Nonlinear_programming)
       function [f, df, d2f] = f2(x)
       f = -x(1)*x(2) - x(2)*x(3);
       if nargout > 1           %% gradient is required
           df = -[x(2); x(1)+x(3); x(2)];
           if nargout > 2       %% Hessian is required
               d2f = -[0 1 0; 1 0 1; 0 1 0];   %% actually not used since
           end                                 %% 'hess_fcn' is provided
       end
       
       function [h, g, dh, dg] = gh2(x)
       h = [ 1 -1 1; 1 1 1] * x.^2 + [-2; -10];
       dh = 2 * [x(1) x(1); -x(2) x(2); x(3) x(3)];
       g = []; dg = [];
       
       function Lxx = hess2(x, lam, cost_mult)
       if nargin < 3, cost_mult = 1; end
       mu = lam.ineqnonlin;
       Lxx = cost_mult * [0 -1 0; -1 0 -1; 0 -1 0] + ...
               [2*[1 1]*mu 0 0; 0 2*[-1 1]*mu 0; 0 0 2*[1 1]*mu];
       
       problem = struct( ...
           'f_fcn',    @(x)f2(x), ...
           'gh_fcn',   @(x)gh2(x), ...
           'hess_fcn', @(x, lam, cost_mult)hess2(x, lam, cost_mult), ...
           'x0',       [1; 1; 0], ...
           'opt',      struct('verbose', 2) ...
       );
       [x, f, exitflag, output, lambda] = nlps_knitro(problem);

   See also NLPS_MASTER, KNITROMATLAB.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [x, f, eflag, output, lambda] = nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt)
0002 %NLPS_KNITRO  Nonlinear programming (NLP) Solver based on Artelys Knitro.
0003 %   [X, F, EXITFLAG, OUTPUT, LAMBDA] = ...
0004 %       NLPS_KNITRO(F_FCN, X0, A, L, U, XMIN, XMAX, GH_FCN, HESS_FCN, OPT)
0005 %   [X, F, EXITFLAG, OUTPUT, LAMBDA] = NLPS_KNITRO(PROBLEM)
0006 %   A wrapper function providing a standardized interface for using
0007 %   Artelys Knitro to solve the following NLP (nonlinear programming) problem:
0008 %
0009 %   Minimize a function F(X) beginning from a starting point X0, subject to
0010 %   optional linear and nonlinear constraints and variable bounds.
0011 %
0012 %       min F(X)
0013 %        X
0014 %
0015 %   subject to
0016 %
0017 %       G(X) = 0            (nonlinear equalities)
0018 %       H(X) <= 0           (nonlinear inequalities)
0019 %       L <= A*X <= U       (linear constraints)
0020 %       XMIN <= X <= XMAX   (variable bounds)
0021 %
0022 %   Inputs (all optional except F_FCN and X0):
0023 %       F_FCN : handle to function that evaluates the objective function,
0024 %           its gradients and Hessian for a given value of X. If there
0025 %           are nonlinear constraints, the Hessian information is
0026 %           provided by the HESS_FCN function passed in the 9th argument
0027 %           and is not required here. Calling syntax for this function:
0028 %               [F, DF, D2F] = F_FCN(X)
0029 %       X0 : starting value of optimization vector X
0030 %       A, L, U : define the optional linear constraints. Default
0031 %           values for the elements of L and U are -Inf and Inf,
0032 %           respectively.
0033 %       XMIN, XMAX : optional lower and upper bounds on the
0034 %           X variables, defaults are -Inf and Inf, respectively.
0035 %       GH_FCN : handle to function that evaluates the optional
0036 %           nonlinear constraints and their gradients for a given
0037 %           value of X. Calling syntax for this function is:
0038 %               [H, G, DH, DG] = GH_FCN(X)
0039 %           where the columns of DH and DG are the gradients of the
0040 %           corresponding elements of H and G, i.e. DH and DG are
0041 %           transposes of the Jacobians of H and G, respectively.
0042 %       HESS_FCN : handle to function that computes the Hessian of the
0043 %           Lagrangian for given values of X, lambda and mu, where
0044 %           lambda and mu are the multipliers on the equality and
0045 %           inequality constraints, g and h, respectively. The calling
0046 %           syntax for this function is:
0047 %               LXX = HESS_FCN(X, LAM)
0048 %           where lambda = LAM.eqnonlin and mu = LAM.ineqnonlin.
0049 %       OPT : optional options structure with the following fields,
0050 %           all of which are also optional (default values shown in
0051 %           parentheses)
0052 %           verbose (0) - controls level of progress output displayed
0053 %               0 = no progress output
0054 %               1 = some progress output
0055 %               2 = verbose progress output
0056 %           knitro_opt  - options struct for Artelys Knitro, value in verbose
0057 %                   overrides these options
0058 %               opts - struct of other values to be passed directly to
0059 %                   Aretelys Knitro via an options file
0060 %               tol_x - termination tol on x
0061 %               tol_f - termination tol on f
0062 %               maxit - maximum number of iterations
0063 %       PROBLEM : The inputs can alternatively be supplied in a single
0064 %           PROBLEM struct with fields corresponding to the input arguments
0065 %           described above: f_fcn, x0, A, l, u, xmin, xmax,
0066 %                            gh_fcn, hess_fcn, opt
0067 %
0068 %   Outputs:
0069 %       X : solution vector
0070 %       F : final objective function value
0071 %       EXITFLAG : exit flag
0072 %           1 = converged
0073 %           negative values = Artelys Knitro specific failure codes
0074 %           (see KNITROMATLAB documentation for details)
0075 %             https://www.artelys.com/docs/knitro/3_referenceManual/knitromatlabReference.html#return-codes-exit-flags
0076 %       OUTPUT : KNITROMATLAB output struct
0077 %           (see KNITROMATLAB documentation for details)
0078 %             https://www.artelys.com/docs/knitro/3_referenceManual/knitromatlabReference.html#output-structure-fields
0079 %           iterations - number of iterations performed
0080 %           funcCount - number of function evaluations
0081 %           constrviolation - maximum of constraint violations
0082 %           firstorderopt - measure of first-order optimality
0083 %       LAMBDA : struct containing the Langrange and Kuhn-Tucker
0084 %           multipliers on the constraints, with fields:
0085 %           eqnonlin - nonlinear equality constraints
0086 %           ineqnonlin - nonlinear inequality constraints
0087 %           mu_l - lower (left-hand) limit on linear constraints
0088 %           mu_u - upper (right-hand) limit on linear constraints
0089 %           lower - lower bound on optimization variables
0090 %           upper - upper bound on optimization variables
0091 %
0092 %   Note the calling syntax is almost identical to that of FMINCON
0093 %   from MathWorks' Optimization Toolbox. The main difference is that
0094 %   the linear constraints are specified with A, L, U instead of
0095 %   A, B, Aeq, Beq. The functions for evaluating the objective
0096 %   function, constraints and Hessian are identical.
0097 %
0098 %   Calling syntax options:
0099 %       [x, f, exitflag, output, lambda] = ...
0100 %           nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt);
0101 %
0102 %       x = nlps_knitro(f_fcn, x0);
0103 %       x = nlps_knitro(f_fcn, x0, A, l);
0104 %       x = nlps_knitro(f_fcn, x0, A, l, u);
0105 %       x = nlps_knitro(f_fcn, x0, A, l, u, xmin);
0106 %       x = nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax);
0107 %       x = nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn);
0108 %       x = nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn);
0109 %       x = nlps_knitro(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt);
0110 %       x = nlps_knitro(problem);
0111 %               where problem is a struct with fields:
0112 %                   f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt
0113 %                   all fields except 'f_fcn' and 'x0' are optional
0114 %       x = nlps_knitro(...);
0115 %       [x, f] = nlps_knitro(...);
0116 %       [x, f, exitflag] = nlps_knitro(...);
0117 %       [x, f, exitflag, output] = nlps_knitro(...);
0118 %       [x, f, exitflag, output, lambda] = nlps_knitro(...);
0119 %
0120 %   Example: (problem from https://en.wikipedia.org/wiki/Nonlinear_programming)
0121 %       function [f, df, d2f] = f2(x)
0122 %       f = -x(1)*x(2) - x(2)*x(3);
0123 %       if nargout > 1           %% gradient is required
0124 %           df = -[x(2); x(1)+x(3); x(2)];
0125 %           if nargout > 2       %% Hessian is required
0126 %               d2f = -[0 1 0; 1 0 1; 0 1 0];   %% actually not used since
0127 %           end                                 %% 'hess_fcn' is provided
0128 %       end
0129 %
0130 %       function [h, g, dh, dg] = gh2(x)
0131 %       h = [ 1 -1 1; 1 1 1] * x.^2 + [-2; -10];
0132 %       dh = 2 * [x(1) x(1); -x(2) x(2); x(3) x(3)];
0133 %       g = []; dg = [];
0134 %
0135 %       function Lxx = hess2(x, lam, cost_mult)
0136 %       if nargin < 3, cost_mult = 1; end
0137 %       mu = lam.ineqnonlin;
0138 %       Lxx = cost_mult * [0 -1 0; -1 0 -1; 0 -1 0] + ...
0139 %               [2*[1 1]*mu 0 0; 0 2*[-1 1]*mu 0; 0 0 2*[1 1]*mu];
0140 %
0141 %       problem = struct( ...
0142 %           'f_fcn',    @(x)f2(x), ...
0143 %           'gh_fcn',   @(x)gh2(x), ...
0144 %           'hess_fcn', @(x, lam, cost_mult)hess2(x, lam, cost_mult), ...
0145 %           'x0',       [1; 1; 0], ...
0146 %           'opt',      struct('verbose', 2) ...
0147 %       );
0148 %       [x, f, exitflag, output, lambda] = nlps_knitro(problem);
0149 %
0150 %   See also NLPS_MASTER, KNITROMATLAB.
0151 
0152 %   MP-Opt-Model
0153 %   Copyright (c) 2010-2020, Power Systems Engineering Research Center (PSERC)
0154 %   by Ray Zimmerman, PSERC Cornell
0155 %
0156 %   This file is part of MP-Opt-Model.
0157 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0158 %   See https://github.com/MATPOWER/mp-opt-model for more info.
0159 
0160 %% options
0161 use_ktropts_file = 1;       %% use a Knitro options file to pass options
0162 create_ktropts_file = 0;    %% generate a Knitro options file on the fly
0163 
0164 %%----- input argument handling  -----
0165 %% gather inputs
0166 if nargin == 1 && isstruct(f_fcn)       %% problem struct
0167     p = f_fcn;
0168     f_fcn = p.f_fcn;
0169     x0 = p.x0;
0170     nx = size(x0, 1);       %% number of optimization variables
0171     if isfield(p, 'opt'),       opt = p.opt;            else,   opt = [];       end
0172     if isfield(p, 'hess_fcn'),  hess_fcn = p.hess_fcn;  else,   hess_fcn = '';  end
0173     if isfield(p, 'gh_fcn'),    gh_fcn = p.gh_fcn;      else,   gh_fcn = '';    end
0174     if isfield(p, 'xmax'),      xmax = p.xmax;          else,   xmax = [];      end
0175     if isfield(p, 'xmin'),      xmin = p.xmin;          else,   xmin = [];      end
0176     if isfield(p, 'u'),         u = p.u;                else,   u = [];         end
0177     if isfield(p, 'l'),         l = p.l;                else,   l = [];         end
0178     if isfield(p, 'A'),         A = p.A;                else,   A=sparse(0,nx); end
0179 else                                    %% individual args
0180     nx = size(x0, 1);       %% number of optimization variables
0181     if nargin < 10
0182         opt = [];
0183         if nargin < 9
0184             hess_fcn = '';
0185             if nargin < 8
0186                 gh_fcn = '';
0187                 if nargin < 7
0188                     xmax = [];
0189                     if nargin < 6
0190                         xmin = [];
0191                         if nargin < 5
0192                             u = [];
0193                             if nargin < 4
0194                                 l = [];
0195                                 A = sparse(0,nx);
0196                             end
0197                         end
0198                     end
0199                 end
0200             end
0201         end
0202     end
0203 end
0204 
0205 %% set default argument values if missing
0206 if isempty(A) || (~isempty(A) && (isempty(l) || all(l == -Inf)) && ...
0207                                  (isempty(u) || all(u == Inf)))
0208     A = sparse(0,nx);           %% no limits => no linear constraints
0209 end
0210 nA = size(A, 1);                %% number of original linear constraints
0211 if isempty(u)                   %% By default, linear inequalities are ...
0212     u = Inf(nA, 1);             %% ... unbounded above and ...
0213 end
0214 if isempty(l)
0215     l = -Inf(nA, 1);            %% ... unbounded below.
0216 end
0217 if isempty(xmin)                %% By default, optimization variables are ...
0218     xmin = -Inf(nx, 1);         %% ... unbounded below and ...
0219 end
0220 if isempty(xmax)
0221     xmax = Inf(nx, 1);          %% ... unbounded above.
0222 end
0223 if isempty(gh_fcn)
0224     nonlinear = false;          %% no nonlinear constraints present
0225 else
0226     nonlinear = true;           %% we have some nonlinear constraints
0227 end
0228 
0229 %% default options
0230 if ~isempty(opt) && isfield(opt, 'verbose') && ~isempty(opt.verbose)
0231     verbose = opt.verbose;
0232 else
0233     verbose = 0;
0234 end
0235 
0236 %% split l <= A*x <= u into less than, equal to, greater than, and
0237 %% doubly-bounded sets
0238 ieq = find( abs(u-l) <= eps );          %% equality
0239 igt = find( u >=  1e10 & l > -1e10 );   %% greater than, unbounded above
0240 ilt = find( l <= -1e10 & u <  1e10 );   %% less than, unbounded below
0241 ibx = find( (abs(u-l) > eps) & (u < 1e10) & (l > -1e10) );
0242 Af  = [ A(ilt, :); -A(igt, :); A(ibx, :); -A(ibx, :) ];
0243 bf  = [ u(ilt);   -l(igt);     u(ibx);    -l(ibx)];
0244 Afeq = A(ieq, :);
0245 bfeq = u(ieq);
0246 
0247 %%-----  set up problem  -----
0248 %% build Jacobian and Hessian structure
0249 randx = rand(size(x0));
0250 nonz = 1e-20;
0251 if nonlinear
0252     [h, g, dhs, dgs] = gh_fcn(randx);
0253     if issparse(dhs)
0254         dhs(dhs ~= 0) = nonz;   %% set non-zero entries to tiny value (for adding later)
0255         dgs(dgs ~= 0) = nonz;   %% set non-zero entries to tiny value (for adding later)
0256         Js = [dhs'; dgs'];
0257     else
0258         dhs = []; dgs = [];
0259         Js = [];
0260     end
0261 else
0262     g = []; h = [];
0263     dhs = []; dgs = dhs; Js = dhs;
0264 end
0265 neq = length(g);
0266 niq = length(h);
0267 if isempty(hess_fcn)
0268     [f_, df_, Hs] = f_fcn(randx);   %% cost
0269 else
0270     lam = struct('eqnonlin', rand(neq, 1), 'ineqnonlin', rand(niq, 1));
0271     Hs = hess_fcn(randx, lam, 1);
0272 end
0273 if issparse(Hs)
0274     Hs(Hs ~= 0) = nonz;     %% set non-zero entries to tiny value (for adding later)
0275 else
0276     Hs = [];
0277 end
0278 
0279 %% function definitions
0280 ktr_gh_fcn   = @(x)constraints(x, gh_fcn, dgs, dhs);
0281 ktr_hess_fcn = @(x, lambda)hessian(x, lambda, f_fcn, hess_fcn, Hs);
0282 
0283 %% basic optimset options needed for ktrlink
0284 if isfield(opt, 'knitro_opt')
0285     knitro_opt = opt.knitro_opt;
0286 else
0287     knitro_opt = struct();
0288 end
0289 kopts = struct();
0290 kopts.GradObj = 'on';
0291 kopts.GradConstr = 'on';
0292 kopts.HessFcn = ktr_hess_fcn;
0293 kopts.Hessian = 'user-supplied';
0294 if issparse(Js)
0295     kopts.JacobPattern = Js;
0296 end
0297 if issparse(Hs)
0298     kopts.HessPattern = Hs;
0299 end
0300 
0301 if use_ktropts_file
0302     if isfield(knitro_opt, 'opt_fname') && ~isempty(knitro_opt.opt_fname)
0303         opt_fname = knitro_opt.opt_fname;
0304     elseif isfield(knitro_opt, 'opt') && knitro_opt.opt
0305         opt_fname = sprintf('knitro_user_options_%d.txt', knitro_opt.opt);
0306     else
0307         %% create ktropts file
0308         ktropts.algorithm           = 1;
0309         ktropts.bar_directinterval  = 0;
0310         ktropts.outlev              = verbose;
0311         if isfield(knitro_opt, 'opts')  %% raw Knitro options for options file
0312             ktropts = nested_struct_copy(ktropts, knitro_opt.opts);
0313         end
0314         if isfield(knitro_opt, 'tol_x') && ~isempty(knitro_opt.tol_x)
0315             ktropts.xtol = knitro_opt.tol_x;
0316         end
0317         if isfield(knitro_opt, 'tol_f') && ~isempty(knitro_opt.tol_f)
0318             ktropts.opttol = knitro_opt.tol_f;
0319         end
0320         if isfield(knitro_opt, 'maxit') && knitro_opt.maxit ~= 0
0321             ktropts.maxit = knitro_opt.maxit;
0322         end
0323 
0324         opt_fname = write_ktropts(ktropts);
0325         create_ktropts_file = 1;    %% make a note that I created it
0326     end
0327 else
0328     if isfield(knitro_opt, 'opts')  %% raw Knitro options for optimset()
0329         kopts = nested_struct_copy(kopts, knitro_opt.opts);
0330     end
0331     kopts.Algorithm = 'interior-point';
0332     if isfield(knitro_opt, 'tol_x') && ~isempty(knitro_opt.tol_x)
0333         kopts.TolX = knitro_opt.tol_x;
0334     end
0335     if isfield(knitro_opt, 'tol_f') && ~isempty(knitro_opt.tol_f)
0336         kopts.TolFun = knitro_opt.tol_f;
0337     end
0338     if isfield(knitro_opt, 'maxit') && knitro_opt.maxit ~= 0
0339         kopts.MaxIter = knitro_opt.maxit;
0340         kopts.MaxFunEvals = 4 * knitro_opt.maxit;
0341     end
0342     if verbose > 1
0343         kopts.Display = 'iter';
0344     elseif verbose == 1
0345         kopts.Display = 'final';
0346     else
0347         kopts.Display = 'off';
0348     end
0349     opt_fname = [];
0350 end
0351 fmoptions = optimset(kopts);
0352 
0353 %%-----  run solver  -----
0354 if have_feature('knitromatlab')
0355     [x, f, eflag, output, Lambda] = knitromatlab(f_fcn, x0, Af, bf, Afeq, bfeq, ...
0356                                     xmin, xmax, ktr_gh_fcn, [], fmoptions, opt_fname);
0357 else
0358     [x, f, eflag, output, Lambda] = ktrlink(f_fcn, x0, Af, bf, Afeq, bfeq, ...
0359                                     xmin, xmax, ktr_gh_fcn, fmoptions, opt_fname);
0360 end
0361 success = (eflag == 0);
0362 if success
0363     eflag = 1;      %% success is 1 (not zero), all other values are Knitro return codes
0364 end
0365 
0366 %% delete ktropts file
0367 if create_ktropts_file  %% ... but only if I created it
0368     delete(opt_fname);
0369 end
0370 
0371 %% fix Lambdas
0372 %% (shadow prices on equality variable bounds can come back on wrong limit)
0373 kl = find(Lambda.lower > 0 & Lambda.upper == 0);
0374 Lambda.upper(kl) = Lambda.lower(kl);
0375 Lambda.lower(kl) = 0;
0376 ku = find(Lambda.upper < 0 & Lambda.lower == 0);
0377 Lambda.lower(ku) = Lambda.upper(ku);
0378 Lambda.upper(ku) = 0;
0379 
0380 %% package up results
0381 nlt = length(ilt);
0382 ngt = length(igt);
0383 nbx = length(ibx);
0384 
0385 %% extract multipliers for linear constraints
0386 kl = find(Lambda.eqlin < 0);
0387 ku = find(Lambda.eqlin > 0);
0388 
0389 mu_l = zeros(size(u));
0390 mu_l(ieq(kl)) = -Lambda.eqlin(kl);
0391 mu_l(igt) = Lambda.ineqlin(nlt+(1:ngt));
0392 mu_l(ibx) = Lambda.ineqlin(nlt+ngt+nbx+(1:nbx));
0393 
0394 mu_u = zeros(size(u));
0395 mu_u(ieq(ku)) = Lambda.eqlin(ku);
0396 mu_u(ilt) = Lambda.ineqlin(1:nlt);
0397 mu_u(ibx) = Lambda.ineqlin(nlt+ngt+(1:nbx));
0398 
0399 lambda = struct( ...
0400     'lower', -Lambda.lower, ...
0401     'upper', Lambda.upper, ...
0402     'eqnonlin', Lambda.eqnonlin, ...
0403     'ineqnonlin', Lambda.ineqnonlin, ...
0404     'mu_l', mu_l, ...
0405     'mu_u', mu_u );
0406 
0407 
0408 %-----  callback functions  -----
0409 function [h, g, dh, dg] = constraints(x, gh_fcn, dgs, dhs)
0410 if isempty(gh_fcn)
0411     nx = length(x);
0412     h = []; g = h; dh = sparse(0, nx); dg = dh;
0413 else
0414     [h, g, dh, dg] = gh_fcn(x);
0415     %% add sparse structure (with tiny values) to current matrices to
0416     %% ensure that sparsity structure matches that supplied
0417     if issparse(dh)
0418         dg = dg + dgs;
0419         dh = dh + dhs;
0420     end
0421 end
0422 
0423 function H = hessian(x, lambda, f_fcn, hess_fcn, Hs)
0424 if isempty(hess_fcn)
0425     [f_, df_, H] = f_fcn(x);      %% cost
0426 else
0427     %% add sparse structure (with tiny values) to current matrices to
0428     %% ensure that sparsity structure matches that supplied
0429     H = hess_fcn(x, lambda, 1);
0430     if issparse(H)
0431         H = H + Hs;
0432     end
0433 end
0434 
0435 %%-----  write_ktropts  -----
0436 function fname = write_ktropts(ktropts)
0437 
0438 %% generate file name
0439 fname = sprintf('ktropts_%06d.txt', fix(1e6*rand));
0440 
0441 %% open file
0442 [fd, msg] = fopen(fname, 'wt');     %% write options file
0443 if fd == -1
0444     error('could not create %d : %s', fname, msg);
0445 end
0446 
0447 %% write options
0448 fields = fieldnames(ktropts);
0449 for k = 1:length(fields)
0450     fprintf(fd, '%s %g\n', fields{k}, ktropts.(fields{k}));
0451 end
0452 
0453 %% close file
0454 if fd ~= 1
0455     fclose(fd);
0456 end

Generated on Fri 09-Oct-2020 11:21:31 by m2html © 2005