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-2015 by Power System Engineering Research Center (PSERC) 0039 % by Ray Zimmerman, PSERC Cornell 0040 % 0041 % $Id: add_constraints.m 2644 2015-03-11 19:34:22Z ray $ 0042 % 0043 % This file is part of MATPOWER. 0044 % Covered by the 3-clause BSD License (see LICENSE file for details). 0045 % See http://www.pserc.cornell.edu/matpower/ for more info. 0046 0047 nonlin = 0; 0048 if iscell(idx) 0049 if ~isempty(varargin) %% linear: indexed named set 0050 % (calls to substruct() are relatively expensive ... 0051 % s1 = substruct('.', name, '()', idx); 0052 % s2 = substruct('.', name, '{}', idx); 0053 % ... so replace them with these more efficient lines) 0054 s1 = struct('type', {'.', '()'}, 'subs', {name, idx}); 0055 s2 = s1; 0056 s2(2).type = '{}'; 0057 0058 %% prevent duplicate named constraint sets 0059 if subsref(om.lin.idx.i1, s1) ~= 0 0060 str = '%d'; for m = 2:length(idx), str = [str ',%d']; end 0061 nname = sprintf(['%s(' str, ')'], name, idx{:}); 0062 error('@opt_model/add_constraints: linear constraint set named ''%s'' already exists', nname); 0063 end 0064 0065 A = varargin{1}; 0066 args = varargin(2:end); 0067 else %% linear: just setting dimensions for indexed set 0068 %% prevent duplicate named constraint sets 0069 if isfield(om.lin.idx.N, name) 0070 error('@opt_model/add_constraints: linear constraint set named ''%s'' already exists', name); 0071 end 0072 0073 A = sparse(0,0); 0074 args = {}; 0075 end 0076 else 0077 if length(varargin) == 1 %% non-linear 0078 %% prevent duplicate named constraint sets 0079 if isfield(om.nln.idx.N, name) 0080 error('@opt_model/add_constraints: nonlinear constraint set named ''%s'' already exists', name); 0081 end 0082 0083 nonlin = 1; 0084 N = idx; 0085 args = {}; 0086 else %% linear: simple named set 0087 %% prevent duplicate named constraint sets 0088 if isfield(om.lin.idx.N, name) 0089 error('@opt_model/add_constraints: linear constraint set named ''%s'' already exists', name); 0090 end 0091 0092 A = idx; 0093 args = varargin; 0094 end 0095 idx = {}; 0096 end 0097 nargs = length(args); 0098 0099 if nonlin %% nonlinear 0100 %% add info about this nonlinear constraint set 0101 om.nln.idx.i1.(name) = om.nln.N + 1; %% starting index 0102 om.nln.idx.iN.(name) = om.nln.N + N; %% ending index 0103 om.nln.idx.N.(name) = N; %% number of constraints 0104 0105 %% update number of nonlinear constraints and constraint sets 0106 om.nln.N = om.nln.idx.iN.(name); 0107 om.nln.NS = om.nln.NS + 1; 0108 0109 %% add to ordered list of nonlinear constraint sets 0110 om.nln.order(om.nln.NS).name = name; 0111 om.nln.order(om.nln.NS).idx = {}; 0112 elseif nargs == 0 %% linear: just setting dimensions for indexed set 0113 %% add info about this linear constraint set 0114 om.lin.idx.i1.(name) = zeros(idx{:}); %% starting index 0115 om.lin.idx.iN.(name) = zeros(idx{:}); %% ending index 0116 om.lin.idx.N.(name) = zeros(idx{:}); %% number of constraints 0117 om.lin.data.A.(name) = cell(idx{:}); 0118 om.lin.data.l.(name) = cell(idx{:}); 0119 om.lin.data.u.(name) = cell(idx{:}); 0120 om.lin.data.vs.(name) = cell(idx{:}); 0121 else %% linear 0122 if nargs >= 3 0123 [l, u, varsets] = deal(args{1:3}); 0124 else 0125 varsets = {}; 0126 if nargs >= 2 0127 [l, u] = deal(args{1:2}); 0128 else 0129 u = []; 0130 if nargs >= 1 0131 l = args{1}; 0132 else 0133 l = []; 0134 end 0135 end 0136 end 0137 0138 [N, M] = size(A); 0139 if isempty(l) %% default l is -Inf 0140 l = -Inf(N, 1); 0141 end 0142 if isempty(u) %% default u is Inf 0143 u = Inf(N, 1); 0144 end 0145 if ~isempty(varsets) && iscell(varsets) 0146 empty_cells = cell(1, length(varsets)); 0147 [empty_cells{:}] = deal({}); %% empty cell arrays 0148 varsets = struct('name', varsets, 'idx', empty_cells); 0149 end 0150 0151 %% check sizes 0152 if size(l, 1) ~= N || size(u, 1) ~= N 0153 error('@opt_model/add_constraints: sizes of A, l and u must match'); 0154 end 0155 if isempty(varsets) 0156 nv = om.var.N; 0157 else 0158 nv = 0; 0159 s = struct('type', {'.', '()'}, 'subs', {'', 1}); 0160 for k = 1:length(varsets) 0161 % (calls to substruct() are relatively expensive ... 0162 % s = substruct('.', varsets(k).name, '()', varsets(k).idx); 0163 % ... so replace it with these more efficient lines) 0164 s(1).subs = varsets(k).name; 0165 s(2).subs = varsets(k).idx; 0166 nv = nv + subsref(om.var.idx.N, s); 0167 end 0168 end 0169 if M ~= nv 0170 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); 0171 end 0172 if isempty(idx) %% linear: simple named set 0173 %% add info about this linear constraint set 0174 om.lin.idx.i1.(name) = om.lin.N + 1; %% starting index 0175 om.lin.idx.iN.(name) = om.lin.N + N; %% ending index 0176 om.lin.idx.N.(name) = N; %% number of constraints 0177 om.lin.data.A.(name) = A; 0178 om.lin.data.l.(name) = l; 0179 om.lin.data.u.(name) = u; 0180 om.lin.data.vs.(name) = varsets; 0181 0182 %% update number of linear constraints and constraint sets 0183 om.lin.N = om.lin.idx.iN.(name); 0184 om.lin.NS = om.lin.NS + 1; 0185 0186 %% add to ordered list of linear constraint sets 0187 om.lin.order(om.lin.NS).name = name; 0188 om.lin.order(om.lin.NS).idx = {}; 0189 else %% linear: indexed named set 0190 %% add info about this linear constraint set 0191 om.lin.idx.i1 = subsasgn(om.lin.idx.i1, s1, om.lin.N + 1); %% starting index 0192 om.lin.idx.iN = subsasgn(om.lin.idx.iN, s1, om.lin.N + N); %% ending index 0193 om.lin.idx.N = subsasgn(om.lin.idx.N, s1, N); %% number of constraints 0194 om.lin.data.A = subsasgn(om.lin.data.A, s2, A); 0195 om.lin.data.l = subsasgn(om.lin.data.l, s2, l); 0196 om.lin.data.u = subsasgn(om.lin.data.u, s2, u); 0197 om.lin.data.vs = subsasgn(om.lin.data.vs, s2, varsets); 0198 0199 %% update number of linear constraints and constraint sets 0200 om.lin.N = subsref(om.lin.idx.iN, s1); 0201 om.lin.NS = om.lin.NS + 1; 0202 0203 %% add to ordered list of linear constraint sets 0204 om.lin.order(om.lin.NS).name = name; 0205 om.lin.order(om.lin.NS).idx = idx; 0206 end 0207 end