%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% SICStus PROLOG: Declaracoes iniciais

:- set_prolog_flag( discontiguous_warnings,off ).
:- set_prolog_flag( single_var_warnings,off ).
:- set_prolog_flag( unknown,fail ).

%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% SICStus PROLOG: Definicoes iniciais

:- op( 900,xfy,com ).
:- op( 900,xfy,::: ).
:- op( 800,fx,se ).
:- op( 900,xfy,com).
:- op( 800,xfy,porque).
:- op( 700,xfx,entao ).
:- op( 300,xfy,ou ).
:- op( 200,xfy,e ).

:- dynamic facto/1.
:- dynamic 'com' /2.
:- dynamic ':::' /2.

%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Regras de Producao: se SINTOMA entao DIAGNOSTICO com Grau de Confianca

(se 'frequencia cardiaca lenta' entao 'bradicardia') com 1. 

(se 'frequencia cardiaca rapida' entao 'taquicardia') com 1. 

(se 'frequencia cardiaca rapida' e 'frequencia cardiaca irregular' entao 'arritmia') com 1.

(se 'taquicardia' e 'consumo de cafe' entao 'taquicardia paroxistica') com 0.7.

(se 'taquicardia' e 'consumo de cafe' entao 'taquicardia paroxistica') com 0.7.

(se 'taquicardia' e 'consumo de alcool' entao 'taquicardia paroxistica') com 0.7.

(se 'emagrecimento' e 'diarreia' e 'flatulencia' entao 'dispepsia') com 0.6. 

(se 'diarreia' e 'flatulencia' e 'mau halito' entao 'dispepsia') com 0.9.

(se 'flatulencia' e 'ausencia de odor' entao 'anosmia') com 0.9.

%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Regras de Producao: se DIAGNOSTICO entao TRATAMENTO porque SINTOMA

( se 'bradicardia' entao 'administracao de atropina' ) porque ( 'frequencia cardiaca lenta' ).

( se 'taquicardia' entao 'dieta alimentar' ) porque ( 'frequencia cardiaca rapida' ).

( se 'arritmia' entao 'cardioversao' ) porque ( 'frequencia cardiaca rapida' e 'frequencia cardiaca irregular' ).

( se 'taquicardia paroxistica' entao 'tossir' ou 'suspender a respiracao por 1 minuto' ) porque ( 'taquicardia' e 'consumo de cafe' ).

( se 'taquicardia paroxistica' entao 'imergir a cabeca em agua fria' ) porque ( 'taquicardia' e 'consumo de alcool' ).

( se 'dispepsia' entao 'gastroscopia' ) porque ( 'emagrecimento' e 'diarreia' e 'flatulencia').

( se 'dispepsia' entao 'saneamento bucal' ) porque ( 'diarreia' e 'flatulencia' e 'mau halito' ).

( se 'anosmia' entao 'remocao de polipos nasais' ) porque ( 'flatulencia' e 'ausencia de odor').


%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Predicado grau_confiança

grau_confianca( G,'impossivel' ) :- G=0.

grau_confianca( G,'pouco provavel' ) :- 0<G, G<0.45.

grau_confianca( G,'algo provavel' ) :- 0.45=<G, G<0.65.

grau_confianca( G,'provavel' ) :- 0.65=<G, G<0.85.

grau_confianca( G,'muito provavel' ) :- 0.85=<G, G<1.

grau_confianca( G,'certo' ) :- G=1.


%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Versao FORWARD CHAINING
% Extensao do predicado diagnostico que permite obter o diagnostico por FORWARD CHAINING
% Extensao do meta-predicado demo2: DIAGNOSTICO, Gf, TRATAMENTO, SINTOMA -> { V,F }

diagnostico( D ) :- demo2(D,Gf,T,S),
                    write('sintomas associados: '),         write(S), nl,
                    write('grau de confianca de diagnostico: '),    write(Gf), nl,
                    write('tratamento: '),      write(T).

%solucoes( ( T,G,F,D ),demo2( T,G,F,D ),R ),
solucoes( I,T,L ) :- findall( I,T,L ).

demo2(D,Gf,T,S) :-
    ( (se S entao D) com G),
    ( (se D entao T) porque S),
    composicao( S, G1),
    G2 is G*G1,
    grau_confianca( G2, Gf ), 
    insere( facto(D) com G2 ).

insere( facto(FACTO) com G ) :-
    nao( facto(FACTO) com G),
    asserta( facto(FACTO) com G),!.
insere( facto(FACTO) com G) :-
    facto(FACTO) com G.


composicao( S , G) :-
    facto(S) com G.
composicao( D1 e D2, G ) :-
    composicao( D1, G1 ),
    composicao( D2, G2 ),
    menor(G1,G2,G). 
composicao( (D1 ou D2),G ) :-
    composicao( D1,G1 ),
    composicao( D2,G2 ),
    maior( G1,G2,G ).
composicao( (D1 ou D2),G ) :-
    composicao( D1,G ),
    nao( composicao( D2,G2 ) ).
composicao( (D1 ou D2),G ) :-
    composicao( D2,G ),
    nao( composicao( D1,G1 ) ).
%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Extensao do predicado inserir_sintomas FORWARD CHAINING

inserir_sintomas( FACTO,G ) :- solucoes( I,+( facto( FACTO ) com G ):::
I,L ),
		              insere1( facto( FACTO ) com G ),
		              teste(L).

teste( [] ).
teste( [R|L] ) :- R,
                  teste( L ).

insere1( facto( FACTO ) com G ) :- assert( facto( FACTO ) com G ).
insere1( facto( FACTO ) com G ) :- retract( facto( FACTO ) com G ), !,fail.


%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Extensao do predicado menor: X,Y,Z -> { V,F }

menor( X,Y,X ) :-
    X < Y.
menor( X,Y,Y ) :-
    X >= Y.
	
%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Extensao do predicado maior: X,Y,Z -> { V,F }

maior( X,Y,X ) :-
     Y<X.
maior( X,Y,Y ) :-
    Y >= X.
	
	
%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Extensao do predicado comprimento: Lista, N -> {V,F}

comprimento( [],0 ).
comprimento([H],1).
comprimento( [X|L],N ) :- comprimento( L,G ),
                          N is G+1.
	
%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Extensao do meta-predicado nao: Questao -> {V,F}

nao( Questao ) :- Questao, !, fail.
nao( Questao ).

%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Extensao do predicado remover que retira os sintomas todos

remover :- retractall( facto( X ) com G ).

%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Invariante que nao permite que sejam introduzidos sintomas repetidos.

+( facto( FACTO ) com GRAU ) ::: ( solucoes( FACTO, ( facto( FACTO ) com G ), S ), comprimento( S,N ), N == 1 ).

%--------------------------------- - - - - - - - - - -  -  -  -  -   -
% Invariante que limita o grau de confianca entre 0 e 1.

+( facto( FACTO ) com GRAU ) ::: ( facto( FACTO ) com G , G>=0, G=<1).
