Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Introdução à programação em lógica, Notas de estudo de Informática

INTRODUÇÃO À PROGRAMAÇÃO EM LÓGICA

Tipologia: Notas de estudo

Antes de 2010

Compartilhado em 06/05/2009

victor-luiz-piza-soares-1
victor-luiz-piza-soares-1 🇧🇷

5 documentos

1 / 34

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Universidade Federal de Campina Grande - UFCG
Centro de Ciências e Tecnologia - CCT
Departamento de Sistemas e Computação - DSC
APOSTILA: INTRODUÇÃO À PROGRAMAÇÃO EM LÓGICA
Alexandre de Andrade Barbosa
Joseluce de Farias Cunha
34 páginas
2006
Av. Aprígio Veloso, 882 Bodocongó
Caixa Postal 10.106
58.109-970 Campina Grande PB Brasil
Fone: 310-1119 Fax: 310-1273
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22

Pré-visualização parcial do texto

Baixe Introdução à programação em lógica e outras Notas de estudo em PDF para Informática, somente na Docsity!

Universidade Federal de Campina Grande - UFCG Centro de Ciências e Tecnologia - CCT Departamento de Sistemas e Computação - DSC

APOSTILA: INTRODUÇÃO À PROGRAMAÇÃO EM LÓGICA

Alexandre de Andrade Barbosa [email protected]

Joseluce de Farias Cunha [email protected]

34 páginas

Av. Aprígio Veloso, 882  Bodocongó Caixa Postal 10. 58.109-970  Campina Grande  PB  Brasil Fone: 310-1119  Fax: 310-

APOSTILA: INTRODUÇÃO À PROGRAMAÇÃO EM

LÓGICA

Alexandre de Andrade Barbosa Departamento de Sistemas e Computação E-mail: [email protected]

Joseluce de Farias Cunha Departamento de Sistemas e Computação E-mail: [email protected]

Av. Aprígio Veloso, 882  Bodocongó  Caixa Postal 10. CEP 58109-970  Campina Grande  PB  Brasil Fone: 310-1119  Fax: 310-1273 (DSC)

Resumo Esta apostila foi criada como material de apoio à disciplina de Lógica Matemática do curso de Ciência da Computação da Universidade Federal de Campina Grande - UFCG. O conteúdo apresentado neste material é relacionado à Programação em Lógica, mais especicamente à linguagem Prolog. Nenhuma revisão sobre Lógica Matemática é apresentada, assim, é necessário que o leitor já possua conhecimento sobre Lógica Proposi- cional e Lógica de 1a^ Ordem. Este texto possuí nível introdutório, uma vez que conhecimentos avançados sobre a linguagem não serão explorados na disciplina em questão.

Palavras-chave: Programação em lógica, Prolog, Lógica.

  • 1 Introdução
    • 1.1 O que é Programação em Lógica/Prolog?
    • 1.2 Como Prolog funciona?
  • 2 Implementações de Prolog
  • 3 Sintaxe SWI-Prolog
    • 3.1 Os comandos write e read
    • 3.2 Comentários
  • 4 Utilizando o SWI-Prolog
  • 5 Fatos, Regras e Consultas
    • 5.1 Regras
    • 5.2 Regras recursivas
    • 5.3 Como Prolog responde consultas
  • 6 Listas
    • 6.1 Checagem de pertinência
    • 6.2 Concatenação
    • 6.3 Adicionando elementos
    • 6.4 Excluindo elementos
  • 7 Aritmética
  • 8 Corte de uxo
  • 9 Exemplos
  • 10 Exercícios
  • 1 Tela inicial do SWI-Prolog Editor Lista de Figuras
  • 2 Árvore genealógica
  • 3 Relação descendente.
  • 4 Árvore para a expressão 2 ∗ a + b ∗ c
  • 5 Jogo Torre de Hanoi

1 Introdução

Esta apostila foi criada para apoiar a disciplina Lógica Matemática, em sua parte nal relacionada à Programação em Lógica. O conteúdo apresentado aqui possui nível in- trodutório, uma vez que a disciplina em questão não fará uso de recursos avançados da linguagem. Estudos mais avançados sobre a Programação em Lógica deverão realizados em disciplinas posteriores. O conteúdo deste texto busca fornecer aspectos mais práticos relacionados à linguagem Prolog, o funcionamento interno da linguagem não será detalhado neste material. Caso o leitor deseje se aprofundar no estudo da linguagem, recomenda-se a leitura de [1], [2], [3] e [4], nos quais este texto é baseado. Espera-se que após a leitura deste material o leitor seja capaz de:

  • compreender e executar programas Prolog;
  • modicar programas Prolog;
  • escrever programas Prolog básicos e intermediários.

1.1 O que é Programação em Lógica/Prolog?

Existem diversos paradigmas de programação, hoje, o paradigma mais utilizado é o paradigma procedural. As linguagens Java, Pascal, C/C++ são ditas linguagens pro- cedurais, pois, nestes programas é necessário implementar um procedimento para resolver determinado problema. Outro paradigma de programação é o paradigma imperativo, que possui a linguagem LISP como sua representante mais famosa. A Programação em Lóg- ica faz parte do paradigma de programação denominado declarativo ou descritivo, neste, deve-se implementar uma descrição do problema e não um conjunto de instruções. A linguagem Prolog é uma representante do paradigma declarativo, esta é a represen- tante mais famosa da Programação em Lógica, a qual se baseia no cálculo de predicados. Prolog foi criada em 1972 por Colmerauer e Roussel, um programa Prolog não possui código para manipular a memória ou realizar desvios condicionais. Isso não signica que Prolog seja superior às outras linguagens, pode-se armar apenas que a linguagem é mais adequada para solucionar uma determinada categoria de problemas. Esta categoria diz respeito aos problemas onde é necessário representar algum tipo de conhecimento, por ex- emplo, em aplicações que realizem computação simbólica, na compreensão de linguagem natural ou em sistemas especialistas.

1.2 Como Prolog funciona?

Um programa Prolog constitui-se de uma coleção de fatos (base de dados) e regras (re- lações lógicas), esses ítens descrevem o domínio de um determinado problema. Esta descrição do problema é avaliada por um interpretador, o qual utilizando um motor de inferência realiza deduções em busca de conclusões válidas para consultas realizadas pe- los usuários. Assim, pode-se armar que a computação destes programas é equivalente a prova de um teorema em lógica.

existem versões livres e comerciais criadas para os principais sistemas operacionais. Al- gumas das implementações mais conhecidas são:

  • Win-Prolog [5] - respeita a sintaxe de Edinburgo, é a implementação mais próxima do dialeto puro. A versão 4.6, a mais recente, está disponível apenas para Windows (98, ME, NT, 2k, XP). É um sistema comercial, mas possui uma versão para testes gratuita.
  • Open Prolog [6] - disponível unicamente para Macintosh (Mac OS 7.5 ou superior). Respeita a sintaxe padrão ISO, baseada na sintaxe de Edinburgo. É um software gratuito, desde que seu autor seja avisado de sua utilização.
  • Ciao Prolog [7] - distribuído gratuitamente, possui licença Library General Public License (LGPL). Respeita a sintaxe padrão ISO, pode ser utilizada em diversos sistemas operacionais, tais como, Windows (98, NT, 2k, XP), Linux, SunOS, Solaris, MacOS X, entre outros.
  • YAP Prolog [8] - criado pela Universidade do Porto em parceria com a Univer- sidade Federal do Rio de Janeiro. Uma das principais características desta imple- mentação é sua velocidade. Respeita a sintaxe padrão ISO, também é compatível com outras implementações de Prolog, tais como, Quintus e SICStus. A versão 5.1. pode ser utilizada em diversas distribuições Linux e Windows.
  • SWI Prolog [9] - software gratuito, sob a licença Lesser GNU Public License. Pode ser utilizado nas plataformas Windows, Linux e MacOS. Possui diversas ferramentas de edição gráca, tais como, J-Prolog Editor e SWI-Prolog-Editor (recomendado). Permite a utilização da linguagem Prolog por outras linguagens, tais como, C/C++ e Java. É uma das implementações mais utilizadas atualmente.
  • SICStus Prolog [10] - é um software comercial, mas possui versão gratuita para avaliação. Respeita a sintaxe padrão ISO e pode ser usada nas plataformas Windows (2k e XP), Linux, Solaris 7, MacOS X e algumas distribuições Unix. Assim como o SWI, possui interfaces para comunicação com outras linguagens, por exemplo, C & C++, .NET, Java, Visual Basic e Tcl/Tk.
  • Amzi! Prolog [11] - pode ser utilizado de maneira conjunta a IDE Eclipse, permite também comunicação com outras linguagens. Possui distribuições gratuitas e comerciais, que podem ser utilizadas em sistemas operacionais diversos, tais como, Windows, Linux, Solaris e HP/UX.
  • Visual Prolog [12] - bastante diferente da versão padrão de Prolog, é fortemente tipado. Também conhecido como PDC Prolog ou Turbo Prolog, possui distribuições gratuitas e comerciais para Windows e Linux. Fornece um ambiente complto para programação, porém, é um dialeto mais complexo que o original.

Outras distribuições Prolog conhecidas são: GNU Prolog [13], XSB [14] e Trinc Prolog [15]. A implementação utilizada ao longo desta apostila é a SWI-Prolog, todo código utilizado nos exemplos e exercícios apresentados aqui foram desenvolvidos nesta versão de Prolog.

3 Sintaxe SWI-Prolog

Assim como todas as linguagens de programação, existem algumas regras que devem ser respeitadas pelo programador. Os dados representados em Prolog podem ser um dos seguintes tipos:

  • variáveis - devem ser iniciados com letras maiúsculas ou underscore (_), seguidos de qualquer caractere alfanumérico. Caso uma variável seja denida apenas com underscore, ela será considerada uma variável anônima, ou seja, não se deseja saber seu valor. Ex.: X, Y1, _Nome, ...;
  • não variáveis;

 atômicas; ∗ átomos - são constantes expressas através de palavras. Devem ser iniciados com letra minúscula seguida de qualquer caractere alfanumérico. Caso seja necessário denir um átomo com letra maiúscula ou número, deve se usar aspas simples. Ex.: joao, João',16', `Marys', ...; ∗ inteiros - qualquer número que não contenha um ponto (.) será considerado um inteiro. Caracteres ASCII entre aspas duplas são considerados inteiros. Ex.: 1, 6, -3, a (interpretado como 97), ...; ∗ números em ponto utuante - qualquer número com um ponto e pelo menos uma casa decimal. Ex.: 5.3 (correto), 7.8 (correto), 7. (incorreto);  não atômicas; ∗ listas - é uma seqüencia de elementos ordenados. Uma lista é declarada entre colchetes e os elementos devem ser separados por vírgula. Pode-se separar a cabeça (1o. elemento) do corpo (demais elementos) de uma lista utilizando |. Ex.: [ a, b, c], [a | b, c ], ....

3.1 Os comandos write e read

O comando write exibe o valor do parâmetro no dispositivo de saída corrente. O dis- positivo padrão é o monitor, assim, o comando write(`Teste de impressão.'). irá exibir a mensagem Teste de impressão. na tela do monitor. O mesmo comando pode ser utilizado para imprimir o valor de qualquer variável. No entanto, não existe um comando padrão Prolog para escrita de expressões for- matadas. Devido a isso, o SWI-Prolog utiliza comandos de extensão, um deste é o comando writef do C-Prolog de Edinburgo. Este comando possui a seguinte sintaxe writef(Formato, Argumentos). Onde as opções para determinar a formatação são:

  • %w - imprime o termo;
  • %d - imprime o termo ignorando seu tipo, por exemplo, \n é impresso como uma string.
  • %s - imprime o termo como uma string;

4 Utilizando o SWI-Prolog

Após realizar o download e a instalação do SWI-Prolog e do SWI-Prolog-Editor, inicie o editor, será apresentada a tela deste, a qual deve ser similar a exibida na Figura 1. Pode-se observar que a tela se divide em duas janelas editáveis, identicadas na imagem com os números 1 e 2. A área 1 corresponde a janela de edição do programa, a área 2 é a janela de interação do usuário com o interpretador. Para que se possa realizar qualquer interação com o programa que está sendo editado é necessário, após salvar o arquivo, clicar sobre botão de consulta, identicado com o número 3. Caso o arquivo seja alterado e o botão não seja acionado o interpretador irá trabalhar com a última versão do programa que foi consultada. O número 4 identica o prompt de comandos, a partir deste é que podem ser enviados os comandos para o interpretador. Todo comando enviado para o interpretador deve obrigatoriamente ser nalizado pelo caractere ponto (.). Por exemplo, o comando ?- write(Teste) não resultará em uma impressão, enquanto o comando ?- write(Teste). resultará na impressão da string `Teste'. O símbolo ?- será usado nos exemplos e exercícios apresentados para representar o prompt de comandos, ele não deve ser digitado. As outras funcionalidades (e.g. salvar, abrir, debug, ... ) existentes no sistema são similares ou idênticas à ações encontradas em diversos sistemas. Maiores detalhes de funcionamento do programa podem ser encontradas no manual do sistema.

Figura 1: Tela inicial do SWI-Prolog Editor

5 Fatos, Regras e Consultas

Como já foi armado, um programa Prolog captura a descrição de um determinado prob- lema. O programador deve implementar um conjunto de fatos e regras relacionados ao problema em questão. Ao longo de toda esta seção serão apresentados alguns fatos, regras e consultas Prolog que podem constituir um programa. Para facilitar a explicação destes conceitos será implementado um programa que descreva as relações de uma família. A Figura 2 exibe a árvore genealógica de uma família, nesta é possível observar que existem diversos tipos de relação, por exemplo, bob é pai de pat, pam é avó de ann, ann é irmã de pat, jim é lho de pat, entre outras.

Figura 2: Árvore genealógica

Para se representar estas relações em Prolog, inicialmente pode-se criar a relação genitor(x, y), signicando que x é genitor de y. Então, podemos inserir na janela de edição do programa os seguintes fatos:

g e n i t o r (pam , bob ). g e n i t o r ( tom , bob ). g e n i t o r ( tom , l i z ). g e n i t o r ( bob , ann ). g e n i t o r ( bob , pat ). g e n i t o r ( pat , jim ).

Estas cláusulas descrevem toda a informação sobre a relação genitor existente na árvore apresentada (domínio). Após a denição desta relação podem ser realizadas consultas no sistema, para isso basta clicar no botão de consulta, e digitar perguntas no prompt de comandos, tal como exibido a seguir:

3 ?− g e n i t o r ( pat , jim ). Yes 4 ?− g e n i t o r ( jim , pat ). No

a consulta rotulada com o número 3, retorna a resposta yes (sim), isso ocorre pois o motor de inferência encontrar o fato correspondente e responder positivamente. Já para

cláusulas separadas por vírgula só sera satisfeita se e somente se todas as cláusulas forem satisfeitas. Do mesmo modo, pode-se armar que uma seqüencia de cláusulas separadas por ponto e vírgula sera satisfeita se ao menos uma cláusula for satisfeita. Um outro conectivo importante é a negação. Para exemplicar a utilização deste conec- tivo serão denidos os predicados homem(x) e mulher(x), signicando que x é homem e x é mulher respectivamente. Assim, são denidos os fatos: mulher (pam ). homem( tom ). homem( bob ). mulher ( l i z ). mulher ( pat ). mulher ( ann ). homem( jim ).

após denidos os fatos, podemos indagar, por exemplo, quem é a mãe de bob, ou seja, deseja-se saber quem é o genitor de bob que é mulher. Para isso, pode-se digitar no prompt de comandos a seguinte pergunta: 9 ?− g e n i t o r (X, bob ) , mulher (X ). X = pam ; No

a mesma consulta poderia ser realizada através da seguintes pergunta: 10 ?− g e n i t o r (X, bob ) , not (homem(X ) ). X = pam ; No

5.1 Regras

Muitas outras consultas podem ser realizadas sobre uma base de fatos, porém, é muito mais interessante utilizar regras, pois o poder de expressão obtido é muito maior. Para exemplicar o uso de regras será denida a relação prole(y,x), signicando que y é prole de x. Esta relação é a relação inversa de genitor(x,y), assim, pode-se armar que y é prole de x se x é genitor de y. Para isso, pode-se criar a seguinte regra na janela de edição do programa: p r o l e (Y,X) :− g e n i t o r (X,Y ).

o símbolo :- pode ser lido como se. A parte da regra a esquerda do símbolo :- é denom- inada de conclusão (ou cabeça), já a parte a direita deste é chamada de condição (ou corpo). Assim, para responder a consulta o interpretador Prolog precisa satisfazer parte condicional da regra, uma vez que não existem fatos relacionados a prole, para então obter uma conclusão. Para isso, são utilizadas substituições, até que se satisfaça a parte condicional ou não existam mais possibilidades de substituição. Consultas são realizadas sobre regras da mesma maneira como se estas fossem fatos, por exemplo, para indagar quem é a prole do indivíduo tom deve-se digitar no prompt de comandos a seguinte consulta: 11 ?− p r o l e (X, tom ).

X = bob ; X = l i z ; No

para satisfazer a regra o interpretador Prolog substituiu a variável X até que encontrou o fato genitor(tom, bob), o qual corresponde a parte condicional da regra prole(Y,X) :- genitor(X,Y), após as substituições adequadas. Posteriormente foi encontrado o fato genitor(tom, liz), o qual também pode satisfazer a regra, nenhuma outra substituição resultou em sucesso. Outras relações podem ser denidas para o exemplo. Pode-se denir as relações mae(x,y) e avos(x,y), apresentadas anteriormente como consultas. Para isso, deve-se digitar na janela de edição do programa as seguintes regras: mae (X,Y) :− g e n i t o r (X,Y) , mulher (X ). avos (X, Z) :− g e n i t o r (X,Y) , g e n i t o r (Y, Z ).

Um outra relação que pode ser denida é a relação irma(x,y), signicando x é irmã de y. Note que deve-se ter cuidado na denição deste relacionamento, pois, pode-se denir este através da seguinte regra: irma (X,Y) :− g e n i t o r (Z ,X) , g e n i t o r (Z ,Y) , mulher (X ).

porém, esta regra permite uma pessoa seja irmã de si mesma, para comprovar isso basta realizar a seguinte consulta: 12 ?− irma ( pat , pat ). Yes

o programador deve estar atento a especicações deste tipo, para descrever corretamente a relação é necessário indicar que x e y precisam ser diferentes, assim a regra correta seria: irma (X,Y) :− g e n i t o r (Z ,X) , g e n i t o r (Z ,Y) , mulher (X) , not (X = Y ).

Uma diferença básica entre uma regra e um fato é que um fato é sempre uma in- formação verdadeira, já uma regra precisa ser avaliada para que se possa determinar se esta é verdadeira ou não. Regras podem depender diretamente de um fato, como no ex- emplo anterior ou de outras regras (inclusive dela mesma). Regras denidas em termos de si mesma são chamadas de regras recursivas ou recorrentes, este tipo de regra será apresentado na seção seguinte.

5.2 Regras recursivas

A recursão é um dos elementos mais importantes da linguagem Prolog, este conceito permite a resolução de problemas signicativamente complexos de maneira relativamente simples. A construção de uma regra recursiva será apresentada através da denição da relação descendente(x,y), signicando que y é um descendente de x, tal como ilustrado na Figura 3. É possível denir esta relação utilizando a relação genitor, assim, uma descendência direta, ou seja, quando x é genitor de y, seria representada com a seguinte regra: d e s c e n d e n t e (X, Z) :− g e n i t o r (X, Z ).

O programa completo que descreve as relações familiares discutidas nesta seção pode ser observado a seguir:

/∗ Programa P r o l o g s o b r e r e l a ç õ e s f a m i l i a r e s. ∗/ g e n i t o r ( pam , bob ). % f a t o g e n i t o r ( tom , bob ). % f a t o g e n i t o r ( tom , l i z ). % f a t o g e n i t o r ( bob , ann ). % f a t o g e n i t o r ( bob , pat ). % f a t o g e n i t o r ( pat , jim ). % f a t o mulher (pam ). % f a t o mulher ( l i z ). % f a t o mulher ( pat ). % f a t o mulher ( ann ). % f a t o homem( tom ). % f a t o homem( bob ). % f a t o homem( jim ). % f a t o p r o l e (Y,X) :− g e n i t o r (X,Y ). % r e g r a mae (X,Y) :− g e n i t o r (X,Y) , mulher (X ). % r e g r a avos (X, Z) :− g e n i t o r (X,Y) , g e n i t o r (Y, Z ). % r e g r a irma (X,Y) :− g e n i t o r (Z ,X) , g e n i t o r (Z ,Y) , mulher (X ). % r e g r a d e s c e n d e n t e (X, Z) :− g e n i t o r (X, Z ). % r e g r a d e s c e n d e n t e (X, Z) :− g e n i t o r (X,Y) , d e s c e n d e n t e (Y, Z ). % r e g r a r e c u r s i v a

Um conjunto de regras utilizados para descrever uma única relação é, em geral, chamada de procedimento (procedure). Assim, as regras relacionadas à descendência, ilustradas no exemplo, podem ser denominadas de procedimento.

5.3 Como Prolog responde consultas

Uma consulta Prolog é sempre um conjunto de metas. Quando uma pergunta é feita, Prolog precisa satisfazer todas as metas. Isso, como já armado, é equivalente a provar um teorema ou realizar uma dedução. Para isso, Prolog busca vericar se a(s) meta(s) são conseqüências lógicas dos fatos e regras contidos no programa. Para ilustrar o pro- cedimento executado para responder uma consulta será utilizado o programa de exemplo, relacionado à relacionamentos familiares. Diga-se que a consulta ?- descendente(tom, pat). seja realizada. Sabe-se que descen- dente(bob, pat) é um fato existente no programa. Este fato seria derivado a partir da primeira regra relacionada a descendência. Além disso, sabe-se que a regra genitor(tom, bob) é um fato. Com isso, e o fato derivado descendente(bob, pat) pode-se concluir de- scendente(tom, pat) utilizando a segunda regra relacionada à descendência existente no programa. Isso ilustra o que foi utilizado pra realizar a prova, será apresentado agora como esta prova foi obtida. Prolog encontra uma prova na ordem inversa a forma ilustrada anteriormente. Prolog inicia com uma meta e, utilizando regras, substitui estas metas por novas metas, até que uma meta seja satisfeita por um fato. Assim, feita a pergunta descendente(tom, pat), Prolog procede da seguinte maneira. Para satisfazer esta meta é procurada alguma cláusula (fato ou regra) da qual a meta possa ser deduzida. Então, são encontradas as duas regras relacionadas à descendência existentes no programa, pois, a cabeça da regra corresponde à meta. Como a regra de-

scendente(X,Z) :- genitor(X,Z). aparece primeiro, e como a meta atual é descendente(tom, pat), as variáveis são substituídas, tal como a seguir:

X = tom, Z = pat

a meta descendente(tom, pat) é substituída pela meta genitor(tom, pat). Como não existe uma cláusula onde a cabeça seja correspondente a esta, Prolog realiza um encaminhamento para trás, ou seja, retorna a meta original para tentar encontrar uma maneira alternativa de satisfazê-la. Então, a regra descendente(X,Z) :- genitor(X,Y), descendente(Y,Z). será utilizada. Mais uma vez, as variáveis X e Z serão substituídas por tom e pat respectivamente, porém Y ainda não foi substituída. Assim, a meta atual dá lugar as metas genitor(tom,Y), descendente(Y, pat). Prolog deve agora satisfazer a conjunção de metas genitor(tom,Y), descendente(Y, pat), isso é feito na ordem em que as metas estão escritas, ou seja, primeiramente Prolog irá tentar satisfazer genitor(tom,Y). Realizando uma busca por cláusulas que satisfaçam a meta, Prolog encontra o fato genitor(tom, bob), assim, Y é substituída por bob. Com isso, a meta atual é descendente(bob, pat). Para satisfazer esta meta a regra descendente(X,Z) :- genitor(X,Z) será usada nova- mente. Observe que esta é uma nova seqüencia de prova, sendo assim, as substituições anteriores não possuem nenhuma relação com esta. Com isso, Prolog usa um novo con- junto de variáveis, e assim, pode-se reescrever a regra como descendente(X1,Z1) :- geni- tor(X1,Z1). Assim, como a cabeça deve corresponder meta, as seguintes substituições são realizadas:

X = bob, Z = pat

e então, a meta atual é trocada para nova meta genitor(bob, pat). Como esta é satisfeita por um fato presente no programa o procedimento acaba.

6 Listas

Listas são um dos tipos de dados mais úteis existentes na linguagem Prolog, diz-se que uma lista é uma seqüência ordenada de uma quantidade qualquer de elementos. Os elementos de uma lista podem ser de qualquer tipo, tais como, números ou átomos. Os elementos contidos em uma lista devem ser separados por vírgulas, e precisam estar entre colchetes. Por exemplo, uma lista pode conter os nomes dos indivíduos do exemplo da seção anterior, esta lista seria denida como:

[pam, liz, pat, ann, tom, bob, jim]

Existem dois tipos de listas, as listas vazias e as não vazias. Uma lista vazia é repre- sentada por [ ]. Listas não vazias podem ser divididas em duas partes, são elas:

  • cabeça - corresponde ao primeiro elemento da lista;
  • cauda - corresponde aos elementos restantes da lista.

Por exemplo, para a lista:

conc([a,b], [], [a,b]) = true conc([a,b], [c,d], [a,b,c,d]) = true

Para denir esta relação é pode-se implementar as seguintes regras: conc ( [ ] , L , L ). conc ( [X| L1 ] , L2 , [X| L3 ] ) :− conc ( L1 , L2 , L3 ).

Denidas as regras, pode-se realizar as seguintes consultas: 6 ?− conc ( [ a , b ] , [ c ] , L ). L = [ a , b , c ] ; No 7 ?− conc ( [ a ] , [ b , c ] , L ). L = [ a , b , c ] ; No

As regras denidas também podem ser usadas para decompor uma lista em suas componentes. Para checar isso, basta realizar a seguinte consulta:

6 ?− conc ( L1 , L2 , [ a , b , c ] ). L1 = [ ] L2 = [ a , b , c ] ; L1 = [ a ] L2 = [ b , c ] ; L1 = [ a , b ] L2 = [ c ] ; L1 = [ a , b , c ] L2 = [ ] ; No

6.3 Adicionando elementos

A adição de um elemento à uma lista pode ser denida de modo simples. Para isso, basta inserir o elemento no início da lista, esta relação é denida através da seguinte regra:

i n s e r e (X, L , [X | L ] ).

com isso, pode-se realizar as seguintes inserções:

7 ?− i n s e r e ( a , [ b , c ] , L ). L = [ a , b , c ] ; No 8 ?− i n s e r e ( [ 1 , 2 ] , 3 , L ). L = [ [ 1 , 2 ] | 3 ] ; No

6.4 Excluindo elementos

A exclusão de um elemento pode ser implementada através das seguintes regras:

e x c l u i (X, [X | T a i l ] , T a i l ). e x c l u i (X, [Y | T a i l ] , [Y | T a i l 1 ] ) :− e x c l u i (X, T a i l , T a i l 1 ).

a primeira regra é utilizada quando o elemento que se deseja excluir corresponde à cabeça da lista. Já a segunda regra exclui um elemento que pertence a cauda da lista. Vale

salientar que esta implementação não exclui todos os elementos existentes na lista que correspondam ao elemento passado como argumento. Denidas as regras podem ser realizadas as seguintes consultas: 9 ?− e x c l u i ( a , [ a , b , c ] , L ). L = [ b , c ] ; No 10 ?− e x c l u i ( b , [ a , b , c ] , L ). L = [ a , c ] ; No 11 ?− e x c l u i ( c , [ a , c , b , c ] , L ). L = [ a , b , c ] ; L = [ a , c , b ] ; No

Existem diversas outras operações nativas de Prolog, um exercício interessante seria realizar a implementação de algumas operações. Pode-se, por exemplo, criar uma operação para checar se uma lista está contida em outra ou uma operação para realizar permutação dos elementos.

7 Aritmética

Geralmente, quando se escreve uma expressão matemática a notação inxa é utilizada, por exemplo 2 ∗a+b∗c, onde 2 , a, b e c são argumentos e + e ∗ são operadores. Em Prolog uma expressão é representada internamente como uma árvore, assim a expressão anterior seria representada pela árvore da Figura 4. Uma maneira de representar em Prolog a expressão em questão utiliza notação prexa, a expressão seria representada como +(∗(2, a), ∗(b, c)). Porém, por ser mais usual a representação inxa também é compreendida pela linguagem.

Figura 4: Árvore para a expressão 2 ∗ a + b ∗ c

Prolog possui denidos operadores para as quatro operações: +, −, ∗, /, para realizar soma, subtração, multiplicação e divisão, respectivamente. Para se obter o resultado de uma operação é necessário utilizar o operador is, tal como ilustrado nas consultas abaixo: 3 ?− X i s 2 + 3. X = 5 ; No 4 ?− X i s 4 − 1. X = 3 ; No 5 ?− X i s 2 ∗ 5.