/*************************************************************/ /* */ /* Universidad de Alicante */ /* */ /* LOGICA DE PRIMER ORDEN */ /* Prolog */ /* */ /* */ /* S. O. : MS-DOS (Windows) */ /* Interprete : SWI-Prolog */ /* Fichero : EJ08.PL */ /* Programa : " FORMAS NORMALES " */ /* Proposiciones, comprueba si es una */ /* a Forma Normal Conjuntiva (FNC) y a */ /* Forma Normal Disyuntiva (FND). */ /* */ /* Se lanza con : */ /* ?- menu. */ /* */ /*************************************************************/ ?- op(10,fx,no). ?- op(100,yfx,o). ?- op(100,yfx,y). ?- op(200,yfx,imp). ?- op(200,yfx,coimp). /*-----------------------------------------------------------*/ /* PROGRAMA PRINCIPAL */ /* */ menu :- cabecera, repeat, leer(Formula), hacer(Formula). hacer(X) :- integer(X), X=0. hacer('A') :- cabecera, ayuda, !, fail. hacer('a') :- cabecera, ayuda, !, fail. hacer(Formula) :- fbf(Formula), formaNormal(Formula,FNC,FND), escribirFormasNormales(FNC,FND), pausa,!, fail. hacer(_) :- pausa,!,fail. /* */ /* Fin Programa Principal */ /* */ /*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/ /* Determinar si es una Formula Bien Formada */ fbf((no P)) :- !,fbf(P). fbf((P y Q)) :- !,fbf(P),fbf(Q). fbf((P o Q)) :- !,fbf(P),fbf(Q). fbf((P imp Q)) :- !,fbf(P),fbf(Q). fbf((P coimp Q)) :- !,fbf(P),fbf(Q). fbf(P) :- atom(P),!,proposicion(P). nl, nl, !, fail. /* proposicion(Prop) <- Prop es una variable proposicional */ proposicion(X) :- miembro(X,[p0,p1,p2,p3,p4,p5,p6,p7,p8,p9]),!. ional'), nl,nl,!,fail. literal(X) :- X=..[Op,_,_], miembro(Op,[y,o,imp,coimp]),!,fail. literal(no X) :- literal(X). literal(X) :- atom(X),proposicion(X). /*-----------------------------------------------------------*/ /* Transformar a Forma Normal */ /* formaNormal(Form,Fnc,Fnd) <- Fnc es la Forma Normal Conjuntiva y Fnd es la Forma Normal Disyuntiva de Form */ formaNormal(Formula,FNC,FND) :- quitarImplicadores(Formula,F1), normalizarNegadores(F1,F2), exteriorizarConjuntor(F2,F31), exteriorizarDisyuntor(F2,F32), !, /* corte para liberar memoria */ ordenarFNC(F31,L41), simplificar(L41,FNC), ordenarFND(F32,L42), simplificar(L42,FND). /* quitarImplicadores(Form,Form1) <- Form1 es la fbf resultado de eliminar implicadores y coimplicadores a la fbf Form */ quitarImplicadores((P imp Q),((no P1) o Q1)) :- !,quitarImplicadores(P,P1), quitarImplicadores(Q,Q1). quitarImplicadores((P coimp Q),(((no P1) o Q1) y ((no Q1) o P1))) :- !, quitarImplicadores(P,P1), quitarImplicadores(Q,Q1). quitarImplicadores((P o Q),(P1 o Q1)) :- !,quitarImplicadores(P,P1), quitarImplicadores(Q,Q1). quitarImplicadores((P y Q),(P1 y Q1)) :- !,quitarImplicadores(P,P1), quitarImplicadores(Q,Q1). quitarImplicadores((no P),(no P1)) :- !,quitarImplicadores(P,P1). quitarImplicadores(P,P). /* normalizarNegadores(Form,Form1) <- Form1 es la fbf resultado de normalizar los negadores a la fbf Form */ normalizarNegadores((no P),P1) :- !,negar(P,P1). normalizarNegadores((P y Q),(P1 y Q1)) :- !,normalizarNegadores(P,P1), normalizarNegadores(Q,Q1). normalizarNegadores((P o Q),(P1 o Q1)) :- !,normalizarNegadores(P,P1), normalizarNegadores(Q,Q1). normalizarNegadores(P,P). /* negar(Form,Form1) <- Form1 es la fbf resultado de negar la fbf Form, pero teniendo en cuenta la leyes de De Morgan */ negar((no P),P1) :- !,normalizarNegadores(P,P1). negar((P y Q),(P1 o Q1)) :- !,negar(P,P1), negar(Q,Q1). negar((P o Q),(P1 y Q1)) :- !,negar(P,P1), negar(Q,Q1). negar(P,(no P)). /* exteriorizarConjuntor(Form,Form1) <- Form1 es la fbf resultado de exteriorizar los conjuntores de la fbf Form */ exteriorizarConjuntor((P o Q),R) :- !, exteriorizarConjuntor(P,P1), exteriorizarConjuntor(Q,Q1), fnc1((P1 o Q1),R). exteriorizarConjuntor((P y Q),(P1 y Q1)) :- !, exteriorizarConjuntor(P,P1), exteriorizarConjuntor(Q,Q1). exteriorizarConjuntor(P,P). fnc1(((P y Q) o R),(P1 y Q1)) :- !, exteriorizarConjuntor((P o R),P1), exteriorizarConjuntor((Q o R),Q1). fnc1((R o (P y Q)),(P1 y Q1)) :- !, exteriorizarConjuntor((R o P),P1), exteriorizarConjuntor((R o Q),Q1). fnc1(P,P). /* exteriorizarDisyuntor(Form,Form1) <- Form1 es la fbf resultado de exteriorizar los Disyuntores de la fbf Form */ exteriorizarDisyuntor((P y Q),R) :- !, exteriorizarDisyuntor(P,P1), exteriorizarDisyuntor(Q,Q1), fnd1((P1 y Q1),R). exteriorizarDisyuntor((P o Q),(P1 o Q1)) :- !, exteriorizarDisyuntor(P,P1), exteriorizarDisyuntor(Q,Q1). exteriorizarDisyuntor(P,P). fnd1(((P o Q) y R),(P1 o Q1)) :- !, exteriorizarDisyuntor((P y R),P1), exteriorizarDisyuntor((Q y R),Q1). fnd1((R y (P o Q)),(P1 o Q1)) :- !, exteriorizarDisyuntor((R y P),P1), exteriorizarDisyuntor((R y Q),Q1). fnd1(P,P). /* ordenarFNC(Form,Form1) <- Form1 es la fbf resultado de ordenar las variables proposicionales de las disyunciones */ ordenarFNC(F,L) :- crearListasFNC(F,Lista), ordenarListas(Lista,L). crearListasFNC(F,Lista) :- F=..[y,F1,F2], crearListasFNC(F1,L1), crearListasFNC(F2,L2), concatena(L1,L2,Lista). crearListasFNC(F,[Lista]) :- crearListaFNC(F,Lista). crearListaFNC(F,[F]) :- literal(F),!. crearListaFNC(F,Lista) :- F=..[o,F1,F2], crearListaFNC(F1,L1), crearListaFNC(F2,L2), concatena(L1,L2,Lista). ordenarListas([],[]). ordenarListas([L1|L2],[LO1|LO2]) :- ordenarLista(L1,LO1), ordenarListas(L2,LO2). orden(E1,E2) :- atom(E1),atom(E2),!,E1@<E2. orden(no E1,no E2) :- atom(E1),atom(E2),!,E1@<E2. orden(E1,no E2) :- atom(E1),atom(E2),!,E1@=<E2. orden(no E1,E2) :- atom(E1),atom(E2),!,E1@<E2. /* ordenarFND(Form,Form1) <- Form1 es la fbf resultado de ordenar las variables proposicionales de las conjunciones */ ordenarFND(F,L) :- crearListasFND(F,Lista), ordenarListas(Lista,L). crearListasFND(F,Lista) :- F=..[o,F1,F2], crearListasFND(F1,L1), crearListasFND(F2,L2), concatena(L1,L2,Lista). crearListasFND(F,[Lista]) :- crearListaFND(F,Lista). crearListaFND(F,[F]) :- literal(F),!. crearListaFND(F,Lista) :- F=..[y,F1,F2], crearListaFND(F1,L1), crearListaFND(F2,L2), concatena(L1,L2,Lista). /* simplificar(Form,Form1) <- Form1 es la fbf resultado de simplificar y ordenar la fbf Form (formato listas)*/ simplificar(F,FS) :- simplifica1(F,F1), simplifica2(F1,F2), inversa(F2,F2I), simplifica2(F2I,F3I), inversa(F3I,FS). simplifica1([],[]). simplifica1([L|Resto],[L1|Resto1]) :- idempotencia(L,L1), simplifica1(Resto,Resto1). simplifica2([],[]). simplifica2([L|Resto],Resto1) :- absorcion(L,Resto),!, simplifica2(Resto,Resto1). simplifica2([L|Resto],[L|Resto1]) :- simplifica2(Resto,Resto1). /* Idempotencia: A o A = A , A y A = A */ idempotencia([],[]). idempotencia([A|[A|Resto]],F) :- idempotencia([A|Resto],F). idempotencia([A|Resto],[A|F]) :- idempotencia(Resto,F). /* Absorcion e idempotencia */ absorcion(_,[]) :- !,fail. absorcion(L1,[L2|_]) :- subconjunto(L2,L1). absorcion(L1,[_|Resto]) :- absorcion(L1,Resto). /*-----------------------------------------------------------*/ /* Pantalla de Ayuda */ ayuda :- nl, write(' El programa lee una formula del Calculo de Proposiciones, comprueba que es'),nl, write('una Formula Bien Formada (fbf), y la transforma a Forma Normal Conjuntiva'),nl, write('(FNC) y a Forma Normal Disyuntiva (FND)'),nl,nl, write(' Las connectivas usadas son:'),nl, tab(10),write('no negacion'), tab(10),write('imp implicador'),nl, tab(10),write('y conjuncion'), tab(8),write('coimp coimplicador'),nl, tab(10),write('o disyuncion'),nl,nl, write(' El Alfabeto utilizado es:'),nl, tab(10),write('Proposiciones p0,...,p9'),nl, nl. /*-----------------------------------------------------------*/ /* Procedimientos diversos */ cabecera :- borraPantalla, tica y Computacion'),nl,nl, write('Practicas PROLOG_______________________________________________FORMAS NORMALES'), nl,nl. pausa :- nl,write('Pulsa <return> para continuar '), skip(10). /* borraPantalla <- borra la pantalla */ borraPantalla :- borraLinea(25). borraLinea(1) :- !,nl. borraLinea(N) :- nl,N1 is N-1,borraLinea(N1). /**** LEER lee una formula del Calculo de proposiciones ****/ leer(F) :- nl,write(' Introduce la formula terminada en punto (.)'), nl,write(' ( 0 Terminar / A Ayuda )'),nl, nl,write(' FORMULA : '), read(F). /**** ESCRIBIR la formula en FNC y FND ****/ escribirFormasNormales(FNC,FND) :- nl,write('FORMA NORMAL CONJUNTIVA:'),nl, escribeFNC(FNC),nl, write('FORMA NORMAL DISYUNTIVA:'),nl, escribeFND(FND). escribeFNC([D|[]]) :- write('('),escribeDisyuncion(D),write(')'),nl. escribeFNC([D|Resto]) :- write('('),escribeDisyuncion(D), write(') y '), escribeFNC(Resto). escribeDisyuncion([A|[]]) :- write(A). escribeDisyuncion([A|Resto]) :- write(A),write(' o '), escribeDisyuncion(Resto). escribeFND([C|[]]) :- write('('),escribeConjuncion(C),write(')'),nl. escribeFND([C|Resto]) :- write('('),escribeConjuncion(C), write(') o '), escribeFND(Resto). escribeConjuncion([A|[]]) :- write(A). escribeConjuncion([A|Resto]) :- write(A),write(' y '), escribeConjuncion(Resto). /**** RUTINAS DE MANIPULACION DE LISTAS ****/ miembro(X,[X|_]). miembro(X,[_|Y]) :- miembro(X,Y). dando lugar a la lista L3 */ concatena([],L,L). concatena([X|L1],L2,[X|L3]) :- concatena(L1,L2,L3). /* ordenarLista(Lista,ListaOrdenada) <- ListaOrdenada es la lista orden(E1,E2) */ ordenarLista([],[]). ordenarLista([E|L],LO) :- ordenarLista(L,LO1), insertar(E,LO1,LO). insertar(E,[Y|L],[Y|L1]) :- orden(Y,E),!,insertar(E,L,L1). insertar(E,L,[E|L]). /* inversa(Lista,Inver) <- Inver es la inversa de la lista Lista */ inversa([],[]). inversa([X|Y],L) :- inversa(Y,Z), concatena(Z,[X],L). /* subconjunto(L1,L2) <- la lista L1 es un subconjunto de la lista L2 */ subconjunto([X|Y],Z) :- miembro(X,Z), subconjunto(Y,Z). subconjunto([],_). :- cabecera,ayuda,tab(4),write('El programa se lanza con :'),nl, tab(20),write('?- menu.'),nl,nl. /***************** FIN DEL PROGRAMA ************************/