














































Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Aprenda a utilizar essa ferramenta que pode lhe ajudar em varios campos da diferentes.
Tipologia: Esquemas
1 / 54
Esta página não é visível na pré-visualização
Não perca as partes importantes!















































Maria Jo˜ao Frade Departamento de Inform´atica Universidade do Minho 2006
2 o^ Ano LMCC (2005/06)
3
PRPROOLLOOGG Uma^ linguagem^ de^ PROgramação^ em^ LÓGica.
O Prolog é uma linguagem de declarativa que usa um fragmento da lógica de 1 ª ordem (as Cláusulas de Horn ) para representar o conhecimento sobre um dado problema.
Um programa em Prolog é um “conjunto” de axiomas e de regras de inferência (definindo relações entre objectos) que descrevem um dado problema. A este conjunto chama-se normalmente base de conhecimento.
A execução de um programa em Prolog consiste na dedução de consequências lógicas da base de conhecimento.
O utilizador coloca questões e o “motor de inferência” do Prolog pesquisa a base de conhecimento à procura de axiomas e regras que permitam (por dedução lógica) dar uma resposta. O motor de inferência faz a dedução aplicando o algoritmo de resolução de 1 ª ordem.
A linguagem Prolog surgiu no início da década de 70.
Factos
mae(sofia,joao). mae(ana,maria). mae(carla,sofia).
pai(paulo,luis). pai(paulo,sofia). pai(luis,pedro). pai(luis,maria).
progenitor(A,B) :- pai(A,B). progenitor(A,B) :- mae(A,B).
avo(X,Y) :- progenitor(X,Z) , progenitor(Z,Y).
Exemplo de um programa Prolog (um conjunto de Cláusulas de Horn ).
Regras
Variáveis (lógicas)
Átomos
5
representadas em Prolog por p :- q1, q2, ..., qn
<cabeça da cláusula> :- <corpo da cláusula>
Os factos são cláusulas de Horn com o corpo vazio.
As variáveis que aparecem nas cláusulas são quantificadas universalmente e o seu âmbito é toda a cláusula, mas podemos ver as variáveis que ocorrem apenas no corpo da cláusula (mas não na cabeça), como sendo quantificadas existencialmente dentro do corpo da cláusula.
Notas:
As questões são cláusulas de Horn com cabeça vazia.
As questões são um meio de extrair informação de um programa. As variáveis que ocorrem nas questões são quantificadas existencialmente.
Exemplos de questões à base de conhecimento.
| ?- avo(paulo,X). X = pedro? ; X = maria? ; X = joao? ; no
| ?- pai(X,maria), pai(X,pedro). X = luis? yes
| ?- avo(paulo,X). X = pedro? yes
| ?- avo(ana,joao). no
| ?- progenitor(luis,maria). yes
| ?- progenitor(X,Y). X = paulo, Y = luis? ; X = paulo, Y = sofia? ; X = luis, Y = pedro? ; X = luis, Y = maria? ; X = sofia, Y = joao? ; X = ana, Y = maria? ; X = carla, Y = sofia? ; no
9
TTeerrmmooss O termos são as entidades sintácticas que representam os objectos (do universo de discurso da lógica de 1 ª ordem). Os termos podem ser constantes , variáveis ou termos compostos.
CCoonnssttaanntteess
Base 10 5 0 27 - Outras bases (de 2 a 36 ) 2'101 8' Código ASCII 0'A 0'z
2.0 -5.71 47.0E3 -0.9e-
Qualquer sequência de caracteres alfanuméricos começada por letra minúscula
Qualquer sequência de + - * / \ ^ >< = ~ :.? @ # $ &
Qualquer sequência de caracteres entre ' ' ! ; [] {}
( 65 e 122 respectivamente)
VVaarriiáávveeiiss
X A _ Valores _aa _5 RESP _VAL
variável anónima
Exemplos:
TTeerrmomoss CCoompmpoossttooss
São objectos estruturados da forma f(t1,...,tn) em que
f é o functor do termo e t1, ..., tn são termos (subtermos). O functor f tem aridade n.
Exemplos:
O nome do functor é um átomo.
suc(0) suc(suc(0)) data(15,abril,2006)
Há functores que podem ser declarados como operadores (infixos, prefixos, posfixos).
Exemplo: +(X,Y) X+Y
11
LLiissttaass
Listas são termos gerados à custa do átomo
e do functor
Exemplo: O^ termo^ .(1,.(2,.(3,[])))^ representa^ a^ lista^ [1,2,3]
O Prolog tem uma notação especial para listas [ head | tail ]
.(a,.(b,.(c,[]))) = [ a | [b,c] ] = [ a , b | [c] ] = [ a , b , c | [] ] = [ a , b , c ]
Exemplo:
SSttrriinngg Uma string é a lista de códigos ASCII dos seus caracteres.
Exemplo: (^) “ PROLOG ” = [80,82,79,76,79,71]
Note que “ PROLOG ” é diferente de ' PROLOG '
12
PPrrooggrraammaass
Um programa é um conjunto de cláusulas de Horn. Ou seja, fórmulas da forma
representadas em Prolog por p :- q1, q2, ..., qn
<cabeça da cláusula> :- <corpo da cláusula>
Factos são cláusula só com cabeça e de corpo vazio. Regras são cláusula com cabeça e corpo não vazio.
% grafo orientado caminho(a,b). caminho(b,c).
/* verifica se existe ligação entre dois nodos dos grafo */ ligacao(X,Y) :- caminho(X,Y). ligacao(X,Y) :- caminho(X,Z), ligacao(Z,Y).
comentários
Exemplo:
Os factos e regras com o mesmo nome (à cabeça) definem um predicado (ou procedimento ). Neste exemplo definimos os predicados caminho/ 2 e ligacao/ 2 (nome/aridade). Note que é possível ter predicados distintos com o mesmo nome mas aridades diferentes.
15
caminho(a,b).
caminho(b,c).
ligacao(X,Y) :- caminho(X,Y).
ligacao(X,Y) :- caminho(X,Z), ligacao(Z,Y).
EsEstrtraattééggiiaa ddee PrProoccuurraa ddee SoSolluuççõõeess
Top Down (de cima para baixo)
Depth-First (profundidade máxima antes de tentar um novo ramo)
Backtracking (volta a tentar encontrar uma prova alternativa)
16
? ligacao(a,K)
? caminho(a,K)
? caminho(c,Z3) , ligação(Z3,K)
? ligacao(b,K)
? ligacao(c,K)
? caminho(b,K)
? caminho(c,K)
? caminho(a,Z 1 ) , ligacao(Z 1 ,K)
? caminho(b,Z 2 ) , ligação(Z 2 ,K)
fail
yes
yes
fail
K = b
K = c
;
;
Backtracking
Backtracking
Backtracking
X=c Y=K
X=a Y=K X=a Y=K
X=c Y=K
Z 1 =b
Z 2 =c
X=b Y=K
X=b Y=K
# 3
# 1
# 4
# 2
# 1
# 3
# 3
# 2
# 4
# 4
17
cam(a,b). cam(b,c).
lig(X,Y) :- cam(X,Y).
lig(X,Y) :- lig(Z,Y), cam(X,Z).
OObbsseerrvvaaççããoo::
ligacao(X,Y) :- caminho(X,Z), ligacao(Z,Y).
lig(X,Y) :- lig(Z,Y), cam(X,Z).
? lig(a,K)
? cam(a,K)
? cam(Z 1 ,K), cam(a,Z 1 )^?^ lig(Z^2 ,K),^ cam(Z^1 ,Z^2 ),^ cam(a,Z^1 )
? cam(a,a)
? lig(Z1,K), cam(a,Z1)
? cam(a,b)
fail
yes
yes
K = b
K = c
;
;
Backtracking
Backtracking
Backtracking
? cam(Z 2 ,K), cam(Z 1 ,Z 2 ), cam(a,Z 1 )
? cam(Z 1 ,a), cam(a,Z 1 )? cam(Z 1 ,b), cam(a,Z 1 )
? cam(a,a) fail Backtracking
fail Backtracking
Ciclo infinito
21
soma(0,N,N). soma(suc(N),M,suc(Z)) :- soma(N,M,Z).
? soma(suc(suc(0)),suc(0),X)
? soma(suc(0),suc(0),Z1)
? soma(0,suc(0),Z2)
N1=suc(0) M1=suc(0) X=suc(Z1)
N2= 0 M2=suc(0) Z1=suc(Z2)
Z 2 =suc( 0 )
X = suc(suc(suc( 0 )))
yes
= suc(Z 1 ) = suc(suc(Z 2 )) = suc(suc(suc( 0 )))
Uma solução para a soma de números naturais
Exemplo de uma árvore de procura
Resolução:
22
OOppeerraaddoorreess
Para conveniência de notaçao, o Prolog permite declarar functores unários ou binários como operadores prefixos , posfixos ou infixos , associando-lhes ainda uma precedência.
:- op ( precedência , tipo , nome )
A declaração de operadores faz-se através da directiva
Nº de 1 e 1200 infixo yfx xfy xfx
associativo à esquerda associativo à direita não associativo
posfixo yf
xf
prefixo
fy fx
Functor ou lista de functores
Exemplos: :- op(500,yfx,[+,-]) :- op(400,yfx,*)
a-d+bc , (a-d)+(bc) e +(-(a,d),*(b,c)) são termos equivalentes
:- op(300,fy,nao)
nao nao p , nao (nao p) e nao(nao(p)) são termos equivalentes
23
ooppeerraaddoorr ddee uunniiffiiccaaççããoo
T 1 = T 2 sucede se o termo T 1 unifica com o termo T 2
Dois termos compostos unicam se os functores principais dos dois termos forem iguais e com a mesma aridade, e os argumentos respectivos unificam.
Uma variável unifica com qualquer termo (gerando a substituição respectiva).
Dois átomos (ou números) só unificam se forem exactamente iguais.
Exemplo: (^) | ?- data( 23 ,maio, 1998 ) = data( 23 ,maio, 1998 ). yes | ?- data( 23 ,maio, 1998 ) = data( 23 ,maio,Ano). Ano = 1998? yes | ?- data( 23 ,maio, 1998 ) = data( 15 ,maio,Ano). no | ?- data( 23 ,maio, 1998 ) = data(X,maio,X). no
==
| ?- hora( 10 , 30 ) = hora(X,Y). X = 10 , Y = 30? yes | ?- hora(H, 30 ) = hora( 10 ,M). H = 10 , M = 30? yes | ?- hora(H, 30 , 12 ) = hora(X,Y,X). H = 12 , X = 12 , Y = 30? yes | ?- hora(H, 30 , 12 ) = hora(X,X,X). no | ?- X = f(X). X = f(f(f(f(f(f(f(f(f(f(...))))))))))? yes
Exemplo:
O Sicstus Prolog permite unificar uma variável com um termo em que essa variável ocorre, permitindo assim a criação de termos cíclicos. Formalmente isto não é desejável mas o teste de ocorrência não é feito por razões de eficiência.
““OOccccuurrss--CChheecckk””
27
CCoommppaarraaççããoo ddee tteerrmmooss
no | ?- X4 == X** no
O Sicstus Prolog tem predicados pré-definidos para comparação (sintáctica) de termos (ver User's Manual ).
Testa se os termos são literalmente iguais.
Testa se os termos não são literalmente iguais.
Exemplos: (^) | ?- X = Y, X == Y. Y = X? yes | ?- X == Y, X = Y. no
@< @> @=< @>=
O Sicstus Prolog establece uma relação de ordem no conjunto de termos (ver o manual). A comparação de termos de acordo com essa ordem pode ser feita com os operadores:
| ?- abcd(1,2) @=< xyz. no
| ?- abcd @< xyz. yes
Exemplos:
| ?- hora(3+5,7-3) = hora(10-2,22).* no | ?- hora(3+5,7-3) == hora(10-2,22).* no | ?- [user]. % consulting user... | :- op(700,xfx,igual). | igual(hora(H1,M1),hora(H2,M2)) :- H1 =:= H2, M1 =:= M2. | % consulted user in module user, 0 msec 504 bytes yes | ?- hora(3+5,7-3) igual hora(10-2,22).* yes | ?-
Permite acrescentar novas regras na base de conhecimento. É um editor muito primitivo (linha a linha). ^D para sair do editor e carregar as novas regras.
[user].
Note que não se está a alterar nenhum ficheiro!
Exemplos:
29
% apaga todas as ocorrências de um dado elemento de uma lista apaga([H|T],H,L) :- apaga(T,H,L). apaga([H|T],X,[H|L]) :- H == X, apaga(T,X,L). apaga([],_,[]).
Defina os seguintes predicados sobre listas:
Exemplos:
% ordenação de uma lista com o algoritmo insertion sort isort([],[]). isort([H|T],L) :- isort(T,T1), ins(H,T1,L).
ins(X,[],[X]). ins(X,[Y|Ys],[Y|Zs]) :- X > Y, ins(X,Ys,Zs). ins(X,[Y|Ys],[X,Y|Ys]) :- X =< Y.
Defina um procedimento que ordene de uma lista segundo o algoritmo quicksort.
somatorio/2 que cálcula o somatório de uma lista.
nesimo/3 que dá o elemento da lista na n-ésima posição
minimo/2 que produz o menor elemento presente numa lista.
inverte([],[]). inverte([H|T],L) :- inverte(T,T1), concatena(T1,[H],L).
inv(Xs,Ys) :- inv(Xs,[],Ys).
inv([X|Xs],Ac,Ys) :- inv(Xs,[X|Ac],Ys). inv([],Ys,Ys).
acumulador
fact(0,1). fact(N,F) :- N>0, N1 is N-1, fact(N1,F1), F is N*F1.
Defina uma outra versão de factorial que utilize um parâmetro de acumulação.
U Ussoo ddee AAccuummuullaaddoorreess
Exemplo:
Considere o seguinte procedimento para o cálculo do factorial
Inversão de uma lista com e sem acumuladores.
33
Escreva um programa para reconhecer se uma fórmula da lógica proposicional está na forma normal conjuntiva, ou seja, é uma conjunção de disjunções de literais. Um literal é um símbolo proposicional ou a sua negação.
:- op(500,yfx,/). :- op(500,yfx,/). :- op(300,fy,~).
Considere a declaração das seguintes conectivas lógicas:
| ?- flatten([a,b,[c,d],[],[[[e,f]],g],h],X). X = [a,b,c,d,e,f,g,h]? yes
Defina o predicado conta_ocorr/3 para contar quantas vezes uma constante ocorre numa lista. (Sugestão: usar atomic/1).
Suponha que tem factos da forma quadrado(Lado). Defina o predicado zoom(+X,?Y,+F) tal que Y é o quadrado que resulta de multiplicar pelo factor F os lados do quadrado X. (Sugestão: usar =..).
34
arv_bin(vazia). arv_bin(nodo(X,Esq,Dir)) :- arv_bin(Esq), arv_bin(Dir).
na_arv(X,nodo(X,,)). na_arv(X,nodo(Y,Esq,)) :- na_arv(X,Esq). na_arv(X,nodo(Y,,Dir)) :- na_arv(X,Dir).
UUmm eexxeemmpplloo ccoomm áárrvvoorreess bbiinnáárriiaass
a
b (^) c
Esta árvore é representada pelo termo
nodo(a, nodo(b,vazia,vazia), nodo(c,vazia,vazia))
Exemplo:
Defina predicados que permitam fazer as travessias preorder , inorder e postorder.
Defina um predicado search_tree/1 que teste se uma dada árvore é uma árvore binária de procura.
binária de procura resultado da inserção de X na árvore binária de procura T1. Defina a relação path(+X,+Tree,?Path) que sucede se Path é o caminho da raiz da árvore binária de procura Tree até X.
35
OO ccuutt !!
O cut****! não deve ser visto como um predicado lógico. Apenas interfere na semântica procedimental do programa. A sua acção é a seguinte: Durante o processo de prova, a 1 ª passagem pelo cut é sempre verdadeira (com sucesso). Se por backtracking se voltar ao cut, então o cut faz falhar o predicado que está na cabeça da regra. O cut “corta” ramos da árvore de procura. Os predicados antes do cut são apenas instanciados uma vez.
x :- p,! , q. x :- r. (^) if p then q else r
Exemplo: x tem um comportamento semelhante a
Green Cut
Red Cut
Chamam-se green cuts aos cuts que só alteram a semântica procedimental do programa, mas não alteram o significado do predicado. Este cuts são usados apenas para melhorar a eficiência. Se forem retirados serão produzidos os mesmos resultados.
Chamam-se red cuts aos cuts que alteram não só a semântica procedimental do programa, como também o seu significado declarativo. Se forem retirados serão produzidos resultados diferentes. A utilização destes cuts deve ser evitada.
minimo(X,Y,Y) :- X >= Y. minimo(X,Y,X) :- X < Y.
min(X,Y,Y) :- X >= Y,!. min(X,Y,X) :- X < Y.
? minimo(3,2,M)
yes
fail
? min(3,2,M)
yes
Ramo cortado pelo cut
Exemplos: (^) minimo e min são predicados equivalentes.
O cut só está a cortar ramos que falham.