ADD_CONSTRAINTS Adds a set of constraints to the model. OM = ADD_CONSTRAINTS(OM, NAME, A, L, U); OM = ADD_CONSTRAINTS(OM, NAME, A, L, U, VARSETS); OM = ADD_CONSTRAINTS(OM, NAME, DIM_LIST); OM = ADD_CONSTRAINTS(OM, NAME, IDX_LIST, A, L, U); OM = ADD_CONSTRAINTS(OM, NAME, IDX_LIST, A, L, U, VARSETS); OM = ADD_CONSTRAINTS(OM, NAME, N, 'NON-LINEAR'); Linear constraints are of the form L <= A * x <= U, where x is a vector made of of the vars specified in VARSETS (in the order given). This allows the A matrix to be defined only in terms of the relevant variables without the need to manually create a lot of zero columns. If VARSETS is empty, x is taken to be the full vector of all optimization variables. If L or U are empty, they are assumed to be appropriately sized vectors of -Inf and Inf, respectively. For nonlinear constraints, the 3rd argument, N, is the number of constraints in the set. Currently, this is used internally by MATPOWER, but there is no way for the user to specify additional nonlinear constraints. Examples: om = add_constraints(om, 'vl', Avl, lvl, uvl, {'Pg', 'Qg'}); om = add_constraints(om, 'Pmis', nb, 'nonlinear'); om = add_constraints(om, 'R', {2, 3}); for i = 1:2 for j = 1:3 om = add_constraints(om, 'R', {i, j}, A{i,j}, ...); end end See also OPT_MODEL, LINEAR_CONSTRAINTS.
0001 function om = add_constraints(om, name, idx, varargin) 0002 %ADD_CONSTRAINTS Adds a set of constraints to the model. 0003 % OM = ADD_CONSTRAINTS(OM, NAME, A, L, U); 0004 % OM = ADD_CONSTRAINTS(OM, NAME, A, L, U, VARSETS); 0005 % OM = ADD_CONSTRAINTS(OM, NAME, DIM_LIST); 0006 % OM = ADD_CONSTRAINTS(OM, NAME, IDX_LIST, A, L, U); 0007 % OM = ADD_CONSTRAINTS(OM, NAME, IDX_LIST, A, L, U, VARSETS); 0008 % OM = ADD_CONSTRAINTS(OM, NAME, N, 'NON-LINEAR'); 0009 % 0010 % Linear constraints are of the form L <= A * x <= U, where 0011 % x is a vector made of of the vars specified in VARSETS (in 0012 % the order given). This allows the A matrix to be defined only 0013 % in terms of the relevant variables without the need to manually 0014 % create a lot of zero columns. If VARSETS is empty, x is taken 0015 % to be the full vector of all optimization variables. If L or 0016 % U are empty, they are assumed to be appropriately sized vectors 0017 % of -Inf and Inf, respectively. 0018 % 0019 % For nonlinear constraints, the 3rd argument, N, is the number 0020 % of constraints in the set. Currently, this is used internally 0021 % by MATPOWER, but there is no way for the user to specify 0022 % additional nonlinear constraints. 0023 % 0024 % Examples: 0025 % om = add_constraints(om, 'vl', Avl, lvl, uvl, {'Pg', 'Qg'}); 0026 % om = add_constraints(om, 'Pmis', nb, 'nonlinear'); 0027 % 0028 % om = add_constraints(om, 'R', {2, 3}); 0029 % for i = 1:2 0030 % for j = 1:3 0031 % om = add_constraints(om, 'R', {i, j}, A{i,j}, ...); 0032 % end 0033 % end 0034 % 0035 % See also OPT_MODEL, LINEAR_CONSTRAINTS. 0036 0037 % MATPOWER 0038 % Copyright (c) 2008-2016, Power Systems Engineering Research Center (PSERC) 0039 % by Ray Zimmerman, PSERC Cornell 0040 % 0041 % This file is part of MATPOWER. 0042 % Covered by the 3-clause BSD License (see LICENSE file for details). 0043 % See http://www.pserc.cornell.edu/matpower/ for more info. 0044 0045 nonlin = 0; 0046 if iscell(idx) 0047 if ~isempty(varargin) %% linear: indexed named set 0048 % (calls to substruct() are relatively expensive ... 0049 % s1 = substruct('.', name, '()', idx); 0050 % s2 = substruct('.', name, '{}', idx); 0051 % ... so replace them with these more efficient lines) 0052 s1 = struct('type', {'.', '()'}, 'subs', {name, idx}); 0053 s2 = s1; 0054 s2(2).type = '{}'; 0055 0056 %% prevent duplicate named constraint sets 0057 if subsref(om.lin.idx.i1, s1) ~= 0 0058 str = '%d'; for m = 2:length(idx), str = [str ',%d']; end 0059 nname = sprintf(['%s(' str, ')'], name, idx{:}); 0060 error('@opt_model/add_constraints: linear constraint set named ''%s'' already exists', nname); 0061 end 0062 0063 A = varargin{1}; 0064 args = varargin(2:end); 0065 else %% linear: just setting dimensions for indexed set 0066 %% prevent duplicate named constraint sets 0067 if isfield(om.lin.idx.N, name) 0068 error('@opt_model/add_constraints: linear constraint set named ''%s'' already exists', name); 0069 end 0070 0071 A = sparse(0,0); 0072 args = {}; 0073 end 0074 else 0075 if length(varargin) == 1 %% non-linear 0076 %% prevent duplicate named constraint sets 0077 if isfield(om.nln.idx.N, name) 0078 error('@opt_model/add_constraints: nonlinear constraint set named ''%s'' already exists', name); 0079 end 0080 0081 nonlin = 1; 0082 N = idx; 0083 args = {}; 0084 else %% linear: simple named set 0085 %% prevent duplicate named constraint sets 0086 if isfield(om.lin.idx.N, name) 0087 error('@opt_model/add_constraints: linear constraint set named ''%s'' already exists', name); 0088 end 0089 0090 A = idx; 0091 args = varargin; 0092 end 0093 idx = {}; 0094 end 0095 nargs = length(args); 0096 0097 if nonlin %% nonlinear 0098 %% add info about this nonlinear constraint set 0099 om.nln.idx.i1.(name) = om.nln.N + 1; %% starting index 0100 om.nln.idx.iN.(name) = om.nln.N + N; %% ending index 0101 om.nln.idx.N.(name) = N; %% number of constraints 0102 0103 %% update number of nonlinear constraints and constraint sets 0104 om.nln.N = om.nln.idx.iN.(name); 0105 om.nln.NS = om.nln.NS + 1; 0106 0107 %% add to ordered list of nonlinear constraint sets 0108 om.nln.order(om.nln.NS).name = name; 0109 om.nln.order(om.nln.NS).idx = {}; 0110 elseif nargs == 0 %% linear: just setting dimensions for indexed set 0111 %% use column vector if single dimension 0112 if length(idx) == 1 0113 idx = {idx{:}, 1}; 0114 end 0115 0116 %% add info about this linear constraint set 0117 om.lin.idx.i1.(name) = zeros(idx{:}); %% starting index 0118 om.lin.idx.iN.(name) = zeros(idx{:}); %% ending index 0119 om.lin.idx.N.(name) = zeros(idx{:}); %% number of constraints 0120 om.lin.data.A.(name) = cell(idx{:}); 0121 om.lin.data.l.(name) = cell(idx{:}); 0122 om.lin.data.u.(name) = cell(idx{:}); 0123 om.lin.data.vs.(name) = cell(idx{:}); 0124 else %% linear 0125 if nargs >= 3 0126 [l, u, varsets] = deal(args{1:3}); 0127 else 0128 varsets = {}; 0129 if nargs >= 2 0130 [l, u] = deal(args{1:2}); 0131 else 0132 u = []; 0133 if nargs >= 1 0134 l = args{1}; 0135 else 0136 l = []; 0137 end 0138 end 0139 end 0140 0141 [N, M] = size(A); 0142 if isempty(l) %% default l is -Inf 0143 l = -Inf(N, 1); 0144 end 0145 if isempty(u) %% default u is Inf 0146 u = Inf(N, 1); 0147 end 0148 if ~isempty(varsets) && iscell(varsets) 0149 empty_cells = cell(1, length(varsets)); 0150 [empty_cells{:}] = deal({}); %% empty cell arrays 0151 varsets = struct('name', varsets, 'idx', empty_cells); 0152 end 0153 0154 %% check sizes 0155 if size(l, 1) ~= N || size(u, 1) ~= N 0156 error('@opt_model/add_constraints: sizes of A, l and u must match'); 0157 end 0158 if isempty(varsets) 0159 nv = om.var.N; 0160 else 0161 nv = 0; 0162 s = struct('type', {'.', '()'}, 'subs', {'', 1}); 0163 for k = 1:length(varsets) 0164 % (calls to substruct() are relatively expensive ... 0165 % s = substruct('.', varsets(k).name, '()', varsets(k).idx); 0166 % ... so replace it with these more efficient lines) 0167 s(1).subs = varsets(k).name; 0168 s(2).subs = varsets(k).idx; 0169 nv = nv + subsref(om.var.idx.N, s); 0170 end 0171 end 0172 if M ~= nv 0173 error('@opt_model/add_constraints: number of columns of A does not match\nnumber of variables, A is %d x %d, nv = %d\n', N, M, nv); 0174 end 0175 if isempty(idx) %% linear: simple named set 0176 %% add info about this linear constraint set 0177 om.lin.idx.i1.(name) = om.lin.N + 1; %% starting index 0178 om.lin.idx.iN.(name) = om.lin.N + N; %% ending index 0179 om.lin.idx.N.(name) = N; %% number of constraints 0180 om.lin.data.A.(name) = A; 0181 om.lin.data.l.(name) = l; 0182 om.lin.data.u.(name) = u; 0183 om.lin.data.vs.(name) = varsets; 0184 0185 %% update number of linear constraints and constraint sets 0186 om.lin.N = om.lin.idx.iN.(name); 0187 om.lin.NS = om.lin.NS + 1; 0188 0189 %% add to ordered list of linear constraint sets 0190 om.lin.order(om.lin.NS).name = name; 0191 om.lin.order(om.lin.NS).idx = {}; 0192 else %% linear: indexed named set 0193 %% add info about this linear constraint set 0194 om.lin.idx.i1 = subsasgn(om.lin.idx.i1, s1, om.lin.N + 1); %% starting index 0195 om.lin.idx.iN = subsasgn(om.lin.idx.iN, s1, om.lin.N + N); %% ending index 0196 om.lin.idx.N = subsasgn(om.lin.idx.N, s1, N); %% number of constraints 0197 om.lin.data.A = subsasgn(om.lin.data.A, s2, A); 0198 om.lin.data.l = subsasgn(om.lin.data.l, s2, l); 0199 om.lin.data.u = subsasgn(om.lin.data.u, s2, u); 0200 om.lin.data.vs = subsasgn(om.lin.data.vs, s2, varsets); 0201 0202 %% update number of linear constraints and constraint sets 0203 om.lin.N = subsref(om.lin.idx.iN, s1); 0204 om.lin.NS = om.lin.NS + 1; 0205 0206 %% add to ordered list of linear constraint sets 0207 om.lin.order(om.lin.NS).name = name; 0208 om.lin.order(om.lin.NS).idx = idx; 0209 end 0210 end