Prolog – 06
Inteligência Artificial
Fábio M. Pereira
Baseado em
Amzi! inc. – www.amzi.com
Aventura em Prolog 2
Aventura em Prolog
 Recursão
 Como a recursão funciona
 Pragmática
 Exercícios
Aventura em Prolog 3
Recursão
 É a habilidade de uma unidade de
código chamar a ela mesma,
repetidamente, se necessário
 É frequentemente uma maneira muito
poderosa e conveniente de representar
certos construtores de programação
 Em Prolog, a recursão ocorre quando
um predicado contém um objetivo que
se refere a ele mesmo
Aventura em Prolog 4
Recursão
 Toda vez que uma regra é chamada,
Prolog usa o corpo da regra para criar
uma nova consulta com novas variáveis
 Uma vez que a consulta é uma nova
cópia cada vez que é chamada, não faz
diferença se uma regra chama outra
regra ou a ela mesma
Aventura em Prolog 5
Recursão
 Uma definição recursiva sempre tem
pelo menos duas partes
 A condição limite (caso base): define um
caso simples que sabemos ser verdadeiro
 O caso recursivo: simplifica o problema
primeiro removendo uma camada de
complexidade, e então chamando ela
mesma
 Em cada nível, a condição limite é testada,
se verdadeira, a recursão pára, se não, a
recursão continua
Aventura em Prolog 6
Exemplo – Nani Search
 Objetos próximos ou aninhados
 O predicado local/2 nos diz que a lanterna
está na escrivaninha e que a escrivaninha
está no escritório, mas não nos indica que a
lanterna está no escritório
?- local(lanterna,escritório).
no
 Usando recursão, iremos escrever um
novo predicado esta_contido_em/2, o
qual irá “cavar” através de camadas de
objetos aninhados
Aventura em Prolog 7
Exemplo – Nani Search
 Para tornar o problema mais
interessante, primeiro iremos adicionar
mais itens aninhados no jogo
 Iremos continuar usando o predicado
local/2 para colocar objetos na
escrivaninha, que por sua vez, podem
conter outros objetos dentro deles
local(envelope, escrivaninha).
local(selo, envelope).
local(chave, envelope).
Aventura em Prolog 8
Exemplo – Nani Search
 Para listar todas as coisas no escritório:
 Primeiro devemos listar os objetos que
estão diretamente no escritório, como a
escrivaninha
 Depois devemos listar os objetos que estão
na escrivaninha
 A seguir objetos que estão dentro dos
objetos que estão na escrivaninha
Aventura em Prolog 9
Exemplo – Nani Search
 A regra:
 Um objeto, O1, está contido em outro
objeto, O2, se O1 está diretamente
localizado em O2  Esta é a condição limite
 Um objeto, O1, está contido em outro
objeto, O2, se algum objeto intermediário,
X, está localizado em O2 e O1 está contido
em X  Aqui é onde nós simplificamos e
fazemos a recursão
Aventura em Prolog 10
Exemplo – Nani Search
 Em Prolog:
 Caso base:
esta_contido_em(O1, O2):-
local(O1, O2).
 Caso recursivo:
esta_contido_em(O1, O2):-
local(X, O2),
esta_contido_em(O1, X).
Aventura em Prolog 11
Exemplo – Nani Search
 Testando...
?- esta_contido_em(X, escritório).
X = escrivaninha ;
X = computador ;
X = lanterna ;
X = envelope ;
X = selo ;
X = chave ;
no
?- esta_contido_em(envelope, escritório).
yes
?- esta_contido_em(maçã, escritório).
no
Aventura em Prolog 12
Como a Recursão Funciona
 Como em todas as chamadas a regras,
as variáveis em uma regra são únicas,
ou o escopo delas é a regra
 Em um caso recursivo, isto significa que
cada chamada à regra, em cada nível,
possui seu próprio conjunto único de
variáveis
 Assim, os valores de X, O1 e O2 no primeiro
nível da recursão são diferentes daqueles
dos segundo nível
Aventura em Prolog 13
Como a Recursão Funciona
 Porém, a unificação entre um objetivo e
a cabeça de uma cláusula obrigue um
relacionamento entre as variáveis de
diferentes níveis
 Acompanhe a execução da consulta a
seguir...
?- esta_contido_em(XQ, escritório).
Aventura em Prolog 14
esta_contido_em(XQ, escritório).
No primeiro nível de recursão:
esta_contido_em(O11, O21) :-
local(X1, O21),
esta_contido_em(O11, X1).
XQ = _01
O11 = _01
O21 = escritório
X1 = _02
Reescrita:
esta_contido_em(_01, escritório) :-
local(_02, escritório),
esta_contido_em(_01, _02).
local/2 satisfeito com _02 = escrivaninha
esta_contido_em(_01, escrivaninha)
Este objetivo unifica com a cabeça de uma nova cópia
da cláusula, no próximo nível de recursão. Após a
unificação, as variáveis são:
XQ = _01 O11 = _01 O12 = _01
O21 = escritório O22 = escrivaninha
X1 = escrivaninha X2 = _03
Aventura em Prolog 15
Como a Recursão Funciona
 Quando a recursão encontra uma solução,
como em ‘envelope’, todos os O1s e X0
imediatamente assumem um valor – utilize o
modo de debug para acompanhar a execução
 Ao escrever um predicado recursivo, é
essencial garantir que a condição limite seja
checada em cada nível, em outro caso, o
programa poderá entrar em loop infinito
 A maneira mais simples de fazer isso, é sempre
definir a condição limite primeiro, garantindo que
ela sempre será tentada antes do caso recursivo
Aventura em Prolog 16
Pragmática
 Considere que o objetivo local(X,Y) será
satisfeito por todas as cláusulas de
local/2
 Por outro lado, os objetivos local(X,
escritório) e local(envelope, X) serão
satisfeitos por poucas cláusulas
 Observe no slide a seguir duas versões
para a regra esta_contido_em/2...
Aventura em Prolog 17
Pragmática
 Ambos darão respostas corretas, mas a
performance de cada um irá depender da
consulta:
 A consulta esta_contido_em(X, escritório) irá
executar mais rápido na primeira versão
 O2 é linkada fazendo com que a busca por local(X,
O2) seja mais fácil do que a busca por duas
variáveis não linkadas
 Por razões similares, a consulta esta_contido_em
(chave, X) seja mais rapidamente executada na
segunda versão
esta_contido_em(O1, O2):-
local(X, O2),
esta_contido_em(O1, X).
esta_contido_em(O1, O2):-
local(O1, X),
esta_contido_em(X, O2).
Aventura em Prolog 18
Exercícios
 Banco de dados genealógico
 Utilize recursão para escrever o predicado
ancestral/2
 Utilize ancestral/2 para encontrar todos os
ancestrais e todos os descendentes de uma
pessoa
 Escreva um predicado descendente/2 que
seja otimizado para descendentes, oposto a
ancestral/2, que deve ser otimizado para
ancestrais
Aventura em Prolog 19
O que vem a seguir?
 Estruturas de Dados
 Unificação
 ...

Aula de Prolog 06 - Recursão

  • 1.
    Prolog – 06 InteligênciaArtificial Fábio M. Pereira Baseado em Amzi! inc. – www.amzi.com
  • 2.
    Aventura em Prolog2 Aventura em Prolog  Recursão  Como a recursão funciona  Pragmática  Exercícios
  • 3.
    Aventura em Prolog3 Recursão  É a habilidade de uma unidade de código chamar a ela mesma, repetidamente, se necessário  É frequentemente uma maneira muito poderosa e conveniente de representar certos construtores de programação  Em Prolog, a recursão ocorre quando um predicado contém um objetivo que se refere a ele mesmo
  • 4.
    Aventura em Prolog4 Recursão  Toda vez que uma regra é chamada, Prolog usa o corpo da regra para criar uma nova consulta com novas variáveis  Uma vez que a consulta é uma nova cópia cada vez que é chamada, não faz diferença se uma regra chama outra regra ou a ela mesma
  • 5.
    Aventura em Prolog5 Recursão  Uma definição recursiva sempre tem pelo menos duas partes  A condição limite (caso base): define um caso simples que sabemos ser verdadeiro  O caso recursivo: simplifica o problema primeiro removendo uma camada de complexidade, e então chamando ela mesma  Em cada nível, a condição limite é testada, se verdadeira, a recursão pára, se não, a recursão continua
  • 6.
    Aventura em Prolog6 Exemplo – Nani Search  Objetos próximos ou aninhados  O predicado local/2 nos diz que a lanterna está na escrivaninha e que a escrivaninha está no escritório, mas não nos indica que a lanterna está no escritório ?- local(lanterna,escritório). no  Usando recursão, iremos escrever um novo predicado esta_contido_em/2, o qual irá “cavar” através de camadas de objetos aninhados
  • 7.
    Aventura em Prolog7 Exemplo – Nani Search  Para tornar o problema mais interessante, primeiro iremos adicionar mais itens aninhados no jogo  Iremos continuar usando o predicado local/2 para colocar objetos na escrivaninha, que por sua vez, podem conter outros objetos dentro deles local(envelope, escrivaninha). local(selo, envelope). local(chave, envelope).
  • 8.
    Aventura em Prolog8 Exemplo – Nani Search  Para listar todas as coisas no escritório:  Primeiro devemos listar os objetos que estão diretamente no escritório, como a escrivaninha  Depois devemos listar os objetos que estão na escrivaninha  A seguir objetos que estão dentro dos objetos que estão na escrivaninha
  • 9.
    Aventura em Prolog9 Exemplo – Nani Search  A regra:  Um objeto, O1, está contido em outro objeto, O2, se O1 está diretamente localizado em O2  Esta é a condição limite  Um objeto, O1, está contido em outro objeto, O2, se algum objeto intermediário, X, está localizado em O2 e O1 está contido em X  Aqui é onde nós simplificamos e fazemos a recursão
  • 10.
    Aventura em Prolog10 Exemplo – Nani Search  Em Prolog:  Caso base: esta_contido_em(O1, O2):- local(O1, O2).  Caso recursivo: esta_contido_em(O1, O2):- local(X, O2), esta_contido_em(O1, X).
  • 11.
    Aventura em Prolog11 Exemplo – Nani Search  Testando... ?- esta_contido_em(X, escritório). X = escrivaninha ; X = computador ; X = lanterna ; X = envelope ; X = selo ; X = chave ; no ?- esta_contido_em(envelope, escritório). yes ?- esta_contido_em(maçã, escritório). no
  • 12.
    Aventura em Prolog12 Como a Recursão Funciona  Como em todas as chamadas a regras, as variáveis em uma regra são únicas, ou o escopo delas é a regra  Em um caso recursivo, isto significa que cada chamada à regra, em cada nível, possui seu próprio conjunto único de variáveis  Assim, os valores de X, O1 e O2 no primeiro nível da recursão são diferentes daqueles dos segundo nível
  • 13.
    Aventura em Prolog13 Como a Recursão Funciona  Porém, a unificação entre um objetivo e a cabeça de uma cláusula obrigue um relacionamento entre as variáveis de diferentes níveis  Acompanhe a execução da consulta a seguir... ?- esta_contido_em(XQ, escritório).
  • 14.
    Aventura em Prolog14 esta_contido_em(XQ, escritório). No primeiro nível de recursão: esta_contido_em(O11, O21) :- local(X1, O21), esta_contido_em(O11, X1). XQ = _01 O11 = _01 O21 = escritório X1 = _02 Reescrita: esta_contido_em(_01, escritório) :- local(_02, escritório), esta_contido_em(_01, _02). local/2 satisfeito com _02 = escrivaninha esta_contido_em(_01, escrivaninha) Este objetivo unifica com a cabeça de uma nova cópia da cláusula, no próximo nível de recursão. Após a unificação, as variáveis são: XQ = _01 O11 = _01 O12 = _01 O21 = escritório O22 = escrivaninha X1 = escrivaninha X2 = _03
  • 15.
    Aventura em Prolog15 Como a Recursão Funciona  Quando a recursão encontra uma solução, como em ‘envelope’, todos os O1s e X0 imediatamente assumem um valor – utilize o modo de debug para acompanhar a execução  Ao escrever um predicado recursivo, é essencial garantir que a condição limite seja checada em cada nível, em outro caso, o programa poderá entrar em loop infinito  A maneira mais simples de fazer isso, é sempre definir a condição limite primeiro, garantindo que ela sempre será tentada antes do caso recursivo
  • 16.
    Aventura em Prolog16 Pragmática  Considere que o objetivo local(X,Y) será satisfeito por todas as cláusulas de local/2  Por outro lado, os objetivos local(X, escritório) e local(envelope, X) serão satisfeitos por poucas cláusulas  Observe no slide a seguir duas versões para a regra esta_contido_em/2...
  • 17.
    Aventura em Prolog17 Pragmática  Ambos darão respostas corretas, mas a performance de cada um irá depender da consulta:  A consulta esta_contido_em(X, escritório) irá executar mais rápido na primeira versão  O2 é linkada fazendo com que a busca por local(X, O2) seja mais fácil do que a busca por duas variáveis não linkadas  Por razões similares, a consulta esta_contido_em (chave, X) seja mais rapidamente executada na segunda versão esta_contido_em(O1, O2):- local(X, O2), esta_contido_em(O1, X). esta_contido_em(O1, O2):- local(O1, X), esta_contido_em(X, O2).
  • 18.
    Aventura em Prolog18 Exercícios  Banco de dados genealógico  Utilize recursão para escrever o predicado ancestral/2  Utilize ancestral/2 para encontrar todos os ancestrais e todos os descendentes de uma pessoa  Escreva um predicado descendente/2 que seja otimizado para descendentes, oposto a ancestral/2, que deve ser otimizado para ancestrais
  • 19.
    Aventura em Prolog19 O que vem a seguir?  Estruturas de Dados  Unificação  ...