function [w,bias,alpha,delta,deltas,res]=trans_b_rmm_bias_hard(Kzz,y,C,B)
% Input:
% Kzz is the Gram matrix of the training examples
% y   is the vector of training labels
% C   is the trade off between the slack and the margin
% B   is the upper bound on the training predictions

% Output:
% w, lambda : parameters learned from the training. If Ktz is the 
%  kernel between the test and the training examples, the predictions
% are given by Ktz*w + lambda
% alpha, dleta, deltas  are the lagrange multipliers on the constraints
% as in the NIPS paper "Relative Margin Machines"

l = length(y);
n = size(Kzz,1);
u = n - l ;
%C = C/l;
prob.c = [zeros(n,1) ;  -ones(l,1)  ;  B*ones(n*2,1);  ];
prob.blx = [-inf*ones(n,1) ;  zeros(l,1);  zeros(n*2,1); ];
prob.bux = [ inf*ones(n,1) ;  C*ones(l,1);  inf(n*2,1); ];

quad =  [ Kzz    sparse(n,2*n+l); ...
          sparse(2*n+l,3*n+l) ];

prob.a = [ sparse(1,n) y'  -ones(1,n)  ones(1,n) ; ...
-speye(n)  [ diag(y) ; sparse(u,l) ]   -speye(n) speye(n);...
];
prob.blc = [ sparse(n+1,1); ];
prob.buc = [ sparse(n+1,1); ];
param.MSK_DPAR_INTPNT_CO_TOL_PFEAS = 1.0e-12;

% Dual feasibility tolerance for the dual solution
param.MSK_DPAR_INTPNT_CO_TOL_DFEAS = 1.0e-12;

% Relative primal-dual gap tolerance.
param.MSK_DPAR_INTPNT_CO_TOL_REL_GAP = 1.0e-12;
param.MSK_IPAR_INTPNT_NUM_THREADS = 2;
param.MSK_IPAR_LOG = 1;
[prob.qosubi,prob.qosubj,prob.qoval] = find(tril(sparse(double(quad))));
[r,res]=mosekopt('minimize echo(0)',prob,param);

alpha = res.sol.itr.xx(n+1:n+l);
delta = res.sol.itr.xx(n+l+1:l+2*n);
deltas = res.sol.itr.xx(l+1+2*n:l+3*n);
w = res.sol.itr.xx(1:n);
bias = res.sol.itr.suc(1) - res.sol.itr.slc(1);
