function [ Sol, ind_zf, tsol ] = DPC_MTFL_ZWZ( Xs, ys, Lambda, opts )
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Changed from the function DPC_MTFL, the difference is that the input Xs and ys are cells instead of matrix and vector
%% Implementation of the sequential DPC rule proposed in
% Safe Screening for Multi-Task Learning with Multiple Data Matrices
% Jie Wang, Peter Wonka, and Jieping Ye.
%
%% input:
% X:
% stacked data matrix, each column corresponds to a feature
% each row corresponds to a data instance
%
% y:
% the response vector
%
% Lambda:
% the parameters sequence
%
% opts:
% settings for the solver
%% output:
% Sol:
% the solution; the ith column corresponds to the solution
% with the ith parameter in Lambda
%
% ind_zf:
% the index of the discarded features; the ith column
% refers to the solution of the ith value in Lambda
%
% t_sol:
% the ith entry of ts_sol records the running time of the
% solver after screening
%% For any problem, please contact Jie Wang (jiewangustc@gmail.com)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X = [];y = [];
for idx_t = 1:length(ys)
X = [X;Xs{idx_t}];
Xs{idx_t} = [];
y = [y;ys{idx_t}];
ys{idx_t}=[];
end
[N,d] = size(X);
npar = length(Lambda); % number of parameters
% ---------------------------- pass parameters -------------------------- %
opts.init = 0; % set .init for warm start
task_ind = opts.ind;
stask = diff(task_ind); % size of each task
T = length(stask); % number of tasks
% --------------------- initialize the output --------------------------- %
Sol = zeros(d,T,npar);
ind_zf = false(d,npar);
%rej_ratio = zeros(1,npar);
% ------- construct sparse matrix to vectorize the computation ---------- %
ft_ind = zeros(1,N);
for i = 1:T
ft_ind(1,task_ind(i)+1:task_ind(i+1))=i; % fg_ind(j) is the index of the group
% which contains the jth feature
end
tS = sparse(ft_ind,1:N,ones(1,N),T,N,N); % ith row refers to the ith task, if the ith row
% refers to the i_s to i_e features, then
% tS(i,i_s:i_e) = 1.
% ------ compute the norm of each feature of each task ||x_l^t||_2 ---------- %
Xtnorm = sqrt(tS*(X.*X));
H = -2*Xtnorm;
[xtnmx,xtnmxind] = max(Xtnorm);
% --------------------------- compute lambda_max ------------------------ %
Xtty = tS*(X.*repmat(y,1,d)); % Xtty is of T*d and Xtty(i,j) = <x_j^i,y_i>
[lambda_max2, indmx] = max(sum(Xtty.*Xtty,1));
lambda_max = sqrt(lambda_max2);
opts.lambda_max = lambda_max;
if opts.rFlag == 1
opts.rFlag = 0; % the parameter value passing to the solver is its
% absolute value rather than a ratio
Lambda = Lambda*lambda_max;
end
% ----------------- sort the parameters in descend order ---------------- %
[Lambdav,Lambda_ind] = sort(Lambda,'descend');
rLambdav = 1./Lambdav;
% ----------------- solve MTFL sequentially with DPC ------------ %
lambdap = lambda_max;
tsol = zeros(1,npar);
for i = 1:npar
fprintf('in DPC step: %d\n',i);
lambdac = Lambdav(1,i);
if lambdac>=lambda_max
%Sol(:,Lambda_ind(i)) = 0; % because Sol is initalized to be 0
ind_zf(:,Lambda_ind(i)) = true;
%rej_ratio(Lambda_ind(i)) = 1;
else
if lambdap==lambda_max
theta = y/lambda_max;
indmx = indmx(1);
nv = (tS'*Xtty(:,indmx)).*X(:,indmx);
else
theta = (y - sum(X.*(Sol(:,:,Lambda_ind(i-1))*tS)',2))*rlambdap;
nv = y*rlambdap-theta;
end
rlambdac = rLambdav(1,i);
nv = nv/norm(nv);
rv = y*rlambdac-theta;
Prv = rv - (nv'*rv)*nv;
o = theta + 0.5*Prv;
r = 0.5*norm(Prv);
% ------- screening by DPC, remove the ith feature if T(i)=1 ----- %
Xtto = tS*(X.*repmat(o,1,d));
q = -2*(Xtto.*Xtnorm);
qpmx = -newton_qp(H,q,r,2*xtnmx,xtnmxind);
Tmt = 1 > (sum(Xtto.*Xtto,1))' + qpmx + 1e-8;
ind_zf(:,Lambda_ind(i)) = Tmt;
nTmt = ~Tmt;
Xr = X(:,nTmt);
if lambdap == lambda_max
opts.x0 = zeros(size(Xr,2),T);
else
opts.x0 = Sol(nTmt,:,Lambda_ind(i-1));
end
% --- solve the group Lasso problem on the reduced data matrix -- %
starts = tic;
[x1, ~, ~]= mtLeastR(Xr, y, lambdac, opts);
tsol(Lambda_ind(i)) = toc(starts);
Sol(nTmt,:,Lambda_ind(i)) = x1;
lambdap = lambdac;
rlambdap = rlambdac;
end
end
end