% prepare an upper bound of number of iterations for the algorithm
numiterSG_ub = 20000;
% initialize the counting on the actual number of iterations in the algorithm
step_count_SG = 0;
% initialize the tolerance for the stopping criteria
tol_SG = 1e-4;

% prepare an 1*(numiterSG_ub+1) zero matrix to store the objectives in each iteration
obj_candidate = zeros(1, numiterSG_ub+1); 
% prepare a d*(numiterSG_ub+1) zero matrix to store the iterates in each iteration by column
w_candidate = zeros(d, numiterSG_ub+1);

w = A(1,:)'; % d*1 double
eta = 0.005; % constant step-size

obj_candidate(1,1) = dot( 1 - b.*(A*w), 1 - b.*(A*w) > 0 ) / n;
w_candidate(:,1) = w;
fprintf('Iter=%i, obj=%f\n', 0, obj_candidate(1,1)+0);
% add +0 to avoid the error: using fprintf. Function is not defined for sparse inputs

for t = 1:numiterSG_ub
    
    % compute the subgradient
    subgrad = - ( (A').*b' ) * ( 1 - b.*(A*w) > 0 ) / n;
    % perform update
    w = w - eta*subgrad;
    
    obj_candidate(1,t+1) = dot( 1 - b.*(A*w), 1 - b.*(A*w) > 0 ) / n;
    w_candidate(:,t+1) = w;
    
    fprintf('Iter=%i, obj=%f\n', t, obj_candidate(1,t+1)+0);
    % add +0 to avoid the error: using fprintf. Function is not defined for sparse inputs
    
    if norm(eta*subgrad, 2) <= tol_SG
        break
    end
    
    step_count_SG = step_count_SG + 1;
end

[obj, index] = min(obj_candidate(1:(step_count_SG+1)));
fprintf('Result of hingle loss minimization is from iter=%i, obj=%f\n', index-1, obj+0);
w = w_candidate(:,index);

figure
plot(0:step_count_SG, obj_candidate(1:(step_count_SG+1)), 'blue')
title('Hinge Loss Minimization')
xlabel('Iteration t')
ylabel('Loss value')