function [X,fobjs,ts] = L0SPCA_OADMM_EP(X,A,NormA,const,rho1,rho2,data_k,max_iter,beta0,alg_xi,timeIntervel,timeLimit,flagDual)
% min_X 0.5*||A-A*X*X'||_F^2 + rho (||X||_1 - ||X||_{topk} ), s.t. X'X = I, s.t. X'X = I
% min_X  0.5*||A-A*X*X'||_F^2 + rho ( ||X||_1 - ||X||_{topk} ), s.t. X'X = I
% min_X  -0.5/m*mdot(A,A*X*X') + const + rho ( ||Y||_1 - ||X||_{topk} ), s.t. Y = X, Y'Y = I
% L(Y,X,Z) = -0.5/m*mdot(A,A*X*X') + const  + rho ( ||Y||_1 - ||X||_{topk} ) + <X-Y,Z> + 0.5 beta ||Y-X||_F^2, s.t. X'X = I
[m,n] = size(A);
Lsmooth = NormA^2/m;

initt = clock;
last_rec_clock = initt;
HandleObj = @(X)L0SPCA_ComputeObj(X,A,rho1,rho2,data_k,const,m);

r = size(X,2);
Y = X+randn(n,r)*0.01;
if(flagDual==1)
Z = randn(n,r)*0.01;
else
Z = randn(n,r)*0.0;
end



[chi,sigma,theta,alpha] = set_default_para_EP(alg_xi);



X_old = X;

ts = []; fobjs = [];
fobj = HandleObj(X);
fobjs = [fobjs;fobj];
ts = [ts;etime(clock,initt)];

if(flagDual==1)
fprintf('OADMM-EP: begin\n');
else
fprintf('SPGM_EP: begin\n');
end

for iter = 1:30000
    
    p = 1/3; beta = beta0*(1+alg_xi*iter^p); mu = chi/beta;
    X_bar = X + alpha * (X-X_old);
    
    % Update X: L(Y,X,Z) = -0.5/m*mdot(A,A*X*X') + const  + rho ( ||Y||_1 - ||X||_{topk} ) + <X-Y,Z> + 0.5 beta ||Y-X||_F^2, s.t. X'X = I
    h_grad = @(X) -A'*(A*X)/m + Z + beta*(X-Y);
    grad_X = h_grad(X_bar)- rho2*top_k_subgrad(X,data_k); %
    Lipschit_constant = Lsmooth + beta;
    X_old = X; X = OrthProj(X_bar - grad_X/(theta*Lipschit_constant));
    
    % Update Y: min_Y -0.5/m*mdot(A,A*X*X') + const  + rho1 ||Y||_1 - rho2 ||X||_{topk} ) + <X-Y,Z> + 0.5 beta ||Y-X||_F^2, s.t. X'X = I
    % min_Y rho ||Y||_1 + <X-Y,Z> + 0.5 beta ||Y-X||_F^2
    % min_Y rho ||Y||_1 + 0.5 beta ||Y-(X+Z/beta)||_F^2
    B = X+Z/beta; beta_bar = beta/rho1;
   
%     if(flag==1)
    % min_Y  [||Y||_1]_{\mu} + 0.5 beta_bar ||Y - B||_F^2
    Y = smooth_prox_l1(B,mu,beta_bar);
%     else
    % min_Y  ||Y||_1 + 0.5 beta_bar ||Y - B||_F^2
    % min_Y  1/beta_bar*||Y||_1 + 0.5 ||Y - B||_F^2
%     Y = prox_l1(B,1/beta_bar);
%     end
    
    % Update Z
    diff = X-Y;
    if(flagDual==1)
    Z = Z + sigma*beta*diff;
    else
     Z = zeros(n,r);
    end
        
    e = norm(diff,'fro');
    cur_clock = clock;
    if(etime(cur_clock,last_rec_clock) > timeIntervel)
        fobj = HandleObj(X);
        ElasTime =  etime(cur_clock,initt);
        fobjs  = [fobjs;fobj];
        ts = [ts;ElasTime];
        last_rec_clock = cur_clock;
        if ElasTime > timeLimit,break; end
        fprintf('iter:%d, fobj:%f, dist:%f, beta:%f\n',iter,fobj,e,beta);
    end
end


if(flagDual==1)
fprintf('OADMM-EP: end\n');
else
fprintf('SPGM_EP: end\n');
end
