Anda di halaman 1dari 143

Universidade Federal de So Carlos Departamento de Computao

Programao Lgica

Prof. Dr. Antonio Francisco do Prado e-mail: prado@dc.ufscar.br


1

Programao Lgica Linguagem PROLOG Fatos, Regras e Controle de Corte Operadores e Listas Entrada e Sada Manipulando Base de Dados Outros Exemplos Metodologia de Programao Lgica Fuzzy Exerccios
2

Programao Lgica

Razes O uso da lgica na representao do raciocnio remonta os estudos de Boole (1815-1864) e de De Morgan (1806-1871) sobre a lgebra de Boole; Em 1879 surge a primeira verso do Clculo de Predicados com o matemtico alemo Gttlob Frege, onde era oferecida uma representao adequada para a formalizao do raciocnio dedutivo; Em 1930, em estudos simultneos, o alemo Kurt Gdel e o francs Jacques Herbrand demonstraram que o mecanismo de prova do Clculo de Predicados poderia oferecer uma prova formal de toda proposio logicamente verdadeira; Ainda na dcada de 30 diversos estudos, entre eles os de Alan Turing e Alonzo Church, aproximaram muito o Clculo de Predicado com a forma como hoje conhecido; Em 1939 toda fundamentao terica bsica da lgica computacional j estava pronta, faltava apenas uma meio prtico para realizar o imenso volume de computaes necessrias aos procedimentos de prova;

Somente nos meados da dcada de 50 que o desenvolvimento dos computadores permitiu experincias mais significativas com o Clculo de Predicados; Em 1958 uma forma simplificada do Clculo de Predicados denominada forma Clausal comeou a despertar o interesse dos estudiosos. Nessa forma de clculo era empregado um tipo muito simples de sentena lgica, a Clusula; Tambm nessa poca (1960) Dag Prawitz props um novo tipo de operao sobre os objetos do Clculo de Predicados, que foi mais tarde conhecido como Unificao; Apesar de toda base terica para a Programao Lgica estar pronta, ela somente se tornou possvel a partir da pesquisa sobre prova matemtica de teoremas, particularmente no desenvolvimento do Princpio da Resoluo por J.A. Robinson (1965); A expresso Programao Lgica (Logic Programming) surge com Robert Kowalski (1974) e designa o uso da lgica como uma linguagem de programao de computadores.

OBS: muitos outros pesquisadores colaboraram para o aparecimento da Programao Lgica. No texto apenas foram relatados alguns deles.
4

Conceitos da Programao Lgica Uma das principais idias em Programao Lgica que um algoritmo constitudo por dois elementos disjuntos: Lgica: corresponde definio do que deve ser solucionado; Controle: estabelece como a soluo pode ser obtida; A tarefa do programador somente descrever (especificar) o componente lgico do algoritmo, deixando o controle da execuo para ser exercido pelo sistema de programao em lgica utilizado; Um Programa em Lgica ento a representao de determinado problema ou situao expressa atravs de um conjunto finito de um tipo especial de sentenas lgicas, denominadas clusulas; O paradigma fundamental da programao em lgica o da Programao Declarativa, em oposio Programao Procedimental tpica das linguagens convencionais; O ponto focal da Programao em Lgica consiste em identificar a noo de computao com a noo de deduo, onde a execuo de programas se reduzem pesquisa da refutao das sentenas do programa em conjunto com a negao da sentena que expressa a consulta, seguindo a regra: "uma refutao a deduo de uma contradio". 5

Os termos "programao em lgica" e "programao Prolog" tendem a ser empregados indistintamente. Deve-se, entretanto, destacar que a linguagem Prolog apenas uma particular abordagem da Programao em Lgica; Pode-se expressar conhecimento (programas e/ou dados) em Prolog por meio de clusulas de dois tipos: Fatos: denota uma verdade incondicional; Regras: definem as condies que devem ser satisfeitas para que uma certa declarao seja considerada verdadeira.

Caractersticas da Programao Lgica Os sistemas de Programao em Lgica em geral e a linguagem Prolog em particular possuem as seguintes propriedades: Funcionam simultaneamente como linguagem de programao e de especificao; Possuem capacidade dedutiva; Operam de forma no-determinstica;

Permitem a representao de relaes reversveis;


Permitem interpretao declarativa, operacional e procedimental; So naturalmente recursivas.
6

Aplicaes da Programao Lgica As principais aplicaes da Programao em Lgica so: Sistemas Baseados em Conhecimento (SBCs) Sistemas de Bases de Dados (BDs); Sistemas Especialistas (SEs); Processamento da Linguagem Natural (PLN); Educao; Modelagem de Arquiteturas No-Convencionais. Linguagens Convencionais x Lgicas
PROGRAMAS CONVENCIONAIS Processamento Numrico Solues Algortmicas Estruturas de Controle e Conhecimento Integradas Difcil Modificao Somente Respostas Totalmente Corretas Somente a Melhor Soluo Possvel PROGRAMAS EM LGICA Processamento Simblico Solues Heursticas Estruturas de Controle e Conhecimento Separadas Fcil Modificao Incluem Respostas Parcialmente Corretas Incluem Todas as Solues Possveis
7

Programao Lgica Linguagem PROLOG Fatos, Regras e Controle de Corte Operadores e Listas Entrada e Sada Manipulando Base de Dados Outros Exemplos Metodologia de Programao Lgica Fuzzy Exerccios
8

Linguagem PROLOG

Linguagens Funcionais x Lgicas


Funcional Programao orientada para funes Diz como fazer para atingir um objetivo Mais voltada para algoritmos que exploram o conhecimento Preocupa-se com aspectos relacionados com a construo de listas, tipos, padro de comparao, estruturas de dados, etc. Camada mais baixa de suporte para as aplicaes Lgica Programao orientada para objetivos (goal) Diz o que fazer para atingir um objetivo Mais voltada para o conhecimento Mais declarativa do que procedural

Nvel mais elevado de abstrao na soluo dos problemas

Concluso Tanto as linguagens Funcionais como Lgicas so importantes e empregadas principalmente em Sistemas Transformacionais, Inteligncia Artificial (IA) e Robtica.
9

Histrico Criado por Alain Colmerauer por volta de 1970 na Universidade de Marselha, Frana. Seu objetivo inicial era servir de apoio a sistemas de Linguagem Natural. Algol 60

Algol 68
Prolog Programao Prolog Para executar um programa em prolog, primeiro deve-se criar um arquivo com a extenso correspondente do interpretador ( .ari, .pl, etc). Depois, execute no interpretador correspondente. Em seu menu acione a opo File e Consult para carregar o programa no interpretador. Se houver algum erro no programa, este ser mostrado na tela, seno o programa est pronto para ser executado (interpretado).

10

A programao Prolog consiste fundamentalmente em: Declarar fatos ou assertivas; Estabelecer regras ou procedimentos; e

Fazer perguntas.
Os fatos e as regras so fornecidos e a linguagem usa deduo para obter respostas para as questes.

11

Consideraes sobre o aprendizado do aluno

Temos observado que o estilo procedimental de programao, talvez por ser o primeiro a ser ensinado, interfere de certa forma, na correta aprendizagem de linguagens como Lisp ou Prolog por parte dos estudantes. Tentaremos minimizar essa interferncia submetendo o aluno a resoluo de conjuntos de problemas semelhantes, principalmente problemas envolvendo listas. essencial que o aluno tente compreender a lgica de programao Prolog, entendendo mecanismos de unificao, backtracking entre outros. Tambm importante que o aluno tente resolver os exerccios propostos no ultimo captulo, para consolidar o seu aprendizado.

12

Programao Lgica Linguagem PROLOG Fatos, Regras e Controle de Corte Operadores e Listas Entrada e Sada Manipulando Base de Dados Outros Exemplos Metodologia de Programao Lgica Fuzzy Exerccios
13

Fatos, Regras e Controle de Corte


Introduo

Um programa Prolog consiste de :

Definio de fatos a respeito de objetos de dados e suas relaes; Definio de regras a respeito de objetos de dados e suas relaes; Interrogao a respeito de objetos de dados e suas relaes.

Um objeto de dados em Prolog definido de acordo com a seguinte rvore :

objetos

objetos simples

estruturas

constantes

variveis
14

tomos

nmeros

tomo a estrutura mais simples do Prolog, eles so construdos por cadeias de letras, dgitos e caracteres especiais( _, +, *). Todo tomo deve possuir a primeira letra minscula. Exemplos de tomos : x_y, maria, copa2002.

Nmeros em Prolog incluem nmeros inteiros e nmeros reais. A sintaxe bem simples : 1, -20.
Variveis so cadeias de letras, dgitos e caracteres sempre comeando com letra maiscula. Estruturas so objetos de dados que tm vrios componentes, podendo cada um deles, por sua vez, ser uma outra estrutura. Por exemplo, uma data pode ser vista como um conjunto de dia, ms e ano. Embora composta por vrios componentes, estruturas so tratadas no programa como objetos simples. A combinao dos componentes de um objeto simples feita atravs de seu funtor. No caso de data, o funtor pode ser data e pode se escrever 7 de setembro de 2002 da seguinte maneira : data(7, setembro, 2002) Note que os componentes 7, setembro e 2002 so todos constantes(2 inteiros e 1 tomo)
15

Fatos, Regras e Controle de Corte

Fatos Um Fato denota uma verdade incondicional. Uma relao pode ser especificada por um fato. Sintaxe : predicado(arg1[,arg2,...,arg n]). Argumentos (arg1...arg n) so objetos quaisquer e Predicado a relao que une esses objetos.

pam

tom

bob

liz

ann

pat

jim
16

progenitor(pam,bob). progenitor(tom,bob). progenitor(tom,liz). progenitor(bob,ann). progenitor(bob,pat). progenitor(pat,jim).

%pam um dos progenitores de bob %tom um dos progenitores de liz

Em Prolog usam-se maisculas para variveis e minsculas para tomos. Questes: tomo ?-progenitor(bob,pat). yes ?-progenitor(liz,pat). no ?-progenitor(X,liz). X=tom ; no ?-progenitor(bob,X). X=ann X=pat varivel ?progenitor(X,Y). X=pam , Y=bob ; X=tom , Y=bob ; X=tom , Y=liz ; X=bob , Y=ann ; X=bob , Y=pat ; X=pat , Y=jim ;
17

Quem so os avs de Jim? (1) Quem progenitor de Jim? (Por exemplo, Y) e (2) Quem progenitor de Y? (Por exemplo, X). X Progenitor

Y
Progenitor jim

Avos

"Encontre X e Y tais que X progenitor de Y e Y progenitor de Jim". Questes: ?-progenitor(X, Y), progenitor(Y, jim). X=bob Y=pat ; Quem neto de Tom? Questes: ?-progenitor(tom, X), progenitor(X, Y). X=bob Y=ann; X=bob Y=pat.
18

Definio de uma extenso da base anterior (caracterstica do objeto): mulher(pam). homem(tom). homem(bob). mulher(liz). mulher(pat). mulher(ann). homem(jim).

Regras As regras definem as condies que devem ser satisfeitas para que uma certa declarao seja considerada verdadeira. Sintaxe : pred(arg/Var,arg/Var) :- pred(arg/Var,arg/Var). cabea (concluso) se (condio) corpo

Onde o smbolo :- indica uma condio (se) e separa a regra em concluso ou cabea da regra e condio ou corpo da regra.

19

Definir a relao filho. Poderia ser definida como: filho(bob,tom). filho(bob,pam). ... Entretanto existe uma maneira mais elegante, que seguiria a seguinte declarao: Para todo X e Y Y filho de X se

X progenitor de Y.

filho(Y, X) :- progenitor(X, Y). "Para todo X e Y, se X progenitor de Y, ento Y filho de X". Questes: ?-filho(jim,pat). yes

filho(Y, X) :- progenitor(X, Y) cabea (concluso) se corpo (condio)


20

Frases Compostas robo(peter). capaz_de_fazer(peter,armas). machuca(armas,pedro). homem(pedro). proibido_fazer(R,B):-robo(R),capaz_de_fazer(R,B), machuca(B,H),humano(H). Questo ? - proibido_fazer(R,B). R = peter , B = armas

Significa: R est proibido de fazer um ato B se R for um rob e R for capaz de fazer B e B machuca H e H for humano.
Para todo R e B proibido_fazer(R,B) se existe H tal que robo(R) e capaz_de_fazer(R,B) e machuca(B,H) e humano(H). humano(H):-homem(H). Hfen Usa-se o hfen para indicar irrelevncia de um objeto Exemplo: aniversario(maria,data(25,janeiro,1979)). aniversario(joao,data(5,janeiro,1956)). signo(Pessoa,aquario):-aniversario(Pessoa,data(Dia,janeiro,_)), Dia >= 20. ? - signo(Pessoa,aquario). Pessoa = maria; no
21

Conjuno e Disjuno Em prolog o operador de conjuno e ( , ) implica na necessidade de aceitao de todas as condies, enquanto o operador de disjuno ou ( ; ) permite a aceitao de uma ou outra condio. Estes operadores permitem a composio de fatos. Exemplos: amiga(X):-(X = maria; X = joana). disjuno ou Definio de uma regra avos: Usando-se a conjuno podemos definir o predicado avos seguindo a seguinte declarao: Para todo X e Z

X progenitor de Y e
Y progenitor de Z. "Para todo X e Z, se X progenitor de Y, e Y progenitor de Z, ento X um dos avos de Z". avos(X,Z):-progenitor(X,Y) , progenitor(Y,Z). Questes: ?-avos(bob,jim). yes ?-avos(liz,jim). no conjuno e ?-avos(pam,X). X=ann ; X=pat
22

Definio de uma regra me: mae(X,Y):-progenitor(X,Y),mulher(X). Questes: ?-mae(pat,jim). yes

?-mae(bob,ann). no

Definio de uma regra irm: irma(X,Y):-progenitor(Z,X),progenitor(Z,Y),mulher(X).

Z progenitor progenitor

mulher

irm

Questes: ?-irma(ann,pat). yes

?-irma(X,pat). X=ann ; X=pat ; no

Definio de uma regra diferente: diferente(X,Y):-X\==Y. %X diferente de Y


23

Definio de uma regra irm usando a regra diferente: irma(X,Y):-progenitor(Z,X),progenitor(Z,Y),diferente(X,Y). Questo: ?-irma(X,pat). X=ann ; no Definio de uma regra tia: tia(X,Y):-progenitor(Z,Y),irma(X,Z). Questo: ?-tia(liz,X). X=ann ; X=pat ; no Recurso Definio de uma regra antepassado Necessita de duas regras: antepassados diretos e antepassados indiretos.
bob

Antepassados diretos

pat jim

Antepassados indiretos

24

Primeira regra bastante simples: Para todo X e Z X antepassado de Z se X progenitor de Z.

antepassado(X, Z) :- progenitor(X, Z).

Segunda regra complicada. A cadeia de progenitores pode se estender indefinidamente: antepassado(X, Z) :- progenitor(X, Y), progenitor(Y, Z). antepassado(X, Z) :- progenitor(X, Y1), progenitor(Y1, Y2), progenitor(Y2, Z). antepassado(X, Z) :- progenitor(X, Y1), progenitor(Y1, Y2), progenitor(Y2, Y3), progenitor(Y3, Z). ....

25

Soluo: definir a regra recursivamente Para todo X e Z X antepassado de Z se existe um Y tal que X progenitor de Y e Y antepassado de Z. X Progenitor Y Antepassado Antepassado

Z A segunda regra fica: antepassado(X, Z) :- progenitor(X, Y), antepassado(Y, Z). Questes: ?-antepassado(X,liz). X=tom ; no

?-antepassado(X,pat). X=bob ; X=pam ; X=tom ; no

26

Controle de Corte H ocasies em que, por um ou outro motivo, desejamos controlar a execuo do programa. Para isso, utilizamos o mecanismo de corte. Operador Cut
Algumas

das principais aplicaes do cut so as

seguintes: Unificao de padres, de forma que quando um padro encontrado os outros padres possveis so descartados (quando uma determinada regra a ltima a ser analisada e haveria problemas na continuidade da verificao das demais regras); Para eliminar da rvore de pesquisa solues alternativas quando uma s suficiente; Especificar regras mutuamente exclusivas, expressas na forma: Se P ento Q seno R; Como indicativo do caso limite ou para evitar que a pesquisa prossiga indefinidamente atravs do backtracking.
Simbolizado Seu

pela exclamao (!).

uso deve ser considerado pelas seguintes razes: Execuo mais rpida do programa (no desperdia tempo tentanto satisfazer objetivos que no contribuiro para a soluco desejada);27 Economiza memria (corta a vore de pesquisa).

Exemplos: Podemos simular a programao procedimental em Prolog. Aqui simularemos a estrutura if-then-else: ifThenElse(X,Y,Z) "Se X for verdadeiro, ento execute Y, seno execute Z". ifThenElse(X, Y, _) :- X, !, Y. ifThenElse(_, _, Z) :- Z. Questo: ?-ifThenElse(X, Y is Z+1, Y is 0).
OBS: este programa emprega meta-variveis (variveis que podem ser instanciadas com chamadas a predicados)

Exemplo do operador Cut: amigo(joana,ana). amigo(maria,ana). amigo(pedro,jose). amigo(pedro,ana). um_unico_amigo(X,Y):-amigo(X,Y),!. Questes: ?- um_unico_amigo(X,ana). ?- um_unico_amigo(pedro,X). X = joana X = jose Mnimo entre dois nmeros: minimo(X,Y,X):-X =< Y, !. minimo(X,Y,Y):-X > Y, !. Questes: ?- minimo(10,3,Min). ?- minimo(12,56,Min). Min = 3 Min = 12

28

Fail O predicado Fail, fora um retrocesso, como se indicasse uma falha. Junto com o corte (Cut), acelera a avaliao de regras economizando memria. Exemplos: Exemplo do operador Fail: cliente(ana,123,bradesco). cliente(jose,456,itau). executa :- cliente(Nome,Conta,Agencia), write(Nome),write( tem conta ),write(Conta), write( na agencia ),write(Agencia),nl,fail.

Neste caso fail fora um backtracking e repete a a impresso.


Questes: ?-executa. ana tem conta 123 na agencia bradesco jose tem conta 456 na agencia itau no

Not (X) O operador unrio not define uma forma particular de negao denominada "negao por falha.
29

Definio de uma regra para exemplificar o not: estudante(jorge). casado(jose). estudante_solteiro(X):-not casado(X), estudante(X).
Questes: ?-estudante_solteiro(jorge). yes

?-estudante_solteiro(jose). no

Cuidados com o Cut e a Negao

O uso do cut pode levar a perda da correspondncia entre o significado declarativo e a interpretao operacional do programa:
Se no houver cuts no programa pode-se trocar a ordem das clusulas e objetivos que seu significado declarativo no ser alterado (h apenas uma possvel perda de performance); Se houver cuts essa alterao pode afetar o significado declarativo levando a resultados inesperados. O uso da negao tambm pode levar a resultados inesperados. Qual o problema do programa abaixo? Questes: r(a).

q(b).
p(X) :- not r(X).

?-q(X), p(X). X = b.

?-p(X), q(X). no
30

Outros Exemplos de Regra Definio das regras positivo e negativo: positivo(X):-X>=0. %X maior ou igual a 0 negativo(X):-X<0. %X menor que 0 Questes: ?-positivo(7). ?-negativo(10). yes no Mximo entre 2 nmeros: max(X,Y,X):-X>=Y. max(X,Y,Y):-X<Y. Mximo entre 2 nmeros usando corte: max(X,Y,X):-X>=Y,!. max(X,Y,Y). Questo: ?-max(10,3,Max). Max=10 Definio das regras par e impar:

par(X):-X mod 2 =:=0


impar(X):-par(X),!,fail. impar(X). Questes: ?-par(6). yes ?-impar(6). no

% o mod de 2 igual a 0

31

Definio de uma funo f(X): f(X, 0):- X < 3. f(X, 2):- 3=< X, X < 6. f(X, 4):- 6 =< X.
4 3

Y=f(X) Y=F(X) 2
1 0 0 1 2 3 4 5 6 X 7 8 9 10

Definio de uma funo f(X) com corte: f(X, 0):- X < 3, ! . f(X, 2):- 3 =< X, X < 6, ! . f(X, 4). Questes: ?-f(1,Y),2<Y. no

?-f(7,Y). Y=4

Definio de uma regra para fatorial: fatorial(0, 1):- !. fatorial(N, F):- N1 is N - 1, %Atribuio fatorial(N1, F1), F is F1 * N. Questo: ?- fatorial(4, F). F = 24
32

Exemplo de recursividade Para o exemplo anterior da regra do Fatorial recursivo, mostrado a execuo passo a passo, note que em todos os passos(com excesso do 5) h unificao com a segunda regra. (primeira regra critrio de parada). Questo: ?- fatorial(4, F). F = 24 Passo 1 : fatorial(4, F) { N = 4, N1 =3, F = F1 * 4, fatorial(N1, F1) }

F=6
Passo 2 : fatorial(3, F) { N = 3, N1 =2, F = F1 * 3, fatorial(N1, F1) } F=2 Passo 3 : fatorial(2, F) { N = 2, N1 =1, F = F1 * 2, fatorial(N1, F1) } F=1 Passo 4 : fatorial(1, F) { N = 1, N1 =0, F = F1 * 1, fatorial(N1, F1) } F=1 Passo 5 : fatorial(0, F) {F = 1 }

33

Definio de uma regra para fatorial com recurso de cauda: fact(N,Fn):-fact(N,Fn,0,1). fact(N,Fn,N,Fn):-!. fact(N,Fn,I,P):-Novoi is I+1,Novop is P*Novoi, fact(N,Fn,Novoi,Novop).

Questo: ?- fact(6, F). F = 720

Recurso de cauda. A recursividade a ltima.

Definio de uma regra para fibonacci: fib(1, 1). fib(2, 1). fib(N, F):- N > 2, N1 is N - 1, fib(N1, F1), N2 is N - 2, fib(N2, F2), F is F1 + F2. Questo: ?- fib(6, F). F=8 ; no

34

Programao Lgica Linguagem PROLOG Fatos, Regras e Controle de Corte Operadores e Listas Entrada e Sada Manipulando Base de Dados Outros Exemplos Metodologia de Programao Lgica Fuzzy Exerccios
35

Operadores e Listas

Operadores Aritmticos

+ * / mod is

Adio Subtrao Multiplicao Diviso Mdulo, o resto inteiro da diviso Atribuio

Exemplo: Clculo de um nmero elevado ao quadrado: ao_quadrado(X,Y):-Y is X*X. Questo: ?- ao_quadrado(6,X). X=36
36

Operadores de Comparao

X>Y X<Y

X maior que Y X menor que Y

X >= Y X maior ou igual a Y X =< Y X menor ou igual a Y X =:= Y Os valores de X e Y so iguais X \== Y Os valores de X e Y so diferentes

Exemplo: Definio de uma regra intervalo aberto: interv_aberto(K,X1,X2):-K > X1,K < X2. Questes: ?- interv_aberto(5,0,5). no

?- interv_aberto(2,0,5). yes

37

Listas As listas so estruturas de dados dinmicas com as quais possvel a construo de vetores e matrizes. Sintaxe : pred([elem,...],[],[elem[elem,...],...],arg,...). Onde elem pode ser qualquer tipo sinttico.

Listas so compostas por cabea e cauda. A cabea de uma lista pode ser qualquer objeto Prolog e a cauda deve ser uma lista. Como a cauda, por sua vez, uma lista, ela a lista vazia ou tem sua prpria cabea e cauda. Sintaxe para Listas

A lista vazia denotada por [] ; a lista que tem cabea X e cauda Y denotada por [X|Y] . Dentro das listas, os elementos so separados por vrgula. Exemplo : Lista [gosto,de, vinho] [X,Y|Z] [[o,gato]] Cabea gosto X [o,gato] Cauda [de, vinho] [Y|Z] []
38

Unificao em listas

Em Prolog, a mais importante operao envolvendo termos chamada unificao. Dois termos T e S unificam se :
1. Se T e S so constantes, ento unificam se e s se S e T so o mesmo objeto. 2. Se S for uma varivel e T qualquer termo, ento unificam, e S instanciado com T ; vicer versa, com a varivel T instanciada com S. 3. Se S e T so estruturas, eles unificam se e s se S e T tem o mesmo funtor principal e todos os elemtentos correspondentes unificam. A seguir so mostrados vrios exemplos de unificao em listas :
Lista 1 [mesa]
[a,b,c,d]

[[ana, Y] | Z]

[ano, bissexto]

Unificao X / mesa Y/[] [X,Y|Z] X/a Y/b Z / [c,d] [[X, foi], [ao, cinema]] X / ana Y / foi Z / [[ao, cinema]] [X,Y|Z] X / ano Y/ bissexto 39 Z/[]

Lista 2 [X|Y]

Lista 1 [ano, bissexto] [data(7,Z,W), hoje] [data(7,W,1993), hoje]

Lista 2 [X,Y,Z] [X,Y] [data(7,X,Y), Z]

Unificao no unifica (aridade diferente) X / data(7,Z,W) Y / hoje X/W Y / 1993 Z / hoje

Busca recursiva Freqentemente necessrio procurar por algum termo Prolog ; isto resulta em uma busca recursiva. Para verificar se um elemento pertence uma lista, usamos o seguinte predicado: pertence(X, [X | _]). % verifica se X esta na cabea pertence(X, [_ | Y]):- pertence(X, Y). % verifica se X % esta na cauda Questes: ?- pertence(a, [h, a, b]). yes ?- pertence( a, [hoje, amanha]). no

?- pertence(X, [a, b, c]). X = a; X = b; X = c; no

40

Goal

?- X = [1,2,3],pertence(a,X). no ?- pertence( a, X),X = [1,2,3]. X = [a |_] %pode ser o 1 elemento de X X = [_ , a | _] %pode ser o 2 elemento de X X = [_ , _ , a | _] %pode ser o 3 elemento de X . . . %computao infinita!

Sequncia de ligao -> da esquerda para a direita

Concluso

Escolha o subgoal com o menor nmero de solues como goal a adivinhar. No caso anterior o goal a adivinhar correto X = [1,2,3], porque tem apenas uma soluo e esta soluo no satisfaz pertence(a,X), porque a no est na lista [1,2,3].

41

Controle em Prolog 1. Iniciar pelo goal 2. Enquanto o goal corrente no vazio faa 2.1. Comece pelo subgoal mais esquerda 2.2. Se uma regra aplica ao subgoal ento 2.2.1. Para esta regra, usando unificadores genricos, volte para 2.1 Seno backtrack fim-se fim-enquanto Exemplo:

anexa([ ],Y,Y ). anexa([H | X],Y,[H| Z]):- anexa(X, Y,Z). prefix(X,Z):-anexa(X,Y,Z). sufix(Y,Z):-anexa(X,Y,Z).

42

1 Subgoal ?- sufix ( [ a ] , L ) , prefix ( L , [ a , b , c ] ). L=[ a] ; %sem backtraing X = [ ] Y = [ b , c ]


O fato sufix ( Y , Z ) :- anexa ( X , Y , Z ) aplica ao subgoal mais esquerda sufix ( [ a ] , L ) A substituio Y -> [ a ] , Z -> L Unifica a cabea da regra com o subgoal sufix ( [ a ] , L ) Tem-se ento: sufix ( [ a ] , L ) if anexa ( _1 , [ a ] , L ) nome Prolog Substituindo pela condio tem-se: anexa ( _1 , [ a ] , L ) , prefix ( L , [ a , b , c ] ) O fato anexa ( [ ] , Y , Y ) aplica ao novo subgoal mais esquerda: [ ] -> _1 , Y -> [ a ] , Y -> L Uma vez que o fato consiste de uma cabea e nenhuma condio, o novo goal corrente torna-se: prefix ( [ a ] , [ a , b , c ] ) substituda -> L Tem-se ento: prefix ( [ a ] , [ a , b , c ] ) if anexa ( [ a ] , _2 , [ a , b , c ] ) . anexa ( [ a ] , _2 , [ a , b , c ] ) if anexa ( [ ] , _2 , [ b , c ] ). anexa ( [ ] , _2 , [ b , c ] ) 2 -> [ b , c ] anexa ( [ ] , [ b , c ] , [ b , c ] ) . L=[ a] ;
43

Modos de Chamada

Usando o exemplo do pertence([arg1], [arg2]) mostrado anteriormente, o que aconteceria se as interrogaes fossem : ?- pertence(a,X) % ou ?- pertence(X,Y) Pode se observar que cada uma delas tem infinitas respostas, uma vez que existem infinitas listas que validam estas interrogaes para o programa pertence. Portanto, necessrio definir se os argumentos devem estar ou no instanciados. Usaremos a seguinte notao para documentar as formas corretas de interrogao : modo(<arg 1>, <arg 2>, .....,<arg n>) onde : <arg i > = + se <arg i > deve estar instanciado. <arg i > = - se <arg i > deve ser varivel livre. <arg i > = ? se <arg i > puder ser qualquer um dos casos. Exemplo : o exemplo pertence ([arg1], [arg2]) tem o modo(? , +).

44

Outros Exemplos de Lista Verificao se um elemento de uma lista no pertence a outra lista, modo(+, +) : nao_pertence(X,Y):- \+ (pertence(Z,X),pertence(Z,Y)). Questes: ?-nao_pertence([a,b],[b,c]). ?- nao_pertence([a,b,c],[d,e,f]). no yes Soma dos elementos de uma lista, modo(+, ?) : soma([ ], 0). soma( [Elem | Cauda], S):- soma(Cauda, S1), S is S1 + Elem. Questo: ?- soma([1, 2, 3, 4, 5, 6], S). S = 21

Verificao se uma lista est ordenada, modo(+) : ordenada([ ]). ordenada([X,Y | Resto]):-X=<Y,ordenada([Y | Resto]). ?-ordenada([3,2,1]). no

Questes: ?-ordenada([1,5,6,6,9,12]). yes

45

Verificao se um termo uma lista, modo(+) : eh_lista([ ]). eh_lista(X):- not var(X), not atom(X).
Onde os predicados: var(X) - Verdadeiro se o termo X uma varivel atom(X) - Verdadeiro se o termo X um tomo

Questes: ?- eh_lista([a, b, c, d, e, f]). yes ?- eh_lista([ ]). yes

?- eh_lista( 2 ) no

Duplicao dos elementos de uma lista, modo(+,?) : duplica([ ], [ ]). duplica( [X | L], [X, X | L1]):- duplica(L, L1). Questo: ?- duplica([1, 2, 3], L). L = [1, 1, 2, 2, 3, 3]
46

Concatenao de duas listas, modo(+,?,?) : concatena([ ], Lista, Lista). concatena([ Elem | Lista1], Lista2, [Elem | Lista3]):concatena(Lista1, Lista2, Lista3). Questo: ?- concatena([um, dois], [tres, quatro], L). L = [um, dois, tres, quatro] Tambm pode se usar o modo modo(-,-,+) para decompor uma lista em duas sublistas. Maior elemento de uma lista numrica, modo(+,?) : max([X], X). % Maior elemento de uma lista com 1 % elemento o prprio elemento max([X, Y | Cauda], Max):- X >= Y, ! , max([X | Cauda], Max). max([X, Y | Cauda], Max):- max([Y | Cauda], Max). Questo: ?- max([1, 10, 100, -1, 20], M). M = 100 ; no N_simo elemento de uma lista, modo(?,?,+) : n_esimo(1, Elem, [Elem | _]). n_esimo(N, Elem, [ _ | Cauda]):- n_esimo(M, Elem, Cauda), N is M + 1. Questo: ?- n_esimo(4, Elem, [a, b, c, d, e]). Elem = d ; no

47

Inverso de uma lista, modo(+,?) : inverter([ ],[ ]). inverter([Elem | Lista1], Lista3):-inverter(Lista1,Lista2), concatena(Lista2,[Elem], Lista3). Questes: ?- inverter([a,b,c], L). L = [c,b,a]

?-inverter([1,2,3,4,5,6],L). L = [6,5,4,3,2,1]

Nmero de elementos em uma lista, modo(+,?) : tamanho([ ],0). tamanho([_ | R], N):-tamanho(R, N1),N is N1+1. Questo: ?- tamanho([a,b,c,d,e], N). N=5

Seleo de determinados elementos de uma lista, em uma lista separada, identificados pela sua posio, modo(+,+,?) : seleciona([ ], _, [ ]). seleciona([M | N], L, [X | Y]):-n_esimo(M, X, L), seleciona(N, L, Y). Questo: ?- seleciona([2, 4], [a, b, c, d, e], L). L = [b, d] ; no
48

Ultimo elemento de uma lista, modo(+,?) : ultimo([Elem], Elem). ultimo([_|Cauda], Elem) :- ultimo(Cauda, Elem). Questes: ?- ultimo([casa, bola, carro], X) X = carro ; no

Elementos consecutivos em uma lista, modo(?,?,+) : consecutivos(E1,E2, [E1, E2|_]). consecutivos(E1, E2, [_|Cauda]) :consecutivos(E1, E2, Cauda). Questes: ?- consecutivos(a, b, [d, e, f, g, a, b]). yes ?- consecutivos(X, Y, [d, e, f, g]). X=d Y=e ; X=e Y=f; X=f Y=g; no

49

Insero de um elemento na 1 posio de uma lista, modo(?,?,?) : inserir(Elem, Lista, [Elem | Lista]). Questo: ?- inserir(a, [b, c, d], L). L = [a, b, c, d] Excluso de um elemento de uma lista, modo(?,+,?) ou modo(+,?,+) : del(X,[X | Corpo],Corpo). del(X,[Y | Corpo], [Y | Corpo1]):-del(X,Corpo,Corpo1). Questo: ?- del(b,[a,b,c], L). L = [a,c] ; no Permutao de uma lista, modo(+,?) : permuta([ ],[ ]). permuta(L,[X | P]):-del(X,L,L1),permuta(L1,P). Questo: ?- permuta([vermelho,azul,verde], L). L = [vermelho,azul,verde] ; L = [vermelho,verde,azul] ; L = [azul,vermelho,verde] ; L = [azul,verde,vermelho] ; L = [verde,vermelho,azul] ; L = [verde,azul,vermelho] ; no
50

Retirar todas as ocorrncias de um elemento em uma lista, modo(+,+,?) : retirar_todas(_, [], []). retirar_todas(Elem, [Elem|Cauda], L):retirar_todas(Elem, Cauda, L). retirar_todas(Elem, [Elem1|Cauda1], [Elem1|Cauda1]) :Elem \== Elem1, retirar_todas(Elem, Cauda, Cauda1). Questes: ?- retirar_todas(a, [c,a, s, a], L). L = [c, s] ; no

Retirar elementos repetidos de uma lista, modo(+,?) : retirar_rep([], []). retirar_rep([Elem|Cauda], [Elem|Cauda1]):retirar_todas(Elem, Cauda, Lista), retirar_rep(Lista, Cauda1). Questes: ?- retirar_rep([a, b, a, b, a, b, a, a, b, a], L). L = [a, b] ; no retirar_rep([a, b, c, d, a, a, a], [a, b, c, d]). yes

51

Insero do elememento em qualquer posio da lista, modo(?,?,+) ou modo(+,+,?) : Inserir_2(Elem, Lista, Lista1) :retirar_elemento(Elem, Lista1, Lista). Questes: modo(+,+,?) ? inserir_2(ana, [pedro, maria], L). L = [ana, pedro, maria] ; L = [ pedro, ana, maria] ; L = [ pedro, maria, ana] ; no modo(?,?,+) : ? inserir_2(X, Y, [1, 2, 3]). X=1 Y = [2, 3] ; X=2 Y = [1, 3] ; X=3 Y = [1, 2] ; no Substituir um elemento em uma lista por outro elemento, modo(?,?,+,?) : substitui(X, Y, [], []). substitui(X, Y, [X|L], [Y|L1]) : - substitui(X, Y, L, L1). substitui(X, Y, [Z|L], [Z|L1]) :- X \== Z, substitui(X, Y, L, L1). Questes: ? substitui(2, 1000, [0, 4, 2, 2],L). L = [0, 4, 1000, 1000] ; no

52

Verificao se uma lista sublista de outra, modo(?,+) : sublista(S, L) :-concatena(L1, L2, L),concatena(S, L3, L2). Questes: ?-sublista(S,[a,b,c]). ?- sublista([c,d,e], [a,b,c,d,e,f]). S=[] ; yes S = [a] ; S = [a,b] ; ?-sublista([c,e],[a,b,c,d,e,f]). S = [a,b,c] ; no S = [b] ; S = [b,c] ; S = [c] ; no Interseco de duas listas em uma terceira, modo(+,?,?) : intersec([X | Y],L,[X | Z]):-pertence(X, L),intersec(Y, L, Z). intersec([_ | X], L, Y):-intersec(X, L, Y). intersec(_, _, [ ]). Questo: ?-intersec([a,b,c,d],[aa,b,d],L). L = [b,d] ; Deslocamento de uma lista para a esquerda, modo(+,?) : desloca([Elem | Cauda], Lista):concatena(Cauda, [Elem], Lista). Questo: ?- desloca([1, 2, 3, 4, 5], L). L = [2, 3, 4, 5, 1]
53

Seleo dos elementos diferentes da 1 lista em relao a 2 lista, armazenando-os em uma lista separada, modo(+,+,?) : diferente([ ],_,[ ]). diferente([X | L1],L2,L):-pertence(X,L2),!, diferente(L1,L2,L). diferente([X | L1],L2,[X | L):-diferente(L1,L2,L). Questo: ?-diferente([a,b,c,d],[b,d,e,f],L). L = [a,c] Diviso de uma lista numrica em duas listas, uma com nmeros positivos outra com negativos, modo(+,?,?) ou modo(?,+,+) : divide([ ], [ ], [ ]). divide([Elem | Cauda], [Elem | Positivos], Negativos):Elem >= 0, ! , divide(Cauda, Positivos, Negativos). divide([Elem | Cauda], Positivos, [Elem | Negativos]):divide(Cauda, Positivos, Negativos). Questo: ?- divide([1, 4, -1, 0, -2, 6], Pos, Neg). Pos = [1, 4, 0, 6] Neg = [-1, -2]

54

Achatar uma lista, modo(+,?) : achatar([], []). achatar([Cab|Caud], ListaA) :eh_lista(Cab), achatar(Cab, CabA), achatar(Caud, CaudA), concatenar(CabA, CaudA, ListaA). achatar([Cab|Caud], [Cab,CaudA]) :- not lista(Cab), achatar(Caud, CaudA). Questes: ? achatar([a, [b, [c, d]],[[e, f, g], h], i], L). L = [a, b, c, d, e, f, g, h, i] ; no Verificar se interseco entre 2 conjuntos no vazia, modo(+,+) : nao_vazia(L1, L2) :- pertence(Elem, L1), pertence(Elem, L2).

Verificar se 2 conjuntos so disjuntos, modo(+,+) : conj_disjuntos(L1, L2) :- not nao_vazia(L1, L2).


Questes: ? conj_disjuntos([a, b, c, d], [d, c, b, a]). no

55

Verificar se 2 conjuntos so iguais, modo(+,+) : conj_iguais([], []). conj_iguais([X|L1], L2) :- del(X, L2, L3), conj_iguais(L1, L3). Questes: ? conj_iguais([a, b, c], [c, b, a]). yes

Unio de 2 conjuntos, modo(+,+,?) : uniao(L1, L2, U) :- concatenar(L1, L2, L3), retirar_rep(L3, U).
Questes: ? uniao([a, b, c], [b, c, d], L). L = [a, b, c, d] ; no

56

Programao Lgica Linguagem PROLOG Fatos, Regras e Controle de Corte Operadores e Listas Entrada e Sada Manipulando Base de Dados Outros Exemplos Metodologia de Programao Lgica Fuzzy Exerccios
57

Entrada e Sada

read(X) Este predicado destina-se leitura de termos do teclado. Todo o termo escrito deve terminar com um ponto ( . ). Este termo pode ser uma palavra isolada, uma lista de letras ou ainda uma string de caracteres. Definio de uma regra para exemplificar o predicado read: oi:-read(X),write(Resposta: ),write(X).

Questes: ?-oi. ola. Resposta: ola yes


?-oi. Ola. Resposta: _00A0 yes % varivel de memria

?- oi. Ola, como vai?. Resposta: Ola, como vai? yes ?- oi. Ola, como vai?. Resposta:[79,108,97,44,32, 99,111,109,111,32, 118,97,105,63] yes %lista de caracteres ASCII
58

write(X) Imprime termos associados a X. So vlidas as mesmas observaes feitas para read. Definio de uma regra quadrado: quadrado:-read(N),Result is N*N,write(Result). Questo: ?-quadrado. (4). 16 yes Definio de uma regra cubo: cubo:-write(Prximo item, por favor: ), read(X), calculocubo(X). Calculocubo(stop):- !. Calculocubo(N):-C is N * N * N, write(Cubo de ),write(N),write( ), write(C),nl,cubo. Questo: ?-cubo. Prximo item, por favor: 5. Cubo de 5 125 Prximo item, por favor: 12. Cubo de 12 1728 Prximo item, por favor: stop. yes

59

tab(X) Escreve uma quantidade X de caracteres espao na sada. Definio de uma regra para exemplificar o predicado tab: escrevetab:-tab(15),write(Soma de 2 Elementos),nl,nl, tab(1),write(Entre com o 1 elemento: ),read(X), tab(1),write(Entre com o 2 elemento: ),read(Y), tab(25),write(________),nl,Total is X+Y, tab(28),write(Total),nl,nl,confirma. confirma:-tab(1),write(Deseja calcular novamente (s/n): ), read(Resp), Resp = s , escrevetab, ! . Questo: ?-escrevetab. Soma de 2 Elementos Entre com o 1 elemento: 123. Entre com o 2 elemento: 456. 579 Deseja calcular novamente (s/n): n.

60

Torre de Hani: hanoi(N):-move(N,a,b,c). move(1,A,_,C):-informa(A,C),!. move(N,A,B,C):N1 is N-1, move(N1,A,C,B), informa(A,C), move(N1,B,A,C). informa(Loc1, Loc2):-write( Move um disco de ) , write(Loc1),write( para ), write(Loc2),nl.

Questo: ?-hanoi(3). Move um disco de a para c Move um disco de a para b Move um disco de c para b Move um disco de a para c Move um disco de b para a Move um disco de b para c Move um disco de a para c yes
61

Criao e Escrita em Arquivo ?- fcreate(arq,'c:\saida.pl',2). yes ?- output(arq). yes ?- hanoi(3). yes ?- fclose(arq). yes Arquivo saida.pl Move o disco de a para c Move o disco de a para b Move o disco de c para b Move o disco de a para c Move o disco de b para a Move o disco de b para c Move o disco de a para c Nota: Caso o arquivo j exista, utilize o comando

fopen(arq,c:\saida.pl,2) no lugar de fcreate(arq,saida.pl,2).

62

Programao Lgica Linguagem PROLOG Fatos, Regras e Controle de Corte Operadores e Listas Entrada e Sada Manipulando Base de Dados Outros Exemplos Metodologia de Programao Lgica Fuzzy Exerccios
63

Manipulando Base de Dados

Definio de uma Base de Dados: gosta(maria, cafe). gosta(jose, cha). gosta(ana, guarana). gosta(pedro, vinho). gosta(jose, coca). gosta(maria, vinho). bagof(X,P,L) Recupera da Base de Dados. L uma lista formada por todo X que satisfaz a condio P. Questes: ?-bagof(X,gosta(X,Y),L). X = _00E4 , % varivel de memria Y = caf , L = [maria] ;

X = _00E4 , Y = cha , L = [jose] ;


X = _00E4 , Y = coca , L = [jose] ;
64

X = _00E4 , Y = guarana , L = [ana] ; X = _00E4 , Y = vinho , L = [pedro, maria] ; no ?-bagof(X,Y^gosta(Y,X),L). %Lista nica X = _00E4 , Y = _00F4 , L = [cafe, cha, guarana, vinho, coca, vinho]

setof(X,P,L) Recupera da Base de Dados. L uma lista ordenada, sem repetio, formada por todo X que satisfaz a condio P. Similar ao predicado bagof. Questo: ?- setof(X, Y^gosta(Y, X), L). X = _00E4 , Y = _00F4 , L = [cafe, cha, coca, guarana, vinho]

65

findall(X,P,L) L uma lista formada por todo X que satisfaz a condio P. A diferena com o bagof que todos os objetos X so coletados mesmo que as variveis em P no sejam parte de X. Definio de uma Base de Dados: pessoa(joao,itau,30). pessoa(jose,nacional,35). pessoa(maria,real,30). Questes: ?- findall(Idade,pessoa(_,_,Idade),Lista). Idade = _0084 , Lista = [30, 35, 30] %Lista com todas as idades ?- findall(Idade/Quem,pessoa(Quem,_,Idade),Lista). Idade = _ , Quem = _ , Lista = [30 / joao,35 / jose,30 / maria] ?- findall(Idade,pessoa(Quem,_,Idade),Lista). Idade = _ , Quem = _ , Lista = [30,35,30] ?-findall(Quem,pessoa(Quem,_,30),Lista). Quem = _0084 , Lista = [joao,maria] %Lista de nomes com 30 anos
66

consult(X) Realiza uma consulta a um determinado Banco de Dados . Consult(X) carrega o contedo do Banco de Dados para a memria. Uma vez carregado o Banco de Dados, os fatos e regras nele contidos podero ser utilizados. Arquivo quad.pl quadrado:read(A), B is A * A, write(B). Questes: ?- consult(c:\quad.pl). yes ?- quadrado. 5. 25 yes

listing(X) Permite a listagem de um determinado predicado que est sendo utilizado. Questo: ?- listing(quadrado). quadrado:read(A), B is A * A, write(B). yes
67

Definio de uma Base de Dados: rapido(ann). lento(tom). lento(pat).


assert Adiciona clusulas na Base de Dados. Questes: ?- assert( ( maisrapido(X, Y):- rapido(X), lento(Y))). X = _0084 , Y = _0098

?- maisrapido(A, B). A = ann , B = tom ;


A = ann , B = pat

asserta e assertz asserta(C) = Adiciona C no comeo da Base de Dados. assertz(C) = Adiciona C no fim da Base de Dados.
68

Questes: ?- assert( p(a) ), assertz( p(b) ), asserta( p(c) ). yes ?- p(X). X=c ; X=a ; X=b retract Remove dados e predicados da Base de Dados em memria. Base de Dados antes da remoo: rapido(ann). lento(tom). lento(pat). Questes: ?- retract( lento(X) ). X = tom ; X = pat ; no ?- maisrapido(A, B). no
69

Programao Lgica Linguagem PROLOG Fatos, Regras e Controle de Corte Operadores e Listas Entrada e Sada Manipulando Base de Dados Outros Exemplos Metodologia de Programao Lgica Fuzzy Exerccios
70

Outros Exemplos

Problema dos Missionrios e Canibais Na margem esquerda de um rio h 5 missionrios e 5 canibais, que querem atravess-lo para a outra margem . H um bote que pode transportar no mximo 3 pessoas ao mesmo tempo. Os missionrios no podem ficar em menor nmero que os canibais em qualquer margem, caso contrrio sero devorados. Como fazer para que todos cheguem a salvo na outra margem do rio?

Resoluo: Consideraremos a seguinte descrio para o conjunto de estados possveis utilizados para representar o problema

(Me, Ce, Bte)

onde,

Me = nmero de missionrios na margem esquerda Ce = nmero de canibais na margem esquerda Bte = 1 se o bote est na margem esquerda, 0 na direita Logo, o estado inicial (5, 5, 1) e o final (0, 0, 0)
71

Representao do Espao de Estados do Problema

(5,5,1) (5,4,0) (5,3,0) (5,4,1) (3,3,0) (4,4,1) (5,1,0) (5,2,1) (2,2,0) (3,3,1) (0,3,0) (0,4,1) (0,1,0) (1,1,1) (0,2,0) (0,3,1) (0,0,0)
72

(5,2,0) (5,3,1)

(4,4,0)

(5,0,0) (5,1,1)

(0,5,1) (0,4,0) (2,2,1) (0,2,1)

O programa prolog que encontra a soluo para este problema usando busca em largura mostrado abaixo. largura([ ],_,_):- write('Soluo no encontrada!'),nl. largura([G|T],_,G):- write('Soluo encontrada!'),nl. largura([S|T],C,G):write('Listas a Percorrer: '),write([S|T]),nl, write('Listas Percorridas: '), write(C),nl, bagof(X,movelargura( S, T, C, X ),Lista), append(T,Lista,O ),!, largura(O, [S|C],G ). largura([S|T],C,G):- largura(T,[S|C],G). movelargura(S,T,C,X):- move(S,X), X \== S, not member(X,T), not member(X,C).

% representao do espao de estados move([5,5,1],[5,2,0]). move([5,5,1],[5,4,0]). move([5,5,1],[4,4,0]). move([5,5,1],[5,3,0]). move([5,2,0],[5,3,1]). move([5,2,0],[5,4,1]). move([4,4,0],[5,4,1]). move([0,1,0],[0,2,1]).
73

move([5,3,0],[5,4,1]). move([5,3,1],[3,3,0]). move([5,3,1],[5,0,0]). move([5,3,1],[5,1,0]). move([5,4,1],[3,3,0]). move([5,4,1],[5,1,0]). move([5,0,0],[5,1,1]). move([5,1,0],[5,2,1]). move([2,2,0],[3,3,1]). move([0,3,0],[0,4,1]). move([0,4,1],[0,2,0]). move([0,5,1],[0,2,0]). move([0,2,0],[2,2,1]).

move([0,1,0],[0,3,1]). move([0,1,0],[1,1,1]). move([0,3,1],[0,0,0]). move([1,1,1],[0,0,0]). move([0,2,1],[0,0,0]). move([5,0,0],[5,2,1]). move([3,3,0],[4,4,1]). move([5,2,1],[2,2,0]). move([3,3,1],[0,3,0]). move([0,3,0],[0,5,1]). move([0,4,1],[0,1,0]). move([0,5,1],[0,4,0]). move([0,2,0],[0,3,1]).

?- largura([[5,5,1]],[ ],[0,0,0]).

Neste caso partiu-se com o Estado Inicial, a Lista dos Percorridos e o Estado Final.

74

Organizao de uma Lista Bubblesort bubblesort(List,Sorted):-swap(List,List1),!, bubblesort(List1,Sorted). bubblesort(Sorted,Sorted). swap([X,Y|Rest],[Y,X|Rest]):-gt(X,Y). swap([Z|Rest],[Z|Rest1]):-swap(Rest,Rest1). gt(X,Y):-X>Y. Questo: ?- bubblesort([9,5,3,8],L). L = [3,5,8,9] Quicksort quicksort([],[]). quicksort([X|Tail],Sorted):-split(X,Tail,Small,Big), quicksort(Small,Sortedsmall),quicksort(Big,Sortedbig), conc(Sortedsmall,[X|Sortedbig],Sorted).
75

split(X,[],[],[]). split(X,[Y|Tail],[Y|Small],Big):-gt(X,Y),!, split(X,Tail,Small,Big). split(X,[Y|Tail],Small,[Y|Big]):-split(X,Tail,Small,Big). conc([],L,L). conc([X|L1],L2,[X|L3]):-conc(L1,L2,L3). gt(X,Y):-X>Y. Questo: ?- quicksort([5,8,0,2,7],L). L = [0,2,5,7,8] ; no Permutation Sort psort(Xs,Ys) :- permutation(Xs,Ys), ordenado(Ys). permutation(Xs,[Z|Zs]) :- select(Z,Xs,Ys), permutation(Ys,Zs). permutation([],[]). ordenado([]). ordenado([X]). ordenado([X,Y|Ys]) :- X <= Y, ordenado([Y|Ys]). Questo: ?- psort([3,4,2,1],Y). Y = [1,2,3,4]
76

Insertion Sort isort([X|Xs],Ys) :- isort(Xs,Zs), insert(X,Zs,Ys). isort([],[]). insert(X,[],[X]). insert(X,[Y|Ys],[Y|Zs]) :- X > Y, insert(X,Ys,Zs). insert(X,[Y|Ys],[X,Y|Ys]) :- X <= Y. Questo: ?- isort([3,2,1],A).

A = [1,2,3]
Investigando um Crime Definio de uma base de dados: possivel_suspeito(fred). possivel_suspeito(mary). possivel_suspeito(jane). possivel_suspeito(george). crime(roubo,john,terca,parque). crime(roubo,robin,quinta,bar). crime(assalto,jim,quarta,bar). estava(fred,terca,parque). inveja(fred,john).
77

principal_suspeito(Pessoa,Crime):crime(Crime,Vitima,Dia,Lugar), possivel_suspeito(Pessoa), estava(Pessoa,Dia,Lugar), tem_motivo_contra(Pessoa,Vitima). principal_suspeito(desconhecido,Crime). tem_motivo_contra(Pessoa,Vitima):inveja(Pessoa,Vitima). Questes: ?- principal_suspeito(Quem,roubo). Quem = fred ; Quem = desconhecido ?- crime(Crime,Vitima,Dia,bar). Crime = roubo , Vitima = robin , Dia = quinta ; Crime = assalto , Vitima = jim , Dia = quarta ;

78

Calculando o M.D.C. de uma Lista de Nmeros Uma das formas de calcularmos o m.d.c de dois nmeros fatorarmos os dois e selecionarmos os fatores primos com os menores expoentes em cada um deles, por exemplo: 18 = 2^1 * 3^2 12 = 2^2 * 3^1

mdc(12, 18) = 2^1 * 3^1 = 6


Outra forma de calcularmos o m.d.c. de dois nmeros seguindo a seguinte regra: 1) Se a diviso do maior nmero pelo menor for exata ento o mdc igual ao menor nmero. 2) Seno o processo repetido usando o menor nmero e o resto da diviso do maior pelo menor. Ex: mdc(18, 12) 18 | 12 01 --06 mdc(12, 06) 12 | 06 12 02 --00

mdc(18, 12) = 6

79

Nosso programa PROLOG utiliza o segundo mtodo com a diferena que o estendemos para uma lista de nmeros e no apenas para dois nmeros:
mdc([A|[]], A) :- !. mdc([A|Calda], N) :- mdc(Calda, B), mdc2(A, B, N), !. mdc2(A, B, B) :- X is A mod B, X is 0, !. mdc2(A, B, N) :- X is A mod B, mdc2(B, X, N).

O predicado mdc possui duas clausulas, a primeira existe para determinarmos qual o mdc de uma lista com apenas um elemento, e a segunda clausula determina o mdc de uma lista com dois ou mais elementos, calculando recursivamente o mdc da calda desta lista e em seguida o mdc da cabeca da lista com o mdc da calda da lista j calculado. As clausulas do predicado mdc2 aplicam os passos 1 e 2 do segundo mtodo mostrado acima. Abaixo mostramos alguns exemplos de execuo do programa:
?- mdc([18,30,12,60], R). R=6 ?- mdc([18,30,10,60], R). R=2 ?- mdc([15,6,12,9], R). R=3 ?- mdc([15,30,20,12], R). R=1 ?- mdc([16,8,32,64], R). R=8

80

O Problema das Damas no Tabuleiro de Xadrez

O enunciado do problema o seguinte: Em um tabuleiro de xadrez, ou de um modo mais geral um tabuleiro de N*N casas, queremos posicionar N damas de modo que nenhuma das damas ataca qualquer outra. A resoluo do problema est diretamente relacionada movimentao exercida pela dama; No jogo de xadrez a dama caminha nas verticais, horizontais e diagonais, deste modo j eliminamos a possibilidade de haver duas ou mais damas numa mesma coluna ou numa mesma linha, restando apenas verificar se todas elas no se atacam nas diagonais. Podemos mapear o problema da seguinte maneira: Para um tabuleiro de N linhas por N colunas colocamos uma dama em cada coluna, cada uma em uma linha diferente da outra e ento comeamos a permutar cada dama de uma certa coluna com cada outra dama de outra coluna, desta forma realizaremos N! permutaes, entre estas permutaes eventualmente encontraremos situaes onde nenhuma dama ataca nenhuma outra, esta situao representa uma soluo. A figura abaixo representa uma das 82 solues encontrada pelo programa PROLOG para um tabuleiro de 8*8 com 8 damas:

?- damas(8,R). R = [1,5,8,6,3,7,2,4]

81

Na figura contamos as linhas de baixo para cima, por exemplo o nmero 5 da resposta corresponde a dama da segunda coluna colocada na quinta linha. A baixo mostramos o cdigo em PROLOG.
damas(NumDamas,Solucao) :- intervalo(1,NumDamas,Lista), permuta(Lista,Solucao), seguro(Solucao). intervalo(A,A,[A]). intervalo(A,B,[A|Calda]) :- A < B, Proximo is A+1, intervalo(Proximo,B,Calda). permuta([],[]). permuta(Lista,[Elemento|Calda]) :retira(Elemento,Lista,NovaLista), permuta(NovaLista,Calda). retira(X,[X|Calda],Calda). retira(X,[Y|Calda],[Y|NovaCalda]) :- retira(X,Calda,NovaCalda). seguro([]). seguro([Cabeca|Calda]) :- seguro(Calda), not ataca(Cabeca,Calda). ataca(Cabeca,Calda) :- ataca(Cabeca,1,Calda). ataca(X,Distancia,[Y|Calda]) :- X is Y+Distancia; X is Y-Distancia. ataca(X,Distancia,[Y|Calda]) :- N1 is Distancia+1, ataca(X,N1,Calda).

O predicado damas composto de dois argumentos NumDamas (nmero de damas) e Solucao (lista que contm a soluo), e dos predicados intervalo (que cria uma lista do tipo [1, 2 ,3 , 4 ,5 ,6 ,7 ,8]), permuta (que realiza todas as permutaes na lista que criamos) e seguro (que testa se uma dada situao gerada a partir de uma permutao uma situao aceitvel, ou seja nenhuma dama ataca nenhuma outra).
82

Calculando Nmeros Primos Os nmeros primos so aqueles divisveis por si e pelo nmero um, desta forma poderamos determinar se um nmero primo dividindo-o por todos os nmeros anteriores a ele e contando quantos nmeros conseguiram dividi-lo sem deixar resto. Este processo seria muito demorado, principalmente se desejssemos calcular uma lista de nmeros primos. Podemos resolver este problema de uma maneira diferente: 1) Criamos uma lista de nmeros consecutivos que comea em 2 e vai at o maior nmero do intervalo no qual queremos encontrar os nmeros primos. 2) Pegamos o primeiro nmero da lista e cortamos todos os seus mltiplos. 3) Repetimos o processo para cada novo elemento na lista. No final do processo a lista restante contm apenas elementos que no possuem divisores diferente do nmero 1, ou seja, apenas nmeros primos. A figura seguir ilustra o processo para os nmeros de 2 a 100.

83

O cdigo PROLOG mostrado a seguir:


primos(Limite, Primos) :- geraLista(2, Limite, Lista), geraPrimos(Lista, Primos). geraLista(Menor, Maior, [Menor|Lista]) :- Menor =< Maior, N is Menor+1, geraLista(N, Maior, Lista), !. geraLista(_, _, []). geraPrimos([], []) :- !. geraPrimos([Primo|Lista], [Primo|MaisPrimos]) :removeMultiplos(Primo, Lista, NovaLista), geraPrimos(NovaLista, MaisPrimos). removeMultiplos(Num, [], []) :- !. removeMultiplos(Num, [Cabeca|Lista], [Cabeca|NovaLista]) :not(0 is Cabeca mod Num), removeMultiplos(Num, Lista, NovaLista), !. removeMultiplos(Num, [Cabeca|Lista], NovaLista) :0 is Cabeca mod Num, removeMultiplos(Num, Lista, NovaLista).

O predicado removeMultiplos gera uma lista que possui apenas nmeros que no so mltiplos de um certo nmero dado. O predicado geraLista constri uma lista com todos os nmeros entre um nmero menor e um maior. O predicado geraPrimos pega o primeiro nmero de uma lista e arranca todos os mltiplos deste elemento, ento pega a esta nova lista e repete o processo. O predicado primos gera uma lista inicialmente com todos os nmeros num intervalo dado e aps isto chama o predicado geraPrimos. A seguir mostramos uma execuo:
?- primo(100,L). L = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73, 79,83,89,97]
84

Encontrando o Menor Caminho Entre Duas Cidades Quando desejamos encontrar o menor caminho entre duas cidades devemos primeiramente conhecer todos os caminhos que nos levam da cidade origem at a cidade destino, para isso devemos montar um grafo onde os ns so as cidades e os arcos so as distncias entre uma cidade e outra. O grafo abaixo representa um exemplo:

Nosso programa PROLOG deve encontrar todos os caminhos possveis entre a cidade origem e a cidade destino e escolher aquele cuja a soma das distncias correspondesnte s viagens de uma cidade para outra a menor. O programa o seguinte:
distancia(a, d, 200). distancia(a, e, 500). distancia(b, e, 100). distancia(b, f, 100). distancia(d, e, 100). distancia(e, g, 300). distancia(f, i, 100). distancia(g, h, 300). vizinho(X, Y, Dist) :- distancia(X, Y, Dist). vizinho(X, Y, Dist) :- distancia(Y, X, Dist). pertence(X, [X|_]). pertence(X, [_|L]) :- pertence(X,L). distancia(b, c, 100). distancia(c, f, 100). distancia(e, i, 400). distancia(h, i, 200).

85

caminho(Origem, Origem, _, [], 0). caminho(Origem, Destino, CidadesVisitadas, [Intermediario|Caminho], Distancia) :vizinho(Origem, Intermediario, Dist1), not(pertence(Intermediario, CidadesVisitadas)), caminho(Intermediario, Destino, [Intermediario|CidadesVisitadas], Caminho, Dist2), Distancia is Dist1 + Dist2. primeiro([[Caminho,Distancia]|Lista], Caminho, Distancia). resolve(Origem, Destino, [Origem|Caminho], Distancia) :bagof([Camin,Dist], caminho(Origem, Destino, [Origem], Camin, Dist), Lista), sort(Lista,ListaOrdenada,[2]), primeiro(ListaOrdenada, Caminho, Distancia).

O predicado distancia determina as distncias entre as cidades, o predicado vizinho determina que se uma cidade dista x de outra ento esta segunda dista x da primeira, o predicado pertence determina se uma elemento j pertence a uma lista ou no (no nosso caso se uma cidade j pertence a uma lista de cidades), o predicado caminho encontra o caminho de uma cidade at outra bem como a distncia total do percurso, o predicado primeiro pega o primeiro elemento de uma lista e o predicado resolve o responsvel por pegar todos os caminhos encontrados e escolher o de menor distncia. A seguir mostramos um exemplo para o grafo anterior:
?- resolve(a, h, Caminho, Distancia). Caminho = [a,d,e,b,f,i,h] , Distancia = 800
86

Busca em Largura em rvore Binria Freqentemente necessitamos realizar buscas em rvores para solucionar problemas, como por exemplo quando queremos verificar todos os estados de um jogo de dama para chegar a uma posio vitoriosa. O backtracking de PROLOG nos permite realizar buscas em profundidade com certa facilidade, no entanto, para alguns problemas necessitamos realizar buscas em largura, o que no uma tarefa to simples. A busca feita da seguinte forma: 1) Coloca-se o n raiz em uma lista 2) Expande-se (gera-se todos os seus filhos) o primeiro elemento da lista e coloca-se o resultado no final da lista 3) Repete-se o processo para o segundo da lista, terceiro da lista, etc..., at que no haja mais elementos para expandir. No final teremos uma lista de ns cuja ordem a ordem da busca em largura. A figura abaixo mostra uma rvore exemplo e os passos do processo descrito acima.

87

O cdigo PROLOG mostrado a seguir:


buscaLargura([], []). buscaLargura([tree(No, Esq, Dir)|Calda], [No|Resultado]) :bagof(X, filho(tree(No, Esq, Dir), X), Lista), append(Calda, Lista, NovaLista), buscaLargura(NovaLista, Resultado), !. buscaLargura([tree(No, Esq, Dir)|Calda], [No|Resultado]) :buscaLargura(Calda, Resultado), !. filho(tree(No, Esq, Dir), Esq) :- Esq \== null. filho(tree(No, Esq, Dir), Dir) :- Dir \== null.

O predicado buscaLargura realiza o processo de expandir o primeiro n da lista, criar uma nova lista que contm tambm os ns expandidos e repetir o processo para cada n sucessivo da lista. O predicado filho usado para retornar cada filho de um certo n. A seguir mostramos a execuo:
?- buscaLargura( [tree(3, tree(1, null, tree(2, null, null)), tree(7, tree(5, tree(4, null, null), tree(6, null, null)), tree(8, null, null)))],R). R = [3,1,7,2,5,8,4,6]

88

Verificao de rvores AVL Neste exemplo mostraremos como verificar se uma dada rvore uma rvore AVL. rvores AVL so rvores binrias de busca que possuem altura mnima, ou seja, em uma rvore de N ns a distncia mxima da raiz a qualquer folha no mximo log(N). rvores de altura mnima so chamadas rvores balanceadas. Portanto devemos verificar duas condies: 1)A rvore binria deve ser uma rvore de busca. 2)A rvore binria deve estar balanceada. Dizemos que uma rvore binria de busca se todos os elementos da subrvore esquerda de qualquer n so menores que este n e todos os elementos da subrvore direita de qualquer n so maiores que este n. Dizemos que uma rvore balanceada se a diferena de altura da subrvore esquerda para a subrvore direita no exceder em mdulo a unidade. Desta forma o teste de rvores AVL fica como mostrado a seguir:
ehAVL(Arvore) :- arvoreBusca(Arvore), balanceada(Arvore). arvoreBusca(null). arvoreBusca(tree(Raiz, ArvoreEsq, ArvoreDir)) :- maior(Raiz, ArvoreEsq), menor(Raiz, ArvoreDir). maior(_, null). maior(Maior, tree(Raiz, ArvoreEsq, ArvoreDir)) :- Maior > Raiz, maior(Raiz, ArvoreEsq), menor(Raiz, ArvoreDir), maior(Maior, ArvoreDir).
89

menor(_, null). menor(Maior, tree(Raiz, ArvoreEsq, ArvoreDir)) :Maior < Raiz, maior(Raiz, ArvoreEsq), menor(Raiz, ArvoreDir), menor(Maior, ArvoreEsq). balanceada(null). balanceada(tree(_, ArvoreEsq, ArvoreDir)) :balanceada(ArvoreEsq), balanceada(ArvoreDir), altura(ArvoreEsq, HE), altura(ArvoreDir, HD), DIF is HE - HD, abs(DIF) =< 1. altura(null, 0). altura(tree(_, ArvoreEsq, ArvoreDir), Altura) :altura(ArvoreEsq, HE), altura(ArvoreDir, HD), Altura is max(HE, HD) + 1.

Na chamada ao predicado ehAVL devemos passar uma estrutura de rvore como a mostrada nos exemplos a seguir:
?- ehAVL(tree(3, tree(1, null, tree(2, null, null)), tree(7, tree(5, tree(4, null, null), tree(6, null, null)), tree(8, null, null)))). yes ?- ehAVL(tree(3, tree(1, null, tree(2, null, null)), tree(7, tree(5, tree(0, null, null), tree(6, null, null)), tree(8, null, null)))). no ?- ehAVL(tree(3, tree(1, null, tree(2, null, null)), tree(7, tree(5, tree(4, null, null), tree(6, null, null)), null))). no

90

Reconhecendo Cadeias de Smbolos Atravs de MEFs Mquinas de Estados Finita (MEF) podem ser representadas de modo simplificado por um conjunto de estados e um conjunto de transies de estados, alm dos estados finais e do estado inicial. Freqentemente desejamos verificar se uma certa cadeia de smbolos pertence a linguagem determinada por uma MEF, para isso devemos aplicar uma seqncia de transies correspondentes aos smbolos dessa seqncia que nos levaro de um estado inicial a um estado final. Caso o estado final pertena ao conjunto de estados finais dizemos que a seqncia de entrada pertence a linguagem determinada pela MEF. Existem ainda MEFs que possuem transies de um determinado estado para mais de um estado, estas MEFs so chamadas MEF indeterminsticas (MEF_ind), diferentemente da primeira conhecida como MEF determinstica (MEF_det). Quando trabalhamos com MEFs_ind devemos ser capazes de determinar qual o conjunto de estados resultante da aplicao de uma transio sobre vrios estados da MEF e no apenas um nico estado resultante da aplicao de uma nica transio sobre um nico estado. O programa que implementamos em PROLOG aceita MEFs_ind embora o exemplo escolhido represente uma MEF_det.
terminal(q8). transicao(q0, a, q3). transicao(q1, b, q2). transicao(q3, b, q4). transicao(q5, a, q8). transicao(q7, a, q4).

transicao(q0, b, q1). transicao(q2, a, q5). transicao(q4, a, q7). transicao(q6, a, q3). transicao(q7, b, q8).

transicao(q1, a, q4). transicao(q3, a, q6). transicao(q4, b, q5). transicao(q6, b, q7). transicao(q8, a, q5).
91

verifica(Estados, Entradas, []) :- aplicaTransicoes(Estados, Entradas, []), write('Nao ha transicao prevista, a MEF para: '), !. verifica(Estados, Entradas, Resposta) :aplicaTransicoes(Estados, Entradas, Resposta), temTerminal(Resposta), write('Sequencia valida: '), !. verifica(Estados, Entradas, Resposta) :aplicaTransicoes(Estados, Entradas, Resposta), write('Sequencia invalida: '), !. aplicaTransicoes([], Entradas, []) :- !. aplicaTransicoes([Estado|[]], [], [Estado]) :- !. aplicaTransicoes([Estado|[]], [Entrada|Sequencia], EstadosFinais) :- transicoes(Estado, Entrada, ListaEstados), aplicaTransicoes(ListaEstados, Sequencia, EstadosFinais), !. aplicaTransicoes([Estado|MaisEstados], Entradas, EstadosFinais) :- aplicaTransicoes([Estado], Entradas, ListaA), aplicaTransicoes(MaisEstados, Entradas, ListaB), uniao(ListaA, ListaB, EstadosFinais). temTerminal([Estado|_]) :- terminal(Estado), !. temTerminal([_|Estados]) :- temTerminal(Estados). transicoes(Estado, Entrada, ListaEstados) :bagof(NovoEstado, transicao(Estado, Entrada, NovoEstado), ListaEstados), !. transicoes(Estado, Entrada, []). uniao([], [], []) :- !. uniao([], Lista, NovaLista) :- tiraRepetidos(Lista, NovaLista), !. uniao(Lista, [], NovaLista) :- tiraRepetidos(Lista, NovaLista), !. uniao([Elem|ListaA], ListaB, NovaLista) :- pertence(Elem, ListaB), uniao(ListaA, ListaB, NovaLista), !. uniao([Elem|ListaA], ListaB, NovaLista) :- pertence(Elem, ListaA), uniao(ListaA, ListaB, NovaLista), !. uniao([Elem|ListaA], ListaB, [Elem|NovaLista]) :- uniao(ListaA, ListaB, NovaLista). tiraRepetidos([], []) :- !.
92

tiraRepetidos([Elem|[]], [Elem]) :- !. tiraRepetidos([Elem|Calda], Saida) :- pertence(Elem, Calda), tiraRepetidos(Calda, Saida), !. tiraRepetidos([Elem|Calda], [Elem|Saida]) :tiraRepetidos(Calda, Saida). pertence(Elem, [Elem|_]) :- !. pertence(Elem, [_|Lista]) :- pertence(Elem, Lista).

Os fatos terminal e transicao determinam a estrutura da MEF (estados, transies e estado final). O predicado verifica possui trs argumentos: uma lista de estados, uma lista representando a seqncia de smbolos de entrada e uma lista de estados finais da MEF correspondente s transies realizadas aps a verificao. No processo de verificao devemos aplicar transies correspondentes aos smbolos de entrada, esta tarefa realizada pelo predicado aplicaTransicoes, neste predicado encontramos um conjunto de estados resultantes das transies correspondentes a uma determinada entrada e repetimos este processo at que se esgotem os smbolos de entrada. No final do processo de aplicao de transies teremos duas listas com estados finais da MEF (uma gerada a partir do primeiro estado da lista de estados e outra gerada a partir dos estados restantes). Devemos agora unir estas duas listas em uma (tarefa realizada pelo predicado uniao) retirando as possveis repeties de estados atravs do predicado tiraRepetidos. Por fim determinamos se o conjunto de estados finais possui ao menos um elemento terminal, esta tarefa realizada pelo predicado temTerminal. A estrutura da MEF mostrada na figura abaixo e aceita as cadeias de as e bs que possuem nmero par de as (2, 4, ..) e exatamente 2 bs em qualquer ordem.
93

Representao grfica da MEF

Algumas possveis execues seriam:


?- verifica([q0], [a,b,a,a,b,a,a,a], R). Sequencia valida: R = [q8] ?- verifica([q0], [b,a,a,b,b,a,a], R). Nao ha transicao prevista, a MEF para: R = [] ?- verifica([q0], [a,b,a,a], R). Sequencia invalida: R = [q4]

Poderiamos ainda iniciar a MEF a partir de mais de um estado como por exemplo q0 e q4, isso acarretaria no reconhecimento de seqncias com um nico b e um nmero impar de as (1, 3, ...) alm das seqncias reconhecidas anteriormente a partir de q0.
?- verifica([q0,q4], [a,b,a,a], R). Sequencia valida: R = [q4,q8] ?- verifica([q0,q4], [a,b,b,a,a], R). Sequencia invalida: R = [q5] ?- verifica([q0,q4], [a,a,b,b,a,a], R). Sequencia valida: R = [q8]

94

O Problema das Jarras Dgua O problema das jarras dgua tradicional consiste de duas jarras de capacidades 3 e 5 litros (inicialmente vazias) e uma fonte dgua para encher as jarras. O objetivo do problema deixar 4 litros na jarra de capacidade 5 litros, para isso podemos realizar as seguintes aes: encher uma jarra, esvaziar uma jarra ou despejar o contedo de uma jarra na outra. Poderamos representar a seqncia de transies que nos conduzem resposta representando os estados das jarras (atravs de pares) entre cada ao tomada. A soluo seria a seguinte: (0,0), (0,5), (3,2), (0,2), (2,0), (2,5), (3,4). Outra maneira de representarmos a soluo seria reportando a seqncia de passos a serem tomados: encher a 2o. jarra, virar a 2o. jarra na 1o., esvaziar a 1o. jarra, virar a 2o. jarra na 1o., encher a 2o. jarra, virar a 2o. jarra na primeira.

Esquema das transies que levam o estado inicial a um estado final

95

O problema que mostramos a seguir estende o problema tradicional das jarras dgua para qualquer nmero de jarras, com qualquer configurao inicial, qualquer capacidade e qualquer configurao final da jarras. Alm disso impomos um limite de transies para alcanarmos o estado final, isto significa que eventualmente podemos no encontrar uma soluo, no porque esta soluo no existe, mas sim porque ela necessita de mais transies do que o limite que colocamos.
move(JarraA, CapacA, JarraB, CapacB, NovoA, NovoB) :NovoA is CapacA, NovoB is JarraB, JarraA\=CapacA. move(JarraA, CapacA, JarraB, CapacB, NovoA, NovoB) :NovoA is 0, NovoB is JarraB, JarraA\=0. move(JarraA, CapacA, JarraB, CapacB, NovoA, NovoB) :NovoA is 0, NovoB is JarraA+JarraB, NovoB<CapacB, JarraA\=0. move(JarraA, CapacA, JarraB, CapacB, NovoA, NovoB) :NovoA is JarraA-(CapacB-JarraB), NovoB is CapacB, CapacB-JarraB=<JarraA, JarraB\=CapacB. altera([Cabeca|Calda], 0, Valor, [Valor|Calda]). altera([Cabeca|Calda], Posicao, Valor, [Cabeca|NovaCalda]) :NovaPosicao is Posicao-1, altera(Calda, NovaPosicao, Valor, NovaCalda). pegaItem([Cabeca|Calda], Cabeca, 0). pegaItem([_|Calda], Elemento, NovoContador) :pegaItem(Calda, Elemento, Contador), NovoContador is Contador+1. pegaJarra(Configuracao, Jarra, Posicao) :pegaItem(Configuracao, Jarra, Posicao). pegaCapacidade(Capacidades, Capac, Posicao) :pegaItem(Capacidades, Capac, Posicao). pertence(X, [X|_]) :- !. pertence(X, [_|Z]) :- pertence(X, Z).
96

transicao(ConfFinal, ConfFinal, Capacidades, Lista, Contador) :- reverse(Lista, NovaLista), write(NovaLista), !. transicao(ConfInicial, ConfFinal, Capacidades, Lista, Contador) :- Contador>0, NovoContador is Contador-1, pegaJarra(ConfInicial, JarraA, PosicaoA), pegaCapacidade(Capacidades, CapacA, PosicaoA), pegaJarra(ConfInicial, JarraB, PosicaoB), pegaCapacidade(Capacidades, CapacB, PosicaoB), PosicaoA\=PosicaoB, move(JarraA, CapacA, JarraB, CapacB, NovoA, NovoB), altera(ConfInicial, PosicaoA, NovoA, ConfTemp), altera(ConfTemp, PosicaoB, NovoB, NovaConf), not(pertence(NovaConf, Lista)), transicao(NovaConf, ConfFinal, Capacidades, [NovaConf|Lista], NovoContador), !. resolve(Inicial, Final, Capacidade, Contador) :caminho(Inicial, Final, Capacidade, [Inicial], Contador).

Os predicados move representam as transies que podemos realizar entre duas jarras: encher, esvaziar e virar uma em outra (virando at encher ou virando todo o contedo). O predicado altera recebe uma lista, uma posio e um valor e retorna uma nova lista igual, exceto na posio recebida, onde o valor ser alterado para o valor recebido. O predicado pegaItem recebe uma lista e devolve um valor e sua posio correspondente na lista, caso a posio j esteja definida pegaItem retorna apenas o valor associado posio. Os predicados pegaJarra e pegaCapacidade apesar de possurem nomes diferentes realizam a mesma tarefa, selecionam um valor e uma posio em uma lista dada.

97

O predicado transicao o corao do algoritmo, no primeiro predicado representamos um estado soluo, ou seja, a configurao atual do problema igual a configurao final do problema. Neste caso mostramos na tela a seqncia de estados que representam a soluo. No segundo predicado, primeiramente testamos e decrementamos um contador para que possamos garantir que no iremos procurar solues que possuam mais que um determinado nmero de transies, aps isso selecionamos duas jarras (na verdade todas as combinaes de duas jarras) e suas respectivas capacidades, ento conferimos se no pegamos duas vezes a mesma jarra. Caso no tenhamos pego, criamos uma nova lista parecida com a lista que possui a configurao atual, mas com os contedos das duas jarras alterados, aps isso verificamos se a nova configurao que construmos no um estado que j faz parte de nossa lista de transies. Caso afirmativo, continuamos o processo procurando agora chegar configurao final partir do novo estado que geramos (com a possibilidade de realizarmos uma transio a menos e com um estado a mais na lista de estados que constituem o caminho soluo). O predicado resolve recebe uma lista que representa a configurao inicial das jarras, uma lista que representa o estado final, uma lista que representa a capacidade das jarras e o nmero mximo de transies que desejamos realizar. A seguir mostramos algumas execues.
?- resolve( [0,1,2], [2,2,4], [2,3,5], 4 ). [ [0,1,2], [1,0,2], [1,2,0], [1,2,5], [2,2,4] ] yes ?- resolve( [3,4], [1,0], [5,7], 4 ). no
98

Note que no ltimo exemplo no conseguimos encontrar uma soluo com 4 transies ou menos. No entanto, se estipularmos 5 transies o problema j passa a ser solvel.
?- resolve( [3,4], [1,0], [5,7], 5 ). [ [3,4], [3,0], [0,3], [5,3], [1,7], [1,0] ] yes

Outro aspecto importante do problema que podemos omitir partes do estado soluo quando no estamos interessados em alguma jarra em especfico:
?- resolve( [0,1], [3,2], [6,4], 10 ). no ?- resolve( [0,1], [3,_], [6,4], 5 ). [ [0,1], [6,1], [3,4] ] yes

Tambm podemos estabelecer relaes de igualdade entre os contedos finais das jarras:
?- resolve( [1,1,3,2], [X,2,X,1], [2,4,5,3], 3 ). [ [1,1,3,2], [0,2,3,2], [0,2,2,3], [2,2,2,1] ] X = 2

99

O Problema da Colorao de Mapas

Quando estamos colorindo um mapa queremos que cada pas, ou estado, possua uma cor diferente de qualquer um de seus vizinhos para que possa ser bem delimitado. Matematicamente est provado que em um plano no podemos interconectar totalmente mais que 4 elementos, ou seja, teremos no mximo 4 pases que fazem fronteira um com o outro sem possibilidade de repetirmos cores. Se inserirmos um quinto pas, onde quer que seja, haver sempre uma cor que j usamos e assim poderemos repeti-la. Desta forma nosso programa de colorao de mapas necessita apenas 4 cores. Uma das diversas resolues a que se segue:
1) Definimos os pases e as fronteiras entre eles. 2) Escolhemos um pas e damos uma cor a ele temporariamente. 3) Preenchemos os seus vizinhos com as cores restantes, tambm temporariamente. 4) Pegamos outro pas e repetimos o processo. 5) Caso no seja possvel distribuir as cores para o pas e seus vizinhos, voltamos no Backtracking de PROLOG e escolhemos outras combinaes de cores. OBS: Como sempre pintamos um pas com uma cor e os vizinhos com as restantes, sempre que conseguirmos pintar o ltimo pas teremos certeza que ele no tem a mesma cor que nenhum de seus vizinhos, e portanto todos ou outros pases j esto pintados corretamente. O cdigo PROLOG o seguinte:
cores([vermelho, amarelo, azul, verde]).
100

mapa([ fronteira(paisA, A, [B, C, D, F]), fronteira(paisB, B, [A, C, D, E, F]), fronteira(paisC, C, [A, B, D]), fronteira(paisD, D, [A, B, C, E, F]), fronteira(paisE, E, [B, D, F]), fronteira(paisF, F, [A, B, D, E]) ] ). pintaMapa(Solucao) :- mapa(Solucao), coloreMapa(Solucao). coloreMapa([Pais|PaisesRestantes]) :- coloreRegiao(Pais), coloreMapa(PaisesRestantes). coloreMapa([]). coloreRegiao(fronteira(Pais, Cor, Vizinhos)) :- cores(Cores), seleciona(Cor, Cores, CoresRestantes), preenche(Vizinhos, CoresRestantes). seleciona(Elem, [Elem|Calda], Calda). seleciona(Elem, [ElemDifer|Calda], [ElemDifer|NovaLista]) :seleciona(Elem, Calda, NovaLista). preenche([Elem|Calda], Lista) :- member(Elem, Lista), preenche(Calda, Lista). preenche([], Lista).

O predicado mapa possui informaes sobre os nomes dos pases, suas cores e as cores de seus vizinhos, servindo com uma base de dados de pases. Note que a cor de cada pas bem como a cor de seus vizinhos so representadas por variveis (letras maisculas), isto , no esto instanciadas e portanto podero assumir diversos valores durante a execuo do programa. O predicado pintaMapa l este mapa que definimos e o colore. O predicado coloreMapa pega o primeiro pas e atribui uma cor a ele e aos seus vizinhos, aps isso repete o processo aos pases restantes. O predicado coloreRegiao seleciona uma cor para um pas e utiliza as cores restantes para preencher os pases restantes.
101

O predicado seleciona pega uma cor entre as 4 cores e retorna uma lista com as cores restantes, e o predicado preenche atribui cores aos pases no permitindo que um pas possua uma cor diferente das cores passadas no segundo argumento deste predicado. A sada do programa contm os nomes dos pases, suas respectivas cores e a listas de cores correspondentes aos pases vizinhos. Note que para cada sada do programa a cor do pas nunca pertence a sua lista de cores de pases vizinhos. A seguir mostramos 3 dos 24 modos diferentes de colorir o mapa do nosso exemplo, e um mapa ilustrativo para cada caso.
?- pintaMapa(R). R = [ regiao(paisA, vermelho, [amarelo, azul, verde, azul]), regiao(paisB, amarelo, [vermelho, azul, verde, vermelho, azul]), regiao(paisC, azul, [vermelho, amarelo, verde]), regiao(paisD, verde, [vermelho, amarelo, azul, vermelho, azul]), regiao(paisE, vermelho, [amarelo, verde, azul]), regiao(paisF, azul, [vermelho, amarelo, verde, vermelho]) ] ;

R = [ regiao(paisA, amarelo, [azul, verde, vermelho, verde]), regiao(paisB, azul, [amarelo, verde, vermelho, amarelo, verde]), regiao(paisC, verde, [amarelo, azul, vermelho]), regiao(paisD, vermelho, [amarelo, azul, verde, amarelo, verde]), regiao(paisE, amarelo, [azul, vermelho, verde]), regiao(paisF, verde, [amarelo, azul, vermelho, amarelo]) ] ;
102

R = [ regiao(paisA, verde ,[amarelo, vermelho, azul, vermelho]), regiao(paisB, amarelo ,[verde, vermelho, azul, verde, vermelho]), regiao(paisC, vermelho, [verde, amarelo, azul]), regiao(paisD, azul, [verde, amarelo, vermelho, verde, vermelho]), regiao(paisE, verde, [amarelo, azul, vermelho]), regiao(paisF, vermelho, [verde, amarelo, azul, verde]) ] ;

103

Sistema Especialista no Planejamento Empresarial Os sistemas especialistas so aplicaes computacionais capazes de simular o comportamento de um especialista humano, em um determinado assunto, a fim de descobrir ou resolver um determinado problema. Os sistemas especialistas esto presentes em vrios ramos da computao como: OCRs, reconhecimento de voz, diagnstico mdico, jogo de xadrez, sistema de computao de bordo de carros, sistema de controle de robs, etc. Nosso exemplo de sistema especialista identifica alguns dos vrios problemas que uma empresa tem que resolver do ponto de vista estratgico. No exemplo colhemos do usurio informaes sobre o estado da empresa bem como as condies gerais do mercado e, atravs destas informaes, inferimos outras coisas (assim como um especialista humano faria). As informaes que colhemos devem estar relacionadas, ou encadeadas, de forma a podermos construir grafos de causa-conseqncia. O grafo abaixo representa trs possveis problemas que devemos verificar e seus relacionamentos de causa-conseqncia.

104

Podemos dizer por exemplo que se: Funcionarios fazem hora-extra frequentemente for verdadeiro e Projetos estao atrasados for verdadeiro ento conclumos (inferimos) que Servico esta sobrecarregado verdadeiro. Nosso programa deve verificar cada um dos trs problemas que representamos fazendo perguntas quando necessrio (texto em preto), tirando concluses (texto em azul) e identificando o problema (texto em vermelho). O cdigo PROLOG o seguinte:
conclusao(Ha necessidade de contratar pessoal, [[Servico esta sobrecarregado, 1], [As vendas aumentaram, 1], [Nivel de informatizacao e bom, 1]]). conclusao(Ha necessidade de informatizar o setor, [[Servico esta sobrecarregado, 1], [As vendas aumentaram, 1], [Nivel de informatizacao e bom, 0]]). conclusao(Ha necessidade de terceirizar o servico, [[Ha viabilidade em terceirizar o servico, 1], [Determinado servico esta custando caro para a empresa, 1], [Investir em tecnologia ao inves de terceirizar o servico nao e viavel, 1]]). regra(Servico esta sobrecarregado, [[Funcionarios fazem horaextra frequentemente, 1], [Projetos estao atrasados, 1]]). regra(Nivel de informatizacao e bom, [[Hardware e software estao atualizados, 1], [Numero de computadores e satisfatorio, 1]]). regra(Ha viabilidade em terceirizar o servico, [[Existe uma empresa especializada no servico a ser terceirizado, 1], [Transporte e comunicacao com a empresa de terceirizacao e caro, 0], [O servico da empresa de terceirizacao e caro, 0]]). regra(Investir em tecnologia ao inves de terceirizar o servico nao e viavel, [[Novas tecnologias para o setor a ser terceirizado sao caras, 1], [Pesquisa com os funcionarios aponta rejeicao com a tecnologia da empresa de terceirizacao, 1]]). 105

pergunta(Frase, Resposta) :- write(Frase), display(' ? (s ou n) : '), read(SimOuNao), trata_resposta(Frase, SimOuNao, Resposta). trata_resposta(Frase, s, 1) :- assert(fato(Frase, 1)), !. trata_resposta(Frase, _, 0) :- assert(fato(Frase, 0)). conhecido(Frase) :- fato(Frase, _). nao_perguntavel(Frase) :- conclusao(Frase, _). nao_perguntavel(Frase) :- regra(Frase, _). calcula_regra([], 1) :- !. calcula_regra([[Frase, Esperado]|Calda], Resultado) :fato(Frase, Esperado), calcula_regra(Calda, Resultado), !. calcula_regra([[Frase, Esperado]|Calda], Resultado) :regra(Frase, Condicoes), calcula_regra(Condicoes, PreResultado), Esperado==PreResultado, calcula_regra(Calda, Resultado), !. calcula_regra([[Frase, Esperado]|Calda], Resultado) :not(conhecido(Frase)), not(nao_perguntavel(Frase)), pergunta(Frase, PreResultado), Esperado==PreResultado, calcula_regra(Calda, Resultado), !. calcula_regra(_, 0). resolve(Problema) :- retractall(fato(_, _)), conclusao(Problema, Condicoes), calcula_regra(Condicoes, 1), !. resolve('No consegui chegar a nenhuma concluso') :- !.

O predicado conclusao relaciona as informaes que podemos inferir para chegar a uma concluso final do problema bem como os fatores que determinam esta inferncia. O predicado regra relaciona todos as informaes que podemos inferir, exceto as inferncias que nos levam a uma concluso. O predicado pergunta utilizado quando precisamos de uma informao mas no a temos, neste caso, o predicado pergunta l a resposta do usurio e trata esta resposta.
106

O predicado trata_resposta utiliza a predicado assert de PROLOG para inserir uma nova clausula chamada fato em tempo de execuo, esta clausula fato relaciona uma pergunta e uma resposta dada pelo usurio. O predicado conhecido verifica se j existe um fato (uma resposta do usurio) relacionado a uma determinada pergunta. O predicado nao_perguntavel verifica se uma certa pergunta no do tipo que o usurio pode responder, ou seja, se ela no uma pergunta e sim o resultado de uma inferncia. O predicado calcula_regra retorna o valor de uma certa inferncia feita atravs de um fato existente, do processamento de outras regras ou de uma pergunta ao usurio. O predicado resolve busca cada um dos problemas possveis e verifica se algum est ocorrendo. A seguir algumas execues do programa:
?- resolve(Problema). Funcionarios fazem hora-extra frequentemente ? (s ou n) : ? s. Projetos estao atrasados ? (s ou n) : ? s. As vendas aumentaram ? (s ou n) : ? s. Hardware e software estao atualizados ? (s ou n) : ? s. Numero de computadores e satisfatorio ? (s ou n) : ? n. Problema = 'Ha necessidade de informatizar o setor

Podemos verificar tambm se um determinado problema est ocorrendo, a resposta ser ento do tipo yes ou no.
?- resolve('Ha necessidade de terceirizar o servico'). Existe uma empresa especializada no servico a ser terceirizado ? (s ou n) : ? s. Transporte e comunicacao com a empresa de terceirizacao e caro ? (s ou n) : ? n. O servico da empresa de terceirizacao e caro ? (s ou n) : ? s. no 107

Programao Lgica Linguagem PROLOG Fatos, Regras e Controle de Corte Operadores e Listas Entrada e Sada Manipulando Base de Dados Outros Exemplos Metodologia de Programao Lgica Fuzzy Exerccios
108

Metodologia de Programao

Critrios de Qualidade de Programao

Para o desenvolvimento de Programas Procedimentais Convencionais de boa qualidade diversos critrios de Engenharia de Software devem ser observados, assim como tcnicas e prticas;
Para um bom estilo de programao em Prolog esses critrios tambm devem ser observados. Cabe salientar que os critrios de Correo e Eficincia so os mais importantes para a construo de programas de boa qualidade. Princpios Gerais de uma Boa Programao Critrios de avaliao: Correo; Eficincia; Transparncia e Legibilidade; Modificabilidade; Robustez; Documentao;
109

A importncia de cada critrio vai depender do problema e das circunstncias em que o programa desenvolvido, e do ambiente em que ser utilizado (o critrio mais importante sem dvida o da correo); Uma das regras gerais para se atingir esses critrios primeiro pensar sobre o problema a ser resolvido e somente iniciar a codificao depois de se ter formulado uma idia clara sobre o que deve ser feito; O processo de converso dessa idia pode ser difcil. Uma abordagem consagrada a de utilizar o "princpio dos refinamentos sucessivos. Essa estratgia apresenta as seguintes vantagens: Permite a formulao de uma soluo inicial nos termos mais relevantes ao problema; Essa soluo inicial , por conseguinte, mais simples e sucinta, sendo a sua correo facilmente verificvel, e; Se cada passo de refinamento for pequeno o suficiente para ser manejado intelectualmente, preserva mais facilmente a sua correo. No caso da linguagem Prolog, pode-se pensar em tal processo como sendo o de refinamento de relaes. Ou pensar em refinamentos de algoritmos, adotando ento a viso procedimental do Prolog.

110

Como Pensar em PROLOG Uma caracterstica importante da linguagem Prolog permitir que seus programas sejam pensados tanto declarativa quanto procedimentalmente; Normalmente as soues declarativas so mais fceis de desenvolver e possuem a clareza e limpidez da pura lgica; Durante o processo de desenvolvimento de uma soluo, deve-se buscar as idias adequadas para decompor um problema em subproblemas de soluo mais fcil.

"Como encontrar os subproblemas apropriados?"


Uso de Recurso Na soluo de problemas envolvendo o processamento sequencial por meio de recurso, uma boa heurstica aplicar pensamento indutivo e resolver os seguintes dois casos separadamente: Os casos triviais, ou bsicos, em que o argumento uma lista vazia ou unitria, e Os casos gerais, em que o argumento uma lista [Cabea|Corpo] e o problema assumido resolvido para "Corpo;
111

Exemplo: Processar uma lista de itens de tal maneira que cada item seja operado por uma mesma regra de transformao: transforma(Lista, F, NovaLista) onde Lista a lista original, F uma regra de transformao e NovaLista a lista de todos os itens transformados. O problema de transformar Lista em NovaLista pode ser subdividido em dois casos: Caso Bsico: Lista = [] Se Lista = [], ento NovaLista = [], independentemente de F. Caso Geral: Lista = [X | Resto] Para transformar uma lista do tipo [X | Resto] em uma lista do tipo [NovoX | NovoResto], transforme Resto, obtendo NovoResto e transforme X, obtendo NovoX. Em Prolog: transforma([], _, []).

transforma([X | Resto], F, [NovoX | NovoResto]) :- G =.. [F, X, NovoX], call(G), transforma(Resto, F, NovoResto).
112

Generalizao Uma boa idia generalizar o problema original, de forma a permitir que a soluo do problema generalizado seja formulada recursivamente; A generalizao de uma relao envolve tipicamente a introduo de um ou mais argumentos extras.

"Como encontrar a generalizao correta?


Exemplo: Problema das oito damas. Temos a relao: oitoDamas(Posio) que ser verdadeira se Posio representar uma posio do tabuleiro tal que nenhuma dama ataque as restantes. Uma idia interessante, nesse caso generalizar o nmero de damas de oito para N, de forma que o nmero de damas se torna o argumento adicional; nDamas(Posio, N) A vantagem dessa generalizao que h uma formulao recursiva imediata para a relao nDamas/2. Uma vez que o problema generalizado est solucionado, a soluo do problema original imediata: oitoDamas(Posio) :- nDamas(Posio, 8).
113

Represetao Grfica de Problemas Na busca por idias para solucionar um dado problema, frequentemente de grande utilidade introduzir alguma representao grfica do mesmo. No caso do Prolog, essa tcnica parece ser especialmente produtiva, pois: Prolog particularmente adequado para problemas envolvendo objetos e relaes entre objetos. De modo geral tais problemas podem ser naturalmente ilustrados por meio de grafos, onde os nodos correspondem a objetos e os arcos a relaes; Os objetos estruturados em Prolog so naturalmente representados por meio de rvores; O significado declarativo dos programas Prolog facilita a traduo de representaes grficas porque, em princpio, a ordem na qual o desenho feito no constitui um fator importante. Exemplo: Definio de uma regra irm (X irm de Y): Z
progenitor(Z,X) progenitor(Z,Y)

irm(X,Y) :progenitor(Z,X), progenitor(Z,Y),

mulher(X)

X
irm (X,Y)

mulher(X).
114

Regras Gerais para uma Boa Programao


As clusulas do programa devem ser curtas. Seu corpo no deve conter mais que uns poucos objetivos. Exemplo: proc1A :- a, b, c. proc1B :- d, e, f. ao invs de proc1 :- a, b, c, d, e, f. Os procedimentos do programa devem tambm ser curtos (conter poucas clusulas); Adotar nomes mnemnicos para procedimentos e variveis; O lay-out dos programas importante, incluindo um bom espaamento, uso de linhas em branco, e identao; importante que as mesmas convenes sejam usadas de forma consistente em todo o programa; O operador cut deve ser usado com cuidado. Seu uso deve ser evitado quando no for absolutamente necessrio; O operador not, devido a sua relao com o cut tambm pode apresentar comportamento inesperado. Se entretanto estivermos em dvida entre usar o not ou o cut, o primeiro prefervel;
115

A modificao do programa por meio dos predicados assert/1 e retract/1 pode degradar em grande escala a transparncia do seu comportamento; A legibilidade pode ser algumas vezes incrementada pela diviso da clusula que contm o ; (correspondendo ao conetivo "ou") em duas.

Exemplo Para ilustrar os pontos discutidos at aqui, vamos considerar a seguinte relao: merge(L1, L2, L3) onde L1 e L2 so listas ordenadas que so reunidas ordenadamente em L3. A abaixo apresentada uma implementao sem muitos critrios: merge(L1, L2, L3) :L1 = [], !, L3 = L2; L2 = [], !, L3 = L1; L1 = [X | Resto1],

L2 = [Y | Resto2],
(X < Y, !, Z = X, merge(Resto1, L2, Resto3); (Z = Y, merge(L1, Resto2, Resto3))), L3 = [Z | Resto3].
116

Agora uma outra implementao apresentada, mas observando-se as regras apresentadas: merge([], L, L). merge(L, [], L). merge([X | R1], [Y | R2], [X | R3]) :X < Y, !, merge(R1, [Y | R2], R3). merge(L1, [Y | R2], [Y | R3]) :merge(L1, R2, R3). Alm dessas regras, duas outras observadas para uma boa programao: Utilizao de comentrios. podem ser

Organizao tabular de procedimentos longos, e;

117

Programao Lgica Linguagem PROLOG Fatos, Regras e Controle de Corte Operadores e Listas Entrada e Sada Manipulando Base de Dados Outros Exemplos Metodologia de Programao Lgica Fuzzy Exerccios
118

Lgica Fuzzy O que Lgica Fuzzy?


Apostadores como Blaise Pascal inventaram a estatstica para calcular as probabilidades de resultados precisos -- que um dado, digamos, venha a cair mostrando o quatro. Os meteorologistas na TV usam nmeros para prever se vai, ou no, chover amanh. Mas, de fato, o prprio conceito de "chuva" difuso. Se dois pingos de gua caem do cu, isso chuva? E o que dizer de cinqenta pingos? E de mil? Suponhamos que a neblina esteja espessa e baixa, e voc sinta gotas de gua em seu rosto. Isso chuva? Onde passa a linha divisria? Quando a no-chuva se torna chuva? Assim, uma definio precisa para Lgica Fuzzy no existe, mas o significado pode ser explicado. Enquanto a Teoria dos Conjuntos e a lgica matemtica divide o mundo com branco e preto, conjuntos fuzzy definem os tons de cinza entre o branco e o preto. Seu uso significativo quando aplicado fenmenos complexos que no so facilmente descritos pelos mtodos matemticos tradicionais, especialmente quando o objetivo obter uma resposta aproximada. Se a "lgica difusa" tem uma origem, esta reside na tentativa da Lgica de se adaptar aos paradoxos de Russel e incerteza de Heisenberg. O lgico polons Jan Lukasiewicz desenvolveu uma lgica "multivalente" nos anos de 1920, refinando a lgica binria do sim-no, da fsica newtoniana, para permitir estados indeterminados. Em 1965, o matemtico Lotfi Zadeh, de Berkeley, aplicou essa nova lgica teoria dos conjuntos, em seu artigo "Conjuntos Difusos", que depois emprestou seu nome lgica 119

O que Lgica Fuzzy? (Cont.)


. Os conjuntos difusos so a chave para as mquinas difusas. A maioria dos artefatos com os quais voc est familiarizado so "burros" isto , rigidamente programados. Um sistema de aquecimento controlado por termostato o exemplo clssico da mquina burra. Quando a temperatura cai abaixo de determinado ponto, o aquecedor ligado; quando ela ultrapassa uma outra determinada temperatura, o aquecedor desligado. O mecanismo binrio: o aquecedor est "ligado" ou "desligado", e quando est ligado, est sempre aquecendo o ambiente com a mesma intensidade. As mquinas difusas, por outro lado, usam conjuntos difusos para produzir respostas mais flexveis, permitindo que se estabelea um determinado grau de quente ou frio. Se decidimos que 20 a temperatura perfeita, podemos dizer a um aquecedor/condicionador de ar para modular seu comportamento, dependendo de quanto a temperatura atual difere de 20 . O aparelho nunca estaria s ligado ou desligado ele estaria sempre ligado em um grau varivel de aquecimento. Concluindo, os conjuntos Fuzzy so uma generalizao dos Conjuntos Clssicos, assim como a Lgica Infinito-Valorada uma generalizao da Lgica Clssica. Lgica Fuzzy uma incorporao dos Conjuntos Fuzzy e pode ser visto como uma extenso da Lgica Infinito-Valorada por aplic-la aos conjuntos fuzzy.
120

Lgica Clssica

Estende

Lgica Infinito Valorada

Correspondncia
Est para

Lgica Fuzzy

Conjuntos Clssicos

Estende

Conjuntos Fuzzy
Nmeros Fuzzy

Figura F1. Envolvimento da Lgica Fuzzy com a lgica tradicional

Elementos da lgica Fuzzy


Um nmero Fuzzy uma funo F(x) composta por vrias outras funes contnuas tal que os valores de retorno esto entre 0 e 1, obrigatoriamente, em um intervalo [a1, b1], e os valores em F(a1) e F(b1) so 0 (zero). Exemplo: F(x) 1

a1

b1

Grfico F2: exemplo de nmero fuzzy 121

Elementos da lgica Fuzzy (continuao)


Nmeros Fuzzy um caso particular dentro dos Conjuntos Fuzzy, cujo o conjunto definido como um par ordenado (x, (x)) onde (x) devolve um valor entre [0, 1] mas no necessariamente sempre incluindo o 0 e o 1, requisitos obrigatrios para um nmero fuzzy. Exemplos de um conjunto fuzzy: 1

0
Grfico F3: exemplo de conjunto fuzzy

Enquanto isso, na Lgica Clssica, uma proposio uma sentena que , logicamente, ou verdade, denotada por 1, ou falsa, denotada por 0. O conjunto T={0, 1} chamado de conjuntos de valores verdadeiros. Exemplo: a proposio o nmero 3 um inteiro verdadeira. J na Lgica Multivalorada permitida a proposio ter mais do que um valor verdadeiro que esteja entre [0, 1], como por exemplo T8 = {0, 1/7, 2/7, 3/7, 4/7, 5/7, 6/7, 1} representa um conjunto com 8 valores verdadeiros. Se o conjunto de valores verdadeiros compreende todos os nmeros reais em [0, 1], ento chamamos a lgica multivalorada de Lgica Infinito-valorada
122

Elementos da lgica Fuzzy (continuao)


A Lgica Fuzzy tem foco em variveis lingusticas da linguagem natural e visa prover fundamentos para resultados aproximados com proposies imprecisas. Exemplo: Velocidade, na linguagem natural, trata de quo rpido algo se move, mas dizer se ele rpido depende de cada indivduo. Assim, podemos definir velocidade como sendo uma varivel lingstica consistindo de conjuntos fuzzy como rpido, meio-rpido, normal, meio-devagar e devagar.

devagar 1 Meio-devagar

normal Meio-rpido

rpido

30

40 50 60 75 80

95

115

150

Grfico F4: conjuntos fuzzy descrevendo velocidade

123

Por que se usa Lgica Fuzzy


Porque facilita o desenvolvimento de softwares baseados em situaes onde a impreciso pode responder melhor s necessidades. Engenheiros acusam uma reduo de metade do tempo de desenvolvimento dos sistemas, aproximadamente. No incio, foram usados sistemas com fuzzy para inmeros produtos comerciais, como lavadoras, chuveiros, aspiradores de p, etc. Por exemplo, a cidade Sendai, Japo, vem usando lgica fuzzy para controle de seus trens do metr desde 1986.

Aplicaes da Lgica Fuzzy


O emprego de Controle de Fuzzy recomendvel: 1 - Para processos muito complexos, quando no h modelo matemtico simples; 2 - Para processos altamente no lineares; O emprego do Controle de Fuzzy no recomendvel se: 1 - A teoria convencional de controle d resultados satisfatrios; 2 - Um modelo matemtico adequado e de fcil resoluo j existe;

Exemplos de aplicaes
Controle simplificado de robs (Fuji Eletric, Toshiba), Prevenco contra flutuaes de temperatura em sistemas de ar condicionado (Mitsubishi, Sharp), Controle eficiente e estvel de fbrica de carros (Nissan), Planejamento otimizado de tabelas de controle de horrios de nibus (Toshiba), Combinao de Lgica Fuzzy e Redes Neurais (Matsushita), Desenvolvimento de sistemas anti-vibrao para cmera filmadora (Matsushita)
124

Estrutura de um programa Fuzzy


Os estgios de fuzzificao, aplicao das regras fuzzy e de-fuzzificao correspondem ao fato do programa ler um dado do meio, digamos a velocidade do carro, descobrir quo rpido, meio-rpido, normal, meio-devagar, devagar (fuzzificao - transformar um dado do meio em uma varivel lingstica), aplicando em seguida as regras fuzzy para chegar em outra varivel lingstica, por exemplo, presso da acelerao, com valores mxima, mdia e mnima. Depois disso tudo, a varivel resultado (presso da acelerao) transformada em um valor real (de-fuzzificao) a ser enviado de volta para o meio. Por exemplo, nosso sistema obteria a velocidade atual do carro, digamos de 120 Km/h, e transformaria esse valor em uma varivel lingstica velocidade, que, pelo grfico F4, podemos concluir que esta ser 57,14% rpida e 0% para as outras definies (meio-rpida, normal, meio-devagar e devagar). Aplicando as regras fuzzy (sero abordadas mais frente) podemos chegar numa outra varivel lingstica presso da acelerao com valores, digamos de 50% em mnima, e 0% em mdia e mxima.
125

Exemplo (viagem de carro)


VARIVEIS FUZZY
VELOCIDADE

REGRAS FUZZY

VARIVEIS FUZZY
PRESSO DA ACELERAAO

RAPIDO MAXIMA MEIO RAPIDO

REGRAS FUZZY

120
Km/h

MEDIA

NORMAL

10 PSI

MEIO DEVAGAR DEVAGAR MINIMA

FUZZIFICAO

PROPAGAO

126 DE-FUZZIFICAO

Ferramentas para Prolog


Existem muitas ferramentas especializadas para o desenvolvimento de programas usando fuzzy, entre elas o FLINT (Fuzzy Logic Inference Toolkit), para o Win-Prolog.

Variveis Fuzzy no FLINT


Pertencem a uma faixa de valores (ex: 0 a 100) Armazenam um nico valor (ex: velocidade) Possuem qualificadores, que subdividem a faixa de valores, compostos de: um nome (qualificador lingstico - rpido) uma funo membro que define o grau de pertinncia do valor para este qualificador. A funo membro definida por: Forma ( /, \, /\, /-\, \-/, \/ ou ?) Curvatura (linear ou curve) Pontos Relevantes (pontos da forma)

Possuem ainda a definio do tipo de mtodo de De-fuzzificao a ser usado (ex: peak, centroid ou uma expresso definida pelo usurio)
127

Qualificadores de variveis Fuzzy


\ / /\ \/ /-\ \-/ ? [A, [A, [A, [A, B] B] B, C] B, C] descida de rampa subida de rampa tringulo para cima tringulo para embaixo

[A, B, C, D] trapezide para cima [A, B, C, D] trapezide para baixo [V1/M1, V2/M2, Vk/Mk] forma livre

Exemplos de Qualificadores
Exemplo de subida de rampa (smbolo /) com pontos A e B e curvatura linear A B Exemplo de descida de trapzio (smbolo \-/) com pontos A, B, C e D com curvatura linear B C A D Exemplo de forma livre (representada por ?). Os pontos V1/M1 um dos segmentos de reta que compoem o grfico. V1/M1
128

Tipos de Curvatura Linear (ex: tringulos, trapzios) Curve Menor que 1 Igual a 1 Maior que 1

Mtodos de De-fuzzificao
Centroid - centro de gravidade (default) obtm o
valor final calculando o centro da rea do grfico gerado pela varivel fuzzy resultante.

Peak - maior nvel da funo. Obtm o valor final


calculando a mdia dos picos da funo resultante

Expresso definida pelo usurio

129

Exemplo de varivel fuzzy no FLINT


Faixa da varivel fuzzy (opcional) Nome da varivel fuzzy

fuzzy_variable(velocidade) [0, 200]; rpido, / , linear, meio-rpido, /\, linear, normal, /\, linear, meio-devagar, /\, linear, devagar, \, linear, peak.

:[ [75, [40, [30, [ 0, 80, 150]; 95, 115]; 60, 80]; 40, 50]; 40 ];

Pontos do grfico Mtodo de-fuzzy Nome do qualificador Formas Curvatura

Definio de Regra Fuzzy


Consistem de conjuntos de condies IF (usando conectivos and e or) Uma concluso (then) Uma concluso opcional (else) So aplicadas s variveis atravs de um processo chamado Propagao
130

Exemplo de declarao de regra no FLINT


Nome da regra fuzzy Nome de varivel de condio Nome do qualificador de condio

fuzzy_rule(risco1) if velocidade is rpida then presso_da_acelerao is mnima else presso_da_acelerao is mdia.

Nome de varivel de concluso

Nomes de qualificador de concluso

Programa exemplo
Implementando um sistema controlador de turbina

131

Variveis Fuzzy
So usadas Throttle, Pressure e Temperature como variveis fuzzy para representar as caractersticas da turbina, alm de podermos definir que Pressure e Temperature sero variveis de entrada enquanto Throttle ser de sada. Para a varivel Temperature definiremos os seguintes modificadores: cold, cool, normal, warm, hot. Para a varivel Pressure defineremos os modificadores: high, low, medium. Para a varivel Throttle, os modificadores negative-large, negative-medium, negativesmall, zero, positive-small, positive-medium, positive-large.

Operadores Lingusticos
necessrio definir alguns operadores lingusticos (sempre definidos dessa maneira para todo programa que usa o FLINT): :- op( 1200, xfy, ( if ) ), op( 1200, xfy, ( then ) ), op( 1200, xfx, ( else ) ),

op( 1100, xfy, ( or


op( op( 700, xfx, ( is 600,

)
)

),
), ), ).

op( 1000, xfy, ( and )

fy, ( not )

Estes so os operadores para as regras fuzzy, definindo condio, concluso, conjuno, disjuno e negao.

132

Definindo as Variveis Fuzzy


Definindo a varivel temperature: fuzzy_variable( temperature ) :[ 0 , 500 ]; cold, cool, warm, hot, \, linear, [ 110 , 165 ]; /\, linear, [ 110 , 165 , 220 ]; /\, linear, [ 220 , 275 , 330 ]; /, linear, [ 275 , 330 ].

normal, /\, linear, [ 165 , 220 , 275 ];

O grfico da funo seria equivalente a:


1

cold

cool

normal

warm

hot

110

165

220

275

330

temperature

133

Definindo as Variveis Fuzzy


Definindo a varivel pressure: fuzzy_variable( pressure ) :[ 0 , 300 ] ; weak, \, linear, [ 10 , 70 low, /\, linear, [ 10 , 70 , 130 ok, /\, linear, [ 70 , 130 , 190 strong, /\, linear, [ 130 , 190 , 250 high, / , linear, [ 190 , 250 O grfico da funo seria equivalente a:

]; ]; ]; ]; ].

weak

low

ok

strong

high

10

70

130

190

250

pressure

134

Definindo as Variveis Fuzzy


Definindo a varivel throttle:
fuzzy_variable( throttle ) :[ -60 , 60 ];

negative_large,

\, linear, [ -45, -30

];

negative_medium, /\, linear, [ -45, -30, -15 ]; negative_small, zero, positive_small, /\, linear, [ -30, -15, /\, linear, [ -15, /\, linear, [ 0, 15, 0, 15, 30, 0 ]; 15 ]; 30 ]; 45 ];

positive_medium, /\, linear, [ positive_large, centroid . /, linear, [

30 , 45 ];

O grfico da funo seria equivalente a:


Negative_medium 1 Negative_small Negative_large zero Positive_small positive_large Positive_medium

10

70

130

190

250

throttle

135

Definindo as Regras Fuzzy


Pode-se definir as regras fuzzy atravs de decises, como por exemplo :

se a temperatura fria e a presso fraca ento aumente a vlvula em grandes quantidaddes


pode ser definida por:

fuzzy_rule(throttle1) if temperature is cold and pressure is weak then throttle is positive_large.


Mas como estas regras iro sempre se aplicar s variveis fuzzy temperature, pressure e throttle, podemos ento colocar todas as regras dentro de uma nica matriz (onde a primeira linha indica quais as variveis a serem usadas, o smbolo * equivalente ao smbolo and da regra fuzzy acima, assim como o smbolo -> equivale ao then):
fuzzy_matrix( t ) :temperature cold cold cold cold cold cool cool cool cool * * * * * * * * * * pressure weak low ok strong high weak low ok strong -> -> -> -> -> -> -> -> -> -> throttle ; positive_large ; positive_medium; positive_small ; negative_small ; negative_medium; positive_large ; positive_medium; zero ; negative_medium;
136

(continuna na prxima pgina).

Definindo as Regras Fuzzy (Continuao)


(continuao da matriz de regras)
cool normal normal normal normal normal warm warm warm warm warm hot hot hot hot hot * * * * * * * * * * * * * * * * high weak low ok strong high weak low ok strong high weak low ok strong high -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> negative_medium; positive_medium; positive_small ; zero ; negative_small ; negative_medium; positive_medium; positive_small ; negative_small ; negative_medium; negative_large ; positive_small ; positive_small ; negative_medium; negative_large ; negative_large .

Definindo a Propagao
Definindo uma nova prograpao das regras fuzzy, ou seja, dados as variveis de entrada (temperature e pressure), como obter a varivel de sada, throttle, atravs dos predicados fuzzy_propagate e fuzzy_variable_value (obteno dos valores) e o predicado fuzzy_reset_membership para garantir que no haver velhos valores armazenados

(continuna na prxima pgina).

137

Definindo a Propagao (Continuao)


Exemplo:
find_throttle(Temperature, Pressure, Throttle):fuzzy_reset_membership( throttle ), fuzzy_variable_value( temperature, Temperature), fuzzy_variable_value( pressure, Pressure ), fuzzy_propagate( minimum, maximum, complement,[t]), fuzzy_variable_value( throttle, Throttle ).

Rodando o exemplo
Aps declarado os operadores lingsticos, as variveis fuzzy, a matriz de regras e finalmente, a propagao, todos listados acima, usaremos o predicado find_throttle para a execuo:

?- find_throttle( 300, 150, Throttle ) . Throttle = -26.040413058933

E assim termina nosso exemplo de como usar lgica fuzzy no


Win-Prolog com o mdulo FLINT.

138

Programao Lgica Linguagem PROLOG Fatos, Regras e Controle de Corte Operadores e Listas Entrada e Sada Manipulando Base de Dados Outros Exemplos Metodologia de Programao Lgica Fuzzy Exerccios
139

Exerccios

1. Um programa Prolog tem as seguintes clusulas : vertical(Seg(ponto(X,Y), ponto(X,Y1)). horizontal(Seg(ponto(X,Y), ponto(X1,Y)). D os resultados das seguintes consultas : ?- vertical(seg(ponto(1,1), ponto(1,2))). ?- vertical(seg(ponto(1,1), ponto(2,Y))). ?- horizontal(seg(ponto(1,1), ponto(2,Y))). ?- vertical(seg(ponto(2,3),P)). 2. D o resultado das seguintes instanciaes : a) point(A,B) = point(1,2) b) point(A,B) = point(X,Y,Z) c) [a, b, c, [ab], [], [[a], c]] = [X, Y|Z] d) [p, [seg], t, q] = [X, [Y], Z|S] e) [X, Y|Z] = [2, [3,4]] f) [lista, de, exercicios, de, PL] = [X, de|W] 3. Construa uma base de dados sobre livros com pelo menos cinco estruturas do tipo : livro( nome(C completo), autor(Schildt), pal_chave([linguagemc, programacao, computacao]))
140

a) Escreva consultas para encontrar : Nome do autor, dado o nome do livro. Nome do livro, dado o nome do autor. As palavras chave, dado o nome do livro. Nome do autor e nome do livro, dado uma palavra chave.

b) Escreva um programa Prolog para, dada uma lista de palavras chave, encontrar nome e autor dos livros que tem pelo menos uma das palavras chave fornecidas. Os livros encontrados devem ser dados um de cada vez.
4. Defina os predicados n_par(Lista) e n_impar(Lista) dara determinar se uma lista tem nmero par ou mpar de elementos. 5. Defina a relao traduz(L1,L2) para traduzir uma lista de nmeros entre 0 e 9 para a palavra correspondente. Por exemplo : traduz([1,2,3], L). L = [um, dois, tres] Use a relao auxiliar : t(0, zero), t(1, um).......... 6. Quais seriam os modos de chamada para os predicados do exerccio anterior? 7. Defina o predicado between(N1, N2, L), tal que, para dois nmeros inteiros dados N1 e N2, guarde na lista L todos os valores X tal que N1 <= X <= N2.
141

8. Escreva um programa Prolog que possa responder a seguinte pergunta : Eu sou meu prprio av?, criando um conjunto de relaes que representem a seguinte situao : Eu me casei com uma viva(W) que tem uma filha adulta(D). Meu pai(F), que nos visitava frequentemente, se apaixounou por minha enteada e casou se com ela. Logo, meu pai se tornou meu enteado e minha enteada tornou se minha madrasta. Alguns meses depois, minha mulher teve um filho(S1), que se tornou cunhado do meu pai, assim como meu tio. A mulher do meu pai, isto , minha enteada, tambm teve um filho(S2). 9. Mostre a execuo de um programa Prolog para o exemplo da regra de Fibonacci recursiva. Procure deixar bem claro os passos onde ocorrem unificao e backtracking. 10. Baseando se no programa que faz busca em largura apresentado no slide 62, faa um programa que execute busca em profundidade. Dica : necessrio apenas uma pequena modificao no algoritmo de busca em largura. 11. Faa, sem olhar em slides anteriores, um programa Prolog que resolva o problema dos missionrios e canibais. 12. Faa, sem olhar em slides anteriores, um programa Prolog que resolva o problema das rainhas em um tabuleiro de xadrez.
142

13. Considere o seguinte problema : Um fazendeiro est na margem norte de um rio com uma cabra, um lobo e um repolho. Existe um bote atravs do qual o fazendeiro pode transportar um elemento por vez para a outra margem do rio. Se o lobo e a cabra ficarem sozinhos numa margem, o lobo comer a cabra. Se a cabra e o repolho ficarem sozinhos em uma margem, a cabra comer o repolho. Como transportar com segurana os trs elementos, considerando o respolho um passageiro? Crie as clusulas move da busca em largura para resolver esse problema. 14. Crie uma representao qualquer em Prolog para rvores. a) Faa um cdigo que verifica se um dado elemento pertence uma rvore. b) Faa um cdigo que mostra todos os elementos de uma rvore(ou guarda todos os elementos em uma lista). c) Faa um cdigo que verifica se a rvore uma AVL. d) Faa cdigos de insero e remoo de elementos da rvore.

143