├── .gitignore ├── README.md ├── case └── case30_modified.m ├── data ├── KaggleLoads.mat └── readme ├── fun ├── B2A.m ├── B_Kekatos.m ├── B_estimate.m ├── B_partial.m ├── L2A.m ├── Pf_limit.m ├── complete.m ├── create_mpc.m ├── evaluation.m ├── get_degree.m ├── get_ftx.m ├── get_lap.m ├── get_lmp.m ├── get_load.m ├── locate.m ├── makeAmatrix.m ├── makeBmatrix.m ├── module_b.m ├── modulehuber.m ├── modulel1.m ├── norm0.m ├── normalize.m ├── plot_mat.m ├── rmse.m ├── solveB1.m └── solveB4.m ├── main.m ├── main_conf.m ├── main_lossy.m ├── offline.m ├── online.m ├── src ├── block_offer.m ├── create_db.m ├── data_preprocess.m ├── dc_opf_Litvinov.m ├── line_reduce.m ├── lossless_LMP.m ├── lossy_LMP.m ├── online_admm.m ├── online_admm2.m ├── online_admm3.m ├── rtmarket.m ├── run_lossy_market.m └── run_rtmarket.m ├── test.m ├── test1.m ├── test2.m ├── test3.m └── test4.m /.gitignore: -------------------------------------------------------------------------------- 1 | data/ 2 | fig/ 3 | *.asv 4 | *.eps 5 | *.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LMP-inferring 2 | Reproduce some interesting facts about local marginal prices (LMP) in electricity market. 3 | 4 | ## Requirements 5 | - [Matpower](http://www.pserc.cornell.edu/matpower/) for building and solving opf problems; 6 | - [Yalmip](https://yalmip.github.io/) and [sdpt3](http://www.math.nus.edu.sg/~mattohkc/sdpt3.html) for solving semidefinite programming problems; 7 | - [epstopdf.exe](https://ctan.org/pkg/epstopdf?lang=en) to convert .eps files to .pdf files while keeping the sizes. It usually has been contained in Texlive. 8 | 9 | ## Reference 10 | Kekatos V, Giannakis G B, Baldick R. Online energy price matrix factorization for power grid topology tracking[J]. IEEE Transactions on Smart Grid, 2016, 7(3): 1239-1248. 11 | -------------------------------------------------------------------------------- /case/case30_modified.m: -------------------------------------------------------------------------------- 1 | function mpc = case30_modified 2 | %CASE30 Power flow data for 30 bus, 6 generator case. 3 | % Please see CASEFORMAT for details on the case file format. 4 | % 5 | % Based on data from ... 6 | % Alsac, O. & Stott, B., "Optimal Load Flow with Steady State Security", 7 | % IEEE Transactions on Power Apparatus and Systems, Vol. PAS 93, No. 3, 8 | % 1974, pp. 745-751. 9 | % ... with branch parameters rounded to nearest 0.01, shunt values divided 10 | % by 100 and shunt on bus 10 moved to bus 5, load at bus 5 zeroed out. 11 | % Generator locations, costs and limits and bus areas were taken from ... 12 | % Ferrero, R.W., Shahidehpour, S.M., Ramesh, V.C., "Transaction analysis 13 | % in deregulated power systems using game theory", IEEE Transactions on 14 | % Power Systems, Vol. 12, No. 3, Aug 1997, pp. 1340-1347. 15 | % Generator Q limits were derived from Alsac & Stott, using their Pmax 16 | % capacities. V limits and line |S| limits taken from Alsac & Stott. 17 | 18 | % MATPOWER 19 | 20 | %% MATPOWER Case Format : Version 2 21 | mpc.version = '2'; 22 | 23 | %%----- Power Flow Data -----%% 24 | %% system MVA base 25 | mpc.baseMVA = 100; 26 | 27 | %% bus data 28 | % bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin 29 | mpc.bus = [ 30 | 1 3 0 0 0 0 1 1 0 135 1 1.05 0.95; 31 | 2 2 21.7 12.7 0 0 1 1 0 135 1 1.1 0.95; 32 | 3 1 2.4 1.2 0 0 1 1 0 135 1 1.05 0.95; 33 | 4 1 7.6 1.6 0 0 1 1 0 135 1 1.05 0.95; 34 | 5 1 0 0 0 0.19 1 1 0 135 1 1.05 0.95; 35 | 6 1 0 0 0 0 1 1 0 135 1 1.05 0.95; 36 | 7 1 22.8 10.9 0 0 1 1 0 135 1 1.05 0.95; 37 | 8 1 30 30 0 0 1 1 0 135 1 1.05 0.95; 38 | 9 1 0 0 0 0 1 1 0 135 1 1.05 0.95; 39 | 10 1 5.8 2 0 0 3 1 0 135 1 1.05 0.95; 40 | 11 1 0 0 0 0 1 1 0 135 1 1.05 0.95; 41 | 12 1 11.2 7.5 0 0 2 1 0 135 1 1.05 0.95; 42 | 13 2 0 0 0 0 2 1 0 135 1 1.1 0.95; 43 | 14 1 6.2 1.6 0 0 2 1 0 135 1 1.05 0.95; 44 | 15 1 8.2 2.5 0 0 2 1 0 135 1 1.05 0.95; 45 | 16 1 3.5 1.8 0 0 2 1 0 135 1 1.05 0.95; 46 | 17 1 9 5.8 0 0 2 1 0 135 1 1.05 0.95; 47 | 18 1 3.2 0.9 0 0 2 1 0 135 1 1.05 0.95; 48 | 19 1 9.5 3.4 0 0 2 1 0 135 1 1.05 0.95; 49 | 20 1 2.2 0.7 0 0 2 1 0 135 1 1.05 0.95; 50 | 21 1 17.5 11.2 0 0 3 1 0 135 1 1.05 0.95; 51 | 22 2 0 0 0 0 3 1 0 135 1 1.1 0.95; 52 | 23 2 3.2 1.6 0 0 2 1 0 135 1 1.1 0.95; 53 | 24 1 8.7 6.7 0 0.04 3 1 0 135 1 1.05 0.95; 54 | 25 1 0 0 0 0 3 1 0 135 1 1.05 0.95; 55 | 26 1 3.5 2.3 0 0 3 1 0 135 1 1.05 0.95; 56 | 27 2 0 0 0 0 3 1 0 135 1 1.1 0.95; 57 | 28 1 0 0 0 0 1 1 0 135 1 1.05 0.95; 58 | 29 1 2.4 0.9 0 0 3 1 0 135 1 1.05 0.95; 59 | 30 1 10.6 1.9 0 0 3 1 0 135 1 1.05 0.95; 60 | ]; 61 | 62 | %% generator data 63 | % bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf 64 | mpc.gen = [ 65 | 1 23.54 0 150 -20 1 100 1 80 0 0 0 0 0 0 0 0 0 0 0 0; 66 | 2 60.97 0 60 -20 1 100 1 80 0 0 0 0 0 0 0 0 0 0 0 0; 67 | 13 37 0 44.7 -15 1 100 1 40 0 0 0 0 0 0 0 0 0 0 0 0; 68 | 22 21.59 0 62.5 -15 1 100 1 50 0 0 0 0 0 0 0 0 0 0 0 0; 69 | 23 19.2 0 40 -10 1 100 1 30 0 0 0 0 0 0 0 0 0 0 0 0; 70 | 27 26.91 0 48.7 -15 1 100 1 55 0 0 0 0 0 0 0 0 0 0 0 0; 71 | ]; 72 | 73 | %% branch data 74 | % fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax 75 | mpc.branch = [ 76 | 1 2 0.02 0.06 0.03 130 130 130 0 0 1 -360 360; 77 | 1 3 0.05 0.19 0.02 130 130 130 0 0 1 -360 360; 78 | 2 4 0.06 0.17 0.02 65 65 65 0 0 1 -360 360; 79 | 3 4 0.01 0.04 0 130 130 130 0 0 1 -360 360; 80 | 2 5 0.05 0.2 0.02 130 130 130 0 0 1 -360 360; 81 | 2 6 0.06 0.18 0.02 65 65 65 0 0 1 -360 360; 82 | 4 6 0.01 0.04 0 90 90 90 0 0 1 -360 360; 83 | 5 7 0.05 0.12 0.01 70 70 70 0 0 1 -360 360; 84 | 6 7 0.03 0.08 0.01 130 130 130 0 0 1 -360 360; 85 | 6 8 0.01 0.04 0 32 32 32 0 0 1 -360 360; 86 | 6 9 0 0.21 0 65 65 65 0 0 1 -360 360; 87 | 6 10 0 0.56 0 32 32 32 0 0 1 -360 360; 88 | 9 11 0 0.21 0 65 65 65 0 0 1 -360 360; 89 | 9 10 0 0.11 0 65 65 65 0 0 1 -360 360; 90 | 4 12 0 0.26 0 65 65 65 0 0 1 -360 360; 91 | 12 13 0 0.14 0 65 65 65 0 0 1 -360 360; 92 | 12 14 0.12 0.26 0 32 32 32 0 0 1 -360 360; 93 | 12 15 0.07 0.13 0 32 32 32 0 0 1 -360 360; 94 | 12 16 0.09 0.2 0 32 32 32 0 0 1 -360 360; 95 | 14 15 0.22 0.2 0 16 16 16 0 0 1 -360 360; 96 | 16 17 0.08 0.19 0 16 16 16 0 0 1 -360 360; 97 | 15 18 0.11 0.22 0 16 16 16 0 0 1 -360 360; 98 | 18 19 0.06 0.13 0 16 16 16 0 0 1 -360 360; 99 | 19 20 0.03 0.07 0 32 32 32 0 0 1 -360 360; 100 | 10 20 0.09 0.21 0 32 32 32 0 0 1 -360 360; 101 | 10 17 0.03 0.08 0 32 32 32 0 0 1 -360 360; 102 | 10 21 0.03 0.07 0 32 32 32 0 0 1 -360 360; 103 | 10 22 0.07 0.15 0 32 32 32 0 0 1 -360 360; 104 | 21 22 0.01 0.02 0 32 32 32 0 0 1 -360 360; 105 | 15 23 0.1 0.2 0 16 16 16 0 0 1 -360 360; 106 | 22 24 0.12 0.18 0 16 16 16 0 0 1 -360 360; 107 | 23 24 0.13 0.27 0 16 16 16 0 0 1 -360 360; 108 | 24 25 0.19 0.33 0 16 16 16 0 0 1 -360 360; 109 | 25 26 0.25 0.38 0 16 16 16 0 0 1 -360 360; 110 | 25 27 0.11 0.21 0 16 16 16 0 0 1 -360 360; 111 | 28 27 0 0.4 0 65 65 65 0 0 1 -360 360; 112 | 27 29 0.22 0.42 0 16 16 16 0 0 1 -360 360; 113 | 27 30 0.32 0.6 0 16 16 16 0 0 1 -360 360; 114 | 29 30 0.24 0.45 0 16 16 16 0 0 1 -360 360; 115 | 8 28 0.06 0.2 0.02 32 32 32 0 0 1 -360 360; 116 | 6 28 0.02 0.06 0.01 32 32 32 0 0 1 -360 360; 117 | ]; 118 | 119 | %%----- OPF Data -----%% 120 | %% generator cost data 121 | % 1 startup shutdown n x1 y1 ... xn yn 122 | % 2 startup shutdown n c(n-1) ... c0 123 | mpc.gencost = [ 124 | 1 0 0 6 0 0 10 260 30 780 50 1500 70 2380 80 2880 ; 125 | 1 0 0 6 0 0 10 210 20 420 40 980 60 1680 80 2540 ; 126 | 1 0 0 6 0 0 5 190 10 380 15 570 30 1200 40 1670 ; 127 | 1 0 0 6 0 0 10 160 20 430 30 840 40 1380 50 2040 ; 128 | 1 0 0 6 0 0 5 170 10 340 12 408 15 510 30 1110 ; 129 | 1 0 0 6 0 0 10 350 20 700 25 875 30 1050 45 1635 ; 130 | ]; 131 | -------------------------------------------------------------------------------- /data/KaggleLoads.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengkd95/LMP-inferring/58cb93ab5a2dc8e0806c3d90c8c7f251b6354f20/data/KaggleLoads.mat -------------------------------------------------------------------------------- /data/readme: -------------------------------------------------------------------------------- 1 | put some load data here 2 | -------------------------------------------------------------------------------- /fun/B2A.m: -------------------------------------------------------------------------------- 1 | function [A,x,f,t] = B2A(B,L,REF,nl) 2 | nb = size(L,1); 3 | nl1 = floor(nl/nb*(nb-1)); 4 | f = []; 5 | t = []; 6 | x = []; 7 | U = triu(B,1); 8 | U_sort = sort(abs(U(:)),'descend'); 9 | e = U_sort(nl1+1); 10 | for i = 1:size(B,1)-1 11 | for j = i+1:size(B,1) 12 | if abs(B(i,j))>e 13 | f = [f;i]; 14 | t = [t;j]; 15 | x = [x;1/abs(B(i,j))]; 16 | end 17 | end 18 | end 19 | f(f>=REF) = f(f>=REF)+1; 20 | t(t>=REF) = t(t>=REF)+1; 21 | 22 | nl2 = nl-nl1; 23 | L_sort = sort(abs(L(:,REF)),'descend'); 24 | e = L_sort(nl2+2); 25 | for i = 1:REF-1 26 | if abs(L(i,REF))>e 27 | f = [f;i]; 28 | t = [t;REF]; 29 | x = [x;1/abs(L(i,REF))]; 30 | end 31 | end 32 | for i = REF+1:nb 33 | if abs(L(i,REF))>e 34 | f = [f;REF]; 35 | t = [t;i]; 36 | x = [x;1/abs(L(i,REF))]; 37 | end 38 | end 39 | 40 | [f,I] = sort(f,'ascend'); 41 | t = t(I); 42 | x = x(I); 43 | Cf = sparse(1:nl, f, ones(nl, 1), nl, nb); 44 | Ct = sparse(1:nl, t, ones(nl, 1), nl, nb); 45 | A = Cf-Ct; 46 | end -------------------------------------------------------------------------------- /fun/B_Kekatos.m: -------------------------------------------------------------------------------- 1 | function B = B_Kekatos(PI,k,avg_degree,e) 2 | % function B = B_Kekatos(PI,k,avg_degree,e) 3 | if nargin < 4 4 | e = 1e-3; 5 | if nargin < 3 6 | avg_degree = 0; 7 | end 8 | end 9 | 10 | kappa1 = k(1); 11 | kappa2 = k(2); 12 | nb = size(PI,1)+1; 13 | IDX_congestion = sum(abs(PI),1)>0 ; 14 | PI = PI(:,IDX_congestion); 15 | 16 | B_solve = sdpvar(nb-1,nb-1); 17 | I = eye(nb-1); 18 | F = [B_solve(:) <= I(:)]; 19 | P = I - ones(nb-1,nb-1); 20 | 21 | optimize(F,norm(B_solve*PI,1)+kappa1*trace(P*B_solve)-kappa2*logdet(B_solve),sdpsettings('solver','sdpt3')); 22 | 23 | BS = value(B_solve); 24 | 25 | if avg_degree>0 26 | degree = mean(diag(BS)); 27 | B = BS * avg_degree/degree; 28 | else 29 | B = BS; 30 | end 31 | B(abs(B)0, B*e>0 6 | 7 | % This function aims to solve the convex opt problem: 8 | % min norm(B*PI,1)+k1*tr(PB)-k2*log|B|+k3*norm(B*e,1) 9 | % s.t. B>0, B<=I, B*e>0 10 | 11 | if nargin < 4 12 | e = 1e-3; 13 | if nargin < 3 14 | avg_degree = 0; 15 | end 16 | end 17 | 18 | kappa1 = k(1); 19 | kappa2 = k(2); 20 | kappa3 = k(3); 21 | nb = size(PI,1)+1; 22 | 23 | B_solve = sdpvar(nb-1,nb-1); 24 | I = eye(nb-1); 25 | P = I - ones(nb-1,nb-1); 26 | E = ones(1,nb-1); 27 | 28 | F = [B_solve(:) <= I(:), B_solve*E' >= 0]; %,... 29 | % diag(B_solve) >= 1/(10*nb)*E' ]; 30 | %f = norm(B_solve*PI,1)+kappa1*trace(P*B_solve)-kappa2*logdet(B_solve)+kappa3*norm(E*B_solve,1); 31 | %f = sum(sqrt(sum((B_solve*PI).^2,2)))+kappa1*sum(sqrt(sum(B_solve.^2,2)))-kappa2*logdet(B_solve)+kappa3*norm(E*B_solve,1); 32 | %f = sum(sqrt(sum((B_solve*PI).^2,2)))+kappa1*trace(P*B_solve)-kappa2*logdet(B_solve)+kappa3*norm(E*B_solve,1); 33 | f = norm(B_solve*PI,1)+kappa1*sum(sqrt(sum(B_solve.^2,2)))-kappa2*logdet(B_solve)+kappa3*norm(E*B_solve,1); 34 | 35 | optimize(F,f,sdpsettings('solver','sdpt3')); 36 | 37 | BS = value(B_solve); 38 | 39 | if avg_degree>0 40 | degree = mean(diag(BS)); 41 | B = BS * avg_degree/degree; 42 | else 43 | B = BS; 44 | end 45 | B(abs(B)= 0]; 15 | 16 | for i = 1:length(row) 17 | F = [F; B_solve(row(i), col(i)) == val(i) ]; 18 | end 19 | 20 | optimize(F,norm(B_solve*PI,1)+kappa1*trace(P*B_solve)-kappa2*logdet(B_solve)+kappa3*norm(E*B_solve,1),sdpsettings('solver','sdpt3')); 21 | 22 | B = value(B_solve); 23 | 24 | B(abs(B) 1e-3 7 | f = [f;i]; 8 | t = [t;j]; 9 | x = [x;1/abs(L(i,j))]; 10 | end 11 | end 12 | end 13 | nl = length(f); 14 | Cf = sparse(1:nl, f, ones(nl, 1), nl, db.N); 15 | Ct = sparse(1:nl, t, ones(nl, 1), nl, db.N); 16 | db.A = Cf-Ct; 17 | db.Ar = db.A; 18 | db.Ar(:,REF) = []; 19 | db.x = 1./x; 20 | db.Lap = L; 21 | db.L = nl; 22 | db.Br = db.Ar' * diag(db.x) * db.Ar; 23 | db.Bri = db.Br^(-1); 24 | end -------------------------------------------------------------------------------- /fun/Pf_limit.m: -------------------------------------------------------------------------------- 1 | function flowlimit = Pf_limit(gen,loads,f,t,x,REF,f0,t0) 2 | nl = length(f); 3 | nb = size(gen,1); 4 | Cf = sparse(1:nl, f, ones(nl, 1), nl, nb); 5 | Ct = sparse(1:nl, t, ones(nl, 1), nl, nb); 6 | A = Cf-Ct; 7 | A(:,REF) = []; 8 | D = diag(x); 9 | B = A'*D*A; 10 | T = [zeros(nl,1),D*A*B^(-1)]; 11 | Pf = T*(gen-loads); 12 | flowlimit = zeros(nl,1); 13 | idx = []; 14 | for i = 1:length(f0) 15 | idx = [idx; find(f==f0(i) & t==t0(i))]; 16 | flowlimit(idx(i)) = max(abs(Pf(idx(i),:))); 17 | end 18 | 19 | end -------------------------------------------------------------------------------- /fun/complete.m: -------------------------------------------------------------------------------- 1 | function Bc = complete(B, t, B_origin, KnownPart, mpc) 2 | REF = find(mpc.bus(:,2)==3); 3 | Bc = B; 4 | j = find(KnownPart.time(:,1) <= t, 1, 'last'); 5 | if j 6 | [row, col, val] = locate(mpc, KnownPart.lines(1:j,1), B_origin); 7 | for i = 1:length(row) 8 | if row(i) < REF && col(i) < REF 9 | Bc(row(i),col(i)) = val(i); 10 | Bc(col(i),row(i)) = val(i); 11 | Bc(row(i),row(i)) = Bc(row(i),row(i))-val(i); 12 | Bc(col(i),col(i)) = Bc(col(i),col(i))-val(i); 13 | elseif row(i) > REF && col(i) < REF 14 | Bc(row(i)-1,col(i)) = val(i); 15 | Bc(col(i),row(i)-1) = val(i); 16 | Bc(row(i)-1,row(i)-1) = Bc(row(i)-1,row(i)-1)-val(i); 17 | Bc(col(i),col(i)) = Bc(col(i),col(i))-val(i); 18 | elseif row(i) < REF && col(i) > REF 19 | Bc(row(i),col(i)-1) = val(i); 20 | Bc(col(i)-1,row(i)) = val(i); 21 | Bc(row(i),row(i)) = Bc(row(i),row(i))-val(i); 22 | Bc(col(i)-1,col(i)-1) = Bc(col(i)-1,col(i)-1)-val(i); 23 | elseif row(i) > REF && col(i) > REF 24 | Bc(row(i)-1,col(i)-1) = val(i); 25 | Bc(col(i)-1,row(i)-1) = val(i); 26 | Bc(row(i)-1,row(i)-1) = Bc(row(i)-1,row(i)-1)-val(i); 27 | Bc(col(i)-1,col(i)-1) = Bc(col(i)-1,col(i)-1)-val(i); 28 | end 29 | end 30 | end 31 | end -------------------------------------------------------------------------------- /fun/create_mpc.m: -------------------------------------------------------------------------------- 1 | function mpc2 = create_mpc(mpc, f, t, x, limit) 2 | mpc2 = mpc; 3 | nl = length(f); 4 | r = zeros(nl,1); 5 | b = zeros(nl,1); 6 | rateA = limit; 7 | rateB = limit; 8 | rateC = limit; 9 | ratio = zeros(nl,1); 10 | angle = zeros(nl,1); 11 | status = ones(nl,1); 12 | angmin = -360 * ones(nl,1); 13 | angmax = 360 * ones(nl,1); 14 | mpc2.branch = [f,t,r,x,b,rateA,rateB,rateC,ratio,angle,status,angmin,angmax]; 15 | 16 | 17 | end -------------------------------------------------------------------------------- /fun/evaluation.m: -------------------------------------------------------------------------------- 1 | function [AUC,TPR,FPR] = evaluation(B0,B) 2 | 3 | nb = size(B,1) + 1; 4 | 5 | B0_triu = triu(B0,1); 6 | B_triu = triu(B,1); 7 | 8 | B0_triu = B0_triu(:); 9 | B_triu = B_triu(:); 10 | 11 | TPR = []; 12 | FPR = []; 13 | for e = eps:5e-2:max(abs(B_triu)) 14 | 15 | IDX0 = find(B0_triu ~= 0); 16 | 17 | IDX = find(abs(B_triu) >= e); 18 | 19 | TP = length(intersect(IDX0,IDX)); 20 | 21 | FP = length(setdiff(IDX,IDX0)); 22 | 23 | % 24 | TPR = [TPR; TP/length(IDX0)]; 25 | % 26 | TPR = [TPR; TP/length(IDX0)]; 27 | 28 | FPR = [FPR; FP/( (nb-1)*(nb-2)/2 - length(IDX0) + eps)]; 29 | end 30 | AUC = sum(([1;FPR]-[FPR;0]).*([1;TPR] + [TPR;0])/2 ); 31 | end -------------------------------------------------------------------------------- /fun/get_degree.m: -------------------------------------------------------------------------------- 1 | function degree = get_degree(mpc) 2 | 3 | REF = find(mpc.bus(:,2) == 3); 4 | B = makeBmatrix(mpc); 5 | L = get_lap(B,REF); 6 | degree = diag(L); 7 | 8 | end -------------------------------------------------------------------------------- /fun/get_ftx.m: -------------------------------------------------------------------------------- 1 | function [f,t,x] = get_ftx(L, nl) 2 | L_triu = abs(triu(L,1)); 3 | value = sort(L_triu(L_triu(:)>0),'descend'); 4 | if length(value) >= nl 5 | [f,t,x] = find(L_triu,nl); 6 | else 7 | [f,t,x] = find(L_triu); 8 | end -------------------------------------------------------------------------------- /fun/get_lap.m: -------------------------------------------------------------------------------- 1 | function L = get_lap(B,REF) 2 | aDA = -sum(B); 3 | aDa = -sum(aDA); 4 | L = [B(1:REF-1,1:REF-1),aDA(1:REF-1)',B(1:REF-1,REF:end); 5 | aDA(1:REF-1), aDa, aDA(REF:end); 6 | B(REF:end,1:REF-1), aDA(REF:end)',B(REF:end,REF:end)]; 7 | % L = L / max(max(L)); 8 | L(abs(L)<1e-4)=0; 9 | end -------------------------------------------------------------------------------- /fun/get_lmp.m: -------------------------------------------------------------------------------- 1 | function mdata2 = get_lmp(db,mdata,time) 2 | mdata2.S = []; 3 | mdata2.M = []; 4 | mdata2.Prices = []; 5 | mdata2.index = []; 6 | mdata2.mu0 = []; 7 | settings = sdpsettings('solver','mosek','verbose',0); 8 | 9 | for i = 1:length(time) 10 | if mod(i,20) == 0 11 | fprintf('%d',i) 12 | end 13 | h = time(i); 14 | loads = mdata.loads(:,h); 15 | c = mdata.c(:,:,h); 16 | % tic, 17 | P = sdpvar(db.N,5); 18 | F = [db.pmin<=P, P<=db.pmax, (sum(loads-sum(P,2))==0):'balance',... 19 | (-db.flowlimit<=diag(db.x)*db.Ar*db.Bri*(sum(P(2:end,:),2)-loads(2:end) )):'conlow',... 20 | (diag(db.x)*db.Ar*db.Bri*(sum(P(2:end,:),2)-loads(2:end) )<=db.flowlimit):'conhigh']; 21 | diagnostic = solvesdp(F,c(:)'*P(:),settings); 22 | if diagnostic.problem, 23 | %% typically infeasible problem 24 | market.mu0 = 0; 25 | market.mul = inf*ones(db.L,1); 26 | market.muh = inf*ones(db.L,1); 27 | market.p = zeros(db.N,1); 28 | market.P = zeros(db.N,1); 29 | market.s = zeros(db.N-1,1); 30 | market.price = zeros(db.N-1,1); 31 | else 32 | market.mu0 = double(dual(F('balance'))); 33 | market.mul = double(dual(F('conlow'))) .* (abs(double(dual(F('conlow'))))>1e-6); 34 | market.muh = double(dual(F('conhigh'))) .* (abs(double(dual(F('conhigh'))))>1e-6); 35 | market.p = sum(double(P),2); 36 | market.P = double(P); 37 | market.s = db.Ar'*diag(db.x)*(market.mul-market.muh); 38 | market.price = db.Bri*market.s; 39 | end 40 | if diagnostic.problem, 41 | str = 'Infeasible.'; 42 | market.success = 0; 43 | market.cong = 0; 44 | else 45 | market.success = 1; 46 | if sum(abs(market.mul-market.muh))==0, 47 | str = 'No congestion.'; 48 | market.cong = 0; 49 | else 50 | str = ''; 51 | market.cong = 1; 52 | end 53 | end 54 | % t = toc; 55 | % fprintf('Demand: %g. Capacity: %g. %s Time: %g\n', sum(loads),sum(sum(db.pmax)),str,t) 56 | %% 57 | % save the results 58 | mdata2.S = [mdata2.S, market.s]; 59 | mdata2.M = [mdata2.M, market.muh-market.mul]; 60 | mdata2.Prices = [mdata2.Prices, market.price]; 61 | mdata2.mu0 = [mdata2.mu0, market.mu0]; 62 | if market.success && market.cong 63 | mdata2.index = [mdata2.index, i]; 64 | end 65 | end 66 | 67 | 68 | 69 | end -------------------------------------------------------------------------------- /fun/get_load.m: -------------------------------------------------------------------------------- 1 | function load = get_load(input,year,month) 2 | num= xlsread(input); 3 | num = num(num(:,2)==year & num(:,3)==month,:); 4 | load = []; 5 | for k = 1:31 6 | try 7 | day_load = num(num(:,4)==k,5:end); 8 | load = [load, day_load]; 9 | catch error 10 | break 11 | end 12 | end 13 | 14 | end -------------------------------------------------------------------------------- /fun/locate.m: -------------------------------------------------------------------------------- 1 | function [row, col, val] = locate(mpc, lines, B0) 2 | L = size(lines,1); 3 | row = zeros(L,1); 4 | col = zeros(L,1); 5 | val = zeros(L,1); 6 | for i = 1:L 7 | row(i) = mpc.branch(lines(i),1); 8 | col(i) = mpc.branch(lines(i),2); 9 | val(i) = B0(row(i),col(i)); 10 | end -------------------------------------------------------------------------------- /fun/makeAmatrix.m: -------------------------------------------------------------------------------- 1 | function A = makeAmatrix(mpc) 2 | 3 | from = mpc.branch(:,1); 4 | to = mpc.branch(:,2); 5 | nl = length(from); 6 | nb = length(mpc.bus(:,1)); 7 | 8 | Cf = sparse(1:nl, from, ones(nl, 1), nl, nb); 9 | Ct = sparse(1:nl, to, ones(nl, 1), nl, nb); 10 | A = Cf-Ct; 11 | 12 | end -------------------------------------------------------------------------------- /fun/makeBmatrix.m: -------------------------------------------------------------------------------- 1 | function B = makeBmatrix(mpc) 2 | from = mpc.branch(:,1); 3 | to = mpc.branch(:,2); 4 | nl = length(from); 5 | nb = length(mpc.bus(:,1)); 6 | REF = find(mpc.bus(:,2)==3); 7 | 8 | Cf = sparse(1:nl, from, ones(nl, 1), nl, nb); 9 | Ct = sparse(1:nl, to, ones(nl, 1), nl, nb); 10 | A = Cf-Ct; 11 | A(:,REF) = []; 12 | 13 | x = mpc.branch(:,4); 14 | D = diag(1./x); 15 | B = A'*D*A; 16 | 17 | end -------------------------------------------------------------------------------- /fun/module_b.m: -------------------------------------------------------------------------------- 1 | function b = module_b(x,alpha) 2 | % This function solves the problem: 3 | % min_(b>=0) alpha*norm(b,1) + 0.5*norm(b-x)^2; 4 | % where x is a Nx1 vector, alpha>0. 5 | idx = find(x > alpha); 6 | b = zeros(length(x),1); 7 | b(idx) = x(idx) - alpha ; 8 | 9 | end -------------------------------------------------------------------------------- /fun/modulehuber.m: -------------------------------------------------------------------------------- 1 | function X = modulehuber(z,Y,alpha,kappa) 2 | % This function solves the problem: 3 | % min_X alpha*huber(X*z,kappa) + 0.5*norm(X-Y,'fro')^2; 4 | % where z is a Nx1 vector, Y is an MxN matrix, alpha>0, and kappa is the 5 | % Huber function parameter 6 | 7 | [M,N] = size(Y); 8 | 9 | t = Y*z; 10 | scalar = z'*z; 11 | 12 | if scalar==0, 13 | X = Y; 14 | else %% scalar>0 15 | g = alpha*kappa*(abs(t) > kappa*(1+alpha*scalar)).*sign(t) + (abs(t) <= kappa*(1+alpha*scalar)).*t/(1/alpha+scalar); 16 | X = Y - g*z'; 17 | end; 18 | 19 | 20 | %%%%%% YALMIP solution follows 21 | % settings = sdpsettings('solver','sedumi','verbose',1); 22 | % 23 | % clear('yalmip') 24 | % X = sdpvar(M,N,'full'); 25 | % 26 | % obj = alpha/2*huber(X*z) + 0.5*norm(X-Y,'fro')^2; 27 | % 28 | % diagnostic = solvesdp([],obj,settings) 29 | % if diagnostic.problem, 30 | % disp([diagnostic.info ' and exiting']); 31 | % solution.X1 = 0; 32 | % return 33 | % end; 34 | % solution.X1 = double(X); -------------------------------------------------------------------------------- /fun/modulel1.m: -------------------------------------------------------------------------------- 1 | function X = modulel1(z,Y) 2 | % This function solves the problem: 3 | % min_X norm(X*z,1) + 0.5*norm(X-Y,'fro')^2; 4 | % where z is a Nx1 vector and Y is an MxN matrix 5 | 6 | [M,N] = size(Y); 7 | 8 | t = Y*z; 9 | scalar = z'*z; 10 | 11 | if scalar==0, 12 | X = Y; 13 | else %% alpha>0 14 | g = sign(t).*min(abs(t)./scalar,1); 15 | X = Y - g*z'; 16 | end; 17 | 18 | % %%%%%% YALMIP solution follows 19 | % settings = sdpsettings('solver','sedumi','verbose',1); 20 | % 21 | % clear('yalmip') 22 | % X = sdpvar(M,N,'full'); 23 | % 24 | % obj = norm(X*z,1) + 0.5*norm(X-Y,'fro')^2; 25 | % 26 | % diagnostic = solvesdp([],obj,settings) 27 | % if diagnostic.problem, 28 | % disp([diagnostic.info ' and exiting']); 29 | % solution.X1 = 0; 30 | % return 31 | % end; 32 | % solution.X1 = double(X); -------------------------------------------------------------------------------- /fun/norm0.m: -------------------------------------------------------------------------------- 1 | function y = norm0(B) 2 | B(abs(B)<1e-4) = 0; 3 | B=B(:); 4 | y = length(find(B~=0)); 5 | end -------------------------------------------------------------------------------- /fun/normalize.m: -------------------------------------------------------------------------------- 1 | function BN = normalize(B) 2 | Bu = triu(B, 1); 3 | Bu = diag(diag(B).^(-1))*Bu; 4 | BN = Bu + Bu' + eye(size(B,1)); 5 | end -------------------------------------------------------------------------------- /fun/plot_mat.m: -------------------------------------------------------------------------------- 1 | function y = plot_mat(B,map,title_txt,norm,e,showtext,savedir) 2 | % y = PLOT_LAP(B,map,norm,e,title_txt,showtext) 3 | %% default arguments 4 | 5 | if nargin < 7 6 | savedir = 'D:\research\MyProject\LMP\Topology\paper\MyPaper\figure\'; 7 | if nargin < 6 8 | showtext = 0; 9 | if nargin < 5 10 | e = 1e-3; 11 | if nargin < 4 12 | norm = 1; 13 | if nargin <3 14 | title_txt = 'MATRIX'; 15 | if nargin <2 16 | map = 'jet'; 17 | end 18 | end 19 | 20 | if nargin < 6 21 | showtext = 0; 22 | if nargin < 5 23 | e = 1e-3; 24 | if nargin < 4 25 | norm = 1; 26 | if nargin <3 27 | title_txt = 'MATRIX'; 28 | if nargin <2 29 | map = 'jet'; 30 | 31 | end 32 | end 33 | end 34 | end 35 | 36 | B = double(B); 37 | B(abs(B) 0 43 | ceil = max(max(L)); 44 | if ceil > 0 45 | L(L>0) = L(L>0)/ceil; 46 | end 47 | floor = min(min(L)); 48 | if floor < 0 49 | L(L<0) = -L(L<0)/floor; 50 | end 51 | end 52 | image(L,'CDataMapping','scaled'), 53 | colorbar 54 | if showtext 55 | hold on; 56 | for i = 1:size(L,1) 57 | for j = 1:size(L,2) 58 | nu = L(i,j); 59 | val = num2str(round(nu,2)); 60 | text(i,j,val) 61 | end 62 | end 63 | hold off; 64 | end 65 | %title(title_txt,'FontSize', 13, 'FontName', 'Times New Roman'); 66 | xlabel('Bus Node', 'FontSize', 13, 'FontName', 'Times New Roman'); 67 | ylabel('Bus Node', 'FontSize', 13,'FontName', 'Times New Roman'); 68 | set(gca,'FontSize',12,'Fontname', 'Times New Roman'); 69 | print(['figure/',title_txt,'.eps'],'-depsc'); 70 | end -------------------------------------------------------------------------------- /fun/rmse.m: -------------------------------------------------------------------------------- 1 | function y = rmse(y1,y2) 2 | y0 = y1(:)-y2(:); 3 | y = sqrt(mean(y0.^2)); 4 | end -------------------------------------------------------------------------------- /fun/solveB1.m: -------------------------------------------------------------------------------- 1 | function B_solve = solveB1(xt, Q2, B1, B2, B3, B4, B5, M12, M13, M14, M15, m10, b, rho, eta, k, lossless) 2 | 3 | N = size(B1,1); 4 | e = ones(N,1); 5 | C = rho*(B2 + B3 + B4 + B5 - M12 - M13 - M14 - M15 + b * e' - m10 * e' + eta/rho*B1); 6 | B1C = C * Q2; 7 | 8 | xt = Q2*xt; 9 | if lossless 10 | B_solve = modulel1(xt,B1C) * Q2; 11 | else 12 | B_solve = modulehuber(xt,B1C,1,k(4)) * Q2; 13 | end 14 | 15 | % settings = sdpsettings('solver', 'sedumi','verbose',1); 16 | % 17 | % clear('yalmip'); 18 | % B = sdpvar(N,N); 19 | % 20 | % obj = norm(B*xt,1) + ... 21 | % rho/2 * norm((B-B2+M12),'fro')^2 + rho/2 * norm((B-B3+M13),'fro')^2 + ... 22 | % rho/2 * norm((B-B4+M14),'fro')^2 + rho/2 * norm((B*e-b+m10),2)^2 + ... 23 | % eta/2 * norm((B-B1),'fro')^2; 24 | % 25 | % optimize([], obj, settings); 26 | % 27 | % B_solve = value(B); 28 | 29 | end 30 | 31 | -------------------------------------------------------------------------------- /fun/solveB4.m: -------------------------------------------------------------------------------- 1 | function B_solve = solveB4(B1, M14, rho, k, T) 2 | 3 | N = size(B1, 1); 4 | B_solve = zeros(N,N); 5 | 6 | C = B1 + M14; 7 | rowC = sqrt(sum(C.^2,2)); 8 | idx = rho*rowC > k(1)/T; 9 | 10 | rowB = (rho*rowC(idx)-k(1)/T)/rho; 11 | B_solve(idx,:) = rho*C(idx,:)./(rho + k(1)/T./rowB); 12 | 13 | end -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | %% 2 | % preprocess 3 | clear, 4 | clc, 5 | addpath('src') 6 | addpath('case') 7 | addpath('fun') 8 | mpc = loadcase('case30'); 9 | REF = find(mpc.bus(:,2)==3); 10 | % delete 'data/KaggleLoads.mat' 11 | 12 | try 13 | load data/KaggleLoads.mat 14 | catch error 15 | disp('Load .mat file does not exist. Generating...') 16 | data_preprocess, 17 | end 18 | block_offer, 19 | db = create_db(mpc,KaggleLoads./0.625,c,pmin,pmax); 20 | clear c pmin pmax, 21 | 22 | %% 23 | % real time market or load the market data. 24 | run_rt = 0; 25 | if run_rt ==1 26 | run_rtmarket 27 | else 28 | load data/mdata.mat 29 | end 30 | load_idx = find(mdata.loads(:,1)>0)'; 31 | %% 32 | % online admm 33 | % load data/Market_with_changes.mat 34 | 35 | Bo = makeBmatrix(mpc); 36 | 37 | L0 = get_lap(Bo,REF); 38 | 39 | plot_mat(L0,'jet','B0 in IEEE case30'); 40 | Bo = Bo / max(max(Bo)); 41 | plot_mat(Bo,'jet','B in IEEE case30'); 42 | 43 | % mdata.PricesClean = normc(mdata.PricesClean); 44 | acc=[]; 45 | tpr=[]; 46 | fpr=[]; 47 | for k = 3:30 48 | rows = []; 49 | cols = []; 50 | vals = []; 51 | for i = 1:28 52 | for j = k:29 53 | if j <= i 54 | continue 55 | end 56 | rows = [rows; i]; 57 | cols = [cols; j]; 58 | vals = [vals; Bo(i,j)]; 59 | end 60 | end 61 | 62 | [~,jb] = rref(mdata.PricesClean(:,1:10)); 63 | B_part = B_partial(mdata.PricesClean(:,jb),[0.01,0.01,0.01*2],rows,cols,vals); 64 | L_part = get_lap(B_part,REF); 65 | [ACC, TPR, FPR] = evaluation(L0(1:k-1,1:k-1), L_part(1:k-1,1:k-1)); 66 | acc = [acc, ACC]; 67 | tpr = [tpr, TPR(1)]; 68 | fpr = [fpr, FPR(1)]; 69 | % plot_mat(B_part,'jet') 70 | end 71 | figure, 72 | plot(acc) 73 | 74 | B_my = B_estimate(mdata.PricesClean(:,1:jb),[0.01,0.01,0.01*2]); 75 | 76 | baseline = evaluation(L0, get_lap(B_my,REF)); 77 | 78 | hold on, 79 | plot(1:30,baseline,'r*'); 80 | hold off; 81 | 82 | acc2 = zeros(29,29); 83 | for i = 1:28 84 | for j = i+1:29 85 | if Bo(i,j) == 0 86 | continue 87 | end 88 | B_part = B_partial(mdata.PricesClean(:,1:jb),[0.01,0.01,0.01*2],i,j,Bo(i,j)); 89 | L_part = get_lap(B_part,REF); 90 | acc2(i,j) = evaluation(L0, L_part); 91 | end 92 | end 93 | figure, 94 | plot(acc2(acc2>0)) 95 | 96 | hold on, 97 | plot(1:41,baseline,'r*'); 98 | hold off; 99 | 100 | plot_mat(B_my,'jet','B my'); 101 | B_keka = B_Kekatos(mdata.PricesClean(:,1:10),[0.01,0.01]); 102 | plot_mat(B_keka,'jet','B keka'); 103 | online_results = online_admm2(mdata.PricesClean(:,10:end), 0.01*[1,1], B_my); 104 | online_results2 = online_admm(mdata.PricesClean(:,10:end), 0.01*[1,1], B_keka); 105 | B_final = online_results.B3(:,:,end); 106 | plot_mat(B_final,'jet','B1'); 107 | L_final = get_lap(B_final,REF); 108 | plot_mat(L_final,'jet','L1'); 109 | B_final2 = online_results2.B3(:,:,end); 110 | plot_mat(B_final2,'jet','B2'); 111 | L_final2 = get_lap(B_final2,REF); 112 | plot_mat(L_final2,'jet','L2'); 113 | 114 | 115 | a = online_results.B3(22,25,:); 116 | b = online_results2.B3(22,25,:); 117 | AUC = zeros(1,length(a)); 118 | AUC2 = zeros(1,length(a)); 119 | parfor i = 1:length(a) 120 | B_final = online_results.B3(:,:,i); 121 | L_final = get_lap(B_final,REF); 122 | 123 | B_final2 = online_results2.B3(:,:,i); 124 | L_final2 = get_lap(B_final2,REF); 125 | AUC(i) = evaluation(L0,L_final); 126 | AUC2(i) = evaluation(L0,L_final2); 127 | end 128 | figure, hold on, 129 | axis([0,9000,0.5,1]) 130 | plot(AUC,'r-'),plot(AUC2,'b-') 131 | hold off 132 | 133 | %% 134 | % [f,t,x] = get_ftx(L_final, 200); 135 | 136 | 137 | 138 | %% 139 | % constructing PTDF matrix from the inferred Laplacian matrix 140 | 141 | for time = 1000:size(mdata.PricesClean,2)-288 142 | t = mdata.index(time); 143 | fprintf('time=%d\n',time) 144 | L_infered = get_lap(online_results.B3(:,:,end),REF); 145 | avg_degree = mean(diag(L_infered)); 146 | L_infered = L_infered/avg_degree * mean(diag(L0)); 147 | db_infered = L2A(L_infered, REF); 148 | Pf = diag(db_infered.x)*db_infered.Ar*db_infered.Bri* ... 149 | (mdata.gen(2:end,1:t)-mdata.loads(2:end,1:t) ); 150 | db_infered.flowlimit = max(abs(Pf),[],2); 151 | 152 | train_error_min = 100; 153 | while (1) 154 | db_infered = line_reduce(db_infered, mdata ,REF, 1:t); 155 | fprintf('nl=%d\n',db_infered.L) 156 | if db_infered.L <= 80 157 | tt = mdata.index((time-287):time); 158 | db_infered.pmin = db.pmin; db_infered.pmax = db.pmax; 159 | mdata2 = get_lmp(db_infered, mdata, tt); 160 | PI = mdata.Prices(:,tt) + repmat(mdata.mu0(:,tt),db.N-1,1); 161 | PI2 = mdata2.Prices + repmat(mdata2.mu0,db.N-1,1); 162 | train_error = rmse(PI(load_idx-1,mdata2.index), PI2(load_idx-1,mdata2.index)); 163 | fprintf('training rmse=%g\n',train_error) 164 | if train_error0); 11 | LoadBase = mpc.bus(LoadBuses,3); 12 | KaggleLoads = get_load('data/Load_history.csv',2008,1); 13 | NormalizedLoads = []; 14 | for day = 1:31 15 | Daily = KaggleLoads(:,(day-1)*24+1:day*24); 16 | DailyMax = diag(max(Daily,[],2)); 17 | NormalizedLoads = [NormalizedLoads DailyMax\Daily]; 18 | end 19 | loads = diag(LoadBase)*NormalizedLoads; 20 | 21 | %% load cost function and generator output limit 22 | block_offer, 23 | db = create_db(mpc,loads./0.625,c,pmin,pmax); 24 | 25 | %% 26 | clear mdata, 27 | % real time market or load the market data. 28 | run_rt = 1; 29 | if run_rt ==1 30 | run_lossy_market 31 | else 32 | load data/mdata_lossy.mat 33 | end 34 | load_idx = find(mdata.loads(:,1)>0)'; 35 | %% 36 | -------------------------------------------------------------------------------- /offline.m: -------------------------------------------------------------------------------- 1 | %% initialize 2 | clear; 3 | clc; 4 | addpath('src'); 5 | addpath('case'); 6 | addpath('fun'); 7 | mpc = case30(); 8 | REF = find(mpc.bus(:,2)==3); 9 | 10 | %% load data 11 | load data/mdata.mat 12 | 13 | %% recovery 14 | B = makeBmatrix(mpc); 15 | B0 = get_lap(B, REF); 16 | B = normalize(B); 17 | B0 = normalize(B0); 18 | Prices = mdata.PricesClean; 19 | T = size(Prices,2); 20 | k = [sqrt(T), sqrt(T), sqrt(T)]; 21 | 22 | %% find subspace of LMP matrix 23 | [~,jb] = rref(mdata.PricesClean); 24 | tic; 25 | Br = B_estimate(mdata.PricesClean(:,jb),k); 26 | toc; 27 | %B_r2 = B_estimate(mdata.PricesClean(:,1:500),[0.01,0.01,0.02]); 28 | 29 | %% 30 | Br0 = get_lap(Br, REF); 31 | Br0 = normalize(Br0); 32 | [AUC, TPR, FPR] = evaluation(B0, Br0); 33 | 34 | %plot_mat(B_r1,'jet','Br in IEEE case30'); 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /online.m: -------------------------------------------------------------------------------- 1 | %% initialize 2 | clear; 3 | clc; 4 | addpath('src'); 5 | addpath('case'); 6 | addpath('fun'); 7 | mpc = case118(); 8 | REF = find(mpc.bus(:,2)==3); 9 | B = makeBmatrix(mpc); 10 | B0 = get_lap(B, REF); 11 | B = normalize(B); 12 | B0 = normalize(B0); 13 | plot_mat(B,'jet','B in IEEE case118'); 14 | plot_mat(B0,'jet','L in IEEE case118'); 15 | N = size(B,1); 16 | 17 | %% load data 18 | load data/mdata118.mat 19 | Prices = mdata.PricesClean; 20 | %Prices = Prices(2:end,:); 21 | lossless = 1; 22 | T = size(Prices,2); 23 | k = [sqrt(T), sqrt(T), sqrt(T), 0.03]; 24 | 25 | count = 0; 26 | AllLines = find(mpc.branch(:,1) ~= REF); 27 | KnownLines = sort(randperm(size(AllLines,1), count)); 28 | KnownPart.time = sort(randperm(T, count))'; 29 | KnownPart.lines = AllLines(KnownLines); 30 | 31 | %% odam 32 | %output = online_admm2(Prices, 0.01*[1,1]); 33 | cycle = 1; 34 | t1 = clock; 35 | for i = 1:cycle 36 | output = online_admm3(Prices, k, mpc, B0, lossless, KnownPart); 37 | end 38 | t2 = clock; 39 | Br0 = get_lap(output.B(:,:,end), REF); 40 | Br0 = normalize(Br0); 41 | [AUC, TPR, FPR] = evaluation(B0, Br0); 42 | fprintf('Mean time: %.4f.\n',etime(t2,t1)/cycle); 43 | fprintf('Mean loss: %.4f.\n',AUC); 44 | 45 | %% evaluate 46 | acc = zeros(floor(size(Prices,2)/10)+1,1); 47 | i = 1; 48 | for t = 1:size(Prices,2) 49 | if rem(t,10) == 0 || t == size(Prices,2) 50 | Br = output.B(:,:,t); 51 | Br0 = get_lap(Br, REF); 52 | Br0 = normalize(Br0); 53 | [ACC, TPR, FPR] = evaluation(B0, Br0); 54 | acc(i,1) = ACC; 55 | i = i+1; 56 | end 57 | end 58 | 59 | %% plot 60 | figure, 61 | plot(acc); 62 | hold on 63 | sz = 20; 64 | scatter(KnownPart.time, acc(KnownPart.time,1), sz,'MarkerEdgeColor','k',... 65 | 'MarkerFaceColor','k',... 66 | 'LineWidth',1.5); 67 | hold off 68 | 69 | %% plot TPR-FPR 70 | figure, 71 | plot([1;FPR;0],[1;TPR;0]); 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/block_offer.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengkd95/LMP-inferring/58cb93ab5a2dc8e0806c3d90c8c7f251b6354f20/src/block_offer.m -------------------------------------------------------------------------------- /src/create_db.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengkd95/LMP-inferring/58cb93ab5a2dc8e0806c3d90c8c7f251b6354f20/src/create_db.m -------------------------------------------------------------------------------- /src/data_preprocess.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengkd95/LMP-inferring/58cb93ab5a2dc8e0806c3d90c8c7f251b6354f20/src/data_preprocess.m -------------------------------------------------------------------------------- /src/dc_opf_Litvinov.m: -------------------------------------------------------------------------------- 1 | function market = dc_opf_Litvinov(loads,c,T,flowlimit,pmin,pmax,LF,l0,D) 2 | % market = dc_opf_Litvinov(loads,c,T,flowlimit,pmin,pmax,loss,LF,l0,D) 3 | % 4 | N = size(T,2); 5 | % T(:,ref) = []; 6 | market.loads = loads; 7 | market.c = c; 8 | tic, 9 | settings = sdpsettings('solver','cplex','verbose',0); 10 | clear('yalmip') 11 | P = sdpvar(N,5); 12 | loss = sdpvar(1); 13 | F = [(pmin<=P):'Pmin', (P<=pmax):'Pmax', ... 14 | (sum(loads-sum(P,2))+loss==0):'balance',... 15 | (loss == LF'*(sum(P,2)-loads)+l0):'loss',... 16 | (-flowlimit<=T*(sum(P(1:end,:),2)-loads(1:end)-D*loss )):'conlow',... 17 | (T*(sum(P(1:end,:),2)-loads(1:end)-D*loss )<=flowlimit):'conhigh']; 18 | 19 | diagnostic = optimize(F,c(:)'*P(:),settings); 20 | 21 | if diagnostic.problem, 22 | %% typically infeasible problem 23 | market.mu0 = 0; 24 | %market.mul = inf*ones(db.L,1); 25 | %market.muh = inf*ones(db.L,1); 26 | market.p = zeros(N,1); 27 | market.P = zeros(N,1); 28 | % market.s = zeros(db.N-1,1); 29 | market.price = zeros(N,1); 30 | market.MEP = zeros(N,1); 31 | market.MCP = zeros(N,1); 32 | market.MLP = zeros(N,1); 33 | market.loss = 0; 34 | else 35 | market.mu0 = double(dual(F('balance'))); 36 | market.mul = double(dual(F('conlow'))) .* (abs(double(dual(F('conlow'))))>1e-6); 37 | market.muh = double(dual(F('conhigh'))) .* (abs(double(dual(F('conhigh'))))>1e-6); 38 | market.tau = double(dual(F('loss'))); 39 | market.p = sum(double(P),2); 40 | market.P = double(P); 41 | market.loss = double(loss); 42 | % market.s = db.Ar'*diag(db.x)*(market.mul-market.muh); 43 | % market.price = T'*(market.mul - market.muh); 44 | market.MEP = -market.tau * ones(N,1); 45 | market.MLP = market.tau * LF; 46 | market.MCP = T' * (market.mul-market.muh) - (T*D*ones(1,N))' * (market.mul-market.muh); 47 | market.price = market.MEP + market.MLP + market.MCP; 48 | % if max(abs(market.price)) > 1.5e1 49 | % market.rare = 1; 50 | % end 51 | end; 52 | 53 | if diagnostic.problem, 54 | str = 'Infeasible.'; 55 | market.success = 0; 56 | market.cong = 0; 57 | else 58 | market.success = 1; 59 | if sum(abs(market.mul-market.muh))==0, 60 | str = 'No congestion.'; 61 | market.cong = 0; 62 | else 63 | str = ''; 64 | market.cong = 1; 65 | end; 66 | end; 67 | t = toc; 68 | % fprintf('Demand: %g. Capacity: %g. %s Time: %g\n', sum(loads),sum(sum(pmax)),str,t) 69 | 70 | end -------------------------------------------------------------------------------- /src/line_reduce.m: -------------------------------------------------------------------------------- 1 | function db2 = line_reduce(db, mdata, REF, time) 2 | % function [L2, f2, t2, x2, T2] = line_reduce(limit, L2, f2, t2, REF) 3 | j = find(db.flowlimit == min(db.flowlimit)); 4 | m = find(db.A(j,:)==1); 5 | n = find(db.A(j,:)==-1); 6 | L2 = db.Lap; 7 | L2(m,m) = L2(m,m) + L2(m,n); 8 | L2(n,n) = L2(n,n) + L2(m,n); 9 | L2(m,n) = 0; 10 | L2(n,m) = 0; 11 | db2 = L2A(L2,REF); 12 | Pf = diag(db2.x)*db2.Ar*db2.Bri* ... 13 | (mdata.gen(2:end,time)-mdata.loads(2:end,time) ); 14 | db2.flowlimit = max(abs(Pf),[],2); 15 | end -------------------------------------------------------------------------------- /src/lossless_LMP.m: -------------------------------------------------------------------------------- 1 | try 2 | load data/KaggleLoads.mat 3 | catch error 4 | disp('Load .mat file does not exist. Generating...') 5 | data_preprocess, 6 | end -------------------------------------------------------------------------------- /src/lossy_LMP.m: -------------------------------------------------------------------------------- 1 | % initialize 2 | l0 = 0; 3 | LF = zeros(db.N,1); 4 | D = zeros(db.N,1); 5 | market = dc_opf_Litvinov(dailyload,db.c,db.T,db.flowlimit,db.pmin,db.pmax,LF,l0,D); 6 | % solve dc power flow 7 | mpc.bus(:,3) = dailyload; 8 | mpc.gen(:,2) = market.p(mpc.gen(:,1)); 9 | pf_results = runpf(mpc, mpopt); 10 | % update parameters 11 | r = mpc.branch(:,3); 12 | l0_temp = l0; 13 | p_branch = (pf_results.branch(:,14) - pf_results.branch(:,16))/2; 14 | p_branch = p_branch / mpc.baseMVA; 15 | LF = 2*(r.*p_branch)'*db.T; 16 | LF = LF'; 17 | Pg = zeros(db.N,1); 18 | Pg(pf_results.gen(:,1),1) = pf_results.gen(:,2); 19 | l0 = market.loss - LF'*(Pg-dailyload); 20 | from = mpc.branch(:,1); 21 | to = mpc.branch(:,2); 22 | Ei = zeros(db.N,1); 23 | for i = 1:db.N 24 | Mi = find(from == i | to == i); 25 | Ei(i) = 0.5 * p_branch(Mi)'.^2 * r(Mi); 26 | end 27 | D = Ei/sum(Ei); 28 | % convergence 29 | while abs(l0_temp-l0)>=1e-3 30 | l0_temp = l0; 31 | market = dc_opf_Litvinov(dailyload,db.c,db.T,db.flowlimit,db.pmin,db.pmax,LF,l0,D); 32 | mpc.gen(:,2) = market.p(mpc.gen(:,1)); 33 | pf_results = runpf(mpc, mpopt); 34 | p_branch = (pf_results.branch(:,14) - pf_results.branch(:,16))/2; 35 | p_branch = p_branch / mpc.baseMVA; 36 | LF = 2*(r.*p_branch)'*db.T; 37 | LF = LF'; 38 | Pg = zeros(db.N,1); 39 | Pg(pf_results.gen(:,1),1) = pf_results.gen(:,2); 40 | l0 = market.loss - LF'*(Pg-dailyload); 41 | from = mpc.branch(:,1); 42 | to = mpc.branch(:,2); 43 | Ei = zeros(db.N,1); 44 | for i = 1:db.N 45 | Mi = find(from == i | to == i); 46 | Ei(i) = 0.5 * p_branch(Mi)'.^2 * r(Mi); 47 | end 48 | D = Ei/sum(Ei); 49 | end 50 | -------------------------------------------------------------------------------- /src/online_admm.m: -------------------------------------------------------------------------------- 1 | function output = online_admm(Prices,k,Bo) 2 | % output = online_admm(Prices,k,Bo); 3 | % It solves the online convex recovery scheme using online ADMM (Banerjee's) on matrix Prices, 4 | % having parameters k = [k1 k2 k3], and with possible initialization at Bo. 5 | % If length(k)==3, then the Huber option is activated, otherwise it is only 6 | % the ell-1 norm cost. 7 | 8 | [N,T] = size(Prices); 9 | 10 | huber = (length(k)==3); 11 | 12 | % admm parameter 13 | rho = sqrt(T); 14 | eta = sqrt(T); 15 | % cost = zeros(ITER,1); 16 | 17 | errorIsBig = true; 18 | iteration = 0; 19 | 20 | %% INITIALIZATION 21 | if nargin<=2, 22 | % primal variables 23 | B1 = eye(N,N); B2 = eye(N,N); B3 = eye(N,N); 24 | S = Prices; 25 | % dual variables 26 | else 27 | B1 = Bo; B2 = Bo; B3 = Bo; 28 | S = Bo*Prices; 29 | end; 30 | M12 = zeros(N,N); 31 | M13 = zeros(N,N); 32 | 33 | P = eye(N) - ones(N,N); 34 | 35 | %% TIME ITERATIONS 36 | output.B3 = zeros(N,N,T); 37 | for time = 1:T, 38 | tic; 39 | %% B1 update 40 | B1c = rho/(2*rho+eta)*(B2 + B3 - M12 - M13) + (eta/(2*rho+eta))*B1 - k(1)/(2*T*(2*rho+eta))*P; 41 | if huber, 42 | B1 = modulehuber(Prices(:,time),B1c,1/(2*rho+eta),k(3)); 43 | else 44 | B1 = modulel1(Prices(:,time)/(2*rho+eta),B1c); 45 | end; 46 | 47 | %% B2 update 48 | B2 = min(B1+M12,eye(N)); 49 | 50 | %% B3 update 51 | Temp = B1 + M13; 52 | Temp = (Temp + Temp')/2; % symmetricized 53 | [U,v] = eig(Temp); 54 | v = diag(v); 55 | B3 = U*diag(v + sqrt(v.^2 + 4*k(2)/T/rho))*U'/2; 56 | output.B3(:,:,time) = B3; 57 | 58 | %% Lagrange multipliers update 59 | M12 = M12 + B1 - B2; 60 | M13 = M13 + B1 - B3; 61 | 62 | cost(time) = sum(sum(abs(S))) + k(1)*trace(P*B1) - k(2)*log(det(B3)); 63 | 64 | % disp(['Iteration ' num2str(iteration) '. Error ' num2str(error) '; Primal:' num2str(error_pri) '; Dual:' num2str(error_dual) '; Cost: ' num2str(cost(iteration))]); 65 | toc 66 | end; 67 | 68 | output.B1 = B1; 69 | output.B2 = B2; 70 | output.B = B3; 71 | output.M12 = M12; 72 | output.M13 = M13; 73 | output.cost = cost; 74 | 75 | clk = clock; 76 | str = ['oADMM' num2str(clk(1)) '_' num2str(clk(2)) '_' num2str(clk(3)) '_' num2str(clk(4)) '.' num2str(clk(5)) '.' num2str(clk(6)) '.mat']; 77 | save(['data/',str],'output'); -------------------------------------------------------------------------------- /src/online_admm2.m: -------------------------------------------------------------------------------- 1 | function output = online_admm2(Prices,k,Bo) 2 | % The modified method 3 | % output = online_admm2(Prices,k,Bo); 4 | % It solves the online convex recovery scheme using online ADMM (Banerjee's) on matrix Prices, 5 | % having parameters k = [k1 k2 k3], and with possible initialization at Bo. 6 | % If length(k)==3, then the Huber option is activated, otherwise it is only 7 | % the ell-1 norm cost. 8 | 9 | [N,T] = size(Prices); 10 | 11 | huber = (length(k)==3); 12 | 13 | % admm parameter 14 | rho = sqrt(T); 15 | eta = sqrt(T); 16 | % cost = zeros(ITER,1); 17 | 18 | errorIsBig = true; 19 | iteration = 0; 20 | 21 | e = ones(N,1); 22 | %% INITIALIZATION 23 | if nargin<=2, 24 | % primal variables 25 | B1 = eye(N,N); B2 = eye(N,N); B3 = eye(N,N); b = e; 26 | S = Prices; 27 | % dual variables 28 | else 29 | B1 = Bo; B2 = Bo; B3 = Bo; b = Bo*e; 30 | S = Bo*Prices; 31 | end; 32 | M12 = zeros(N,N); 33 | M13 = zeros(N,N); 34 | m10 = zeros(N,1); 35 | 36 | P = eye(N) - ones(N,N); 37 | Q = (2*rho+eta) * eye(N,N) + rho * (e * e'); 38 | [V,D,W] = eig(Q); 39 | Q2 = W*(D.^0.5)*W'; 40 | Q2 = Q2^(-1); 41 | 42 | %% TIME ITERATIONS 43 | output.B3 = zeros(N,N,T); 44 | for time = 1:T, 45 | tic; 46 | %% B1 update 47 | B1c = rho*(B2 + B3 - M12 - M13 + b * e' - m10 * e' + ... 48 | eta/rho*B1 - k(1)/(T*rho)*P) * Q2 ; 49 | pt = Q2 * Prices(:,time); 50 | if huber, 51 | B1 = modulehuber(pt,B1c,1,k(3)) * Q2; 52 | else 53 | B1 = modulel1(pt,B1c) * Q2; 54 | end; 55 | 56 | %% B2 update 57 | B2 = min(B1+M12,eye(N)); 58 | 59 | %% B3 update 60 | Temp = B1 + M13; 61 | Temp = (Temp + Temp')/2; % symmetricized 62 | [U,v] = eig(Temp); 63 | v = diag(v); 64 | B3 = U*diag(v + sqrt(v.^2 + 4*k(2)/T/rho))*U'/2; 65 | output.B3(:,:,time) = B3; 66 | 67 | %% b update 68 | b = module_b(B1*e+m10, k(1)/(N-1)/T/rho); 69 | 70 | %% Lagrange multipliers update 71 | M12 = M12 + B1 - B2; 72 | M13 = M13 + B1 - B3; 73 | m10 = m10 + B1*e - b; 74 | cost(time) = sum(sum(abs(S))) + k(1)*trace(P*B1) - k(2)*log(det(B3)) + k(1)/(N-1)*norm(b,1); 75 | 76 | % disp(['Iteration ' num2str(iteration) '. Error ' num2str(error) '; Primal:' num2str(error_pri) '; Dual:' num2str(error_dual) '; Cost: ' num2str(cost(iteration))]); 77 | toc; 78 | if rem(time,1000) == 0 79 | plot_mat(B3,'jet','Br in IEEE case30'); 80 | end 81 | end; 82 | 83 | output.B1 = B1; 84 | output.B2 = B2; 85 | output.B = B3; 86 | output.b = b; 87 | output.M12 = M12; 88 | output.M13 = M13; 89 | output.m10 = m10; 90 | output.cost = cost; 91 | 92 | clk = clock; 93 | str = ['oADMM' num2str(clk(1)) '_' num2str(clk(2)) '_' num2str(clk(3)) '_' num2str(clk(4)) '.' num2str(clk(5)) '.' num2str(clk(6)) '.mat']; 94 | save(['data/',str],'output'); 95 | -------------------------------------------------------------------------------- /src/online_admm3.m: -------------------------------------------------------------------------------- 1 | function output = online_admm3(Prices, k, mpc, B_origin, lossless, KnownPart, B0) 2 | 3 | T = size(Prices,2); 4 | N = size(mpc.bus,1)-1; 5 | 6 | rho = sqrt(T); 7 | eta = sqrt(T); 8 | 9 | e = ones(N,1); 10 | 11 | if nargin<=6 12 | % primal variables 13 | B1 = eye(N,N); B2 = eye(N,N); B3 = eye(N,N); B4 = eye(N,N); B5 = eye(N,N); 14 | b = ones(N,1); 15 | % dual variables 16 | else 17 | B1 = B0; B2 = B0; B3 = B0; B4 = B0; 18 | b = B0*e; 19 | end 20 | M12 = zeros(N,N); 21 | M13 = zeros(N,N); 22 | M14 = zeros(N,N); 23 | M15 = zeros(N,N); 24 | m10 = zeros(N,1); 25 | 26 | Q = (4*rho+eta) * eye(N,N) + rho * (e * e'); 27 | [V,D,W] = eig(Q); 28 | Q2 = W*(D.^0.5)*W'; 29 | Q2 = Q2^(-1); 30 | 31 | output.B = zeros(N,N,T); 32 | for t = 1:T 33 | %tic; 34 | xt = Prices(:,t); 35 | %% B1 update 36 | B1 = solveB1(xt, Q2, B1, B2, B3, B4, B5, M12, M13, M14, M15, m10, b, rho, eta, k, lossless); 37 | output.B(:,:,t) = B1; 38 | %B1 = complete(B1, t, B_origin, KnownPart, mpc); 39 | %% B2 update 40 | B2 = min(B1+M12,eye(N)); 41 | %B2 = complete(B2, t, B_origin, KnownPart, mpc); 42 | %% B3 update 43 | Temp = B1 + M13; 44 | Temp = (Temp + Temp')/2; % symmetricized 45 | [U,v] = eig(Temp); 46 | v = diag(v); 47 | B3 = U*diag(v + sqrt(v.^2 + 4*k(2)/T/rho))*U'/2; 48 | %B3 = complete(B3, t, B_origin, KnownPart, mpc); 49 | %% B4 update 50 | B4 = solveB4(B1, M14, rho, k, T); 51 | %B4 = complete(B4, t, B_origin, KnownPart, mpc); 52 | %% B5 update 53 | B5 = B1 + M15; 54 | B5 = complete(B5, t, B_origin, KnownPart, mpc); 55 | %output.B(:,:,t) = B5; 56 | %% b update 57 | b = module_b(B1*e+m10, k(3)/T/rho); 58 | %% Lagrange multipliers update 59 | M12 = M12 + B1 - B2; 60 | M13 = M13 + B1 - B3; 61 | M14 = M14 + B1 - B4; 62 | M15 = M15 + B1 - B5; 63 | m10 = m10 + B1*e - b; 64 | %toc; 65 | %if rem(t,1000) == 0 66 | % plot_mat(B5,'jet','Br in IEEE case30'); 67 | %end 68 | end 69 | 70 | output.B1 = B1; 71 | output.B2 = B2; 72 | output.B3 = B3; 73 | output.B4 = B4; 74 | output.B5 = B5; 75 | output.b = b; 76 | output.M12 = M12; 77 | output.M13 = M13; 78 | output.M14 = M14; 79 | output.M15 = M15; 80 | output.m10 = m10; 81 | 82 | %clk = clock; 83 | %str = ['oADMM' num2str(clk(1)) '_' num2str(clk(2)) '_' num2str(clk(3)) '_' num2str(clk(4)) '.' num2str(clk(5)) '.' num2str(clk(6)) '.mat']; 84 | %save(['data/',str],'output'); 85 | 86 | end 87 | 88 | -------------------------------------------------------------------------------- /src/rtmarket.m: -------------------------------------------------------------------------------- 1 | function market = rtmarket(db, h) 2 | % function market = rtmarket(h); 3 | % Function for running the real-time market corresponding to a single 5-min 4 | % interval in the hour indicated by input h. Piece-wise linear up to 5 5 | % implemented. 6 | % After loading the database file db30.mat (see nced.m), it draws randomly costs and load demands, 7 | % and then solves the linear program involved using YALMIP. Lagrange 8 | % multipliers and prices are stored in output structure market. 9 | 10 | % load db30.mat 11 | 12 | %% sample random quantities 13 | loads = db.loads(:,h) + sqrt(db.loads(:,h)/10).*randn(db.N,1); 14 | market.loads = loads; 15 | market.rare = 0; 16 | 17 | c = db.c + (((rand(db.N,1) - 0.5)*5) * ones(1,5)) .* (db.c~=0); 18 | market.c = c; 19 | %% Solve market using yalmip 20 | tic, 21 | settings = sdpsettings('solver','cplex','verbose',0); 22 | clear('yalmip') 23 | P = sdpvar(db.N,5); 24 | F = [(db.pmin<=P):'Pmin', (P<=db.pmax):'Pmax', ... 25 | (sum(loads-sum(P,2))==0):'balance',... 26 | (-db.flowlimit<=diag(db.x)*db.Ar*db.Bri*(sum(P(2:end,:),2)-loads(2:end) )):'conlow',... 27 | (diag(db.x)*db.Ar*db.Bri*(sum(P(2:end,:),2)-loads(2:end) )<=db.flowlimit):'conhigh']; 28 | 29 | diagnostic = optimize(F,c(:)'*P(:),settings); 30 | if diagnostic.problem, 31 | %% typically infeasible problem 32 | market.mu0 = 0; 33 | market.mul = inf*ones(db.L,1); 34 | market.muh = inf*ones(db.L,1); 35 | market.p = zeros(db.N,1); 36 | market.P = zeros(db.N,1); 37 | market.s = zeros(db.N-1,1); 38 | market.price = zeros(db.N-1,1); 39 | else 40 | market.mu0 = double(dual(F('balance'))); 41 | market.mul = double(dual(F('conlow'))) .* (abs(double(dual(F('conlow'))))>1e-6); 42 | market.muh = double(dual(F('conhigh'))) .* (abs(double(dual(F('conhigh'))))>1e-6); 43 | market.p = sum(double(P),2); 44 | market.P = double(P); 45 | market.s = db.Ar'*diag(db.x)*(market.mul-market.muh); 46 | market.price = db.Bri*market.s; 47 | if max(abs(market.price)) > 1.5e2 48 | market.rare = 1; 49 | end 50 | end; 51 | 52 | if diagnostic.problem, 53 | str = 'Infeasible.'; 54 | market.success = 0; 55 | market.cong = 0; 56 | else 57 | market.success = 1; 58 | if sum(abs(market.mul-market.muh))==0, 59 | str = 'No congestion.'; 60 | market.cong = 0; 61 | else 62 | str = ''; 63 | market.cong = 1; 64 | end; 65 | end; 66 | t = toc; 67 | fprintf('Demand: %g. Capacity: %g. %s Time: %g\n', sum(loads),sum(sum(db.pmax)),str,t) 68 | %disp(['Demand: ' num2str(sum(loads)) '. Capacity: ' num2str(sum(sum(db.pmax))) '. ' str]) 69 | 70 | -------------------------------------------------------------------------------- /src/run_lossy_market.m: -------------------------------------------------------------------------------- 1 | %% 2 | % run lossy real time market 3 | mpopt = mpoption; 4 | mpopt.out.all = 0; 5 | mpopt.model = 'DC'; 6 | disp('generating LMP for every 5 minutes...'); 7 | mdata.Prices = []; 8 | mdata.MEP = []; 9 | mdata.MCP = []; 10 | mdata.MLP = []; 11 | mdata.index = []; 12 | mdata.loads = []; 13 | mdata.gen = []; 14 | mdata.loss = []; 15 | mdata.c = []; 16 | for h = 1:744 17 | fprintf('hour %d:\n',h); 18 | dailyload = db.loads(:,h); 19 | lossy_LMP, 20 | for i = 1:12 21 | dailyload = db.loads(:,h) + sqrt(db.loads(:,h)/10).*randn(db.N,1); 22 | c = db.c + (((rand(db.N,1) - 0.5)*5) * ones(1,5)) .* (db.c~=0); 23 | market = dc_opf_Litvinov(dailyload,c,db.T,db.flowlimit,db.pmin,db.pmax,LF,l0,D); 24 | mdata.Prices = [mdata.Prices, market.price]; 25 | mdata.MEP = [mdata.MEP, market.MEP]; 26 | mdata.MCP = [mdata.MCP, market.MCP]; 27 | mdata.MLP = [mdata.MLP, market.MLP]; 28 | mdata.loads = [mdata.loads, dailyload]; 29 | mdata.gen = [mdata.gen, market.p]; 30 | mdata.loss = [mdata.loss, market.loss]; 31 | mdata.c(:,:,h*12-12+i) = c; 32 | if market.success && market.cong 33 | mdata.index = [mdata.index, (h-1)*12+i]; 34 | end 35 | end 36 | end 37 | mdata.PricesClean = mdata.Prices(:,mdata.index); 38 | save data/mdata_lossy.mat mdata -------------------------------------------------------------------------------- /src/run_rtmarket.m: -------------------------------------------------------------------------------- 1 | %% 2 | % run real time market 3 | 4 | disp('generating LMP for every 5 minutes...') 5 | mdata.S = []; 6 | mdata.M = []; 7 | mdata.Prices = []; 8 | mdata.index = []; 9 | mdata.loads = []; 10 | mdata.gen = []; 11 | mdata.c = []; 12 | mdata.mu0 = []; 13 | for h = 1:744 14 | fprintf('hour %d:\n',h) 15 | for i = 1:12 16 | market = rtmarket(db, h); 17 | mdata.S = [mdata.S, market.s]; 18 | mdata.M = [mdata.M, market.muh-market.mul]; 19 | mdata.Prices = [mdata.Prices, market.price]; 20 | mdata.loads = [mdata.loads, market.loads]; 21 | mdata.gen = [mdata.gen, market.p]; 22 | mdata.mu0 = [mdata.mu0, market.mu0]; 23 | mdata.c(:,:,h*12-12+i) = market.c; 24 | if market.success && market.cong && ~market.rare 25 | mdata.index = [mdata.index, (h-1)*12+i]; 26 | end 27 | end 28 | end 29 | mdata.PricesClean = mdata.Prices(:,mdata.index); 30 | mdata.SClean = mdata.S(:,mdata.index); 31 | mdata.MClean = mdata.M(:,mdata.index); 32 | 33 | save data/mdata.mat mdata -------------------------------------------------------------------------------- /test.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengkd95/LMP-inferring/58cb93ab5a2dc8e0806c3d90c8c7f251b6354f20/test.m -------------------------------------------------------------------------------- /test1.m: -------------------------------------------------------------------------------- 1 | %% initialize 2 | clear; 3 | clc; 4 | addpath('src'); 5 | addpath('case'); 6 | addpath('fun'); 7 | mpc = case30(); 8 | REF = find(mpc.bus(:,2)==3); 9 | B = makeBmatrix(mpc); 10 | B0 = get_lap(B, REF); 11 | B = normalize(B); 12 | B0 = normalize(B0); 13 | N = size(B,1); 14 | 15 | %% load data 16 | load data/mdata.mat 17 | Prices = mdata.PricesClean; 18 | %Prices = Prices(2:end,:); 19 | lossless = 1; 20 | T = size(Prices,2); 21 | k = [sqrt(T), sqrt(T), sqrt(T), 0.03]; 22 | Prices = Prices(:,1:500); 23 | %counts = [20, 40, 60, 80, 100, 120, 140]; 24 | %counts = [5, 10, 15, 20, 25, 30, 35]; 25 | counts = 0; 26 | cycle = 1; 27 | AUC_lists = zeros(length(counts),cycle); 28 | Time_lists = zeros(length(counts),1); 29 | B_sets = zeros(length(counts), N, N, cycle); 30 | AllLines = find(mpc.branch(:,1) ~= REF); 31 | 32 | for j = 1:length(counts) 33 | count = counts(j); 34 | time = 0; 35 | for i = 1:cycle 36 | KnownLines = sort(randperm(size(AllLines,1), count)); 37 | KnownPart.time = sort(randperm(T, count))'; 38 | KnownPart.lines = AllLines(KnownLines); 39 | time_start = clock; 40 | output = online_admm3(Prices, k, mpc, B0, lossless, KnownPart); 41 | time_end = clock; 42 | time = time + etime(time_end,time_start); 43 | B_sets(j,:,:,i) = output.B(:,:,end); 44 | Br = output.B(:,:,end); 45 | Br0 = get_lap(Br, REF); 46 | Br0 = normalize(Br0); 47 | [AUC, TPR, FPR] = evaluation(B0, Br0); 48 | AUC_lists(j,i) = AUC; 49 | end 50 | Time_lists(j,1) = time/cycle; 51 | fprintf('Mean time when %d lines are known: %.4f.\n',counts(j),time/cycle); 52 | fprintf('Mean loss when %d lines are known: %.4f.\n',counts(j),mean(AUC_lists(j,:))); 53 | end 54 | 55 | %str = ['lossy' '_' 'auc' '30_lossy.mat']; 56 | %save(['data/',str],'AUC_lists'); 57 | 58 | %% 59 | % a = load(['data/' 'lossy' '_' 'auc' '.mat']); 60 | % b = load(['data/' 'lossy' '_' 'auc' '30_r.mat']); 61 | % AUC_lists = [a.AUC_lists; b.AUC_lists]; 62 | 63 | figure 64 | boxplot(AUC_lists','Labels',{'20', '40', '60', '80', '100', '120', '140'}); 65 | xlabel('Number of Known Lines', 'FontSize', 13, 'FontName', 'Times New Roman'); 66 | ylabel('Box Plot of AUC-ROC', 'FontSize', 13, 'FontName', 'Times New Roman'); 67 | ylim([0.7,1]); 68 | print(['figure/','lossy_auc_distribute','118.eps'],'-depsc'); 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /test2.m: -------------------------------------------------------------------------------- 1 | %% initialize 2 | clear; 3 | clc; 4 | addpath('src'); 5 | addpath('case'); 6 | addpath('fun'); 7 | mpc = case30(); 8 | REF = find(mpc.bus(:,2)==3); 9 | B = makeBmatrix(mpc); 10 | B0 = get_lap(B, REF); 11 | B = normalize(B); 12 | B0 = normalize(B0); 13 | %plot_mat(B0,'jet','Primal L'); 14 | 15 | %% load data 16 | load data/mdata_lossy.mat 17 | Prices = mdata.PricesClean; 18 | Prices = Prices(2:end,:); 19 | lossless = 0; 20 | T = size(Prices,2); 21 | k = [sqrt(T), sqrt(T), sqrt(T), 0.03]; 22 | 23 | count = 10; 24 | AllLines = find(mpc.branch(:,1) ~= REF); 25 | KnownLines = sort(randperm(size(AllLines,1), count)); 26 | KnownPart.time = sort(randperm(T, count))'; 27 | KnownPart.lines = AllLines(KnownLines); 28 | 29 | %% odam 30 | output = online_admm3(Prices, k, mpc, B0, lossless, KnownPart); 31 | Br0 = get_lap(output.B(:,:,end), REF); 32 | Br0 = normalize(Br0); 33 | [AUC, TPR, FPR] = evaluation(B0, Br0); 34 | %% evaluate 35 | 36 | for t = 1:size(Prices,2) 37 | if rem(t,500) == 0 || t == size(Prices,2) 38 | Br = output.B(:,:,t); 39 | Br0 = get_lap(Br, REF); 40 | Br0 = normalize(Br0); 41 | plot_mat(Br0,'jet',['Recovered L at ' num2str(t) '-th interval (loss-less 30)']); 42 | end 43 | end 44 | 45 | -------------------------------------------------------------------------------- /test3.m: -------------------------------------------------------------------------------- 1 | %% initialize 2 | clear; 3 | clc; 4 | addpath('src'); 5 | addpath('case'); 6 | addpath('fun'); 7 | mpc = case30(); 8 | REF = find(mpc.bus(:,2)==3); 9 | B = makeBmatrix(mpc); 10 | B0 = get_lap(B, REF); 11 | B = normalize(B); 12 | B0 = normalize(B0); 13 | N = size(B,1); 14 | 15 | %% load data 16 | load data/mdata_lossy.mat 17 | Prices = mdata.PricesClean; 18 | Prices = Prices(2:end,:); 19 | lossless = 0; 20 | T = size(Prices,2); 21 | k = [sqrt(T), sqrt(T), sqrt(T), 0.03]; 22 | counts = [5, 10, 15, 20, 25, 30, 35]; 23 | AllLines = find(mpc.branch(:,1) ~= REF); 24 | acc = zeros(length(counts), floor(size(Prices,2)/10)+1); 25 | index = zeros(length(counts), floor(size(Prices,2)/10)+1); 26 | 27 | for j = 1:length(counts) 28 | count = counts(j); 29 | KnownLines = sort(randperm(size(AllLines,1), count)); 30 | KnownPart.time = sort(randperm(T, count))'; 31 | KnownPart.lines = AllLines(KnownLines); 32 | output = online_admm3(Prices, k, mpc, B0, lossless, KnownPart); 33 | i = 1; 34 | for t = 1:size(Prices,2) 35 | if rem(t,10) == 0 || t == size(Prices,2) 36 | Br = output.B(:,:,t); 37 | Br0 = get_lap(Br, REF); 38 | Br0 = normalize(Br0); 39 | [ACC, TPR, FPR] = evaluation(B0, Br0); 40 | acc(j,i) = ACC; 41 | index(j,i) = t; 42 | i = i+1; 43 | end 44 | end 45 | [m,p] = max(acc(j,:)); 46 | Br0 = get_lap(output.B(:,:,index(j,p)), REF); 47 | Br0 = normalize(Br0); 48 | plot_mat(Br0,'jet',['Recovered L when ' num2str(counts(j)) ' lines are known (lossy)']); 49 | end 50 | -------------------------------------------------------------------------------- /test4.m: -------------------------------------------------------------------------------- 1 | %% initialize 2 | clear; 3 | clc; 4 | addpath('src'); 5 | addpath('case'); 6 | addpath('fun'); 7 | mpc = case30(); 8 | REF = find(mpc.bus(:,2)==3); 9 | B = makeBmatrix(mpc); 10 | B0 = get_lap(B, REF); 11 | B = normalize(B); 12 | B0 = normalize(B0); 13 | N = size(B,1); 14 | 15 | %% load data 16 | load data/mdata_lossy.mat 17 | Prices = mdata.PricesClean; 18 | Prices = Prices(2:end,:); 19 | lossless = 0; 20 | T = size(Prices,2); 21 | k = [sqrt(T), sqrt(T), sqrt(T), 0.03]; 22 | counts = [5, 10, 15, 20, 25, 30, 35]; 23 | AllLines = find(mpc.branch(:,1) ~= REF); 24 | acc = zeros(length(counts), floor(size(Prices,2)/10)+1); 25 | 26 | for j = 1:length(counts) 27 | count = counts(j); 28 | KnownLines = sort(randperm(size(AllLines,1), count)); 29 | KnownPart.time = sort(randperm(T, count))'; 30 | KnownPart.lines = AllLines(KnownLines); 31 | output = online_admm3(Prices, k, mpc, B0, lossless, KnownPart); 32 | i = 1; 33 | for t = 1:size(Prices,2) 34 | if rem(t,10) == 0 || t == size(Prices,2) 35 | Br = output.B(:,:,t); 36 | Br0 = get_lap(Br, REF); 37 | Br0 = normalize(Br0); 38 | [ACC, TPR, FPR] = evaluation(B0, Br0); 39 | acc(j,i) = ACC; 40 | i = i+1; 41 | end 42 | end 43 | end 44 | %% 45 | figure, 46 | for i = 1:length(counts) 47 | plot(acc(i,:)); 48 | hold on; 49 | end 50 | hold off; 51 | xlabel('Time Interval', 'FontSize', 13, 'FontName', 'Times New Roman'); 52 | ylabel('AUC-ROC', 'FontSize', 13,'FontName', 'Times New Roman'); 53 | l1= legend('5 Lines', '10 Lines', '15 Lines','20 Lines', '25 Lines', '30 Lines', '35 Lines','Location','southeast'); 54 | set(l1,'Fontname', 'Times New Roman') 55 | set(gca,'xticklabel',{'0','1000','2000','3000','4000','5000','6000'}); 56 | print(['figure/','Comparsion between different lines 30(lossy)','.eps'],'-depsc'); 57 | --------------------------------------------------------------------------------