function fns = agent_Prob_PCA(D, N, fns)
% D is the dataset, stroed in cell.
% N is number of sample
% fns is a structure related to Problem, and contains 
%    fns.cost, 
%    fns.egrad,
%    fns.partialegrad, 

    fns.cost  = @(x) cost(x, D, N);

    fns.egrad = @(x) partialegrad(x, D, 1:N);
    fns.partialegrad = @(x, S) partialegrad(x, D, S);
    
    fns.grad = @(x) fns.M.egrad2rgrad(x, fns.egrad(x));
    fns.partialgrad = @(x, S) fns.M.egrad2rgrad(x, fns.partialegrad(x, S));

end

function output = cost(x, D, N)
    tmp = 0;
    for i = 1:N
        tmp = tmp + singlecost(x, D{i});
    end
    output = tmp / N;
end

function output = partialegrad(x, D, S)
    tmp = zeros(size(x));
    for i = reshape(S, 1, length(S))
        tmp = tmp + singleegrad(x, D{i});
    end
    output = tmp / length(S);
end

function output = singlecost(x, Di)    
    tmp = Di' * x;
    output = - 0.5 * trace(tmp' * tmp);
end

function output = singleegrad(x, Di)
    output = - Di * (Di' * x);
end
