├── README.md ├── RandomGraphGenerator.m ├── Synchronous_dp.m ├── admm_syn_con_LS.m ├── admm_syn_con_ave.m ├── admm_syn_con_lasso.m ├── dual_syn_con_LS.m ├── dual_syn_con_ave.m ├── dual_syn_con_lasso.m ├── graphSigIni.m ├── inc2adj.m ├── linspecer.m ├── pdmm_syn_con_LS.m ├── pdmm_syn_con_ave.m ├── pdmm_syn_con_lasso.m ├── randl.m ├── subPert_converplot.m ├── subPert_privplot.m └── test_all.m /README.md: -------------------------------------------------------------------------------- 1 | # Privacy_Preserving_Distributed_Optimization_Subspace 2 | 3 | This is the code to reproduce the plots of the paper 4 | "Privacy-preserving distributed optimization via subspace perturbation: a general framework". 5 | 6 | Qiongxiu Li, Richard Heusdens, Mads Græsbøll Christensen 7 | 8 | Arxiv preprint: http://arxiv.org/abs/2004.13999 9 | # How to run 10 | Download the zip file and run test_all.m file. 11 | -------------------------------------------------------------------------------- /RandomGraphGenerator.m: -------------------------------------------------------------------------------- 1 | %%%%routing of multipoint connections%%%% 2 | function Geograph = RandomGraphGenerator(Room_size,TotalNodeNum,sigma,sign) 3 | radius=sqrt(2*log(TotalNodeNum)/TotalNodeNum); 4 | node_x=Room_size(1).*abs(rand(TotalNodeNum,1)); 5 | node_y=Room_size(1).*abs(rand(TotalNodeNum,1)); 6 | A=ones(TotalNodeNum); 7 | B=ones(TotalNodeNum); 8 | A=A-diag(diag(B)); 9 | for i=1:TotalNodeNum 10 | for j=i+1:TotalNodeNum 11 | d=sqrt(power(node_x(i)-node_x(j),2)+power(node_y(i)-node_y(j),2)); 12 | if radius0]; %C matrix in PDMM 31 | Geograph.PC_matrix = circshift(Geograph.C_matrix,numEdge/2); %PC matrix in PDMM 32 | Geograph.S_matrix=[Geograph.C_matrix,Geograph.PC_matrix]; %incidence matrix of bipartite graph in PDMM 33 | 34 | %ADMM related 35 | Geograph.A_admm=[abs(Inci_matrix<0);abs(Inci_matrix>0)]; 36 | B_matrix=[-1*eye(numEdge/2,numEdge/2);-1*eye(numEdge/2,numEdge/2)]; 37 | Geograph.B_admm=B_matrix; 38 | Geograph.S_admm=[Geograph.A_admm,Geograph.B_admm];%incidence matrix of bipartite graph in ADMM 39 | 40 | if rank(Inci_matrix)==TotalNodeNum-1 41 | sign=1; 42 | else 43 | print('Graph is not connected, please generate again') 44 | end 45 | Geograph.sign=sign;%sign=1 means the graph is connected 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Synchronous_dp.m: -------------------------------------------------------------------------------- 1 | %%%%%% paper ''Differentially private average consensus: Obstructions, trade-offs, and 2 | %%%%%%optimal algorithm design'' by Nozari.et.al 3 | 4 | function output = Synchronous_dp( Geograph, error_th, iteration_max,sigma) 5 | [M,numb_aver] = size(Geograph.node_val); 6 | x_AverEst = Geograph.node_val; 7 | AverReal = mean(Geograph.node_val); 8 | AverReal_matrix = ones(M,1)*AverReal; 9 | MSE_error = 1/(M*numb_aver)*(norm(x_AverEst(:)-AverReal_matrix(:)))^2; 10 | iteration = 1; 11 | tranCnt=0;%calculate the transimission times in each iteration 12 | dmax=max(sum(Geograph.weight)); 13 | E=Geograph.weight; 14 | a=1/dmax; 15 | h=a/2; %h should be smaller than a 16 | L=diag(sum(E))-E;%graph laplacian matrix 17 | % s=2*rand(M,1); 18 | s=ones(M,1); 19 | S=diag(s); 20 | q_vec=abs(s-1)+(1-abs(s-1)).*rand(M,1); 21 | thetaVec=x_AverEst; 22 | sum_vec=zeros(M,1); 23 | numEdge=sum(sum(Geograph.weight)); 24 | while iteration <= iteration_max 25 | %%% privacy concerned sycronous averaing using differential privacy 26 | r_vec=sigma*randl(M,1).*power(q_vec,iteration); 27 | x_vec=thetaVec+r_vec;%update transmitted message with laplacian nosie with varaince sigma 28 | % thetaVec=thetaVec-h*L*x_vec; 29 | thetaVec=thetaVec-h*L*x_vec+S*r_vec; 30 | sum_vec=sum_vec+r_vec; 31 | x_AverEst=thetaVec; 32 | MSE_error(iteration) = 1/(M*numb_aver)*(norm(x_AverEst(:)-AverReal_matrix(:)))^2; 33 | tranCnt=tranCnt+numEdge; 34 | transmission(iteration)=tranCnt; 35 | if MSE_error(iteration)0),:)=1; 30 | x_dif(find(x_true<0),:)=-1; 31 | for i=1:n 32 | ind_i=(i-1)*ni+1:i*ni; 33 | for j=1:u 34 | f_deri(i,j)=(H_matrix(ind_i,:)*x_true-y_vec(ind_i)).'*H_matrix(ind_i,j); 35 | end 36 | f_deri(i,:)=f_deri(i,:)+x_dif'; 37 | end 38 | %%save the matrix inverse result 39 | invH=zeros(n,u,u); 40 | for i=1:n 41 | ind_i=(i-1)*ni+1:i*ni; 42 | invH(i,:,:)=pinv(H_matrix(ind_i,:).'*H_matrix(ind_i,:)+c*N_degree(i)*eye(u,u)); 43 | end 44 | 45 | tem=A_admm*x_est+B_admm*u_matrix; 46 | MSE_error = (norm(repmat(y_vec,1,n)-H_matrix*x_est.')+lamda*norm(x_est,1)+sum(diag(v_matrix*(tem)'))+0.5*c*sum(sum(tem.^2,2).^(1/2))); 47 | iteration = 1; 48 | transmission=0; 49 | tranCnt=0; 50 | while iteration <= iteration_max 51 | for i=1:n 52 | ind_i=(i-1)*ni+1:i*ni; 53 | x_est(i,:)=(reshape(invH(i,:,:),u,u)*wthresh(H_matrix(ind_i,:).'*y_vec(ind_i)-(c*(A_admm(:,i).')*B_admm*u_matrix+A_admm(:,i).'*v_matrix).','s',lamda)).'; 54 | end 55 | u_matrix=diag(inv(B_admm.'*B_admm)).*(-1/c*(B_admm.'*v_matrix)-B_admm.'*A_admm*x_est); 56 | v_matrix=v_matrix+c*(A_admm*x_est+B_admm*u_matrix); 57 | MSE_error(iteration) = 1/(n*u)*(norm(x_est-repmat(x_true,1,n).'))^2; 58 | Vr1=S*v_matrix; 59 | Vl1=(eye(numEdge)-S)*v_matrix; 60 | V_nCon_error(iteration)=1/(n*u)*(norm(Vl1))^2; 61 | V_Con_error(iteration)=1/(n*u)*(norm(A_admm.'*Vr1-(f_deri)))^2; 62 | tranCnt=tranCnt+numEdge; 63 | transmission(iteration)=tranCnt; 64 | if MSE_error(iteration)0),:)=1; 30 | x_dif(find(x_true<0),:)=-1; 31 | for i=1:n 32 | ind_i=(i-1)*ni+1:i*ni; 33 | for j=1:u 34 | f_deri(i,j)=(H_matrix(ind_i,:)*x_true-y_vec(ind_i)).'*H_matrix(ind_i,j); 35 | end 36 | f_deri(i,:)=f_deri(i,:)+x_dif'; 37 | end 38 | invH=zeros(n,u,u); 39 | %%save the matrix inverse result 40 | invH=zeros(n,u,u); 41 | for i=1:n 42 | ind_i=(i-1)*ni+1:i*ni; 43 | invH(i,:,:)=pinv(H_matrix(ind_i,:).'*H_matrix(ind_i,:)+c*N_degree(i)*eye(u,u)); 44 | end 45 | 46 | MSE_error = 1/(n*u)*(norm(x_est-repmat(x_true,1,n).'))^2; 47 | iteration = 1; 48 | transmission=0; 49 | tranCnt=0; 50 | while iteration <= iteration_max 51 | for i=1:n 52 | ind_i=(i-1)*ni+1:i*ni; 53 | x_est(i,:)=(reshape(invH(i,:,:),u,u)*wthresh(H_matrix(ind_i,:).'*y_vec(ind_i)-(S_matrix(:,i).'*z_matrix).','s',lamda)).'; 54 | end 55 | z_matrix=z_matrix+c*S_matrix*x_est; 56 | MSE_error(iteration) = 1/(n*u)*(norm(x_est-repmat(x_true,1,n).'))^2; 57 | Zr1=S*z_matrix; 58 | Zl1=(eye(numEdge)-S)*z_matrix; 59 | Z_nCon_error(iteration)=1/(numEdge*u)*(norm(Zl1))^2; 60 | Z_Con_error(iteration)=1/(numEdge*u)*(norm(S_matrix.'*Zr1-f_deri))^2; 61 | tranCnt=tranCnt+numEdge; 62 | transmission(iteration)=tranCnt; 63 | if MSE_error(iteration)ni %%underdetermined system 6 | H_matrix=sigma*randn(n*ni,u); 7 | tem=randperm(u,0.1*u); 8 | x_true=zeros(u,1); 9 | x_true(tem)=randn(0.1*u,1); 10 | Geograph.x_true=x_true; 11 | Geograph.H_matrix=H_matrix; %regression matrix in the network 12 | Geograph.y_vec=H_matrix*Geograph.x_true; %observation vector in the network y=Hx+v, v is noise 13 | else %%overdetermined system 14 | H_matrix=sigma*randn(n*ni,u); 15 | Geograph.H_matrix=H_matrix; %regression matrix in the network 16 | Geograph.y_vec=H_matrix*randn(u,1); %observation vector in the network 17 | end -------------------------------------------------------------------------------- /inc2adj.m: -------------------------------------------------------------------------------- 1 | function mAdj = inc2adj(mInc) 2 | if ~issparse(mInc) 3 | mInc = sparse(mInc); 4 | end 5 | if ~all(ismember(mInc(:), [-1, 0, 1])) 6 | error('inc2adj:wrongMatrixInput', 'Matrix must contain only {-1,0,1}'); 7 | end 8 | if ~all(any(mInc, 2)) 9 | error('inc2adj:wrongMatrixInput', 'Invalid incidence matrix - each edge must be connected to at least one node.'); 10 | end 11 | mInc = mInc.'; 12 | if any(mInc(:) == -1) % directed graph 13 | iN_nodes = size(mInc,1); % columns must be vertices!!! 14 | 15 | [vNodes1, dummy] = find(mInc == 1); % since MATLAB 2009b 'dummy' can be replaced by '~' 16 | [vNodes2, dummy] = find(mInc == -1); % since MATLAB 2009b 'dummy' can be replaced by '~' 17 | 18 | mAdj = sparse(vNodes1, vNodes2, 1, iN_nodes, iN_nodes); 19 | 20 | else % undirected graph 21 | 22 | L = mInc*mInc.'; % using Laplacian 23 | mAdj = L - diag(diag(L)); 24 | 25 | end 26 | if any(mAdj(:) > 1) 27 | warning('inc2adj:wrongMatrixInput', 'Multi-edge detected!'); 28 | end 29 | end -------------------------------------------------------------------------------- /linspecer.m: -------------------------------------------------------------------------------- 1 | % function lineStyles = linspecer(N) 2 | % This function creates an Nx3 array of N [R B G] colors 3 | % These can be used to plot lots of lines with distinguishable and nice 4 | % looking colors. 5 | % 6 | % lineStyles = linspecer(N); makes N colors for you to use: lineStyles(ii,:) 7 | % 8 | % colormap(linspecer); set your colormap to have easily distinguishable 9 | % colors and a pleasing aesthetic 10 | % 11 | % lineStyles = linspecer(N,'qualitative'); forces the colors to all be distinguishable (up to 12) 12 | % lineStyles = linspecer(N,'sequential'); forces the colors to vary along a spectrum 13 | % 14 | % % Examples demonstrating the colors. 15 | % 16 | % LINE COLORS 17 | % N=6; 18 | % X = linspace(0,pi*3,1000); 19 | % Y = bsxfun(@(x,n)sin(x+2*n*pi/N), X.', 1:N); 20 | % C = linspecer(N); 21 | % axes('NextPlot','replacechildren', 'ColorOrder',C); 22 | % plot(X,Y,'linewidth',5) 23 | % ylim([-1.1 1.1]); 24 | % 25 | % SIMPLER LINE COLOR EXAMPLE 26 | % N = 6; X = linspace(0,pi*3,1000); 27 | % C = linspecer(N) 28 | % hold off; 29 | % for ii=1:N 30 | % Y = sin(X+2*ii*pi/N); 31 | % plot(X,Y,'color',C(ii,:),'linewidth',3); 32 | % hold on; 33 | % end 34 | % 35 | % COLORMAP EXAMPLE 36 | % A = rand(15); 37 | % figure; imagesc(A); % default colormap 38 | % figure; imagesc(A); colormap(linspecer); % linspecer colormap 39 | % 40 | % See also NDHIST, NHIST, PLOT, COLORMAP, 43700-cubehelix-colormaps 41 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 42 | % by Jonathan Lansey, March 2009-2013 ? Lansey at gmail.com % 43 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 44 | % 45 | %% credits and where the function came from 46 | % The colors are largely taken from: 47 | % http://colorbrewer2.org and Cynthia Brewer, Mark Harrower and The Pennsylvania State University 48 | % 49 | % 50 | % She studied this from a phsychometric perspective and crafted the colors 51 | % beautifully. 52 | % 53 | % I made choices from the many there to decide the nicest once for plotting 54 | % lines in Matlab. I also made a small change to one of the colors I 55 | % thought was a bit too bright. In addition some interpolation is going on 56 | % for the sequential line styles. 57 | % 58 | % 59 | %% 60 | function lineStyles=linspecer(N,varargin) 61 | if nargin==0 % return a colormap 62 | lineStyles = linspecer(128); 63 | return; 64 | end 65 | if ischar(N) 66 | lineStyles = linspecer(128,N); 67 | return; 68 | end 69 | if N<=0 % its empty, nothing else to do here 70 | lineStyles=[]; 71 | return; 72 | end 73 | % interperet varagin 74 | qualFlag = 0; 75 | colorblindFlag = 0; 76 | if ~isempty(varargin)>0 % you set a parameter? 77 | switch lower(varargin{1}) 78 | case {'qualitative','qua'} 79 | if N>12 % go home, you just can't get this. 80 | warning('qualitiative is not possible for greater than 12 items, please reconsider'); 81 | else 82 | if N>9 83 | warning(['Default may be nicer for ' num2str(N) ' for clearer colors use: whitebg(''black''); ']); 84 | end 85 | end 86 | qualFlag = 1; 87 | case {'sequential','seq'} 88 | lineStyles = colorm(N); 89 | return; 90 | case {'white','whitefade'} 91 | lineStyles = whiteFade(N);return; 92 | case 'red' 93 | lineStyles = whiteFade(N,'red');return; 94 | case 'blue' 95 | lineStyles = whiteFade(N,'blue');return; 96 | case 'green' 97 | lineStyles = whiteFade(N,'green');return; 98 | case {'gray','grey'} 99 | lineStyles = whiteFade(N,'gray');return; 100 | case {'colorblind'} 101 | colorblindFlag = 1; 102 | otherwise 103 | warning(['parameter ''' varargin{1} ''' not recognized']); 104 | end 105 | end 106 | % *.95 107 | % predefine some colormaps 108 | set3 = colorBrew2mat({[141, 211, 199];[ 255, 237, 111];[ 190, 186, 218];[ 251, 128, 114];[ 128, 177, 211];[ 253, 180, 98];[ 179, 222, 105];[ 188, 128, 189];[ 217, 217, 217];[ 204, 235, 197];[ 252, 205, 229];[ 255, 255, 179]}'); 109 | set1JL = brighten(colorBrew2mat({[228, 26, 28];[ 55, 126, 184]; [ 77, 175, 74];[ 255, 127, 0];[ 255, 237, 111]*.85;[ 166, 86, 40];[ 247, 129, 191];[ 153, 153, 153];[ 152, 78, 163]}')); 110 | set1 = brighten(colorBrew2mat({[ 55, 126, 184]*.85;[228, 26, 28];[ 77, 175, 74];[ 255, 127, 0];[ 152, 78, 163]}),.8); 111 | % colorblindSet = {[215,25,28];[253,174,97];[171,217,233];[44,123,182]}; 112 | colorblindSet = {[215,25,28];[253,174,97];[171,217,233]*.8;[44,123,182]*.8}; 113 | set3 = dim(set3,.93); 114 | if colorblindFlag 115 | switch N 116 | % sorry about this line folks. kind of legacy here because I used to 117 | % use individual 1x3 cells instead of nx3 arrays 118 | case 4 119 | lineStyles = colorBrew2mat(colorblindSet); 120 | otherwise 121 | colorblindFlag = false; 122 | warning('sorry unsupported colorblind set for this number, using regular types'); 123 | end 124 | end 125 | if ~colorblindFlag 126 | switch N 127 | case 1 128 | lineStyles = { [ 55, 126, 184]/255}; 129 | case {2, 3, 4, 5 } 130 | lineStyles = set1(1:N); 131 | case {6 , 7, 8, 9} 132 | lineStyles = set1JL(1:N)'; 133 | case {10, 11, 12} 134 | if qualFlag % force qualitative graphs 135 | lineStyles = set3(1:N)'; 136 | else % 10 is a good number to start with the sequential ones. 137 | lineStyles = cmap2linspecer(colorm(N)); 138 | end 139 | otherwise % any old case where I need a quick job done. 140 | lineStyles = cmap2linspecer(colorm(N)); 141 | end 142 | end 143 | lineStyles = cell2mat(lineStyles); 144 | end 145 | % extra functions 146 | function varIn = colorBrew2mat(varIn) 147 | for ii=1:length(varIn) % just divide by 255 148 | varIn{ii}=varIn{ii}/255; 149 | end 150 | end 151 | function varIn = brighten(varIn,varargin) % increase the brightness 152 | if isempty(varargin), 153 | frac = .9; 154 | else 155 | frac = varargin{1}; 156 | end 157 | for ii=1:length(varIn) 158 | varIn{ii}=varIn{ii}*frac+(1-frac); 159 | end 160 | end 161 | function varIn = dim(varIn,f) 162 | for ii=1:length(varIn) 163 | varIn{ii} = f*varIn{ii}; 164 | end 165 | end 166 | function vOut = cmap2linspecer(vIn) % changes the format from a double array to a cell array with the right format 167 | vOut = cell(size(vIn,1),1); 168 | for ii=1:size(vIn,1) 169 | vOut{ii} = vIn(ii,:); 170 | end 171 | end 172 | %% 173 | % colorm returns a colormap which is really good for creating informative 174 | % heatmap style figures. 175 | % No particular color stands out and it doesn't do too badly for colorblind people either. 176 | % It works by interpolating the data from the 177 | % 'spectral' setting on http://colorbrewer2.org/ set to 11 colors 178 | % It is modified a little to make the brightest yellow a little less bright. 179 | function cmap = colorm(varargin) 180 | n = 100; 181 | if ~isempty(varargin) 182 | n = varargin{1}; 183 | end 184 | if n==1 185 | cmap = [0.2005 0.5593 0.7380]; 186 | return; 187 | end 188 | if n==2 189 | cmap = [0.2005 0.5593 0.7380; 190 | 0.9684 0.4799 0.2723]; 191 | return; 192 | end 193 | frac=.95; % Slight modification from colorbrewer here to make the yellows in the center just a bit darker 194 | cmapp = [158, 1, 66; 213, 62, 79; 244, 109, 67; 253, 174, 97; 254, 224, 139; 255*frac, 255*frac, 191*frac; 230, 245, 152; 171, 221, 164; 102, 194, 165; 50, 136, 189; 94, 79, 162]; 195 | x = linspace(1,n,size(cmapp,1)); 196 | xi = 1:n; 197 | cmap = zeros(n,3); 198 | for ii=1:3 199 | cmap(:,ii) = pchip(x,cmapp(:,ii),xi); 200 | end 201 | cmap = flipud(cmap/255); 202 | end 203 | function cmap = whiteFade(varargin) 204 | n = 100; 205 | if nargin>0 206 | n = varargin{1}; 207 | end 208 | thisColor = 'blue'; 209 | if nargin>1 210 | thisColor = varargin{2}; 211 | end 212 | switch thisColor 213 | case {'gray','grey'} 214 | cmapp = [255,255,255;240,240,240;217,217,217;189,189,189;150,150,150;115,115,115;82,82,82;37,37,37;0,0,0]; 215 | case 'green' 216 | cmapp = [247,252,245;229,245,224;199,233,192;161,217,155;116,196,118;65,171,93;35,139,69;0,109,44;0,68,27]; 217 | case 'blue' 218 | cmapp = [247,251,255;222,235,247;198,219,239;158,202,225;107,174,214;66,146,198;33,113,181;8,81,156;8,48,107]; 219 | case 'red' 220 | cmapp = [255,245,240;254,224,210;252,187,161;252,146,114;251,106,74;239,59,44;203,24,29;165,15,21;103,0,13]; 221 | otherwise 222 | warning(['sorry your color argument ' thisColor ' was not recognized']); 223 | end 224 | cmap = interpomap(n,cmapp); 225 | end 226 | % Eat a approximate colormap, then interpolate the rest of it up. 227 | function cmap = interpomap(n,cmapp) 228 | x = linspace(1,n,size(cmapp,1)); 229 | xi = 1:n; 230 | cmap = zeros(n,3); 231 | for ii=1:3 232 | cmap(:,ii) = pchip(x,cmapp(:,ii),xi); 233 | end 234 | cmap = (cmap/255); % flipud?? 235 | end 236 | -------------------------------------------------------------------------------- /pdmm_syn_con_LS.m: -------------------------------------------------------------------------------- 1 | 2 | function output=pdmm_syn_con_LS(Geograph,error_th,iteration_max,Pmax,c,flag) 3 | [Nn,u] = size(Geograph.H_matrix); 4 | ni=Geograph.ni; 5 | n=Nn/ni; 6 | N_degree = sum(Geograph.weight).'; 7 | numEdge=Geograph.m; 8 | if flag==1||flag==3 9 | z_matrix=Pmax*randn(numEdge,u); 10 | else 11 | z_matrix=zeros(numEdge,u); 12 | end 13 | 14 | H_matrix=Geograph.H_matrix; 15 | y_vec=Geograph.y_vec; 16 | C_matrix=Geograph.C_matrix; 17 | x_est=zeros(n,u); 18 | x_true = mldivide(H_matrix,y_vec); 19 | 20 | Z_struct.z_ji_matrixIni=z_matrix; 21 | S_matrix=Geograph.S_matrix; 22 | C_matrix=Geograph.C_matrix; 23 | PC_matrix=Geograph.PC_matrix; 24 | S=S_matrix*pinv(S_matrix.'*S_matrix)*S_matrix.'; 25 | if flag==3 26 | z_matrix=S*z_matrix; 27 | end 28 | Zr=S*z_matrix; 29 | Zl=(eye(numEdge)-S)*z_matrix; 30 | f_deri=zeros(n,u); %initialize the derivative of f(x) 31 | for i=1:n 32 | ind_i=(i-1)*u+1:i*u; 33 | for j=1:u 34 | f_deri(i,j)=(H_matrix(ind_i,:)*x_true-y_vec(ind_i)).'*H_matrix(ind_i,j); 35 | end 36 | end 37 | 38 | 39 | 40 | 41 | Zfixed=-pinv([C_matrix.';PC_matrix.'])*[f_deri+c*(C_matrix.')*C_matrix*repmat(x_true,1,n).';f_deri+c*(C_matrix.')*PC_matrix*repmat(x_true,1,n).']; 42 | 43 | MSE_error = 1/(n*u)*(norm(x_est-repmat(x_true,1,n).'))^2; 44 | iteration = 1; 45 | transmission=0; 46 | tranCnt=0; 47 | while iteration <= iteration_max 48 | for i=1:n 49 | ind_i=(i-1)*ni+1:i*ni; 50 | x_est(i,:)=(pinv(H_matrix(ind_i,:).'*H_matrix(ind_i,:)+c*N_degree(i)*eye(u,u))*(H_matrix(ind_i,:).'*y_vec(ind_i)-(C_matrix(:,i).'*z_matrix).')).'; 51 | end 52 | z_matrix=circshift(z_matrix,numEdge/2)+2*circshift(c*C_matrix*x_est,numEdge/2); 53 | 54 | MSE_error(iteration) = 1/(n*u)*(norm(x_est-repmat(x_true,1,n).'))^2; 55 | Zr1=S*z_matrix; 56 | Zl1=(eye(numEdge)-S)*z_matrix; 57 | Z_nCon_error(iteration)=1/(numEdge*u)*(norm(Zl1))^2; 58 | Z_Con_error(iteration)=1/(numEdge*u)*(norm(Zr1-Zfixed))^2; 59 | tranCnt=tranCnt+n;%each node only broadcast once a iteration 60 | transmission(iteration)=tranCnt; 61 | if MSE_error(iteration)0),:)=1; 32 | x_dif(find(x_true<0),:)=-1; 33 | for i=1:n 34 | ind_i=(i-1)*ni+1:i*ni; 35 | for j=1:u 36 | f_deri(i,j)=(H_matrix(ind_i,:)*x_true-y_vec(ind_i)).'*H_matrix(ind_i,j); 37 | end 38 | f_deri(i,:)=f_deri(i,:)+x_dif'; 39 | end 40 | %%save the matrix inverse result 41 | invH=zeros(n,u,u); 42 | for i=1:n 43 | ind_i=(i-1)*ni+1:i*ni; 44 | invH(i,:,:)=pinv(H_matrix(ind_i,:).'*H_matrix(ind_i,:)+c*N_degree(i)*eye(u,u)); 45 | end 46 | 47 | 48 | 49 | Zfixed=-pinv([C_matrix.';PC_matrix.'])*[f_deri+c*(C_matrix.')*C_matrix*repmat(x_true,1,n).';f_deri+c*(C_matrix.')*PC_matrix*repmat(x_true,1,n).']; 50 | 51 | MSE_error = 1/(n*u)*(norm(x_est-repmat(x_true,1,n).'))^2; 52 | iteration = 1; 53 | transmission=0; 54 | tranCnt=0; 55 | theta=0.1; 56 | while iteration <= iteration_max 57 | for i=1:n 58 | ind_i=(i-1)*ni+1:i*ni; 59 | x_est(i,:)=(reshape(invH(i,:,:),u,u)*wthresh((H_matrix(ind_i,:).'*y_vec(ind_i)-(C_matrix(:,i).'*z_matrix).'),'s',lamda)).'; 60 | end 61 | z_matrixTem=circshift(z_matrix,numEdge/2)+2*circshift(c*C_matrix*x_est,numEdge/2); 62 | z_matrix=((1-theta)*z_matrixTem+theta*z_matrix); 63 | MSE_error(iteration) = 1/(n*u)*(norm(x_est-repmat(x_true,1,n).'))^2; 64 | Zr1=S*z_matrix; 65 | Zl1=(eye(numEdge)-S)*z_matrix; 66 | Z_nCon_error(iteration)=1/(numEdge*u)*(norm(Zl1))^2; 67 | Z_Con_error(iteration)=1/(numEdge*u)*(norm(Zr1-Zfixed))^2; 68 | tranCnt=tranCnt+n;%each node only broadcast once a iteration 69 | transmission(iteration)=tranCnt; 70 | if MSE_error(iteration)','<'}; 16 | figure; 17 | set(gca,'fontsize',15) 18 | p= plot(output_a1.transmission(:),output_a1.MSE_error(:),strcat('b-'),'Marker',Markers{3},'MarkerIndices',1:intVal1:length(output_a1.MSE_error),'MarkerSize',10,'linewidth',1.1); 19 | hold on; plot(output_a1.transmission(:),output_a1.Z_Con_error(:),strcat('b-'),'Marker',Markers{6},'MarkerIndices',1:intVal1:length(output_a1.Z_Con_error(:)),'MarkerSize',10,'linewidth',1.1); 20 | hold on; plot(output_a1.transmission(:),output_a1.Z_nCon_error(:),strcat('b-'),'Marker',Markers{9},'MarkerIndices',1:intVal1:length(output_a1.Z_nCon_error(:)),'MarkerSize',10,'linewidth',1.1); 21 | hold on; plot(output_a2.transmission(:),output_a2.MSE_error(:),strcat('r-'),'Marker',Markers{3},'MarkerIndices',1:intVal1:length(output_a2.MSE_error(:)),'MarkerSize',10,'linewidth',1.1); 22 | hold on; plot(output_a2.transmission(:),output_a2.Z_Con_error(:),strcat('r-'),'Marker',Markers{6},'MarkerIndices',1:intVal1:length(output_a2.Z_Con_error(:)),'MarkerSize',10,'linewidth',1.1); 23 | hold on; plot(output_a2.transmission(:),output_a2.Z_nCon_error(:),strcat('r-'),'Marker',Markers{9},'MarkerIndices',1:intVal1:length(output_a2.Z_nCon_error(:)),'MarkerSize',10,'linewidth',1.1); 24 | ylim([error_th Pmax^2*10]) 25 | % xlim([0 60]) 26 | grid on 27 | legend({'Proposed: x^{(k)}-x*','Proposed: (\Pi_{H})v^{(k)}-v*','Proposed: (I-\Pi_{H})v^{(k)}','Non-private: x^{(k)}-x*','Non-private: (\Pi_{H})v^{(k)}-v*','Non-private: (I-\Pi_{H})v^{(k)}'},'location','northeast','FontSize',10) 28 | set(gca, 'YScale', 'log') 29 | xlabel ('Transmissions'); ylabel ('MSE') 30 | title(strcat('Distributed ', name,' of ADMM' ) ) 31 | set(gca, 'FontSize', 12) 32 | set(gca,'linewidth',2); 33 | 34 | 35 | figure; 36 | set(gca,'fontsize',15) 37 | p= plot(output_p1.transmission(:),output_p1.MSE_error(:),strcat('b-'),'Marker',Markers{3},'MarkerIndices',1:intVal2:length(output_p1.MSE_error),'MarkerSize',10,'linewidth',1.1); 38 | hold on; plot(output_p1.transmission(:),output_p1.Z_Con_error(:),strcat('b-'),'Marker',Markers{6},'MarkerIndices',1:intVal2:length(output_p1.Z_Con_error(:)),'MarkerSize',10,'linewidth',1.1); 39 | hold on; plot(output_p1.transmission(:),output_p1.Z_nCon_error(:),strcat('b-'),'Marker',Markers{9},'MarkerIndices',1:intVal2:length(output_p1.Z_nCon_error(:)),'MarkerSize',10,'linewidth',1.1); 40 | hold on; plot(output_p2.transmission(:),output_p2.MSE_error(:),strcat('r-'),'Marker',Markers{3},'MarkerIndices',1:intVal2:length(output_p2.MSE_error(:)),'MarkerSize',10,'linewidth',1.1); 41 | hold on; plot(output_p2.transmission(:),output_p2.Z_Con_error(:),strcat('r-'),'Marker',Markers{6},'MarkerIndices',1:intVal2:length(output_p2.Z_Con_error(:)),'MarkerSize',10,'linewidth',1.1); 42 | hold on; plot(output_p2.transmission(:),output_p2.Z_nCon_error(:),strcat('r-'),'Marker',Markers{9},'MarkerIndices',1:intVal2:length(output_p2.Z_nCon_error(:)),'MarkerSize',10,'linewidth',1.1); 43 | ylim([error_th,Pmax^2*10]) 44 | xlim([sum(sum(aveRes.Geograph.weight)) inf]) 45 | grid on 46 | legend({'Proposed: x^{(k)}-x*','Proposed: (\Pi_{H})\lambda^{(k)}-\lambda*','Proposed: (I-\Pi_{H})\lambda^{(k)}','Non-private: x^{(k)}-x*','Non-private: (\Pi_{H})\lambda^{(k)}-\lambda*','Non-private: (I-\Pi_{H})\lambda^{(k)}'},'location','northeast','FontSize',10) 47 | set(gca, 'YScale', 'log') 48 | xlabel ('Transmissions'); ylabel ('MSE') 49 | title(strcat('Distributed ', name,' of PDMM' ) ) 50 | set(gca, 'FontSize', 12) 51 | set(gca,'linewidth',2); 52 | 53 | figure; 54 | set(gca,'fontsize',15) 55 | p= plot(output_d1.transmission(:),output_d1.MSE_error(:),strcat('b-'),'Marker',Markers{3},'MarkerIndices',1:intVal3:length(output_d1.MSE_error),'MarkerSize',10,'linewidth',1.1); 56 | hold on; plot(output_d1.transmission(:),output_d1.Z_Con_error(:),strcat('b-'),'Marker',Markers{6},'MarkerIndices',1:intVal3:length(output_d1.Z_Con_error(:)),'MarkerSize',10,'linewidth',1.1); 57 | hold on; plot(output_d1.transmission(:),output_d1.Z_nCon_error(:),strcat('b-'),'Marker',Markers{9},'MarkerIndices',1:intVal3:length(output_d1.Z_nCon_error(:)),'MarkerSize',10,'linewidth',1.1); 58 | hold on; plot(output_d2.transmission(:),output_d2.MSE_error(:),strcat('r-'),'Marker',Markers{3},'MarkerIndices',1:intVal3:length(output_d2.MSE_error(:)),'MarkerSize',10,'linewidth',1.1); 59 | hold on; plot(output_d2.transmission(:),output_d2.Z_Con_error(:),strcat('r-'),'Marker',Markers{6},'MarkerIndices',1:intVal3:length(output_d2.Z_Con_error(:)),'MarkerSize',10,'linewidth',1.1); 60 | hold on; plot(output_d2.transmission(:),output_d2.Z_nCon_error(:),strcat('r-'),'Marker',Markers{9},'MarkerIndices',1:intVal3:length(output_d2.Z_nCon_error(:)),'MarkerSize',10,'linewidth',1.1); 61 | ylim([error_th, inf]) 62 | grid on 63 | legend({'Proposed: x^{(k)}-x*','Proposed: (\Pi_{H})u^{(k)}-u*','Proposed: (I-\Pi_{H})u^{(k)}','Non-private: x^{(k)}-x*','Non-private: (\Pi_{H})u^{(k)}-u*','Non-private: (I-\Pi_{H})u^{(k)}'},'location','northeast','FontSize',10) 64 | set(gca, 'YScale', 'log') 65 | xlabel ('Transmissions'); ylabel ('MSE') 66 | title(strcat('Distributed ', name,' of Dual Ascent' ) ) 67 | set(gca, 'FontSize', 12) 68 | set(gca,'linewidth',2); 69 | -------------------------------------------------------------------------------- /subPert_privplot.m: -------------------------------------------------------------------------------- 1 | %%%plot the comparison of admm and pdmm under different privacy levels 2 | function subPert_privplot(error_th,ave_Res,name) 3 | intVal1=ave_Res.intVal(1); 4 | intVal2=ave_Res.intVal(2); 5 | intVal3=ave_Res.intVal(3); 6 | N=10; 7 | Markers = {'o','x','s','v','d','^','>','<'}; 8 | figure; 9 | set(gca,'fontsize',15) 10 | for i=1:3 11 | plot( ave_Res.admm(i).transmission(:),ave_Res.admm(i).MSE_error(:),strcat('b-'),'Marker',Markers{i},'MarkerIndices',1:intVal1:length(ave_Res.admm(i).MSE_error),'MarkerSize',10,'linewidth',1.1); 12 | hold on 13 | end 14 | ylim([error_th inf ]) 15 | % xlim([0 60]) 16 | set(gca,'fontsize',15) 17 | grid on 18 | legend({'p-ADMM: $7*{10}^{-7}$','p-ADMM: $7*{10}^{-5}$','p-ADMM: $7*{10}^{-3}$'},'location','northeast','FontSize',15,'Interpreter','Latex') 19 | set(gca, 'YScale', 'log') 20 | xlabel ('Transmissions'); ylabel ('||x^{(k)}-x*||^{2}') 21 | title(strcat('Privacy Levels: Distributed ', name)) 22 | set(gca, 'FontSize', 12) 23 | set(gca,'linewidth',2); 24 | 25 | figure; 26 | set(gca,'fontsize',15) 27 | for i=1:3 28 | 29 | plot( ave_Res.pdmm(i).transmission(:),ave_Res.pdmm(i).MSE_error(:),strcat('b-'),'Marker',Markers{i},'MarkerIndices',1:intVal2:length(ave_Res.pdmm(i).MSE_error),'MarkerSize',10,'linewidth',1.1); 30 | hold on 31 | end 32 | set(gca,'fontsize',15) 33 | ylim([error_th inf]) 34 | xlim([sum(sum(ave_Res.Geograph.weight)) inf]) 35 | grid on 36 | legend({'p-PDMM: $7*{10}^{-7}$','p-PDMM: $7*{10}^{-5}$','p-PDMM: $7*{10}^{-3}$'},'location','northeast','FontSize',15,'Interpreter','Latex') 37 | set(gca, 'YScale', 'log') 38 | xlabel ('Transmissions'); ylabel ('||x^{(k)}-x*||^{2}') 39 | title(strcat('Privacy Levels: Distributed ', name)) 40 | set(gca, 'FontSize', 12) 41 | set(gca,'linewidth',2); 42 | 43 | figure; 44 | set(gca,'fontsize',15) 45 | for i=1:3 46 | plot( ave_Res.dual(i).transmission(:),ave_Res.dual(i).MSE_error(:),strcat('b-'),'Marker',Markers{i},'MarkerIndices',1:intVal3:length(ave_Res.dual(i).MSE_error),'MarkerSize',10,'linewidth',1.1); 47 | hold on 48 | end 49 | set(gca,'fontsize',15) 50 | ylim([error_th inf]) 51 | % xlim([0 60]) 52 | grid on 53 | legend({'p-Dual: $7*{10}^{-7}$','p-Dual: $7*{10}^{-5}$','p-Dual: $7*{10}^{-3}$'},'location','northeast','FontSize',15,'Interpreter','Latex') 54 | set(gca, 'YScale', 'log') 55 | xlabel ('Transmissions'); ylabel ('||x^{(k)}-x*||_{2}^{2}') 56 | title(strcat('Privacy Levels: Distributed ', name)) 57 | set(gca, 'FontSize', 12) 58 | set(gca,'linewidth',2); 59 | 60 | -------------------------------------------------------------------------------- /test_all.m: -------------------------------------------------------------------------------- 1 | % This is test function for 'Privacy-preserving distributed optimization via subspace 2 | % perturbation: a general framework' 3 | % written by Qiongxiu Li, qili@create.aau.dk, in Aalborg, Denmark on 01.02.2020. 4 | 5 | 6 | %%%test function for three applications: avergae, least square, lasso 7 | close all;clear all;clc; 8 | %%%Global parameter setting 9 | TotalNodeNum=20;%Network size 10 | c=0.1;%penalty parameter of ADMM and PDMM 11 | Room_size = [1,1]; 12 | sigma=1;%variance of private data 13 | 14 | %%%Random geometric graph generaation 15 | sign=0; 16 | Geograph= RandomGraphGenerator(Room_size,TotalNodeNum,sigma,sign); 17 | Geograph_ave=Geograph; 18 | 19 | flag=0;%0 means zero initalization, 1 means random initialization, 3 means nonzero initializatin within converging subspace 20 | % %%%distributed average consensus application 21 | fprintf('Generating results for distributed average consensus\n') 22 | error_th = 1e-10; 23 | iteration_max = 1e3; 24 | Pmax=1000*sigma; %noise variance 25 | ave_Res.Geograph=Geograph_ave; 26 | ave_Res.intVal=[12,7,5]; 27 | ave_Res.output_a1=admm_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,1); 28 | ave_Res.output_a2=admm_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,3); 29 | ave_Res.output_p1=pdmm_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,1); 30 | ave_Res.output_p2=pdmm_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,3); 31 | ave_Res.output_d1=dual_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,1); 32 | ave_Res.output_d2=dual_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,3); 33 | subPert_converplot(error_th,ave_Res,Pmax,' Average Consensus'); 34 | 35 | ave_Res.admm(1)=ave_Res.output_a1; 36 | ave_Res.pdmm(1)=ave_Res.output_p1; 37 | ave_Res.dual(1)=ave_Res.output_d1; 38 | ave_Res.intVal=[10,5,5]; 39 | ave_Res.dp(1) = Synchronous_dp( Geograph_ave, error_th,iteration_max,0); 40 | for i=1:2 41 | Pmax=Pmax/10; 42 | ave_Res.admm(i+1)=admm_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,1); 43 | ave_Res.pdmm(i+1)=pdmm_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,1); 44 | ave_Res.dual(i+1)=dual_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,1); 45 | ave_Res.dp(i+1) = Synchronous_dp( Geograph_ave, error_th,iteration_max,Pmax); 46 | end 47 | subPert_privplot(error_th,ave_Res,' Average Consensus'); 48 | 49 | 50 | % % distributed least square application without regularization 51 | fprintf('Generating results for distributed least squares\n') 52 | u=3;ni=5; %overdetermined system 53 | Geograph_LS=graphSigIni(Geograph,sigma,u,ni); 54 | Pmax=1000*sigma; 55 | LS_Res.Geograph=Geograph_LS; 56 | error_th = 1e-10; 57 | iteration_max = 1e4; 58 | LS_Res.intVal=[200,80,1000]; 59 | LS_Res.output_a1=admm_syn_con_LS(Geograph_LS,error_th,iteration_max,Pmax,c,1); 60 | LS_Res.output_a2=admm_syn_con_LS(Geograph_LS,error_th,iteration_max,Pmax,c,3); 61 | LS_Res.output_p1=pdmm_syn_con_LS(Geograph_LS,error_th,iteration_max,Pmax,c,1); 62 | LS_Res.output_p2=pdmm_syn_con_LS(Geograph_LS,error_th,iteration_max,Pmax,c,3); 63 | LS_Res.output_d1=dual_syn_con_LS(Geograph_LS,error_th,iteration_max,Pmax,c,1); 64 | LS_Res.output_d2=dual_syn_con_LS(Geograph_LS,error_th,iteration_max,Pmax,c,3); 65 | subPert_converplot(error_th,LS_Res,Pmax,' Least Squares'); 66 | % 67 | LS_Res.admm(1)=LS_Res.output_a1; 68 | LS_Res.pdmm(1)=LS_Res.output_p1; 69 | LS_Res.dual(1)=LS_Res.output_d1; 70 | for i=1:2 71 | Pmax=Pmax/10; 72 | LS_Res.admm(i+1)=admm_syn_con_LS(Geograph_LS,error_th,iteration_max,Pmax,c,1); 73 | LS_Res.pdmm(i+1)=pdmm_syn_con_LS(Geograph_LS,error_th,iteration_max,Pmax,c,1); 74 | LS_Res.dual(i+1)=dual_syn_con_LS(Geograph_LS,error_th,iteration_max,Pmax,c,1); 75 | 76 | end 77 | subPert_privplot(error_th,LS_Res,' Least Squares'); 78 | 79 | 80 | 81 | %%%distributed least square with L1 regularization, Lasso 82 | fprintf('Generating results for distributed lasso\n') 83 | u=100;ni=3; %underdetermined system 84 | Geograph_lasso=graphSigIni(Geograph,sigma,u,ni); 85 | Pmax=1000*sigma; 86 | error_th = 1e-3; 87 | c=0.2;%penalty parameter of ADMM and PDMM 88 | iteration_max = 1e3; 89 | lamda=0.4;%%sparsity controller 90 | Lasso_Res.intVal=[120,180,120]; 91 | Lasso_Res.Geograph=Geograph_lasso; 92 | Lasso_Res.output_a1=admm_syn_con_lasso(Geograph_lasso,error_th,iteration_max,Pmax,c,lamda,1); 93 | Lasso_Res.output_a2 =admm_syn_con_lasso(Geograph_lasso,error_th,iteration_max,Pmax,c,lamda,3); 94 | Lasso_Res.output_d1=dual_syn_con_lasso(Geograph_lasso,error_th,iteration_max,Pmax,c,lamda,1); 95 | Lasso_Res.output_d2=dual_syn_con_lasso(Geograph_lasso,error_th,iteration_max,Pmax,c,lamda,3); 96 | iteration_max = 2e3; 97 | Lasso_Res.output_p1=pdmm_syn_con_lasso(Geograph_lasso,error_th,iteration_max,Pmax,c,lamda,1); 98 | Lasso_Res.output_p2=pdmm_syn_con_lasso(Geograph_lasso,error_th,iteration_max,Pmax,c,lamda,3); 99 | subPert_converplot(error_th,Lasso_Res,Pmax,' LASSO'); 100 | % Lasso_Res.admm(1)=Lasso_Res.output_a1; 101 | % Lasso_Res.pdmm(1)=Lasso_Res.output_p1; 102 | % Lasso_Res.dual(1)=Lasso_Res.output_d1; 103 | % for i=1:2 104 | % Pmax=Pmax/10; 105 | % Lasso_Res.admm(i+1)=admm_syn_con_lasso(Geograph_lasso,error_th,iteration_max,Pmax,c,lamda,1); 106 | % Lasso_Res.pdmm(i+1)=pdmm_syn_con_lasso(Geograph_lasso,error_th,iteration_max,Pmax,c,lamda,1); 107 | % Lasso_Res.dual(i+1)=dual_syn_con_lasso(Geograph_lasso,error_th,iteration_max,Pmax,c,lamda,1); 108 | % end 109 | % subPert_privplot(error_th,Lasso_Res,' LASSO'); 110 | 111 | 112 | % %%%comparison with differential privacy for distributed average consensus 113 | fprintf('Generating results for comarison with differential privacy in distributed average consensus\n') 114 | error_th = 1e-5; 115 | iteration_max = 2e2; 116 | Pmax=sigma; 117 | ave_Res.Geograph=Geograph_ave; 118 | ave_Res.intVal=[12,7,5]; 119 | ave_Res.pdmm(1)=pdmm_syn_con_ave(Geograph_ave,error_th,iteration_max,0,c,1); 120 | ave_Res.admm(1)=admm_syn_con_ave(Geograph_ave,error_th,iteration_max,0,c,1); 121 | ave_Res.dp(1) = Synchronous_dp( Geograph_ave, error_th,iteration_max,0); 122 | for i=1:2 123 | Pmax=Pmax*10; 124 | ave_Res.pdmm(i+1)=pdmm_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,1); 125 | ave_Res.admm(i+1)=admm_syn_con_ave(Geograph_ave,error_th,iteration_max,Pmax,c,1); 126 | ave_Res.dp(i+1) = Synchronous_dp( Geograph_ave, error_th,iteration_max,Pmax); 127 | end 128 | Markers = {'o','x','s','v','d','^','>','<'}; 129 | figure; 130 | set(gca,'fontsize',12) 131 | for i=1:3 132 | plot( ave_Res.pdmm(i).transmission(:),ave_Res.pdmm(i).MSE_error(:),strcat('b-'),'Marker',Markers{i},'MarkerIndices',1:5:length(ave_Res.pdmm(i).MSE_error),'MarkerSize',10,'linewidth',1.1); 133 | hold on 134 | plot( ave_Res.admm(i).transmission(:),ave_Res.admm(i).MSE_error(:),strcat('g-'),'Marker',Markers{i},'MarkerIndices',1:10:length(ave_Res.admm(i).MSE_error),'MarkerSize',10,'linewidth',1.1); 135 | hold on 136 | plot( ave_Res.dp(i).transmission(:),ave_Res.dp(i).MSE_error(:),strcat('r-'),'Marker',Markers{i},'MarkerIndices',1:20:length(ave_Res.dp(i).MSE_error),'MarkerSize',10,'linewidth',1.1); 137 | hold on 138 | end 139 | set(gca,'fontsize',15) 140 | ylim([error_th 1e5]) 141 | yticks([error_th 1e1 1e5]) 142 | xlim([0 3e4]) 143 | grid on 144 | legend({'p-PDMM: $10^4$','p-ADMM: $10^4$','DP: $10^4$','p-PDMM: $10^2$','p-ADMM: $10^2$','DP: $10^2$','p-PDMM: 0','p-ADMM: 0','DP: $0$'},'location','best','FontSize',15,'Interpreter','Latex') 145 | set(gca, 'YScale', 'log') 146 | % set(gca, 'XScale', 'log') 147 | xlabel ('Transmissions'); ylabel ('||x^{(k)}-x*||^{2}') 148 | set(gca, 'FontSize', 15) 149 | set(gca,'linewidth',1.1); 150 | 151 | 152 | 153 | 154 | --------------------------------------------------------------------------------