function x_new = x_step(samples, labels, rho, z, u, c)
% 
% x_step(samples, labels, rho, z, u, c): perform the update of the variable x at node i.
% 
% SAMPLES: sample matrix
%   [nbSamplePerNode, spaceDim]
% 
% LABELS: the label for each data point {-1; 1}
% 
% RHO: rho parameter (>0)
% 
% Z: Zij variable, between node i and j
%   [spaceDim+1, N(i)] N(i) = number of nodes connected to node i
% 
% U: Uij running sum of the residuals
%   [spaceDim+1, N(i)]
% 
% C: SVM soft margin (>0)
% 
% X_NEW: the classifier hyperplane
%   [spaceDim+1, 1]
%   x = [x_a', x_0]' (x_0 is the intercept term)
% 
% 

% Check the input variables

[nbSamplePerNode, spaceDim] = size(samples);
[a, N_i] = size(z);
[b, d] = size(u);

assert(nbSamplePerNode > 0);
assert(spaceDim > 0);
assert(length(labels) == nbSamplePerNode);
assert(min(labels) == -1);
assert(max(labels) == 1);
assert(rho > 0);
assert(N_i >= 0);

if (N_i ~= 0) 
    assert(a == spaceDim + 1);
    assert(b == a);
    assert(d == N_i);
    assert(c >= 0);
end

if (N_i == 0)% If this is a simple SVM optimization problem, we do not solve the same objective
    
    % In this case, we deal with a SVM classifier. Therefore, fi(x) is:
    %   1/2 norm2[x_a]^2 + c * sum_(over k in nbSamplePerNode){ epsilon_k }
    %   subject to:
    %     label_k * (x_a'*sample_k + x_0) >= 1 - epsilon_k, for all k in
    %     nbSamplePerNode

    cvx_begin quiet
        variable x_a(spaceDim)
        variable x_0
        variable epsilon(nbSamplePerNode)

        minimize( x_a'*x_a + c * norm(epsilon, 1))

        subject to
            labels .* (samples * x_a) >= 1 - epsilon
    cvx_end


    x_new = [x_a; x_0];
    return;
    
end

% ELSE (General case)

% We are going to minimize the following objective function in the x-step
% J(x) = fi(x) + rho/2 * sum_(over j in N(i)){ norm2[x - Zij + Uij]^2 }
% 
% The argmin(J(x)) will be x_new
% 
% In our case, we deal with a SVM classifier. Therefore, fi(x) is:
%   1/2 norm2[x_a]^2 + c * sum_(over k in nbSamplePerNode){ epsilon_k }
%   subject to:
%     label_k * (x_a'*sample_k + x_0) >= 1 - epsilon_k, for all k in
%     nbSamplePerNode

cvx_begin quiet
    variable x_a(spaceDim)
    variable x_0
    variable epsilon(nbSamplePerNode)
    variable x_rep((spaceDim+1) * N_i) % replication of x_a, used for simplifying the wrinting of the objective function
    
    minimize( x_a'*x_a + c * norm(epsilon, 1) + rho/2 * (x_rep - z(:) + u(:))'*(x_rep - z(:) + u(:)) )
    
    subject to
        x_rep == repmat([x_a; x_0], [N_i, 1])
        labels .* (samples * x_a) >= 1 - epsilon
cvx_end


x_new = [x_a; x_0];
return;


end