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