PARAMS_LEGACY_COST Returns cost parameters for legacy user-defined costs. CP = OM.PARAMS_LEGACY_COST() CP = OM.PARAMS_LEGACY_COST(NAME) CP = OM.PARAMS_LEGACY_COST(NAME, IDX) [CP, VS] = OM.PARAMS_LEGACY_COST(...) [CP, VS, I1, IN] = OM.PARAMS_LEGACY_COST(...) With no input parameters, it assembles and returns the parameters for the aggregate legacy user-defined cost from all legacy cost sets added using ADD_LEGACY_COST. The values of these parameters are cached for subsequent calls. The parameters are contained in the struct CP, described below. If a NAME is provided then it simply returns parameter struct CP for the corresponding named set. Likewise for indexed named sets specified by NAME and IDX. An optional 2nd output argument VS indicates the variable sets used by this cost set. The size of CP.N will be consistent with VS. If NAME is provided, optional 3rd and 4th output arguments I1 and IN indicate the starting and ending row indices of the corresponding cost set in the full aggregate cost matrix CP.N. Let X refer to the vector formed by combining the corresponding varsets VS, and F_U(X, CP) be the cost at X corresponding to the cost parameters contained in CP, where CP is a struct with the following fields: N - nw x nx sparse matrix (optional, identity matrix by default) Cw - nw x 1 vector H - nw x nw sparse matrix (optional, all zeros by default) dd, mm - nw x 1 vectors (optional, all ones by default) rh, kk - nw x 1 vectors (optional, all zeros by default) These parameters are used as follows to compute F_U(X, CP) R = N*X - rh / kk(i), R(i) < -kk(i) K(i) = < 0, -kk(i) <= R(i) <= kk(i) \ -kk(i), R(i) > kk(i) RR = R + K U(i) = / 0, -kk(i) <= R(i) <= kk(i) \ 1, otherwise DDL(i) = / 1, dd(i) = 1 \ 0, otherwise DDQ(i) = / 1, dd(i) = 2 \ 0, otherwise Dl = diag(mm) * diag(U) * diag(DDL) Dq = diag(mm) * diag(U) * diag(DDQ) w = (Dl + Dq * diag(RR)) * RR F_U(X, CP) = 1/2 * w'*H*w + Cw'*w See also OPT_MODEL, ADD_LEGACY_COST, EVAL_LEGACY_COST.
0001 function [cp, vs, i1, iN] = params_legacy_cost(om, name, idx) 0002 %PARAMS_LEGACY_COST Returns cost parameters for legacy user-defined costs. 0003 % CP = OM.PARAMS_LEGACY_COST() 0004 % CP = OM.PARAMS_LEGACY_COST(NAME) 0005 % CP = OM.PARAMS_LEGACY_COST(NAME, IDX) 0006 % [CP, VS] = OM.PARAMS_LEGACY_COST(...) 0007 % [CP, VS, I1, IN] = OM.PARAMS_LEGACY_COST(...) 0008 % 0009 % With no input parameters, it assembles and returns the parameters 0010 % for the aggregate legacy user-defined cost from all legacy cost sets 0011 % added using ADD_LEGACY_COST. The values of these parameters are cached 0012 % for subsequent calls. The parameters are contained in the struct CP, 0013 % described below. 0014 % 0015 % If a NAME is provided then it simply returns parameter struct CP for the 0016 % corresponding named set. Likewise for indexed named sets specified 0017 % by NAME and IDX. 0018 % 0019 % An optional 2nd output argument VS indicates the variable sets used by 0020 % this cost set. The size of CP.N will be consistent with VS. 0021 % 0022 % If NAME is provided, optional 3rd and 4th output arguments I1 and IN 0023 % indicate the starting and ending row indices of the corresponding 0024 % cost set in the full aggregate cost matrix CP.N. 0025 % 0026 % Let X refer to the vector formed by combining the corresponding varsets VS, 0027 % and F_U(X, CP) be the cost at X corresponding to the cost parameters 0028 % contained in CP, where CP is a struct with the following fields: 0029 % N - nw x nx sparse matrix (optional, identity matrix by default) 0030 % Cw - nw x 1 vector 0031 % H - nw x nw sparse matrix (optional, all zeros by default) 0032 % dd, mm - nw x 1 vectors (optional, all ones by default) 0033 % rh, kk - nw x 1 vectors (optional, all zeros by default) 0034 % 0035 % These parameters are used as follows to compute F_U(X, CP) 0036 % 0037 % R = N*X - rh 0038 % 0039 % / kk(i), R(i) < -kk(i) 0040 % K(i) = < 0, -kk(i) <= R(i) <= kk(i) 0041 % \ -kk(i), R(i) > kk(i) 0042 % 0043 % RR = R + K 0044 % 0045 % U(i) = / 0, -kk(i) <= R(i) <= kk(i) 0046 % \ 1, otherwise 0047 % 0048 % DDL(i) = / 1, dd(i) = 1 0049 % \ 0, otherwise 0050 % 0051 % DDQ(i) = / 1, dd(i) = 2 0052 % \ 0, otherwise 0053 % 0054 % Dl = diag(mm) * diag(U) * diag(DDL) 0055 % Dq = diag(mm) * diag(U) * diag(DDQ) 0056 % 0057 % w = (Dl + Dq * diag(RR)) * RR 0058 % 0059 % F_U(X, CP) = 1/2 * w'*H*w + Cw'*w 0060 % 0061 % See also OPT_MODEL, ADD_LEGACY_COST, EVAL_LEGACY_COST. 0062 0063 % MATPOWER 0064 % Copyright (c) 2017, Power Systems Engineering Research Center (PSERC) 0065 % by Ray Zimmerman, PSERC Cornell 0066 % 0067 % This file is part of MATPOWER. 0068 % Covered by the 3-clause BSD License (see LICENSE file for details). 0069 % See https://matpower.org for more info. 0070 0071 if nargin > 1 %% individual set 0072 if nargin < 3 0073 idx = {}; 0074 end 0075 if isempty(idx) %% name, no index provided 0076 if prod(size(om.cost.idx.i1.(name))) == 1 %% simple named set 0077 N = om.cost.data.N.( name); 0078 Cw = om.cost.data.Cw.(name); 0079 [nw, nx] = size(N); 0080 e1 = ones(nw, 1); 0081 e0 = zeros(nw, 1); 0082 cp = struct(... 0083 'N', N, ... 0084 'Cw', Cw, ... 0085 'H', sparse(nw, nw), ... %% default => no quadratic term 0086 'dd', e1, ... %% default => linear 0087 'rh', e0, ... %% default => no shift 0088 'kk', e0, ... %% default => no dead zone 0089 'mm', e1 ); %% default => no scaling 0090 if isfield(om.cost.data.H, name) && ~isempty(om.cost.data.H.(name)) 0091 cp.H = om.cost.data.H.(name); 0092 end 0093 if isfield(om.cost.data.dd, name) && ~isempty(om.cost.data.dd.(name)) 0094 cp.dd = om.cost.data.dd.(name); 0095 end 0096 if isfield(om.cost.data.rh, name) && ~isempty(om.cost.data.rh.(name)) 0097 cp.rh = om.cost.data.rh.(name); 0098 end 0099 if isfield(om.cost.data.kk, name) && ~isempty(om.cost.data.kk.(name)) 0100 cp.kk = om.cost.data.kk.(name); 0101 end 0102 if isfield(om.cost.data.mm, name) && ~isempty(om.cost.data.mm.(name)) 0103 cp.mm = om.cost.data.mm.(name); 0104 end 0105 if nargout > 1 0106 vs = om.cost.data.vs.(name); 0107 if nargout > 3 0108 i1 = om.cost.idx.i1.(name); %% starting row index 0109 iN = om.cost.idx.iN.(name); %% ending row index 0110 end 0111 end 0112 else %% indexing required 0113 error('@opt_model/params_legacy_cost: legacy cost set ''%s'' requires an IDX arg', name); 0114 end 0115 else %% indexed named set 0116 % (calls to substruct() are relatively expensive ... 0117 % s = substruct('.', name, '{}', idx); 0118 % ... so replace it with these more efficient lines) 0119 sc = struct('type', {'.', '{}'}, 'subs', {name, idx}); 0120 N = subsref(om.cost.data.N, sc); 0121 Cw = subsref(om.cost.data.Cw, sc); 0122 [nw, nx] = size(N); 0123 e1 = ones(nw, 1); 0124 e0 = zeros(nw, 1); 0125 cp = struct(... 0126 'N', N, ... 0127 'Cw', Cw, ... 0128 'H', sparse(nw, nw), ... %% default => no quadratic term 0129 'dd', e1, ... %% default => linear 0130 'rh', e0, ... %% default => no shift 0131 'kk', e0, ... %% default => no dead zone 0132 'mm', e1 ); %% default => no scaling 0133 if isfield(om.cost.data.H, name) && ~isempty(subsref(om.cost.data.H, sc)) 0134 cp.H = subsref(om.cost.data.H, sc); 0135 end 0136 if isfield(om.cost.data.dd, name) && ~isempty(subsref(om.cost.data.dd, sc)) 0137 cp.dd = subsref(om.cost.data.dd, sc); 0138 end 0139 if isfield(om.cost.data.rh, name) && ~isempty(subsref(om.cost.data.rh, sc)) 0140 cp.rh = subsref(om.cost.data.rh, sc); 0141 end 0142 if isfield(om.cost.data.kk, name) && ~isempty(subsref(om.cost.data.kk, sc)) 0143 cp.kk = subsref(om.cost.data.kk, sc); 0144 end 0145 if isfield(om.cost.data.mm, name) && ~isempty(subsref(om.cost.data.mm, sc)) 0146 cp.mm = subsref(om.cost.data.mm, sc); 0147 end 0148 if nargout > 1 0149 vs = subsref(om.cost.data.vs, sc); 0150 if nargout > 3 0151 sn = sc; sn(2).type = '()'; %% num array field 0152 i1 = subsref(om.cost.idx.i1, sn); %% starting row index 0153 iN = subsref(om.cost.idx.iN, sn); %% ending row index 0154 end 0155 end 0156 end 0157 else %% aggregate 0158 cache = om.cost.params; 0159 if isempty(cache) %% build the aggregate 0160 nx = om.var.N; %% number of variables 0161 nw = om.cost.N; %% number of cost rows 0162 Nt = sparse(nx, nw); %% use N transpose for speed 0163 Cw = zeros(nw, 1); 0164 H = sparse(nw, nw); %% default => no quadratic term 0165 dd = ones(nw, 1); %% default => linear 0166 rh = Cw; %% default => no shift 0167 kk = Cw; %% default => no dead zone 0168 mm = dd; %% default => no scaling 0169 0170 %% fill in each piece 0171 for k = 1:om.cost.NS 0172 name = om.cost.order(k).name; 0173 idx = om.cost.order(k).idx; 0174 [cp, vs, i1, iN] = om.params_legacy_cost(name, idx); 0175 [mk, nk] = size(cp.N); %% size of Nk 0176 if mk 0177 Nkt_full = sparse(nx, nw); 0178 if isempty(vs) 0179 if nk == nx %% full size 0180 Nkt_full(:, i1:iN) = cp.N'; 0181 else %% vars added since adding this cost set 0182 Nk_all_cols = sparse(mk, nx); 0183 Nk_all_cols(:, 1:nk) = cp.N; 0184 Nkt_full(:, i1:iN) = Nk_all_cols'; 0185 end 0186 else 0187 jj = om.varsets_idx(vs); %% indices for var set 0188 Nk_all_cols = sparse(mk, nx); 0189 Nk_all_cols(:, jj) = cp.N; 0190 Nkt_full(:, i1:iN) = Nk_all_cols'; 0191 end 0192 Nt = Nt + Nkt_full; 0193 Cw(i1:iN) = cp.Cw; 0194 H_all_cols = sparse(mk, nw); 0195 H_all_cols(:, i1:iN) = cp.H'; 0196 H(:, i1:iN) = H_all_cols'; 0197 dd(i1:iN) = cp.dd; 0198 rh(i1:iN) = cp.rh; 0199 kk(i1:iN) = cp.kk; 0200 mm(i1:iN) = cp.mm; 0201 end 0202 end 0203 0204 %% cache aggregated parameters 0205 om.cost.params = struct( ... 0206 'N', Nt', 'Cw', Cw, 'H', H, 'dd', dd, 'rh', rh, 'kk', kk, 'mm', mm ); 0207 cp = om.cost.params; 0208 else %% return cached values 0209 cp = cache; 0210 end 0211 if nargout > 1 0212 vs = {}; 0213 end 0214 end