function [x_best,fobjs,ts]=AccerlatedProximalGradientBacktracking(x,hObjSmooth,hObjNonSmooth,hProx,maxiter,timeLimit,timeIntervel)
% An implemnetation of "FISTA with backtracking".

% References: A Fast Iterative Shrinkage-Thresholding Algorithm for Linear
% Inverse Problems, Amir Beck, Marc Teboulle, SIIMS 2009.

% This program solves the following optimization problem:
% f(x) + g(x)
% where we assume that f is smooth g is non-smooth
% hObjSmooth:           x   ->  [fobj,grad]
% hObjNonSmooth:        x   ->  [fobj]
% hProx:          [a,theta] ->  arg min_{x} 0.5 || x - a ||^2 + theta*g(x)

% One xample:

% function example_LeastR
% clear, clc;
% %  min  1/2 || A x - y||^2 + lambda * ||x||_1
% % f(x) + g(x)
% % 0.5 L ||x-xt||^2 + <x-xt,g> + g(x)
% % 0.5 L ||x-(xt-g/L)||^2 + g(x)
% % proximal mapping:
%
% % 0.5 ||x - a||^2 + theta*g(x)
%
%
% m=1000;  n=100;    % The data matrix is of size m x n
% A=randn(m,n);       % the data matrix
% y = randn(m,1);
% lambda=0.2;
% hObjSmooth = @(x)computeObj(x,A,y);
% hObjNonSmooth = @(x)lambda*sum(abs(x));
% x=zeros(n,1);
% hProx = @(a,theta)computeprox(a,theta,lambda);
% [x1, his]= AccerlatedProximalGradient(x,hObjSmooth,hObjNonSmooth,hProx);
% plot(his)
%
% function [fobj,grad] = computeObj(x,A,y)
% diff = A*x-y;
% fobj = 1/2*norm(diff)^2 ;
% grad = A'*diff ;
%
% function [x] = computeprox(a,theta,lambda)
% % 0.5 ||x - a||^2 + theta*g(x)
% [x] = threadholding_l1(a,lambda*theta);
%
% function [x] = threadholding_l1(a,lambda)
% % solving the following OP:
% % min_{x} 0.5 ||x - a||^2 + lambda * sum(abs(x))
% x = sign(a).*max(0,abs(a)-lambda);




L = 0.01;
alpha=1;
xp=x;
y=x;
x_best = x;
hObjF = @(x)hObjSmooth(x) + hObjNonSmooth(x);

f_curr = hObjF(x);
f_best = f_curr;

initt = clock;
last_rec_clock = initt;
ts = []; fobjs = [];
fobjs = [fobjs;f_curr];
ts = [ts;etime(clock,initt)];

for iterStep=1:maxiter,
    %     fprintf('*');
    [fobjy,grady] = hObjSmooth(y);
    xp = x;
    
    max_in = 10000;
    for in=1:max_in,
        % min_{x} 0.5 ||x-(xt-g/L)||^2 + 1/L*h(x)
        [x] = hProx(y-grady/L,1/L);
        Fnew = hObjF(x);
        % Check condition. Refer to Algborithm
        x_minus_y = x-y;
        if (Fnew <= fobjy + mdot(x_minus_y,grady) + 0.5*L*norm(x_minus_y,'fro')^2 + hObjNonSmooth(x)),
            break;
        else
            L = 2*L;
        end
    end

    alphap = alpha;
    alpha = 0.5*(1+ sqrt(4*alpha*alpha +1));
    beta = (alphap-1)/alpha;
    y = x + beta*(x-xp);
    
    f_curr = Fnew;
    if(f_curr<f_best)
        f_best = f_curr;
        x_best = x;
    end
 
    cur_clock = clock;
    if(etime(cur_clock,last_rec_clock) > timeIntervel)
        ElasTime =  etime(cur_clock,initt);
        fobjs  = [fobjs;f_curr];
        ts = [ts;ElasTime];
        last_rec_clock = cur_clock;
        if ElasTime > timeLimit
            break;
        end
    end

end

fobjs = fobjs(:);


