% APRENDIZAJE AUTOMÁTICO (G. Pajares y J. M. de la Cruz, Eds.)
% Editorial: RA-MA
% Capítulo 5: Máquinas de Vectores Soporte
% Autores: Jesús Antonio Vega Sánchez y Sebastián Dormido Canto

function [correctas,auxsal,resultado]=clasifica(numeroclases,Xtest,svmC,nsvC,bC,kernel,param);

% La función CLASIFICA realiza la clasificación de la entrada Xtest 
%
% Los parámetros de entrada son:
%                - numeroclases: es un escalar y representa el número de clases entre las que se
%                                desea clasificar. Por ej. si se tiene {BOL5,ECE7,RX306} el valor de
%                                numeroclases sería 3.
%
%                - Xtest: matriz de vectores a testear, tiene el mismo formato que XX
%
%                - svmC: almacena los vectores soporte de todas las máquinas (se almacenan en filas), la penúltima
%                       columna almacena el valor de la etiqueta {1,-1} para saber si pertenece a la clase k ó
%                       al resto y en la última columna el valor de alpha
%
%                - nsvC: almacena el número de vectores soporte de cada una de las k máquinas
%
%                - bC: alamcena el término bias de las k máquinas
%
%                - kernel: es un string donde se introduce la función de transformación a utilizar.                  
%                          Los valores para kernel pueden ser: 
%                                                           'linear'  -
%                                                           'poly'    - [1,p1] p1 is degree of polynomial
%                                                           'erfb'    - [1,p1] p1 is width of rbfs (sigma)
%                                                           'rbf'     - [1,p1] p1 is width of rbfs (sigma)
%                                                           'sigmoid' - [p1, p2] p1 is scale, p2 is offset                                                      
%                                                           
%
%                - param: es un vector de dimensión 2 que almacena los parámetros de las funciones kernel que
%                         se pueden utilizar. Por ejemplo param=[2 1]; 


%fprintf('Clasificación\n') 
clasifica=[];
auxX=[];
conta=0;
correctas=[];
auxsal=[];

for k=1:numeroclases
   if k==1
      svm=svmC(1:nsvC(k),:);
      else
         svm=svmC(sum(nsvC(1:k-1))+1:sum(nsvC(1:k)),:);
   end      
   b0=bC(k);
   nalphanY=svm(:,end).*svm(:,end-1);
 
   nnX = size(svm,1);
   
   %Cálculo del signo para ver a que clase pertenece el Xtest  
   nXtest=size(Xtest,1);
   nH = zeros(nnX,nXtest);  
   for i=1:nnX
      for j=1:nXtest
          nH(i,j) = svkernel2(kernel,svm(i,1:(end-2)),Xtest(j,:),param);
      end
   end
 
   M=size(nH,2);   % Nº de vectores sobre los que decidir
   for i=1:M
        nH(:,i)=nH(:,i).*nalphanY;
   end
   D=sum(nH);

%fprintf('Clasificación\n') 
auxsal=[auxsal,D'+b0];

   sal=sign(D'+b0);
   length(sal);
   
  
   for i=1:length(sal)
       if sign(sal(i))==1
          clasifica=[clasifica;[i,k]];
   	 end;
	end;
end;

clasifica=sortrows(clasifica);

aux=1;
clasificaAux=[];
[filas,columnas]=size(clasifica);
while aux <= filas
   valor=clasifica(aux,:);
   if length(find(clasifica(:,1)==valor(1,1))) > 1
      
   else
     clasificaAux=[clasificaAux;clasifica(aux,:)];
   end
   aux=aux+1;
end   

resultado=[];

	for i=1:size(Xtest,1)
      if not(isempty(clasificaAux))     
	      valor=find(clasificaAux(:,1)==i);
      else
         valor=0;
      end;
         
      if valor >=1
        % disp(['La señal nº ',num2str(i),' es de clase ', num2str(clasificaAux(valor,2))]); 
         resultado=[resultado;[i clasificaAux(valor,2)]];
      else
        % disp(['La señal nº ',num2str(i),' no es clasificable']);
         resultado=[resultado;[i 0]];
         %prob=max(clasificaAux(find(clasificaAux(:,1)==i),:));   
      end
   end 
   %resultado
  % auxsal=[[1:(size(auxsal,1))]',auxsal];
   %auxsal(1:10,:)
   %for k=1:numeroclases
   % correctas(k)=length(find(clasificaAux(:,2)==k));
   %end
   
   %Para clasificar todo se toma el criterio de seleccionar la distancia mas cercana a cero
   %[a,b]=max(auxsal(:,2:end),[],2)

