function [AlphaY, SVs, Bias, Para, Ns] = osuSVMTrain(Samples, Labels, Parameters,Verbose)
% USAGE:
% [AlphaY, SVs, Bias, Para, Ns] = osuSVMTrain(Samples, Labels, Parameters)
% [AlphaY, SVs, Bias, Para, Ns] = osuSVMTrain(Samples, Labels, Parameters,Verbose)
%
% DESCRIPTION:
% Construct a SVM classifier (both multi-class case and 2-class case)
%
% INPUTS:
% Samples: all the training patterns. (a row of column vectors)
% Lables: the corresponding class labels for the training patterns in Samples.
%         (a row vector) (labels are like 1, 2, 3, ..., M )
% Parameters: the paramters required by the training algorithm. 
%             (a 10-element row vector)
%            +-----------------------------------------------------------------
%            |Kernel Type| Degree | Gamma | Coefficient | C |Cache size|epsilon| 
%            +-----------------------------------------------------------------
%				 -------------------------------------------+
%            | SVM Type |	nu (nu-svm) | loss tolerance |				
%				 -------------------------------------------+
%            where Kernel Type:
%                   0 --- Linear
%                   1 --- Polynomial: (Gamma*<X(:,i),X(:,j)>+Coefficient)^Degree
%                   2 --- RBF: (exp(-Gamma*|X(:,i)-X(:,j)|^2))
%                   3 --- Sigmoid: tanh(Gamma*<X(:,i),X(:,j)>+Coefficient)
%                  Gamma: If the input value is zero, Gamma will be set defautly as
%                         1/(max_pattern_dimension) in the function. If the input
%                         value is non-zero, Gamma will remain unchanged in the 
%                         function.
%                  C: Cost of the constrain violation (for C-SVC & C-SVR)
%                  Cache Size: as the buffer to hold the <X(:,i),X(:,j)> (in MB)
%                  epsilon: tolerance of termination criterion
%                  SVM Type: 
%                   0 --- c-SVM classifier
%                   1 --- nu-SVM classifier
%                   2 --- 1-SVM 
%                   3 --- c-SVM regressioner
%                  nu: the nu used in nu-SVM classifer (for 1-SVM and nu-SVM)
%						 loss tolerance: the epsilon in epsilon-insensitive loss function	
% Verbose: =0: the program will be very quite, providing little feedback
%          =2: the program will be very verbose, providing lots of the feedback
%          =1: the situation between the above two.
%          default: 0
% 
% OUTPUTS:
% AlphaY: Alpha * Y, where Alpha is the non-zero Lagrange Coefficients
%                    Y is the corresponding labels. 
%     in multi-class case:
%        [AlphaY_Class1, AlphaY_Class2, ..., AlphaY_ClassM]
%        +----Ns(1)----+----Ns(2)-----+----+---Ns(M)------+
% SVs : support vectors. That is, the patterns corresponding the non-zero
%       Alphas.
%     in multi-class case:
%        [SVs_Class1, SVs_Class2, ..., SVs_ClassM]
%        +--Ns(1)---+---Ns(2)---+----+---Ns(M)---+
% Bias : the bias in the decision function, which is AlphaY*Kernel(SVs',x)-Bias.
%     in multi-class case:
%        [Bias_Class1, Bias_Class2, ..., Bias_ClassM]
% Para: it is the same as the input 'Parameters'.
% Ns: number of SVs for each class (a row vector). This parameter is valid only
%     for the multi-class case, and is 0 for the 1-class case and 2-class case.
%
if (nargin < 3) | (nargin > 4)
   disp(' Incorrect number of input variables.\n');
   help osuSVMTrain;
else
   if nargin == 3
      Verbose = 0;
   end
   Mmax=max(Labels); %label: 1, 2, 3, ..., M
   Mmin=min(Labels); %label: 1, 2, 3, ..., M
   M = Mmax-Mmin + 1; % number of classes
   if Verbose > 0
      fprintf('\n Constructing a %d-class SVM classifier.\n',M);
   end
   if M == 1 % for the 1-class case
      Ns=0;
      if Parameters(8) ~= 2 
         disp('Warning: your samples are all from one class. Thus, 1-SVM is adopted\n.');
         Parameters(8) = 2;
         Labels = ones(size(Labels));
      end
      [AlphaY, SVs, Bias, Para] = SVMTrain(Samples, Labels, Parameters,Verbose);
   elseif M == 2 % for the 2-class case
      Ns=0;
      Labels=(1.5-Labels)*2; % change to {1 -1} labels, required by SVMTrain.m
      [AlphaY, SVs, Bias, Para] = SVMTrain(Samples, Labels, Parameters,Verbose);
   else
      for i=1:M % for the multi-class case, using 1-to-rest method
         CurrentLabels = (Labels == i);
         % change the labels from {1..M} format to {1 -1} format one class by one class
         NonClassLabelInd =find(CurrentLabels == 0);
         CurrentLabels(NonClassLabelInd)=-1*ones(1,length(NonClassLabelInd));
         % call the basic 2-class SVM training program
         if Verbose > 0
            fprintf(1,'\n Class %d: \n',i);
         end
         [curAlphaY, curSVs, curBias,Para] = SVMTrain(Samples, CurrentLabels, Parameters,Verbose);
         if Verbose > 0
            fprintf('\n');
         end
         % assemble the output SVM model parameters
         if i==1
            AlphaY=curAlphaY;
            SVs=curSVs;
            Bias=curBias;
            Ns=length(curAlphaY);
         else
            AlphaY=[AlphaY curAlphaY];
            SVs=[SVs curSVs];
            Bias=[Bias curBias];
            Ns=[Ns length(curAlphaY)];
         end
      end
   end
end


 