function model = ssvm2(X,options)
% SSVM2 Single-class SVM with L2-soft margin.
%
% Synopsis:
% model = ssvm2(X,options)
%
% Description:
% This function trains the single-class SVM with L2-soft margin.
% The task is to find hyperplane passing through the origin
% such that the input vectors lie on one side of the hyperplane.
% The margin between data and the hypeplane should be maximized.
% In the case of data its convex hull contains the origin
% (non-separable data) the L2-soft margin relaxation is applied.
% The hyperplane is sought for in the feature space induced by
% the prescribed kernel.
%
% Input:
% X [dim x num_data] Input vectors.
%
% options [struct] Control parameters:
% .ker [string] Kernel identifier.
% .arg [1xnars] Kernel argument(s).
% .solver [string] Used quadratic programming solver; options are
% 'mdm','kozinec' or 'npa' (default).
% .tmax [1x1] Maximal number of iterations.
% .tolabs [1x1] Absolute tolerance stopping condition.
% .tolrel [1x1] Relative tolerance stopping condition.
%
% Output:
% model [string] Hyperplane in the kernel feature sapce:
% .Alpha [nsv x 1] Weights.
% .b [1x1] Bias equal to 0.
% .sv.X [dim x nsv] Selected vectors.
% .options [struct] Copy of input options.
% .exitflag [1x1] Indicates which stopping condition was used:
% UB <= tolabs -> exit_flag = 1 Abs. tolerance.
% (UB-LB)/(LB+1) <= tolrel -> exit_flag = 2 Relative tolerance.
% t >= tmax -> exit_flag = 0 Number of iterations.
% .UB [1x1] Upper bound on the optimal solution.
% .LB [1x1] Lower bound on the optimal solution.
% .t [1x1] Number of iterations.
% .kercnt [1x1] Number of kernel evaluations.
% .margin [1x1] Achieved margin.
% .trnerr [1x1] Training error.
% .History [2x(t+1)] UB and LB with respect to number of iterations.
%
% Example:
% load('scales','X');
% model = ssvm2(X);
% figure; axis([-1 1 -1 1]); grid on;
% ppatterns(X); ppatterns(model.sv.X,'ob',13);
% pline(model);
%
% See also
% SVMCLASS, SVM.
%
% Modifications:
% 15-jun-2004, VF
% 23-Jan-2004, VF
% 22-Jan-2004, VF
% 19-Oct-2003, VF
if nargin >= 2, options = c2s( options); else options = []; end
if ~isfield( options, 'ker'), options.ker = 'linear'; end
if ~isfield( options, 'arg'), options.arg = 1; end
if ~isfield( options, 'C'), options.C = inf; end
if ~isfield(options,'tolabs'), options.tolabs = 0; end
if ~isfield(options,'tolrel'), options.tolrel = 1e-3; end
if ~isfield(options,'tmax'), options.tmax = inf; end
if ~isfield(options,'solver'), options.solver = 'npa'; end
[Alpha,exitflag,UB,LB,t,kercnt,margin,trnerr,History] = ...
ssvm2_mex(X,options.ker,options.arg,options.C,...
options.solver,options.tmax,options.tolabs,options.tolrel);
inx = find( Alpha > 0);
model.Alpha = Alpha(inx);
model.b = 0;
model.sv.X = X(:,inx);
model.sv.inx = inx;
model.nsv = length(inx);
if strcmpi('linear',options.ker) == 1,
model.W = model.sv.X*model.Alpha;
end
model.margin = margin;
model.UB = UB;
model.LB = LB;
model.t = t;
model.kercnt = kercnt;
model.exitflag = exitflag;
model.trnerr = trnerr;
model.options = options;
model.classifier = 'svmclass';
model.LB_History = History(1,:);
model.UB_History = History(2,:);
return;