EVAL_NLN_CONSTRAINT Builds and returns full set of nonlinear constraints. G = OM.EVAL_NLN_CONSTRAINT(X, ISEQ) G = OM.EVAL_NLN_CONSTRAINT(X, ISEQ, NAME) G = OM.EVAL_NLN_CONSTRAINT(X, ISEQ, NAME, IDX_LIST) [G, DG] = OM.EVAL_NLN_CONSTRAINT(...) Builds the nonlinear equality or inequality constraints (ISEQ equal to 1 or 0, respectively) and optionally their gradients for the full set of constraints or an individual named subset for a given value of the vector X, based on constraints added by ADD_NLN_CONSTRAINT. g(X) = 0 h(X) <= 0 Example: [g, dg] = om.eval_nln_constraint(x, 1) [h, dh] = om.eval_nln_constraint(x, 0) See also OPT_MODEL, ADD_NLN_CONSTRAINT, EVAL_NLN_CONSTRAINT_HESS.
0001 function [g, dg] = eval_nln_constraint(om, x, iseq, name, idx) 0002 %EVAL_NLN_CONSTRAINT Builds and returns full set of nonlinear constraints. 0003 % G = OM.EVAL_NLN_CONSTRAINT(X, ISEQ) 0004 % G = OM.EVAL_NLN_CONSTRAINT(X, ISEQ, NAME) 0005 % G = OM.EVAL_NLN_CONSTRAINT(X, ISEQ, NAME, IDX_LIST) 0006 % [G, DG] = OM.EVAL_NLN_CONSTRAINT(...) 0007 % Builds the nonlinear equality or inequality constraints (ISEQ equal to 0008 % 1 or 0, respectively) and optionally their gradients for the full set 0009 % of constraints or an individual named subset for a given value of the 0010 % vector X, based on constraints added by ADD_NLN_CONSTRAINT. 0011 % 0012 % g(X) = 0 0013 % h(X) <= 0 0014 % 0015 % Example: 0016 % [g, dg] = om.eval_nln_constraint(x, 1) 0017 % [h, dh] = om.eval_nln_constraint(x, 0) 0018 % 0019 % See also OPT_MODEL, ADD_NLN_CONSTRAINT, EVAL_NLN_CONSTRAINT_HESS. 0020 0021 % MP-Opt-Model 0022 % Copyright (c) 2008-2020, Power Systems Engineering Research Center (PSERC) 0023 % by Ray Zimmerman, PSERC Cornell 0024 % 0025 % This file is part of MP-Opt-Model. 0026 % Covered by the 3-clause BSD License (see LICENSE file for details). 0027 % See https://github.com/MATPOWER/mp-opt-model for more info. 0028 0029 %% initialize 0030 if nargin < 5 0031 idx = {}; 0032 end 0033 0034 %% get constraint type 0035 if iseq %% equality constraints 0036 om_nlx = om.nle; 0037 else %% inequality constraints 0038 om_nlx = om.nli; 0039 end 0040 0041 if nargin < 4 %% full set 0042 %% initialize g, dg 0043 g = NaN(om_nlx.N, 1); 0044 if nargout > 1 0045 dg = sparse(0, om.var.N); %% build gradient by stacking 0046 end 0047 0048 %% calls to substruct() are relatively expensive, so we pre-build the 0049 %% structs for addressing cell and numeric array fields, updating only 0050 %% the subscripts before use 0051 sc = struct('type', {'.', '{}'}, 'subs', {'', 1}); %% cell array field 0052 sn = sc; sn(2).type = '()'; %% num array field 0053 0054 %% fill in each piece 0055 for k = 1:om_nlx.NS 0056 name = om_nlx.order(k).name; 0057 idx = om_nlx.order(k).idx; 0058 if isempty(idx) 0059 if ~isfield(om_nlx.data.fcn, name) 0060 continue; %% skip, there is no function handle stored here, 0061 %% the function value for this named set was included 0062 %% in the value computed by a previous named set 0063 end 0064 N = om_nlx.idx.N.(name); %% number of constraint functions 0065 %% evaluated for this named set 0066 if isfield(om_nlx.data.include, name) 0067 N = N + sum(om_nlx.data.include.(name).N); 0068 end 0069 else 0070 % (calls to substruct() are relatively expensive ... 0071 % sn = substruct('.', name, '()', idx); 0072 % sc = substruct('.', name, '{}', idx); 0073 % ... so replace them with these more efficient lines) 0074 sn(1).subs = name; 0075 sn(2).subs = idx; 0076 sc(1).subs = name; 0077 sc(2).subs = idx; 0078 N = subsref(om_nlx.idx.N, sn); 0079 end 0080 if N %% non-zero number of rows 0081 if isempty(idx) 0082 fcn = om_nlx.data.fcn.(name); %% fcn for kth constraint set 0083 i1 = om_nlx.idx.i1.(name); %% starting row index 0084 iN = i1 + N - 1; %% ending row index 0085 vs = om_nlx.data.vs.(name); %% var sets 0086 else 0087 fcn = subsref(om_nlx.data.fcn, sc); %% fcn for kth constraint set 0088 i1 = subsref(om_nlx.idx.i1, sn); %% starting row index 0089 iN = subsref(om_nlx.idx.iN, sn); %% ending row index 0090 vs = subsref(om_nlx.data.vs, sc); %% var sets 0091 end 0092 xx = om.varsets_x(x, vs); 0093 if nargout < 2 0094 gk = fcn(xx); %% evaluate kth constraint w/o gradient 0095 else 0096 [gk, dgk] = fcn(xx); %% evaluate kth constraint and gradient 0097 0098 if isempty(vs) %% all rows of x 0099 if size(dgk, 2) == om.var.N 0100 dg = [dg; dgk]; 0101 else %% must have added vars since adding 0102 %% this constraint set 0103 dg(i1:iN, 1:size(dgk, 2)) = dgk; 0104 end 0105 else %% selected rows of x 0106 jj = om.varsets_idx(vs); %% column indices for var set 0107 dgi = sparse(N, om.var.N); 0108 dgi(:, jj) = dgk; 0109 dg = [dg; dgi]; 0110 end 0111 end 0112 g(i1:iN) = gk; %% assign kth constraint 0113 end 0114 end 0115 else %% individual named set 0116 if isempty(idx) && prod(size(om_nlx.idx.i1.(name))) ~= 1 0117 error('@opt_model/eval_nln_constraint: nonlinear constraint set ''%s'' requires an IDX_LIST arg', name) 0118 end 0119 [N, fcn, hess, vs] = om.params_nln_constraint(iseq, name, idx); 0120 xx = om.varsets_x(x, vs); 0121 if nargout < 2 0122 g = fcn(xx); 0123 else 0124 [g, dg] = fcn(xx); 0125 end 0126 end