%%%************************************************************************
%%% INTELIGENCIA ARTIFICIAL II.                                 CURSO 01-02
%%% EXAMEN PRÁCTICO                                     Árboles de decisión
%%%************************************************************************

%%%************************************************************************
% Definidos en Prolog los siguientes operadores.

:- op(875, xfx, hecho).
:- op(875, xfx, #).
:- op(825, fx, si).
:- op(850, xfx, entonces).
:- op(800, xfy, o). % Asociatividad a la derecha
:- op(775, xfy, y). % Asociatividad a la derecha

:- op(850, xfx, se_deduce_de).
:- op(850, xfx, esta_afirmado_por).
:- op(800, xfx, porque).

% pregunta(?Pregunta) :-
%      "Pregunta se deduce de la base de conocimiento y escribe la
%       justificaci\'on de que tal deducci\'on es correcta".

%% Es necesario modificar la siguiente relación para utilizar una relación
%% prueba con un argumento más, los antecedentes de la demostración.

% pregunta(P) :-
% 	prueba(P,Prueba),
% 	escribe_prueba(Prueba).

prueba(P, P esta_afirmado_por F) :- 
        F hecho P.

prueba(P, P se_deduce_de R porque Prueba) :- 
        R # si C entonces P,
        prueba(C, Prueba). 

prueba(P1 y P2, Prueba1 y Prueba2) :- 
        prueba(P1, Prueba1),
        prueba(P2, Prueba2). 

prueba(P1 o _P2, Prueba1) :- 
        prueba(P1, Prueba1).

prueba(_P1 o P2, Prueba2) :- 
        prueba(P2, Prueba2).


escribe_lista([]).
escribe_lista([X|L]) :- write(X), escribe_lista(L).

%%%%%%%%%%%% Escritura de la prueba

escribe_prueba(Prueba) :-
	nl,write('****** Prueba encontrada:'),nl,
	escribe_prueba_aux(0,Prueba).


escribe_prueba_aux(N,A se_deduce_de B porque Prueba):-
        M is N+2,
        escribe_prueba_aux(M,Prueba),tab(N),
        escribe_lista(['luego, segun ',B,' se concluye que ',A,',']),nl.

escribe_prueba_aux(N,A y B):-
        escribe_prueba_aux(N,A),tab(N),write('y'),nl,
        escribe_prueba_aux(N,B).

escribe_prueba_aux(N,P esta_afirmado_por F):-
        tab(N),escribe_lista(['por ',F,', sabemos que ',P,',']),nl.

%%%************************************************************************
%% Ejemplo de sesión:
%%
% ?- [examen].
% ...
% Yes
% ?- [animal].
% ...
% Yes
% ?- pregunta(oblongo es un Que).

% ¿Es verdad oblongo tiene plumas? (si/no/porque) no.
% ¿Es verdad oblongo vuela bien? (si/no/porque) no.
% ¿Es verdad oblongo tiene pelo? (si/no/porque) si.
% ¿Es verdad oblongo come carne? (si/no/porque) porque.

% === Porque:
% La regla r3 dice que probando:
% oblongo es mamifero y (oblongo come carne o oblongo tiene dientes afilados y oblongo tiene garras y oblongo tiene ojos oblicuos)
% se tiene: 
% oblongo es carnivoro
% ¿Es verdad oblongo come carne? (si/no/porque) porque.

% === Porque:
% La regla r4 dice que probando:
% oblongo es carnivoro y oblongo tiene color pardo y oblongo tiene manchas oscuras
% se tiene: 
% oblongo es un guepardo
% ¿Es verdad oblongo come carne? (si/no/porque) porque.
% Porque esa fue su pregunta!!
% ¿Es verdad oblongo come carne? (si/no/porque) si.
% ¿Es verdad oblongo tiene color pardo? (si/no/porque) si.
% ¿Es verdad oblongo tiene manchas oscuras? (si/no/porque) no.
% ¿Es verdad oblongo tiene dientes afilados? (si/no/porque) no.
% ¿Es verdad oblongo da leche? (si/no/porque) no.
% ¿Es verdad oblongo tiene rayas negras? (si/no/porque) si.

% ****** Prueba encontrada:

%       por usted, sabemos que oblongo tiene pelo,
%     luego, segun r1 se concluye que oblongo es mamifero,
%     y
%     por usted, sabemos que oblongo come carne,
%   luego, segun r3 se concluye que oblongo es carnivoro,
%   y
%   por usted, sabemos que oblongo tiene color pardo,
%   y
%   por usted, sabemos que oblongo tiene rayas negras,
% luego, segun r5 se concluye que oblongo es un tigre,

% Que = tigre 

% Yes
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%% SOLUCIÓN:

pregunta(P) :-
	prueba(P,Prueba, []),
	escribe_prueba(Prueba).

prueba(P, P esta_afirmado_por F, _) :- 
        F hecho P.

prueba(P, P se_deduce_de R porque Prueba, Antecesores) :- 
        R # si C entonces P,
        prueba(C, Prueba, [R # si C entonces P|Antecesores]). 

prueba(P1 y P2, Prueba1 y Prueba2, Antecesores) :- 
        prueba(P1, Prueba1, Antecesores),
        prueba(P2, Prueba2, Antecesores). 

prueba(P1 o _P2, Prueba1, Antecesores) :- 
        prueba(P1, Prueba1, Antecesores).

prueba(_P1 o P2, Prueba2, Antecesores) :- 
        prueba(P2, Prueba2, Antecesores).

%%% Prueba con pregunta.

prueba(P,P esta_afirmado_por usted, _) :-
        preguntable(P),
	respuesta(P,si).

prueba(P,P esta_afirmado_por usted, Antecesores) :-
	preguntable(P),
	not(respuesta(P,_)),
        pregunta(P,R,Antecesores),
	assert(respuesta(P,R)),R=si.
	
%% Las siguientes relaciones son copia del metaintérprete PORQUE.

:- dynamic respuesta/2.

pregunta(P,Respuesta, Antecesores) :-
	escribe_lista(['¿Es verdad ',P,'? (si/no/porque) ']),
	read(Replica),
        interpreta(P,Respuesta,Replica, Antecesores).

interpreta(_,Replica, Replica, _) :-
	Replica \== porque.

interpreta(P,Respuesta,porque, [R|Reglas]) :-
%%%	write('Se usa en'), nl,
	escribe_regla(R),
	pregunta(P,Respuesta,Reglas).
interpreta(P,Respuesta,porque, []) :-
	write('Porque esa fue su pregunta!!'),nl,
	pregunta(P,Respuesta,[]).

%%% Una escritura más simple de las reglas.

escribe_regla(R # si C entonces P) :- 
	nl,write('=== Porque:'),nl,
	escribe_lista(['La regla ',R,' dice que probando:']),nl,
	write(C), nl,
        write('se tiene: '),nl,write(P),nl. 

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