function [X,fobjs,ts] = L0SPCA_RADMM(X,A,NormA,const,rho1,rho2,data_k,max_iter,betaRADMM,timeIntervel,timeLimit)
% 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;
Z = randn(n,r)*0.01;

XP = X;
dtX = zeros(n,r);

ts = []; fobjs = [];
fobj = HandleObj(X);
fobjs = [fobjs;fobj];
ts = [ts;etime(clock,initt)];
 
mu = 1/betaRADMM;
gamma = 0.1;delta = 1e-4;
fprintf('RADMM: begin\n');
for iter = 1:30000
    
    % Solve the minimization problem:
    %  -0.5*mdot(HX,X) + mdot(X,Z) + 0.5*beta*norm(XY,'fro')^2 - rho2* tksum(X,data_k);

    fun = @(X) ComputeObj(X,A,m,data_k,betaRADMM,Y,rho2,Z);
    [F, G] = fun(X);
    dtX = G - X*G'*X;
    nrmG  = norm(dtX, 'fro');
    tau = 0.001;
    
    XP = X; FP = F;  dtXP = dtX;
    for jj = 1:1000
        eta = tau*gamma^jj; %1/betaRADMM*
        Delta = - eta*dtX;
        X = retr(XP,Delta);
        [F] = fun(X);
        if abs(eta)<1e-10 || F <= FP-eta*delta*nrmG^2;
            break;
        end
        
    end
    
    % Solve the minimization problem:
    % rho1 [||Y||_1]_{mu} + <X-Y,Z> + 0.5 beta ||Y-X||_F^2, s.t. X'X = I
    % where mu = 1 / beta
    % rho ||Y||_1 + <X-Y,Z> + 0.5 beta ||Y-X||_F^2
    % rho ||Y||_1 + 0.5 beta ||Y-(X+Z/beta)||_F^2
    B = X+Z/betaRADMM;
    beta_bar = betaRADMM/rho1;
    % min_Y  [||Y||_1]_{\mu} + 0.5 beta_bar ||Y - B||_F^2
    Y = smooth_prox_l1(B,mu,beta_bar);
    
    % Update Z
    diff = X-Y; Z = Z + betaRADMM*diff;
    
    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,betaRADMM);
    end
end
fprintf('RADMM: end\n');
function [F,G] = ComputeObj(X,A,m,data_k,beta,Y,rho2,Z)
HX = A'*(A*X)/m;
XY = X-Y;
F = -0.5*mdot(HX,X) + mdot(X,Z) + 0.5*beta*norm(XY,'fro')^2 - rho2* tksum(X,data_k);
if(nargout==2)
    G = -HX + Z + beta*XY  - rho2*top_k_subgrad(X,data_k);
end
