0001 function [mpc, flag] = sgvm_branch_perm(mpc, opt)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0018 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0019 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0020 nl = size(mpc.branch,1);
0021
0022
0023 if QT > size(mpc.branch,2)
0024
0025 perm = randperm(nl);
0026 mpc.branch(:,BR_R:ANGMAX) = mpc.branch(perm, BR_R:ANGMAX);
0027 return
0028 end
0029
0030
0031 if ~isfield(opt.vm.branchperm, 'overload_frac')
0032 overload_frac = 1;
0033 else
0034 overload_frac = opt.vm.branchperm.overload_frac;
0035 end
0036 Sf = sqrt(mpc.branch(:,PF).^2 + mpc.branch(:,QF).^2);
0037 St = sqrt(mpc.branch(:,PT).^2 + mpc.branch(:,QT).^2);
0038
0039 S = max(Sf,St) / mpc.baseMVA;
0040
0041 r = mpc.branch(:,RATE_A) / mpc.baseMVA;
0042
0043 R = mpc.branch(:, BR_R);
0044 X = mpc.branch(:, BR_X);
0045
0046 perm = (1:nl).';
0047
0048
0049 overloaded = find(S./r > overload_frac);
0050
0051
0052
0053
0054 [~,tmp] = sort(S(overloaded) - r(overloaded), 'descend');
0055 overloaded = overloaded(tmp);
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 available = true(nl,1);
0068 for k = 1:length(overloaded)
0069 if ~available(overloaded(k))
0070
0071 continue
0072 end
0073 B = find( (r*overload_frac >= S(overloaded(k))) & (S <= r(overloaded(k))*overload_frac) & available );
0074 if isempty(B)
0075 if S(overloaded(k)) <= r(overloaded(k))
0076
0077 continue
0078 end
0079 B = find( S <= r(overloaded(k)) & available );
0080 if isempty(B)
0081
0082 continue
0083 end
0084
0085 [~, tmp] = min(S(overloaded(k)) - r(B));
0086 idx = B(tmp);
0087 end
0088
0089
0090
0091
0092 [~, tmp1] = sort((R(overloaded(k)) - R(B)).^2 + (X(overloaded(k)) - X(B)).^2);
0093 [~, tmp2] = sort( S(overloaded(k)) - r(B) );
0094 [~, tmp3] = sort( S(B) - r(overloaded(k)) );
0095
0096
0097
0098 test_stat = full(sparse([tmp1; tmp2; tmp3], 1, repmat(1:length(B), 1, 3), length(B), 1));
0099 [~, tmp] = min(test_stat);
0100 idx = B(tmp);
0101
0102 perm(overloaded(k)) = idx;
0103 perm(idx) = overloaded(k);
0104 available([overloaded(k), idx]) = false;
0105 end
0106
0107
0108 if ~all(perm == (1:nl).')
0109 flag = 1;
0110 mpc.branch(:,BR_R:ANGMAX) = mpc.branch(perm, BR_R:ANGMAX);
0111 else
0112
0113 flag = 0;
0114 end
0115
0116 return
0117
0118
0119
0120
0121
0122
0123 vars = struct();
0124 max_block_size = 1000;
0125 nblock = ceil(nl/max_block_size);
0126 avgnum = nl/nblock;
0127 available_ids = true(nl,1);
0128 ptr = 0;
0129 for k = 1:nblock
0130 if k == nblock
0131 ids = find(available_ids);
0132 nelem = length(ids);
0133 elseif mod(k,2) == 0
0134 nelem = floor(avgnum);
0135 ids = find(available_ids);
0136 ids = ids(randperm(length(ids), nelem));
0137 ids = sort(ids);
0138 available_ids(ids) = false;
0139 else
0140 nelem = ceil(avgnum);
0141 ids = find(available_ids);
0142 ids = ids(randperm(length(ids), nelem));
0143 ids = sort(ids);
0144 available_ids(ids) = false;
0145 end
0146 vars.(['Pi', num2str(k)]) = struct('first', ptr+1, 'last', ptr + nelem^2, 'ids', ids);
0147 ptr = ptr + nelem^2;
0148 end
0149
0150 prob = struct();
0151
0152 vars.t = struct('first', ptr+1, 'last', ptr+nl);
0153 ptr = ptr + nl;
0154
0155 vars.tr = struct('first', ptr+1, 'last', ptr+nl);
0156 ptr = ptr + nl;
0157 vars.tx = struct('first', ptr+1, 'last', ptr+nl);
0158 ptr = ptr + nl;
0159
0160
0161
0162
0163
0164
0165
0166
0167 prob.A = [];
0168 prob.l = [];
0169 prob.u = [];
0170
0171 total_vars = ptr;
0172
0173 Sf = sqrt(mpc.branch(:,PF).^2 + mpc.branch(:,QF).^2);
0174 St = sqrt(mpc.branch(:,PT).^2 + mpc.branch(:,QT).^2);
0175
0176 S = max(Sf,St) / mpc.baseMVA;
0177
0178 r = mpc.branch(:,RATE_A) / mpc.baseMVA;
0179
0180 R = mpc.branch(:, BR_R);
0181 X = mpc.branch(:, BR_X);
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 rows = cell(nblock, 1);
0227 for k = 1:nblock
0228 v = ['Pi', num2str(k)];
0229 nelem = length(vars.(v).ids);
0230
0231
0232
0233 tidx = sgvm_ensure_col_vect(vars.t.first - 1 + vars.(v).ids).';
0234 A = sparse([1:nelem, reshape(ones(nelem,1)*(1:nelem), 1, nelem*nelem) ],...
0235 [tidx, vars.(v).first:vars.(v).last], ...
0236 [ones(1,nelem), repmat(r(vars.(v).ids).', 1, nelem)], nelem, total_vars);
0237 lb = S(vars.(v).ids);
0238 ub = Inf(nelem,1);
0239 prob = update_Albub(prob, A, lb, ub);
0240
0241
0242
0243
0244
0245 tidx = sgvm_ensure_col_vect(vars.tr.first - 1 + vars.(v).ids).';
0246 A = sparse([1:nelem, reshape(ones(nelem,1)*(1:nelem), 1, nelem*nelem) ],...
0247 [tidx, vars.(v).first:vars.(v).last],...
0248 [ones(1,nelem), repmat(R(vars.(v).ids).', 1, nelem)], nelem, total_vars);
0249 lb = R(vars.(v).ids);
0250 ub = Inf(nelem,1);
0251 prob = update_Albub(prob, A, lb, ub);
0252
0253 tidx = sgvm_ensure_col_vect(vars.tr.first - 1 + vars.(v).ids).';
0254 A = sparse([1:nelem, reshape(ones(nelem,1)*(1:nelem), 1, nelem*nelem) ],...
0255 [tidx, vars.(v).first:vars.(v).last],...
0256 [-ones(1,nelem), repmat(R(vars.(v).ids).', 1, nelem)], nelem, total_vars);
0257 lb = -Inf(nelem,1);
0258 ub = R(vars.(v).ids);
0259 prob = update_Albub(prob, A, lb, ub);
0260
0261
0262
0263
0264
0265 tidx = sgvm_ensure_col_vect(vars.tx.first - 1 + vars.(v).ids).';
0266 A = sparse([1:nelem, reshape(ones(nelem,1)*(1:nelem), 1, nelem*nelem) ],...
0267 [tidx, vars.(v).first:vars.(v).last],...
0268 [ones(1,nelem), repmat(X(vars.(v).ids).', 1, nelem)], nelem, total_vars);
0269 lb = X(vars.(v).ids);
0270 ub = Inf(nelem,1);
0271 prob = update_Albub(prob, A, lb, ub);
0272
0273 tidx = sgvm_ensure_col_vect(vars.tx.first - 1 + vars.(v).ids).';
0274 A = sparse([1:nelem, reshape(ones(nelem,1)*(1:nelem), 1, nelem*nelem) ],...
0275 [tidx, vars.(v).first:vars.(v).last],...
0276 [-ones(1,nelem), repmat(X(vars.(v).ids).', 1, nelem)], nelem, total_vars);
0277 lb = -Inf(nelem,1);
0278 ub = X(vars.(v).ids);
0279 prob = update_Albub(prob, A, lb, ub);
0280
0281
0282
0283 A = sparse(reshape(ones(nelem,1)*(1:nelem), 1, nelem*nelem),...
0284 vars.(v).first:vars.(v).last, 1, nelem, total_vars);
0285 lb = ones(nelem,1);
0286 ub = ones(nelem,1);
0287 prob = update_Albub(prob, A, lb, ub);
0288
0289
0290
0291 A = sparse(reshape((1:nelem).'*ones(1,nelem), 1, nelem*nelem),...
0292 vars.(v).first:vars.(v).last, 1, nelem, total_vars);
0293 lb = ones(nelem,1);
0294 ub = ones(nelem,1);
0295 prob = update_Albub(prob, A, lb, ub);
0296
0297
0298
0299 A = sparse(1, vars.(v).first:vars.(v).last, ...
0300 repmat(r(vars.(v).ids).', 1, nelem), 1, total_vars);
0301 lb = sum(r(vars.(v).ids).');
0302 ub = sum(r(vars.(v).ids).');
0303 prob = update_Albub(prob, A, lb, ub);
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313 if k == 1
0314 rows{1} = [1, size(prob.A,1)];
0315 else
0316 rows{k} = [rows{k-1}(2)+1, size(prob.A, 1)];
0317 end
0318 end
0319 A = [];
0320
0321
0322
0323
0324
0325
0326
0327 prob.xmin = zeros(total_vars,1);
0328 prob.xmax = Inf(total_vars,1);
0329
0330 prob.xmax(vars.Pi1.first:vars.(['Pi', num2str(nblock)]).last) = 1;
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355 prob.c = sparse([vars.t.first:vars.t.last,...
0356 vars.tr.first:vars.t.last,...
0357 vars.tx.first:vars.t.last], 1, 1, total_vars, 1);
0358
0359
0360
0361
0362
0363
0364
0365
0366 prob.opt.verbose = opt.vm.branchperm.verbose;
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380 [x, f, eflag, output, lambda] = qps_matpower(prob);
0381
0382 if eflag
0383
0384 perm = zeros(nl,1);
0385 for k = 1:nblock
0386 v = ['Pi', num2str(k)];
0387 nelem = length(vars.(v).ids);
0388 ptmp = sgvm_extract_perm(reshape(x(vars.(v).first:vars.(v).last), nelem, nelem));
0389 perm(vars.(v).ids) = vars.(v).ids(ptmp);
0390 end
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408 if length(unique(perm)) ~= nl
0409 error(['sgvm_branch_perm: binarzation of Pi by selecting maximum entry in each row ',...
0410 'failed to return a valid permutation.'])
0411 end
0412 else
0413 error('sgvm_branch_perm: optimization failed to converge.')
0414 end
0415
0416
0417 mpc.branch(:,BR_R:ANGMAX) = mpc.branch(perm, BR_R:ANGMAX);
0418
0419 function prob = update_Albub(prob, A, lb, ub)
0420
0421
0422 prob.A = [prob.A; A];
0423 prob.l = [prob.l; lb];
0424 prob.u = [prob.u; ub];
0425
0426 function [f, df, d2f] = obj_fnc(x, lambda, nblock, vars)
0427
0428 v = ['Pi', num2str(nblock)];
0429 f = sum(x(vars.t.first:vars.t.last)) + ...
0430 -lambda*sum(x(vars.Pi1.first:vars.(v).last).^2);
0431 if nargout > 1
0432 df = [ ones(vars.t.last-vars.t.first + 1, 1); ...
0433 -2*lambda*x(vars.Pi1.first:vars.(v).last)];
0434 if nargout > 2
0435 d2f = sparse(vars.Pi1.first:vars.(v).last,...
0436 vars.Pi1.first:vars.(v).last, -2*lambda, length(x), length(x));
0437 end
0438 end