% Pr\'actoca 4 de RA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% En esta ocasi\'on vamos a acercarnos al problema del aprendizaje 
% autom\'atico. Suministramos al sistema ejemplos positivos y 
% negativos (hechos Prolog) y se pide que el sistema devuelva un 
% programa Prolog (hechos y reglas) que clasifique correctamente 
% los ejemplos.
% Vamos a adaptar para esta pr\'actica una versi\'on simplificada 
% del sistema de Programaci\'on L\'ogica Inductiva "TRACY", 
% desarrollado por F. Bergadano y D. Gunetti en 1994.
% El programa devuelve un programa Prolog, es decir, un conjunto 
% ordenado de cl\'ausulas, tomadas de un conjunto C suministrado por 
% el usuario. El espacio de b\'squeda es el conjunto de todos
% los posibles subconjuntos ordenados de cl\'ausulas de $C$. Usamos
% el "backtracking" como sistema de b\'usqueda.                     
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 1:
% Vamos a definir primero el conjunto de entrenamiento. En esta 
% pra\'ctica vamos a pedir a nuestro sistema que nos de una 
% soluci\'on al problema de encontrar una definici\'on al concepto 
% "numero par" con la notacion "0, s(s(0)), s(s(s(s(0)))), ..."
% El conjunto de entrenamiento vendr\'a definido por dos predicados
% "listapositivo(L1)" y "listanegativo(L2)" donde L1 y L2 son las 
% listas de ejemplos correspondientes.
% Se pide definir un procedimiento
%                  genera_entrenamiento(N).
% que incorpore a la base de conocimiento de Prolog los hechos:
%       "listapositivo([p1,p2,p2,...,pN])"
%       "listanegativo([i1,i2,i2,...,iN])"
% con la lista de los N primeros numeros pares e impares 
% respectivamente y que elimine cualquier otro conjunto de 
% entrenamiento que hubiera en la base de datos.
%    Ejemplo:
%
%    ?- genera_entrenamiento(2).
%       Yes
%    ?- listapositivo(L).
%       L = [par(0), par(s(s(0)))] ;
%       No
%    ?- listanegativo(L).
%       L = [par(s(0)), par(s(s(s(0))))] ;
%       No
%    ?- genera_entrenamiento(3).
%       Yes
%    ?- listapositivo(L).
%       L = [par(0), par(s(s(0))), par(s(s(s(s(0)))))] ;
%    ?- listanegativo(L).
%       L = [par(s(0)), par(s(s(s(0)))), par(s(s(s(s(s(0))))))] ;
%       No
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% A continuaci\'on suministramos un conjunto de cl\'ausulas 
% numeradas del 1 al 7. La salida de nuestro sistemas ser\'a un 
% conjunto ordenado de n\'umeros que representaran algunas de las 
% cl\'ausulas. Tales cl\' ausulas forman un programa Prolog que 
% puede ser visto como una definicion del predicado "par"
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Conjunto de cl\'ausulas:
    
par(0):- allowed(1), marker(1).
par(s(X)):- allowed(2), par(X), marker(2).
par(s(s(X))):- allowed(3), par(X), marker(3).
par(s(s(X))):- allowed(4), par(s(X)), marker(4).
par(s(s(s(X)))):- allowed(5), par(X), marker(5).
par(s(s(s(X)))):- allowed(6), par(s(X)), marker(6).
par(s(s(s(X)))):- allowed(7), par(s(s(X))), marker(7).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 2:
% Define un predicado 
%                         recuerda(Atomo,Clausulas)
% que tome como entrada un atomo cerrado y devuelva los numeros (del
% 1 al 7) de las clausulas usadas en la primera refutacion de Atomo.
%    Ejemplo:
%
%       ?- recuerda(par(s(s(s(0)))),L).
%          L = [1, 2] ;
%          No
% 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 3:
% Definir un predicado
%               refuta(Atomo,Lista1,Lista2)
% que tome como dato de entrada un Atomo y una lista de n\'umeros
% y devuelva "Yes" si podemos encontrar una refutaci\'on del 
% Atomo con las cl\'ausulas correspondientes a los n\'umeros
% de la lista. Lista2 es la lista de los n\'umeros correspondientes 
% a las cl\'ausulas usadas en la primera refutaci\'on.
%
%       Ejemplo:
%
%      ?- refuta(par(s(s(s(s(s(0)))))),[1,3,5,6,7],L).
%         L = [1, 3, 5] ;
%         No
%
%      ?- refuta(par(s(s(s(s(s(s(0))))))),[1,5],L).
%         L = [1, 5] ;
%         No
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 4:
%  Definir un predicado
%                  trynegs(L)
% que tome como entrada una lista de atomos L y tenga exito si no 
% podemos probar ninguno de los atomos (con las clausulas 
% permitidas en ese momento.
%
%  Ejemplo de uso:
%

prueba_1:- abolish(allowed/1),
           assert(allowed(1)),
           assert(allowed(3)),
           trynegs([par(s(0)),par(s(s(s(0))))]).

prueba_2:- abolish(allowed/1),
           assert(allowed(1)),
           assert(allowed(3)),
           trynegs([par(s(0)),par(s(s(0))),par(s(s(s(0))))]).


%   ?- prueba_1.
%      Yes
%
%   ?- prueba_2.
%      No
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 5:
% Definir un predicado
%             resetallowed
% que deje los predicados "allowed", "marker" y "contador" como
% al principio de la sesi\'on.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 6:
%  Definir un procedimiento
%             notneg(Clausulas,Marca)
% que siempre tenga \'exito. Toma como dato de entrada una lista
% de numeros "Clausulas" y devuelve una marca que puede ser
% "a" o "b".
% - Si a partir de la lista de clausulas "Clausulas" podemos
%   refutar alg\'un ejemplo negativo, entonces Marca = b.
% - Si esto no ocurre, entonces Marca = a
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 7:
% Definir un predicado
%         tracer(Lista,Final,Acum)
% que tome como dato de entrada una lista de ejemplos (positivos)
% y devuelva la "Lista" numerica de las clausulas con las que
% podemos probar todos los ejemplos negativos, pero ninguno
% de los negativos.
% Para ello, tomamos el primer ejemplo "E" de "Lista", encuentra 
% una refutacion para el y marca que clausulas han sido usadas. 
% Si a partir de ellas no se deriva ningun ejemplo negativo 
% las guarda y sigue con el siguiente ejemplo. Si conseguimos 
% derivar algun ejemplo negativo X=a falla y PROLOG hara 
% backtraking y volvera  a intentar una nueva refutacion 
% de "E" con nuevas clausulas.
%      Ejemplo de uso:


prueba_3(T):-
	tracer([par(0)],T,[]).


prueba_4(T):-
	listapositivo(LP),
	tracer(LP,T,[]).


%    ?- prueba_3(Tracer).
%         Tracer = [1] ;
%         No
%
%    ?- prueba_4(Tracer).
%        Tracer = [1, 3] 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 8:
%   Definir el predicado
%                    tracy
% que sin recibir argumentos devuelva la lista de numeros
% correspondientes a las clausulas solucion del problema.
%   Ejemplo de uso:
%
%   ?- tracy.
%      [1, 3]
%      Yes
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 9:
%  Definir un procedimiento
%           tracy_cl(Nombre)
% que tome como dato de entrada el nombre del fichero (sin 
% extension .pl) y escriba las clausulas solucion a
% nuestro programa en el fichero "Nombre" (con extension
% .pl) ya listas para ser usadas como definicion del predicado
% par.
%    Ejemplo de uso:
%
%     ?- tracy_cl(par).
%        Yes
%
% Y si consultamos el fichero "par.pl" obtenemos
%
%   par(0).
%   par(s(s(A))) :-
%        par(A),
%	 true.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

