├── .gitattributes ├── BayesLinearRegression.py ├── BayesianLR_python.m ├── DLPF.m ├── DataGeneration.m ├── LICENSE ├── README.md ├── RegressionForward.m ├── RegressionInverse.m ├── StartUp.m ├── TestAccuracyForward.m └── TestAccuracyInverse.m /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /BayesLinearRegression.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Apr 5 14:25:50 2017 4 | 5 | @author: Yuxiao Liu 6 | """ 7 | 8 | import numpy as np 9 | from sklearn.linear_model import ARDRegression 10 | import pandas as pd 11 | 12 | def bayeslr_python(fname, threshold): 13 | # this function conducts the bayesian linear regression 14 | # the data interaction from matlab is through excel files due to the restriction of matrix interation 15 | X = pd.read_excel(fname, sheetname=0, header=None, index=None) 16 | Y = pd.read_excel(fname, sheetname=1, header=None, index=None) 17 | X_row,X_col = X.shape 18 | Y_row,Y_col = Y.shape 19 | 20 | judge_Y = ~(pd.DataFrame.sum(Y, axis=0) == np.zeros(Y_col)) 21 | 22 | X_blr = np.zeros((Y_col,X_col+1)) 23 | sigma_blr = np.zeros((Y_col,X_col)) 24 | 25 | for i in range(0,Y_col): 26 | if judge_Y[i]: 27 | y = Y.ix[:,i] 28 | clf = ARDRegression() 29 | # clf.n_iter = 500 30 | clf.threshold_lambda = threshold 31 | 32 | clf.fit(X, y) 33 | coef = clf.coef_.T 34 | X_blr[i, :] = np.hstack((coef,clf.intercept_)) 35 | 36 | X_blr = pd.DataFrame(X_blr) 37 | with pd.ExcelWriter(fname) as writer: 38 | X_blr.to_excel(writer, sheet_name=str(0), index=None, header=None) 39 | -------------------------------------------------------------------------------- /BayesianLR_python.m: -------------------------------------------------------------------------------- 1 | function [ X_blr ] = BayesianLR_python( X,Y,threshold, address, case_name) 2 | % this function conduct the Bayesian linear regression by calling the python function 3 | 4 | fname = 'bayesian_lr.xlsx'; 5 | fname = [address case_name '_' fname]; 6 | 7 | if (exist(fname, 'file') == 2) 8 | delete(fname) 9 | end 10 | 11 | sheet = 1; 12 | xlswrite(fname, X, sheet) 13 | sheet = 2; 14 | xlswrite(fname, Y, sheet) 15 | py.BayesLinearRegression.bayeslr_python(fname, threshold) 16 | sheet = 1; 17 | X_blr = xlsread(fname, sheet); 18 | 19 | end 20 | 21 | -------------------------------------------------------------------------------- /DLPF.m: -------------------------------------------------------------------------------- 1 | function [Xp_dlpf, Xq_dlpf, Pbus, BranchFlow, busAgl, busVol]=DLPF(mpc) 2 | % This code realizes Decoupled Linearized Power Flow (DLPF),this code is from the publication of "Yang J, Zhang N, Kang C, et al. A State-Independent Linear Power Flow Model with Accurate Estimation of Voltage Magnitude[J]. IEEE Transactions on Power Systems, 2016, PP(99):1-1." 3 | 4 | % Define matpower constants 5 | define_constants; 6 | % Load case 7 | [baseMVA, bus, gen, branch] = deal(mpc.baseMVA, mpc.bus, mpc.gen, mpc.branch); 8 | [ref, pv, pq] = bustypes(bus, gen); 9 | 10 | % Matrices 11 | Ybus = makeYbus(mpc); 12 | Gbus = real(Ybus); 13 | Bbus = imag(Ybus); 14 | GP = Gbus; 15 | BD = diag(sum(Bbus)); %shunt elements 16 | BP = -Bbus + BD; 17 | BQ = -Bbus; 18 | GQ = -Gbus; %GQ approxiately equals -Gbus 19 | Sbus = makeSbus(baseMVA, bus, gen); 20 | Pbus = real(Sbus); 21 | Qbus = imag(Sbus); 22 | 23 | % 24 | Xp_dlpf = [BP GP]; 25 | Xq_dlpf = [GQ BQ]; 26 | 27 | % Matrices in equation (11) 28 | % | Pm1 | | B11 G12 | | delta | 29 | % | | = | | * | | 30 | % | Qm1 | | G21 B22 | | voltage | 31 | B11 = BP([pv;pq],[pv;pq]); 32 | G12 = GP([pv;pq],pq); 33 | G21 = GQ(pq,[pv;pq]); 34 | B22 = BQ(pq,pq); 35 | Pm1 = Pbus([pv;pq]) - GP([pv;pq],ref)*bus(ref,VM) - GP([pv;pq],pv)*bus(pv,VM); 36 | Qm1 = Qbus(pq) - BQ(pq,ref)*bus(ref,VM) - BQ(pq,pv)*bus(pv,VM); 37 | 38 | % Matrices in equation (17) 39 | t1 =G12/B22; 40 | t2 =G21/B11; 41 | B11m = B11 - t1*G21; 42 | B22m = B22 - t2*G12; 43 | Pm2 = Pm1 - t1*Qm1; 44 | Qm2 = Qm1 - t2*Pm1; 45 | 46 | % Calculate voltage magnitude 47 | n = size(bus,1); 48 | busVol = zeros(n,1); 49 | busVol(ref) = bus(ref,VM); 50 | busVol(pv) = bus(pv,VM); 51 | busVol(pq) = B22m\Qm2; 52 | % Calculate voltage phase angle 53 | busAgl = ones(n,1)*bus(ref,VA); 54 | busAgl([pv;pq]) = busAgl([pv;pq]) + B11m\Pm2/pi*180; 55 | % Calculate line lossless MW flow 56 | branch(:,TAP) = 1; 57 | BranchFlow = (busVol(branch(:,F_BUS))./branch(:,TAP)-busVol(branch(:,T_BUS))).*branch(:,BR_R)./(branch(:,BR_X).^2+branch(:,BR_R).^2)*baseMVA ... 58 | +(busAgl(branch(:,F_BUS))-busAgl(branch(:,T_BUS))).*branch(:,BR_X)./(branch(:,BR_X).^2+branch(:,BR_R).^2)/180*pi./branch(:,TAP)*baseMVA; 59 | 60 | 61 | -------------------------------------------------------------------------------- /DataGeneration.m: -------------------------------------------------------------------------------- 1 | function [] = ... 2 | DataGeneration(case_name, Q_per, data_name, dc_ac, G_range, ... 3 | upper_bound, lower_bound, Q_range, V_range, data_size, L_range, ... 4 | random_load, Va_range, ref, L_corr) 5 | % this function generates the data of P, Q, V, and theata 6 | define_constants; 7 | 8 | mpc = ext2int(loadcase(case_name)); 9 | 10 | num_load = size(mpc.bus, 1); 11 | num_branch = size(mpc.branch, 1); 12 | num_train = data_size; 13 | %% generate the load based on the assumption that the load is random or is correlated 14 | if (random_load == 1) 15 | load_index = rand([data_size, num_load]) * (upper_bound - lower_bound) ... 16 | + lower_bound * ones(data_size, num_load); 17 | elseif (random_load == 0) 18 | load_index = rand([data_size, 1]) * (upper_bound - lower_bound) ... 19 | + lower_bound * ones(data_size, 1); 20 | load_index = load_index * ones(1, num_load) ... 21 | + rand([data_size, num_load]) * L_range; 22 | else 23 | 24 | end 25 | X_load = load_index * diag(mpc.bus(:, PD)'); 26 | %% data generation through power flow calculation, the Matpower Toolbox is required 27 | data.P = zeros(num_train, num_load); 28 | data.Va = zeros(num_train, num_load); 29 | if(dc_ac) 30 | data.Q = zeros(num_train, num_load); 31 | data.V = zeros(num_train, num_load); 32 | data.Va_dc = zeros(num_train, num_load); 33 | data.P_dc = zeros(num_train, num_load); 34 | end 35 | gen_ini = mpc.gen(:, PG); 36 | bus_ini = mpc.gen(:, VG); 37 | for i = 1:num_train 38 | mpc.bus(:, PD) = X_load(i, :)'; 39 | mpc.bus(:, QD) = mpc.bus(:, PD) .* (Q_per * ones(size(mpc.bus(:, QD))) ... 40 | + Q_range * rand(size(mpc.bus(:, QD)))); 41 | mpc.gen(:, PG) = gen_ini + rand(size(mpc.gen(:, PG))) - 0.5 * ones(size(mpc.gen(:, PG))) * G_range; 42 | mpc.gen(:, VG) = bus_ini + (rand(size(mpc.gen(:, VG))) - 0.5 * ones(size(mpc.gen(:, VG)))) * V_range; 43 | %% generate the data based on AC power flow equations or based on DC power flow equations 44 | if(dc_ac) 45 | [MVAbase, bus, gen, branch] = runpf(mpc); 46 | mpc.bus(:,VM) = bus(:,VM); 47 | [I2E, bus, gen, branch] = ext2int(bus, gen, branch); 48 | [MVAbase_dc, bus_dc, gen_dc, branch_dc] = rundcpf(mpc); 49 | [I2E, bus_dc, gen_dc, branch_dc] = ext2int(bus_dc, gen_dc, branch_dc); 50 | [~, ~, data.P_dlpf(i, :), data.PF_dlpf(i, :), data.Va_dlpf(i, :), data.V_dlpf(i, :)] = DLPF(mpc); 51 | data.Va_dc(i, :) = bus_dc(:, VA)'; 52 | 53 | Sbus_dc = makeSbus(MVAbase_dc, bus_dc, gen_dc); 54 | data.P_dc(i, :) = real(Sbus_dc)'; 55 | data.PF_dc(i, :) = branch_dc(:, PF)'; 56 | else 57 | [MVAbase, bus, gen, branch] = rundcpf(mpc); 58 | end 59 | %% save the generation results into the data struct 60 | Sbus = makeSbus(MVAbase, bus, gen); 61 | data.P(i, :) = real(Sbus)'; 62 | data.Q(i, :) = imag(Sbus)'; 63 | data.V(i, :) = bus(:, VM)'; 64 | data.Va(i, :) = bus(:, VA)'; 65 | data.PF(i, :) = branch(:, PF)'; 66 | data.PT(i, :) = branch(:, PT)'; 67 | data.QF(i, :) = branch(:, QF)'; 68 | data.QT(i, :) = branch(:, QT)'; 69 | end 70 | B = makeBdc(MVAbase, bus, mpc.branch); 71 | %% save to files 72 | eval(['save ', data_name, ' data num_load num_branch B;']); 73 | end 74 | 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Yuxiao Liu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## data-driven-power-flow-linearization 2 | 3 | This code studies a linearized PF model through a data-driven approach. 4 | 5 | The model is proposed in paper: Yuxiao Liu, Ning Zhang, Yi Wang, Jingwei Yang, Chongqing Kang,["Data-Driven Power Flow Linearization: A Regression Approach"](https://www.researchgate.net/publication/320726856_Data-Driven_Power_Flow_Linearization_A_Regression_Approach), published on IEEE Transactions on Smart Grid 6 | 7 | This source code is distributed in the hope that it will be helpful for your research and personal use. Any commercial/business use should be agreed by the authors of the above mentioned paper. 8 | 9 | We do request that publications in which this code is adopted, explicitly acknowledge that fact by citing the above mentioned paper. 10 | 11 | Note that the Matpower platform and the matlab python engine is required in this code. 12 | -------------------------------------------------------------------------------- /RegressionForward.m: -------------------------------------------------------------------------------- 1 | function [Xp, Xq, Xpf, Xqf, Xpt, Xqt] =... 2 | RegressionForward(regression, num_load, data, address, case_name) 3 | % this function conduct the forward regression by calling different regressioin algorithms 4 | switch regression 5 | case 0 % ordinary least squares 6 | for i = 1:num_load 7 | p = data.P(:, i); 8 | V_Va_p = [data.Va * pi / 180 data.V ones(size(data.V, 1), 1)]; 9 | b = regress(p, V_Va_p); 10 | Xp(i, :) = b'; 11 | q = data.Q(:, i); 12 | V_Va_q = [data.Va * pi / 180 data.V ones(size(data.V, 1), 1)]; 13 | b = regress(q, V_Va_q); 14 | Xq(i, :) = b'; 15 | end 16 | 17 | Xpf = []; 18 | Xqf = []; 19 | Xpt = []; 20 | Xqt = []; 21 | case 1 % partial least squares 22 | k = rank(data.V) + rank(data.Va); 23 | k = min(k, size(data.P,1)-1); 24 | X_pls = [data.Va * pi / 180 data.V]; 25 | Y_p_pls = data.P; 26 | [~,~,~,~,Xp] = plsregress(X_pls, Y_p_pls, k); 27 | Xp = Xp'; 28 | temp = Xp(:,1);Xp(:,1) = [];Xp = [Xp temp]; 29 | 30 | Y_q_pls = data.Q; 31 | [~,~,~,~,Xq] = plsregress(X_pls, Y_q_pls, k); 32 | Xq = Xq'; 33 | temp = Xq(:,1);Xq(:,1) = [];Xq = [Xq temp]; 34 | 35 | Xpf = []; 36 | Xqf = []; 37 | Xpt = []; 38 | Xqt = []; 39 | case 2 % bayesian linear regression 40 | threshold = 10000; 41 | X = [data.Va * pi / 180 data.V]; 42 | Y = [data.P data.Q]; 43 | X_blr = BayesianLR_python( X,Y ,threshold, address, case_name); 44 | [row, ~] = size(X_blr); 45 | row = row/2; 46 | Xp = X_blr(1:row, :); 47 | Xq = X_blr(row + 1:2 * row, :); 48 | Xpf = []; 49 | Xqf = []; 50 | Xpt = []; 51 | Xqt = []; 52 | otherwise 53 | error('no such regression method'); 54 | end 55 | -------------------------------------------------------------------------------- /RegressionInverse.m: -------------------------------------------------------------------------------- 1 | function [Xva, Xv, Xpf, Xqf] =... 2 | RegressionInverse(regression, num_load, data, ref, address ,case_name, is_sigma) 3 | % this function conduct the inverse regression by calling different regressioin algorithms 4 | switch regression 5 | case 0 % ordinary least squares 6 | for i = 1:num_load 7 | P = data.P; 8 | P(:, ref) = zeros; 9 | PQ_va = [P data.Q ones(size(data.V, 1), 1)]; 10 | [b,~,~,~,~] = regress(data.Va(:, i) * pi / 180, PQ_va); 11 | Xva(i, :) = b'; 12 | [b,~,~,~,~] = regress(data.V(:, i), PQ_va); 13 | Xv(i, :) = b'; 14 | end 15 | Xpf = []; 16 | Xqf = []; 17 | case 1 % partial least squares 18 | P = data.P; 19 | P(:, ref) = zeros; 20 | k = rank(P) + rank(data.Q) + 1; 21 | k = min(k, size(data.P, 1) - 1); 22 | X_pls = [P data.Q]; 23 | Y_va_pls = data.Va * pi / 180; 24 | Y_va_pls(:, ref) = data.P(:, ref); 25 | [~,~,~,~,Xva] = plsregress(X_pls, Y_va_pls, k); 26 | Xva = Xva'; 27 | temp = Xva(:,1);Xva(:,1) = [];Xva = [Xva temp]; 28 | 29 | Y_v_pls = data.V; 30 | [~,~,~,~,Xv] = plsregress(X_pls, Y_v_pls, k); 31 | Xv = Xv'; 32 | temp = Xv(:,1);Xv(:,1) = [];Xv = [Xv temp]; 33 | 34 | Y_pf_pls = data.PF; 35 | [~,~,~,~,Xpf] = plsregress(X_pls, Y_pf_pls, k); 36 | Xpf = Xpf'; 37 | temp = Xpf(:,1);Xpf(:,1) = [];Xpf = [Xpf temp]; 38 | 39 | Y_qf_pls = data.QF; 40 | [~,~,~,~,Xqf] = plsregress(X_pls, Y_qf_pls, k); 41 | Xqf = Xqf'; 42 | temp = Xqf(:,1);Xqf(:,1) = [];Xqf = [Xqf temp]; 43 | case 2 % bayesian linear regression 44 | threshold = 900000; 45 | P = data.P; 46 | P(:, ref) = zeros; 47 | X = [P data.Q]; 48 | Y_va_pls = data.Va * pi / 180; 49 | Y_va_pls(:, ref) = data.P(:, ref); 50 | Y_v_pls = data.V; 51 | Y = [Y_va_pls Y_v_pls]; 52 | X_blr = BayesianLR_python( X,Y, threshold, address, case_name); 53 | 54 | [row, ~] = size(X_blr); 55 | row = row/2; 56 | Xva = X_blr(1:row, :); 57 | Xv = X_blr(row + 1:2 * row, :); 58 | 59 | Y_pf_pls = data.PF; 60 | Y_qf_pls = data.QF; 61 | Y = [Y_pf_pls Y_qf_pls]; 62 | [X_blr] = BayesianLR_python( X,Y, threshold, address, case_name); 63 | 64 | [row, ~] = size(X_blr); 65 | row = row/2; 66 | Xpf = X_blr(1:row, :); 67 | Xqf = X_blr(row + 1:2 * row, :); 68 | otherwise 69 | error('no such regression method'); 70 | end 71 | -------------------------------------------------------------------------------- /StartUp.m: -------------------------------------------------------------------------------- 1 | % The algorithm in this file is based on the following publications: 2 | % Liu Y, Zhang N, Wang Y, et al. Data-Driven Power Flow Linearization: A Regression Approach. IEEE Transactions on Smart Grid, 2018. 3 | % This is the start up m-file of the data-driven power flow linearization master 4 | clc; 5 | clear; 6 | %% define parameters 7 | generate_data = 1;%1,data generation is needed; 0,data is already generated 8 | generate_test_data = 1;%1,data generation is needed; 0,data is already generated 9 | upper_bound = 1.2;%upper bound of generated load 10 | lower_bound = 0.8;%lower bound of generated load 11 | regression = 1; %0-least squares 1-pls regression 2-bayesian linear regression 12 | for_or_inv = 1;% 0-forward regression;1-inverse regression 13 | 14 | G_range = 0.1; %range of power generation variations 15 | Q_range = 0.25; %range of Q variations 16 | Q_per = 0.2; %Q percentage on P 17 | V_range = 0.01; %range of voltage magnitude variations of PV buses 18 | L_range = 0.05; %range of load in different nodes 19 | L_corr = 0.9; %covariance 20 | Va_range = 7;%degree 21 | Va_num = []; 22 | dc_ac = 1; %0-dc;1-ac; 23 | random_load = 1; %1,random 0,not random with bounder 2,not random with covariance 24 | 25 | data_size = 500;% training data size 26 | data_size_test = 300;% testing data size 27 | case_name = 'case5'; 28 | address = '';% address to read and save the data filess 29 | 30 | %% training data generation 31 | data_name = [address case_name '_training_data']; 32 | if (generate_data) 33 | mpc = ext2int(loadcase(case_name)); 34 | [ref, pv, pq] = bustypes(mpc.bus, mpc.gen); 35 | DataGeneration(case_name, Q_per, data_name, dc_ac, G_range, ... 36 | upper_bound, lower_bound, Q_range, V_range, data_size, L_range, ... 37 | random_load, Va_range, ref, L_corr); 38 | end 39 | load([data_name,'.mat']); 40 | 41 | %% linear regression 42 | % get bus index lists of each type of bus 43 | mpc = ext2int(loadcase(case_name)); 44 | [ref, pv, pq] = bustypes(mpc.bus, mpc.gen); 45 | 46 | [Xp_dlpf, Xq_dlpf,~, ~, ~] = DLPF(mpc); 47 | Xp_dlpf = full(Xp_dlpf); 48 | Xq_dlpf = full(Xq_dlpf); 49 | 50 | if (for_or_inv == 0) 51 | [Xp, Xq, Xpf, Xqf, Xpt, Xqt] =... 52 | RegressionForward(regression, num_load, data, address, case_name); 53 | else 54 | [Xva, Xv, Xpf, Xqf] =... 55 | RegressionInverse(regression, num_load, data, ref, address, case_name); 56 | end 57 | 58 | %% generate testing data 59 | upper_bound = 1.2; 60 | lower_bound = 0.8; 61 | data_name = [address case_name '_testing_data']; 62 | if (generate_test_data) 63 | DataGeneration(case_name, Q_per, data_name, dc_ac, G_range,... 64 | upper_bound, lower_bound, Q_range, V_range, data_size_test, L_range, ... 65 | random_load, Va_range, ref, L_corr); 66 | end 67 | load([data_name,'.mat']); 68 | num_train = size(data.P, 1); 69 | 70 | %% verify the accuracy 71 | if (for_or_inv == 0) 72 | [delta, test] = ... 73 | TestAccuracyForward(num_train, data, Xp, Xq, Xp_dlpf, Xq_dlpf, B); 74 | else 75 | [ref, pv, pq] = bustypes(mpc.bus, mpc.gen); 76 | [data, delta] = ... 77 | TestAccuracyInverse(num_train, data, Xv, Xva, ref, pv, pq, num_load); 78 | end 79 | -------------------------------------------------------------------------------- /TestAccuracyForward.m: -------------------------------------------------------------------------------- 1 | function [delta, test] = ... 2 | TestAccuracyForward(num_train, data, Xp, Xq, Xp_dlpf, Xq_dlpf, B) 3 | % this function test the accuracy of forward regression 4 | %% calculate the results by data-driven linearized equations 5 | for i = 1:num_train 6 | test.p.fitting(i, :) = [data.Va(i,:) * pi / 180 data.V(i,:) 1] * Xp'; 7 | test.p.dcpf(i, :) = B * data.Va(i, :)' * pi / 180; 8 | test.p.dlpf(i, :) = [data.Va(i,:) * pi / 180 data.V(i,:)]*Xp_dlpf'; 9 | test.q.fitting(i, :) = [data.Va(i,:) * pi / 180 data.V(i,:) 1]*Xq'; 10 | test.q.dlpf(i, :) = [data.Va(i,:) * pi / 180 data.V(i,:)]*Xq_dlpf'; 11 | end 12 | 13 | %% calculate the errors, note that the value of nan or inf is removed 14 | temp = abs((data.P - test.p.fitting)./data.P); 15 | temp(find(isnan(temp)==1)) = []; 16 | temp(find(isinf(temp)==1)) = []; 17 | delta.p.fitting = mean(mean(temp)) * 100; 18 | 19 | temp = abs((data.P - test.p.dcpf)./data.P); 20 | temp(find(isnan(temp)==1)) = []; 21 | temp(find(isinf(temp)==1)) = []; 22 | delta.p.dcpf = mean(mean(temp)) * 100; 23 | 24 | temp = abs((data.P - test.p.dlpf)./data.P); 25 | temp(find(isnan(temp)==1)) = []; 26 | temp(find(isinf(temp)==1)) = []; 27 | delta.p.dlpf = mean(mean(temp)) * 100; 28 | 29 | temp = abs((data.Q - test.q.fitting)./data.Q); 30 | temp(find(isnan(temp)==1)) = []; 31 | temp(find(isinf(temp)==1)) = []; 32 | delta.q.fitting = mean(mean(temp)) * 100; 33 | 34 | temp = abs((data.Q - test.q.dlpf)./data.Q); 35 | temp(find(isnan(temp)==1)) = []; 36 | temp(find(isinf(temp)==1)) = []; 37 | delta.q.dlpf = mean(mean(temp)) * 100; 38 | -------------------------------------------------------------------------------- /TestAccuracyInverse.m: -------------------------------------------------------------------------------- 1 | function [data, delta] = ... 2 | TestAccuracyInverse(num_train, data, Xv, Xva, ref, pv, pq, num_load) 3 | % this function test the accuracy of inverse regression 4 | % note that the regression matrix is reordered 5 | % |Va_pq | | ||P_pq | | | 6 | % |Va_pv | |X11 X12 ||P_pv | |C1| 7 | % |P_ref | | ||1 | | | 8 | % |V_pq | = | ||Q_pq | + | | 9 | % | | | || | | | 10 | % |V_pv | |X21 X22 ||Q_pv | |C2| 11 | % |V_ref | | ||Q_ref| | | 12 | % Y = X * a 13 | X11 = [Xva([pq; pv; ref], [pq; pv; ref; pq + num_load]);... 14 | Xv(pq, [pq; pv; ref; pq + num_load])]; 15 | X12 = [Xva([pq; pv; ref], [pv; ref] + num_load);... 16 | Xv(pq, [pv; ref] + num_load)]; 17 | X21 = Xv([pv; ref], [pq; pv; ref; pq + num_load]); 18 | X22 = Xv([pv; ref], [pv; ref] + num_load); 19 | C1 = [Xva([pq; pv; ref],2*num_load + 1);Xv(pq,2*num_load + 1)]; 20 | C2 = Xv([pv; ref],2*num_load + 1); 21 | 22 | P = data.P; 23 | P(:, ref) = data.Va(:, ref); 24 | Va = data.Va; 25 | Va(:, ref) = data.P(:, ref); 26 | 27 | %% calculate the results by data-driven linearized equations 28 | for i = 1:num_train 29 | Y2 = data.V(i, [pv; ref])'; 30 | a1 = [P(i, [pq; pv; ref])'; data.Q(i, pq)']; 31 | a2 = X22 \ (Y2 - X21 * a1 - C2); 32 | 33 | num_pq = size(pq,1); 34 | num_pv = size(pv,1); 35 | Q_pv = a2(1:num_pv); 36 | Q_ref = a2(num_pv + 1:num_pv + 1); 37 | 38 | Y1 = X11 * a1 + X12 * a2 + C1; 39 | 40 | 41 | V = zeros(num_load, 1); 42 | Va = zeros(num_load, 1); 43 | Q = data.Q(i, :); 44 | V([pv; ref]) = data.V(i, [pv; ref]); 45 | V(pq) = Y1(num_load + 1: num_load + num_pq); 46 | Va(ref) = data.Va(i, ref); 47 | Va([pq; pv]) = Y1(1: num_pq + num_pv) / pi * 180; 48 | P(i, ref) = Y1(num_pq + num_pv + 1); 49 | Q([pv; ref]) = [Q_pv; Q_ref]'; 50 | 51 | data.V_fitting(i, :) = V'; 52 | data.Va_fitting(i, :) = Va'; 53 | data.P_fitting(i, :) = P(i, :); 54 | data.Q_fitting(i, :) = Q; 55 | end 56 | 57 | %% calculate the errors, note that the value of nan or inf is removed 58 | temp = abs((data.Va - data.Va_fitting)); 59 | temp(find(isnan(temp)==1)) = []; 60 | temp(find(isinf(temp)==1)) = []; 61 | delta.va.fitting = mean(mean(temp)); 62 | 63 | temp = abs((data.V(:,pq) - data.V_fitting(:,pq))); 64 | temp(find(isnan(temp)==1)) = []; 65 | temp(find(isinf(temp)==1)) = []; 66 | delta.v.fitting = mean(mean(temp)); 67 | 68 | temp = abs((data.Va - data.Va_dlpf)); 69 | temp(find(isnan(temp)==1)) = []; 70 | temp(find(isinf(temp)==1)) = []; 71 | delta.va.dlpf = mean(mean(temp)); 72 | 73 | temp = abs((data.V(:,pq) - data.V_dlpf(:,pq))); 74 | temp(find(isnan(temp)==1)) = []; 75 | temp(find(isinf(temp)==1)) = []; 76 | delta.v.dlpf = mean(mean(temp)); 77 | 78 | temp = abs((data.PF - data.PF_dc)./data.PF); 79 | temp(find(isnan(temp)==1)) = []; 80 | temp(find(isinf(temp)==1)) = []; 81 | delta.pf.dcpf = mean(mean(temp)) * 100; 82 | 83 | temp = abs((data.PF - data.PF_dlpf)./data.PF); 84 | temp(find(isnan(temp)==1)) = []; 85 | temp(find(isinf(temp)==1)) = []; 86 | delta.pf.dlpf = mean(mean(temp)) * 100; 87 | 88 | end 89 | --------------------------------------------------------------------------------