



















































Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Prepara tus exámenes
Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Prepara tus exámenes con los documentos que comparten otros estudiantes como tú en Docsity
Encuentra los documentos específicos para los exámenes de tu universidad
Estudia con lecciones y exámenes resueltos basados en los programas académicos de las mejores universidades
Responde a preguntas de exámenes reales y pon a prueba tu preparación
Consigue puntos base para descargar
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Comunidad
Pide ayuda a la comunidad y resuelve tus dudas de estudio
Ebooks gratuitos
Descarga nuestras guías gratuitas sobre técnicas de estudio, métodos para controlar la ansiedad y consejos para la tesis preparadas por los tutores de Docsity
Asignatura: Lògica computacional, Profesor: , Carrera: Enginyeria Informàtica, Universidad: UAB
Tipo: Apuntes
1 / 59
Esta página no es visible en la vista previa
¡No te pierdas las partes importantes!




















































Vicenç Torra http://www.iiia.csic.es/~vtorra
1. Introducció al Prolog
Prolog (PROgramming in LOGic) és un llenguatge de programació basat en la lògica. Així, mentre que els llenguatges imperatius (C, Java, Ada, Pascal, Basic) es defineixen en termes de procediments i accions, i el seu element bàsic és l'assignació, en el cas dels llenguatges lògics els programes es basen en establir relacions entre objectes i la computació correspon
a demostrar si una relació es compleix. Això s’aconsegueix emprant l'anomenada resolució.
La construcció de programes es basa en la declaració de fets (establiment de relacions entre objectes) i regles (que ens permeten concloure sobre unes relacions a partir d'unes altres). Després, el programa s'executa quan es consulta al sistema per la validesa d'una determinada relació. El sistema, davant la consulta, intentarà demostrar la seva validesa a partir dels fets i les regles declarats prèviament.
La característica de que el llenguatge es basi en les relacions diferencia Prolog, i els altres llenguatges lògics, dels llenguatges funcionals i dels imperatius. En els llenguatges funcionals els programes es veuen com la definició d'una funció i l'execució correspon a aplicar una funció (que pot ser tan complexa com es vulgui) a unes dades (que també poden ser tan complexes com es vulgui). Així, per exemple, un programa de gestió de nòmines es pot veure com una funció que pren les dades de les nòmines dels empleats i en calcula, per exemple, allò que s'ha d'ingressar a hisenda. Un exemple més senzill és el cas del factorial, on definim una funció que donat un nombre en calcula el seu factorial. Per exemple, en ML tendriem una definició de factorial com ara:
fun fact (x) = if x=0 then 1 else x*fact(x-1);
En el cas del Prolog el que tenim és una relació entre objectes. No hi ha, per tant, un valor que sigui el d'entrada i un altre que sigui el de sortida. Si seguim amb l'exemple del factorial, en Prolog el que farem serà de finir una relació factorial que donats dos nombres x i y es complirà quan y correspongui al factorial de x. Així, per exemple, la relació factorial(x,y) es satisfarà pels parells (0,1), (1,1), (2,2), (3,6), (4,24), (5,120), .... Evidentment, pels parells (x,y) on y no sigui el factorial de x la relació no es satisfarà. Així, la relació serà falsa, per exemple, per (0,5), (1,3), (2,4) i (5,12).
Un cop hem definit la relació factorial, el Prolog ens permet conèixer el factorial d'un determinat valor x 0. Això correspon a demanar "quin es el valor y que satisfà factorial(x 0 ,y)". Per exemple, la pregunta "quin és el valor y que satisfà factorial (3,y)" correspon a saber quin és el factorial de 3. Tanmateix, el fet de tenir relacions, i no funcions, ens permet fer un altre tipus de preguntes. Per exemple, podem demanar "quin és el valor x, si és que n'hi ha cap, que té 120 com a factorial". Això és, quin és (o quins són) els x tal que existeix la relació factorial(x,120). En aquest cas, el Prolog ens deduirà que x=5. Si, en canvi, demanam "quin és el valor x, si és que n'hi ha cap, que té 121 com a factorial" ens trobarem que Prolog ens dirà que no n'hi ha cap. Això succeeix perquè la
L'ordre en que posem els objectes a la relació és arbitrari, però, evidentment, s'haurà d'anar alerta de que sigui coherent al llarg de tot el programa. Així, per analogia amb el que hem escrit més amunt, el fet:
pare(joan,ricard).
voldrà dir que en Ricard és el pare d'en Joan, i no que en Joan és el pare d’en Ricard.
Un cop escrits aquests fets, si els volem emprar en el nostre programa haurem d'escriure'ls en un fitxer i incorporar- los al sistema mitjançant una consulta del fitxer (la majoria d'intèrprets de Prolog inclouen un predicat "consult" per fer aquesta incorporació).
1.2. Execució d'un programa: una consulta
Mentre que en un llenguatge imperatiu forçar l'execució d'un programa correspon a fer una
crida a un procedime nt, en els llenguatges lògics l'execució d'un programa correspon a fer una pregunta al sistema per tal de que aquest ens digui si una certa relació és certa o és
falsa. Això correspon, de fet, a demanar una demostració de la certesa de la relació.
Si consideram que hem incorporat al nostre Prolog els predicats "pare" i "oposat" descrits més amunt, podem demanar al sistema si és cert que el pare de na Pepa és en Joan.
?- pare(pepa,joan).
A aquesta pregunta, el sistema respondrà que si perquè, analitzant el seu conjunt de fets, en troba un que coincideix exactament amb el de la pregunta. L'anàlisi d'aquesta correspondència és el que s'anomena unificació o coincidència de patrons (en anglès, unification o pattern matching ).
La comparació entre el terme que estam consultant i els que tenim emmagatzemats consisteix en comparar primer el nom de les relacions i, si aquests noms coincideixen, en comparar després els arguments (un a un).
Ara podem demanar si nord i sud són oposats. Aquesta pregunta s'aconsegueix escrivint a l'intèrpret (a partir d'ara emprarem "?-" per expressar que estam interrogant al sistema):
?- oposat(nord,sud).
El sistema també conclourà aquí que es compleix. Tanmateix si demanam:
?- oposat(sud,nord).
el sistema ens respon que no. Això és degut a que no troba cap relació (cap fet) amb el nom "oposat" i on el primer objecte sigui sud i el segon nord. El resultat d'aquesta pregunta és provocat pel fet que l'ordre en que es posen els objectes en la relació és, en general, rellevant. Observau que si haguéssim demanat pare(joan, pepa) – que correspon a demanar si el pare d’en Joan és na Pepa – hauríem desitjat que la resposta del sistema hagués estat “la relació no es compleix”. Per això, en Prolog hem d'especificar quan un predicat és simètric. Aquest és el cas del concepte "oposat" atès que nord és oposat de sud i a la vegada sud és oposat de nord.
D'acord amb això, hem d'afegir els dos fets següents:
oposat(sud,nord). oposat(oest,est).
En incorporar aquests dos fets al sistema Prolog, la mateixa consulta d'abans ens retornaria que si que es compleix.
Els sistemes que responen que un fet és fals quan no són capaços de demostrar- lo (que com hem vist amb la pregunta oposat(sud,nord) és el cas de Prolog) es diu que satisfan la hipòtesis del món tancat (en anglès closed world assumption ). Això correspon a la situació de que tot allò que és cert es pot demostrar a partir del que hi ha en el sistema i que no hi ha res que es compleixi més enllà d'aquestes declaracions.
1.3. Les variables
En els fets i en les interrogacions expressades més amunt hem emprat només constants. Això és, elements que estaven completament determinats (nord, sud, pepa, joan, ...). En general podem emprar també variables. En veiem a continuació un exemple.
Per a construir un exemple definim primer un conjunt de fets que corresponen a les relacions d'adjacència existents entre els punts cardinals. Així, expressam que nord i est són
punts cardinals adjacents i que nord i oest també. Aquestes relacions són les següents:
adjacent(nord,est). adjacent(nord,oest). adjacent(sud,est). adjacent(sud,oest). adjacent(est,nord).
avaluat en cert, però pare(pepa,ricard) també. Des del punt de vista de la lògica aquesta relació s’hauria interpretat com: “per a tot X pare(pepa, X)”.
IMPORTANT : · Constants: cadenes de caràcters començades amb minúscules. · Variables: cadenes de caràcters començades amb majúscules.
Observau que una variable en un fet declarat correspon a una variable quantificada amb un per tot, mentre que una variable en un fet presentat al sistema en una consulta correspon a una variable quantificada amb un existencial.
1.4. La conjunció
En Prolog expressam conjuncions de predicats posant- los entre comes. Així, si volem saber quin és el punt cardinal que és adjacent a nord i que és oposat a oest podem escriure:
?-adjacent(nord,Quin), oposat(Quin,oest).
El resultat del sistema és:
?- adjacent(nord,Quin), oposat(Quin,oest). Quin = est ; No
D’acord amb el que s’ha dit anteriorment, aquesta consulta correspon a demanar si existeix cap Q tal que es compleix adjacent(nord, Q) i oposat(Q, oest).
1.5. Les regles
Les implicacions en la lògica de primer ordre s'expressen en Prolog com a regles. Això és, amb expressions de la forma "si .... aleshores ...." on el que hi ha a la part dreta i a la part esquerra són relacions. A continuació es dóna un exemple de regla:
si x és un animal i x té plomes aleshores x és un ocell.
En Prolog les regles s'escriuen posant primer el conseqüent (la conclusió), després el símbol ":- " que es llegeix "si" i després l'antecedent (les condicions que s'han de complir per a que la conclusió sigui certa). El conseqüent i els antecedents s'expressen emprant la
notació Prolog. Típicament l'antecedent serà un conjunt de predicats separats per comes (això és, conjuncions). A més a més, de conseqüent només n'hi pot haver un. En una regla tenim que el conseqüent és conegut com a cap i l'antecedent com el cos.
D'acord amb tot això, per exemple, la regla de més amunt s'escriu en Prolog:
ocell(X):-animal(X), plomes(X).
Per tant, tenim que el cap és "ocell(X)" i el cos és "animal(X), plomes(X)".
La regla anterior es llegeix en Prolog com segueix:
x és un ocell si x és un animal i x té plomes.
Un altre exemple és el següent:
germana(X,Y):-dona(X),pares(X,M,P),pares(Y,M,P).
En aquesta regla estam dient que x és una germana si x és una dona i els pares de x (M per mare i P per pare) són els mateixos que els pares de y. Formalment, això es llegirà “per tot X,Y germana(X,Y) si existeixen M i P tal que es compleixi dona(X), pares(X,M,P) i pares(Y,M,P).
En una regla, les variables que hi ha al conseqüent (a l’esquerra) estan quantificades universalment mentre que les que hi ha a l’antecedent (a la dreta del “:- ”) estan quantificades amb un existencial.
Atès que les regles només tenen un consegüent, es poden veure com si fossin definicions de conceptes: el concepte és el que apareix en el consegüent. Així podem dir que definim els ocells com aquells animals amb plomes, o que germana de y queda definit com una dona que té els mateixos pares que y.
Quan diverses regles conclouen sobre el mateix predicat (o dit d'una altra manera, quan es fan servir diverses regles per a definir un predicat), podem emprar noms de variables difererents en regles diferents. Per exemple, si consideram les dues regles següents per a definir el concepte "ocell":
si x és un animal i x té plomes aleshores x és un ocell.
correspon a tenir dues regles:
p:-p1,p2. p:-p3,p4.
1.7. El Prolog i la lògica
Hem dit més amunt que els fets de Prolog corresponen als predicats en la lògica. Els predicats i les regles vàlids en Prolog correspon al que en el món de la lògica s'anomena clàusules de Horn. Així, tenim que un programa correspon a un conjunt de clàusules, que poden ser o bé predicats (fets) o bé regles.
1.8. El procediment del Prolog
Com s'ha dit, el Prolog és un llenguatge lògic i el que intenta és fer una demostració, validar, allò que consultam al sistema. La forma de procedir quan fem una consulta (això és, la forma de construir la demostració) segueix sempre el mateix esquema.
Davant d'una pregunta nostra, el sistema intenta trobar entre el seu conjunt de fets i regles un element que coincideixi amb el de la pregunta. Així, el Prolog va prenent cadascun dels predicats que apareixen en la nostra consulta i els intenta validar amb els que té emmagatzemats. Per a repassar els que té emmagatzemats procedeix semp re en l'ordre en que es troben a la base de fets i regles. Quan hi ha diversos predicats a la consulta, els intenta validar d'esquerra a dreta. Quan n'hi ha un que no pot ser validat, la demostració s'atura.
Per establir la coincidència entre dos fets, tal com ja hem dit abans, comprovarà que el nom de les relacions coincideixi i, després, comprovarà que els arguments també ho facin. Quan els arguments són constants, tenim coincidència si són iguals. Quan en els arguments hi ha variables, les variables quedaran lligades per tal de que sigui possible la igualtat. Així, els fets "relacio(A,argument2)" i "relacio(argument1,argument2)" coincideixen quan s'associa a la variable A el valor "argument1". De la mateixa manera, "relacio(A,argument2)" i "relacio(B,argument2)" coincideixen quan es lliguen les dues variables "A" i "B" de manera que a partir d'aquest punt les dues variables denotaran el mateix objecte (sigui el que sigui aquest objecte).
Ara il·lustrem el procediment considerant el sistema amb els següents predicats emmagatzemats:
oposat(nord,sud). oposat(est,oest). oposat(sud,nord).
oposat(oest,est).adjacent(nord,est). adjacent(nord,oest). adjacent(sud,est). adjacent(sud,oest). adjacent(est,nord). adjacent(est,sud). adjacent(oest,nord). adjacent(oest,sud).
Per construir un exemple prenem la consulta feta anteriorment:
?- adjacent(nord,Quin). Quin = est; Quin = oest; No
La construcció d'aquestes dues solucions es fa d'acord amb l'ordre en que apareixen en la base de fets i regles. De fet, davant de la nostra pregunta "adjacent(nord,Quin)", el Prolog repassa els fets que tenim emmagatzemats en ordre fins que en troba un que coincideix amb la pregunta. Així, primer compara amb "oposat(nord,sud)" i en trobar que no coincideixen (els noms de les relacions són diferents) passa a comparar amb el següent. Atès que aquest tampoc no coincideix (és "oposat(est, oest)") passa al següent, i després va avançant fins que troba "adjacent(nord, est)". Com que aquest fet es pot fer coincidir si la variable Quin s'associa a "est", el sistema dóna aquesta associació com a resultat. En el moment de fer el lligam entre la variable "Quin" i "est", el Prolog deixa una marca per indicar fins on havia comprovat les associacions.
En demanar més solucions mitjançant el punt i coma (";"), el Prolog reprèn la cerca de solucions a partir del punt on ho havia deixat. Així en repassar els fets emmagatzemats a partir de la marca deixada anteriorment trobarà la nova solució en comparar la consulta "adjacent(nord,Quin)" amb el fe t "adjacent(nord,oest)". En fer l'associació de la variable "Quin" amb "oest" deixarà una nova marca en el sistema.
En demanar de nou noves solucions mitjançant el punt i coma, el Prolog reprendrà la cerca en la darrera posició marcada. Tanmateix, com que ara no hi ha més solucions possibles, el sistema arribarà al final de la llista de fets sense trobar-ne cap altre. En arribar al final
respondrà amb un "No".
1.8.1. Cas amb reconsideració automàtica de fets
Un altre exemple d'execució és el que s'obté quan demanam:
No
1.8.2. Cas on s'aplica una regla
Ara consideram l'aplicació d'una regla. L'objectiu és descobrir qui són els pares de na Pepa. Els fets i les regles que emprarem són les següents:
pare(pepa,joan). mare(pepa,maria). dona(pepa). pare(ricard,joan). mare(ricard,maria). pares(X,M,P):-pare(X,P),mare(X,M). germana(X,Y):-dona(X),pares(X,M,P),pares(Y,M,P).
La pregunta que activarà el sistema serà:
?- pares(pepa,Mare,Pare).
Davant d'aquesta pregunta el sistema cerca un fet o una regla que s'hi pugui unificar seguint
l'ordre habitual (l'ordre de definició). Així es trobarà l'única regla possible: és la que diu que M i P són els pares de na Pepa si P és el pare i M és la mare. La unificació entre la regla trobada i la pregunta s'aconsegueix associant les variables M i Mare, les variables P i Pare i a més a més lligant la variable X de la regla amb la constant "pepa". D'acord amb això, tenim Mare i Pare són els pares de "pepa" si existeix un P i un M tal que es cert que "pare(pepa,Pare)" i "mare(pepa,Mare)". Per tant, tenim que la pregunta anterior queda substituïda per la següent:
?- pare(pepa,Pare),mare(pepa,Mare).
Atès que aquesta clàusula és el resultat de resoldre la clàusula de la pregunta amb la del programa se l'anomena resolvent. Aquesta nova clàusula s'obtindrà cercant primer un fet o una regla per "pare(pepa,Pare)" i després, quan això estigui demostrat, cercant un fet o una regla per "mare(pepa,Mare)". Evidentment, això permetrà trobar que la nostra qüestió es satisfà quan Pare=joan i Mare=maria.
En el cas de que la regla inclogués predicats que per resoldre'ls calgués considerar una altra regla (com és el cas de germana definit més amunt, que necessita conèixer els pares),
tendrem que en el moment de cercar la demostració un predicat es pot substituir pel cos de la regla. Així, per exemple, si consideram la pregunta:
?- germana(pepa,ricard).
El Prolog intentarà primer resoldre:
?- dona(pepa),pares(pepa,M,P),pares(ricard,M,P).
atès que aquesta clàusula s'obté de la pregunta "germana(pepa,ricard)" i la regla " germana(X,Y):-dona(X),pares(X,M,P),pares(Y,M,P)". En trobar que el primer fet es compleix, això quedarà reduït a:
?- pares(pepa,M,P),pares(ricard,M,P).
Aleshores intentarà resoldre "pares(pepa,M,P)" (atès el Prolog sempre intenta resoldre d'esquerra a dreta). Per a resoldre qui són els pares de na Pepa necessita la regla que defineix pares. Després de fer la unificació corresponent (X=pepa, i les variables M i P) el Prolog observa que per resoldre "pares(pepa,M,P)" n'hi ha prou en resoldre "pare(pepa,P)" i "mare(pepa,M)". Per tant, ara té pendent:
?- pare(pepa,P),mare(pepa,M),pares(ricard,M,P).
El primer fet queda demostrat fent: P=joan. Queda pendent (tenint en compte aquesta substitució):
?- mare(pepa,M),pares(ricard,M,joan).
Fent ara M=maria, el primer fet també queda demostrat i queda pendent:
?- pares(ricard,maria,joan).
PAS 2: Determinam les substitucions per tal que el cap de la clàusula del programa i la clàusula de la pregunta siguin iguals. Això s'aconsegueix amb les següents substitucions:
{X'/pepa, M'/M, P'/P}
Això vol dir, hem de substituir X' per pepa, M' per M i P' per P.
PAS 3: Substituïm la pregunta pel cos de la clàusula del programa. Això vol dir que hem de substituir "pares(pepa,M,P)" per "pare(X',P'),mare(X',M')". Això és:
?- pare(X',P'),mare(X',M').
PAS 4: Aplicam la substitució al resultat anterior obtenint la clàusula següent:
?- pare(pepa,P),mare(pepa,M).
Ara passam a una descripció del funcionament de l'intèrpret en pseudocodi.
El procés d'execució comença amb la crida a la funció resoldre amb la clàusula de pregunta.
1.9. Sintaxi de Prolog: detalls
En aquesta secció es presenten amb més detall alguns dels objectes que han aparegut fins ara.
1.9.1. Constants: àtoms i nombres
En Prolog hi ha dos tipus de constants: els àtoms i els nombres. Els nombres corresponen a cadenes de dígits. Els àtoms poden ser qualsevol dels termes següents:
duc_cheshire
=====> <...>
'Prolog'
1.9.2. Variables
Les variables en Prolog s'expressen com cadenes de caràcters, dígits o "" començats per majúscula o "":
X, Resultat, _325, _
La variable "" té en Prolog un significat especial, denota una variable anònima. Així, emprarem "" quan no ens interessa el contingut d'una variable, però a la vegada és imprescindible posar-ne una perquè el predicat necessita un argument. Per exemple, la usarem si en una regla una variable només apareix una vegada. És important subratllar que cada aparició de "_" correspon a una variable amb un nom diferent.
A continuació donam un exemple d'ús de "_". Es defineix el predicat habitable(X) que s'avalua en cert quan X és un planeta on hi habita algú. Per definir aquest predicat consideram primer els fets:
habita(joan, terra). habita(marcia, mart).
que indiquen que en Joan habita la terra i que en Marcià habita mart.
D'acord amb això, per definir el predicat habitable consideram la regla:
c) si els dos elements són variables, aleshores les dues variables queden lligades.
a) si els dos arguments que comparem són dues constants, s'avalua l'argument de la dreta i es comparen els dos objectes. El predicat retorna cert quan els dos objectes són iguals. Per exemple: 2 is 2 retorna: cert 2 is 3 retorna : fals 2 is 1+1 retorna: cert (ara 1+1 s'avalua en 2). 2+1 is 1+2 retorna: fals (l'expressió de la dreta s'avalua i resulta 3, però la de l'esquerra no. Per tant, comparam 2+1 amb 3). 2+1 is 2+1 retorna: fals (com el cas anterior, l'expressió de la dreta s'avalua i la de l'esquerra no. Per tant comparem 2+1 amb 3). b) si l'argument de l'esquerra és una variable i el de la dreta una constant, aleshores la variable queda lligada a la constant.
En els altres casos, dóna error (l'expressió no es pot avaluar). Això és, el predicat "is" dóna error quan:
a) els dos arguments són variables (no instanciades). b) l'argument de l'esquerra és una constant (o variable instanciada) i el de la dreta és una variable (no instanciades).
D'acord amb tot això, es poden usar variables en l'argument de la dreta del predicat sempre i quan estiguin instanciades (tenguin un valor associat). Per tant és correcte fer:
?-N is 5, N2 is N*N.
Atès que N és conegut en calcular N*N. En canvi no és correcte fer:
?- N2 is N*N, N is 5.
2+2=2+3 Yes 2+3=2+3 No 2+3=3+2 Yes
A continuació es dóna la definició d'un predicat densitat que calcula la densitat d'un país en termes de la població i l'àrea. Aquest predicat empra el predicat "is" per tal de forçar el càlcul del quocient.
poblacio(catalunya, 7000000). area(catalunya,45000). densitat(X,Y):-poblacio(X,P), area(X,A), Y is P/A.