function [path, relative_error] = FNSL_lowrank(X, Y, A0, Astar, kmax, rAstar)

% FNSL_lowrank    Solve low-rank transition estimation by FNSL
% [path, relative_error] = FNSL_lowrank(X, Y, A0, Astar, kmax, rAstar)
% X - Data matrix
% Y - Measurement matrix
% A0 - Initial point
% Astar - Real transition matrix
% kmax - Maximum iteration
% rAstar - Rank of real transition matrix
% path - Path of iteration points
% relative_error - Relative errors of iteration points

[n, d] = size(X);

%%%%%Initialization
path = [];
function_value = [];
relative_error = [];


alpha0 = 1;
etaMin = max(eig(X.' * X)) / 10;
eta00 = etaMin;

Aavg0 = A0;
Q0 = 0;

lambda0 = 1.6*sqrt(d * n);


k = 1;


while k <= kmax
    
    while 1
    if k == 1
        alpha = alpha0;
        eta = alpha * eta00;
    else
        alpha = (- alpha0 * eta0 + sqrt(alpha0^2 * eta0^2 + 4 * eta00 * alpha0 * eta0)) / 2 / eta00;
        eta = alpha * eta00;
    end
    
    Amd = (1 - alpha) * Aavg0 + alpha * A0;
    
    temp = A0 - 1 / eta * X' * (X * Amd - Y');
    
    A = prox_operator_nuclear(temp, lambda0, 1 / eta);
        
    Gamma = norm(A - A0)^2  - alpha / eta * norm(X * (A - A0), 'fro')^2;
    
    Q = (1 - 1 / k)^2 * Q0 + Gamma;
    
    if Q < - 1 / k^2
        eta00 = 2 * eta00;
    else
        break
    end
    end
    
    Aavg = (1 - alpha) * Aavg0 + alpha * A;

    k = k + 1;
    path = [path, reshape(Aavg, d * d, 1)];
    
    relative_error = [relative_error, norm(A - Astar', 'fro') / norm(Astar', 'fro')];
    
    
    eta00 = max(etaMin, norm(X*(A - A0), 'fro')^2 / norm(A - A0, 'fro')^2);
    alpha0 = alpha;
    Aavg0 = Aavg;
    A0 = A;
    Q0 = Q;
    eta0 = eta;    
    
end
        
        
end
