function [model, loo_err, coeff, best_idx_modello] = kls_train_adapt_zita_K(model,prev_outs)

% Train an Adaptive Kernel Least Square, considering prior knowledge.
% It looks for the best prior knowledge model and the best weight to use.

% References:
% T. Tommasi, B. Caputo. "The more you know, the less you learn: from 
% knowledge transfer to one-shot learning of object categories". BMVC 2009.

% This code is part of the supplementary material to the CVPR 2010 paper
% "Safety in Numbers: Learning Categories from Few Examples with Multi 
% Model Knowledge Trasfer", T. Tommasi, F. Orabona, B. Caputo.

% Copyright (C) 2009-2010, Tatiana Tommasi
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.
%
% Contact the author: ttommasi [at] idiap.ch


n = size(model.K,1);

model.K=[model.K ones(n,1); ones(1,n) 0];
	
index_p=find(model.Y==1);
l_p=numel(index_p);
index_m=find(model.Y==-1);
l_m=numel(index_m);
zita=zeros(1,numel(model.Y));
zita(index_p)=numel(model.Y)/(2*l_p);
zita(index_m)=numel(model.Y)/(2*l_m);

if numel(model.C)==1
    id=1/model.C*diag(1./zita); 
    id=[id zeros(n,1)];
    id=[id ; zeros(1,n+1)];
    id(end,end)=0;
else
    id=diag(1./model.C); id(end+1,end+1)=0;
end
G=pinv(model.K+id);
dd=diag(G);

x1=G*[(model.Y)';0];
model.beta = x1(1:end-1);
model.b = x1(end);

loo_pred=model.Y'-model.beta./dd(1:end-1);
   

for j=1:numel(prev_outs)
    if numel(prev_outs{j})==0, continue; end
    x2=G*[prev_outs{j};0];

    term_prev{j}=x2(1:end-1)./dd(1:end-1);
    beta_prev{j}=x2;
end

for idx_modello=1:numel(prev_outs)
    if numel(prev_outs{idx_modello})==0, continue; end
    
    t=0:0.01:1;
    
    for j=1:numel(t)
        out=loo_pred+t(j)*term_prev{idx_modello};

        
        for i=1:numel(model.Y)
            marg(i)=(model.Y(i)*(model.Y(i)-out(i))-1); %Cawley
        end
        obj(j)=sum(zita./(1+exp(-10*marg)));
       
    end

    [mx,idx]=min(obj);
    
    best_idx(idx_modello)=idx;
    best_obj(idx_modello)=mx;
end

pos=find(best_obj~=0);
[mx, best_idx_modello]=min(best_obj(pos));
coeff=t(best_idx(pos(best_idx_modello)));
    

model.beta=model.beta-coeff*beta_prev{pos(best_idx_modello)}(1:end-1);
model.b=model.b-coeff*beta_prev{pos(best_idx_modello)}(end);

loo_err=0;

best_idx_modello=pos(best_idx_modello);

