Ensino de IA Simbólica
com Abordagem à Resolução de Problemas
Vivian Cremer Claudio Cesar de S ´a
viviancremer@yahoo.com.br claudio@joinville.udesc.br
Roteiro da Aula - Parte II
Principais métodos de busca;
Exemplo 1: Problema do labirinto (Busca em Largura);
Exemplo 2: Problema do pastor, lobo, ovelha e repolho
(Busca em Profundidade);
Exemplo 3: Problema do caminho mínimo (
A
∗).
Métodos de Buscas
O objetivo é apresentar os principais métodos de
busca;
Quando aplicados a problemas em particular, sua
eficácia torna-se altamente dependente do modo
como eles exploram o conhecimento específico de
cada domínio de aplicação.
Métodos de Busca
Métodos de buscas cegas:
Busca em Largura;
Busca em Profundidade;
Busca em Largura com Custo Uniforme;
Busca com Profundidade Limitada;
Busca em Profundidade Iterativa;
Busca Bidirecional.
Métodos de Busca
Métodos de buscas heurísticas:
Busca gulosa;
Algoritmo
A
∗;
Algoritmo
IDA
∗;
Exemplo 1: Problema do Labirinto
entrada
saída 1
saída 2
7
1
8
14
19
20
21
9
15
22
16
10
11
12
18
17
23
4
5
6
2
3
Regras para o Labirinto
As regras que conduzem o caminho por entre o labirinto
são dadas por:
1.
Entrar no labirinto ::
[entrada]
|
{liga(entrada,X)}
=⇒
[X]
|
{}
2.
Mover-se de um lugar para outro ::
[X]
|
{liga(X,Y)}
=⇒
[Y]
|
{}
3.
Sair do labirinto ::
[X]
|
{liga(X,saida)}
=⇒
[saida]
|
{}
Em Prolog ...
conexao(A,B) :- liga(A,B). conexao(A,B) :- liga(B,A).
liga(entrada,7). liga(7,8). liga(7,1). liga(8,14). liga(8,9). liga(14,20). liga(9,15). liga(20,19). liga(20,21). liga(15,21). liga(21,22). liga(22,16). liga(16,10). liga(10,11). liga(11,12). liga(12,18). liga(12,6). liga(18,17). liga(18,saida2). liga(17,23). liga(23,saida2). liga(6,5). liga(5,4). liga(1,2). liga(2,3). liga(3,saida1).
←-Voltar
EE para o Labirinto
←-
Voltar
entrada 7 1 8 9 14 2 20 15 3 21 19 22 16 10 11 12 6 18 17 saída 1Busca em Largura
1
2
4
5
9
6
10
7
8
3
Nível 0
Nível 1
Nível 2
Nível 3
a
b
c
d
e
f
g
h
i
j
Procedimento de Busca
busca_largura([[Nodo|Caminho]|_],[Nodo|Caminho]):-objetivo(Nodo).
busca_largura([Nodo|Caminho],Solucao):-expandir(Nodo, Expansao_do_Nodo),
append(Caminho,Expansao_do_Nodo, Novo_caminho),
busca_largura(Novo_caminho, Solucao).
Código Fonte
labirinto :- caminho(entrada,Solucao),
reverse(Solucao,Sol_invertida),
write(’Caminho: ’),
imprima(Sol_invertida),
write(’\n’).
labirinto.
todas_saidas :- labirinto, fail.
imprima([]):- !.
imprima([Cabeca|_]):- objetivo(Cabeca),
write(Cabeca),!.
imprima([Cabeca|Cauda]):- !,write(Cabeca), write(’,’),
imprima(Cauda).
imprima(Arg):- write(Arg).
Código Fonte
caminho(Nodo_inicial,
Solucao):-busca_largura([[Nodo_inicial]], Solucao).
busca_largura([[Nodo|Caminho]|_],[Nodo|Caminho]):-objetivo(Nodo).
busca_largura([Nodo|Caminho],Solucao):-expandir(Nodo, Expansao_do_Nodo),
append(Caminho,Expansao_do_Nodo, Novo_caminho),
busca_largura(Novo_caminho, Solucao).
Código Fonte
expandir([Nodo|Caminho],Expansao_do_Nodo)
:-findall([Novo_nodo,Nodo|Caminho],
(conexao(Nodo, Novo_nodo),
not(member(Novo_nodo,[Nodo|Caminho]))),
Expansao_do_Nodo), !.
expandir(_,[]).
Código Fonte
conexao(A,B) :- liga(A,B). conexao(A,B) :- liga(B,A).
/*********************************************** * Representacao da conectividade do labirinto * ***********************************************/
liga(entrada,7). liga(7,8). liga(7,1). liga(8,14). liga(8,9). liga(14,20). liga(9,15). liga(20,19). liga(20,21). liga(15,21). liga(21,22). liga(22,16). liga(16,10). liga(10,11). liga(11,12). liga(12,18). liga(12,6). liga(18,17). liga(18,saida2). liga(17,23). liga(23,saida2). liga(6,5). liga(5,4). liga(1,2). liga(2,3). liga(3,saida1).
Resultados
?- labirinto.
Caminho:
entrada,7,1,2,3,saida1
Yes
Resultados
?- todas_saidas.
Caminho: entrada,7,1,2,3,saida1
Caminho: entrada,7,8,14,20,21,22,16,10,11,12,18,saida2
Caminho: entrada,7,8,9,15,21,22,16,10,11,12,18,saida2
Caminho: entrada,7,8,14,20,21,22,16,10,11,12,18,17,23,saida2
Caminho: entrada,7,8,9,15,21,22,16,10,11,12,18,17,23,saida2
No
?-Exemplo 2: Problema do Pastor
Rio
Barco c/
2 lugares
Pastor
Lobo
Ovelha
Repolho
Definindo estado inicial e final
X
Estado inicial:
[esquerda,esquerda,esquerda,esquerda], isto é,
[P,L,O,R] se encontram na margem esquerda;
X
Estado Final: [direita,direita,direita,direita], isto é,
[P,L,O,R] chegarem com segurança a margem oposta
do rio;
X
Exemplo: [direita,esquerda,direita,esquerda], quer dizer
que o Pastor e a Ovelha encontram-se na margem
direita do rio, enquanto que o Lobo e o Repolho
encontram-se na margem esquerda do rio.
Regras do Problema do Pastor
As regras que conduzem a travessia são:
1.
Ir o homem sozinho ::
[X,L,O,R]
|
{oposto(X,Y), seguro(Y,L,O,R)}
=⇒
[Y,L,O,R]
|
{ }
J
2.
Ir o homem com o lobo ::
[X,X,O,R]
|
{oposto(X,Y), seguro(Y,Y,O,R)}
=⇒
[Y,Y,O,R]
|
{ }
J
3.
Ir o homem com a ovelha ::
[X,L,X,R]
|
{oposto(X,Y), seguro(Y,L,Y,R)}
=⇒
[Y,L,Y,R]
|
{ }
J
4.
Ir o homem com o repolho ::
[X,L,O,X]
|
{oposto(X,Y), seguro(Y,L,O,Y)}
=⇒
[Y,L,O,Y]
|
{ }
J
Regra 1
move(estado(X,L,O,R),estado(Y,L,O,R)):-oposto(X,Y).
oposto(esquerda,direita).
oposto(direita,esquerda).
/* O lobo come a ovelha */
inseguro( estado(P,X,X,_) ):- oposto(P,X),!.
/* A ovelha come o repolho */
Regra 2
move(estado(X,X,O,R),estado(Y,Y,O,R)):-oposto(X,Y).
←-
Voltar
Regra 3
move(estado(X,L,X,R),estado(Y,L,Y,R)):-oposto(X,Y).
Regra 4
move(estado(X,L,O,X),estado(Y,L,O,Y)):-oposto(X,Y).
←-
Voltar
EE para o Problema do Pastor
P L O R L R P L R L P O O P O R R P L O L R P O P L O R P O R L*
*
O P L R P O L R P L O R O P L R P O L R P L O R←-
Voltar
Busca em Profundidade
1
2
3
4
5
6
8
10
9
11
7
Procedimento de Busca:
busca_profundidade( X , L)
:-X == estado(direita,direita,direita,direita), nl,
write(’==============================================’), qtd_move(L,N),
write(’\n Uma solu\c{c}{\˜a}o com ’), write(N), write(’ movimentos {\’e} dada por:: \n’),
reverse(L,L_invertida), imprima_caminho(L_invertida). busca_profundidade(Estado_inicial, Visitados):-move(Estado_inicial,Proximo_estado), not( inseguro(Proximo_estado) ), not( eh_membro(Proximo_estado,Visitados) ),
Código Fonte
travessia
:-busca_profundidade(estado(esquerda,esquerda,esquerda,esquerda), [estado(esquerda,esquerda,esquerda,esquerda)]).
travessia.
todas_travessias :- travessia, fail.
Código Fonte
busca_profundidade( X , L)
:-X == estado(direita,direita,direita,direita), nl,
write(’==============================================’), qtd_move(L,N),
write(’\n Uma solucao com ’), write(N), write(’ movimentos {\’e} dada por:: \n’), reverse(L,L_invertida), imprima_caminho(L_invertida). busca_profundidade(Estado_inicial, Visitados):-move(Estado_inicial,Proximo_estado), not( inseguro(Proximo_estado) ), not( eh_membro(Proximo_estado,Visitados) ),
Código Fonte
/* Move Pastor + Lobo */
move(estado(X,X,O,R),estado(Y,Y,O,R)):-oposto(X,Y).
/*Move Pastor + Ovelha */
move(estado(X,L,X,R),estado(Y,L,Y,R)):-oposto(X,Y).
/* Move Pastor + Repolho */
move(estado(X,L,O,X),estado(Y,L,O,Y)):-oposto(X,Y).
/* Move Pastor sozinho */
move(estado(X,L,O,R),estado(Y,L,O,R)):-oposto(X,Y).
Código Fonte
/* Declarando o conceito de oposto */
oposto(esquerda,direita).
oposto(direita,esquerda).
/* O lobo come a ovelha */
inseguro( estado(P,X,X,_) ):- oposto(P,X),!.
/* A ovelha come o repolho */
Código Fonte
qtd_move([],0).
qtd_move([_|L],N)
:-qtd_move(L,N1),
N is N1 + 1.
eh_membro(X,[X|_]):-!.
eh_membro(X,[_|L]):- eh_membro(X,L).
imprima_caminho( [H1,H2|T] )
:-imprima_movimento(H1,H2),
imprima_caminho([H2|T]).
imprima_caminho( _ ).
Código Fonte
/* as travessias */
imprima_movimento( estado(X,W,G,C), estado(Y,W,G,C) ) :-!, write(’O Pastor atravessa o rio da margem ’),
write(X), write(’ para a margem ’), write(Y), nl.
imprima_movimento( estado(X,X,G,C), estado(Y,Y,G,C) ) :-!, write(’O Pastor leva o Lobo da margem ’),
write(X), write(’ do rio para a margem ’), write(Y),nl.
imprima_movimento( estado(X,W,X,C), estado(Y,W,Y,C) ) :-!, write(’O Pastor leva a Ovelha da margem ’),
write(X), write(’ do rio para a margem ’), write(Y),nl.
imprima_movimento( estado(X,W,G,X), estado(Y,W,G,Y) ) :-!, write(’O Pastor leva o Repolho da margem ’),
Resultados
?- travessia.
============================================== Uma solução com 8 movimentos é dada por::
O Pastor leva a Ovelha da margem esquerda do rio para a margem direita O Pastor atravessa o rio da margem direita para a margem esquerda
O Pastor leva o Lobo da margem esquerda do rio para a margem direita O Pastor leva a Ovelha da margem direita do rio para a margem esquerda O Pastor leva o Repolho da margem esquerda do rio para a margem direita O Pastor atravessa o rio da margem direita para a margem esquerda
O Pastor leva a Ovelha da margem esquerda do rio para a margem direita Yes
Resultados
?- todas_travessias.
============================================== ...
============================================== Uma solução com 8 movimentos é dada por::
O Pastor leva a Ovelha da margem esquerda do rio para a margem direita O Pastor atravessa o rio da margem direita para a margem esquerda
O Pastor leva o Repolho da margem esquerda do rio para a margem direita O Pastor leva a Ovelha da margem direita do rio para a margem esquerda O Pastor leva o Lobo da margem esquerda do rio para a margem direita O Pastor atravessa o rio da margem direita para a margem esquerda
O Pastor leva a Ovelha da margem esquerda do rio para a margem direita No
Exemplo 3: Problema do caminho mínimo
Garuva
Joinville
Itajaí
Balneário
Camboriú
Blumenau
Brusque
Jaraguá
Rio do Sul
São Bento
Lages
Caçador
36
53
45
94
9
43
40
47
67
89
134
301
Mafra 65
74
68
204
Regras do problema
Algumas regras se fazem necessárias, tais como:
Partir de Joinville ::
[Joinville]
|
{estrada(Joinville,C,D), D é a menor distância }
=⇒
[C]
|
{ }
Mover-se de uma cidade qualquer para outra ::
[A]
|
{estrada(A,B,D), D é a menor distância }
=⇒
[B]
|
{ }
Chegar em Lages ::
[C]
|
{estrada(C,Lages,D), D é a menor distância }
=⇒
[Lages]
|
{ }
Regras
estrada(bal_camboriu, brusque, 43). estrada(bal_camboriu,itajai, 9). estrada(blumenau, brusque, 40). estrada(blumenau, itajai, 47). estrada(blumenau, jaragua, 67). estrada(blumenau, rio_do_sul, 89). estrada(cacador, jaragua, 301). estrada(cacador, mafra, 204). estrada(garuva, joinville, 36). estrada(garuva, sao_bento, 74). estrada(itajai, joinville, 94). estrada(jaragua, joinville, 53). estrada(jaragua, sao_bento, 45). estrada(joinville, sao_bento, 68). estrada(mafra, sao_bento, 65). estrada(rio_do_sul, lages, 134). ←-VoltarEE do problema
Joinville
Garuva Itajaí
São Bento Joinville Camboriú Blumenau Joinville
... ...
... ... ...
Algoritmo
A
∗
A
∗é uma maneira de melhorar o algoritmo de busca em
largura com custo uniforme e o algoritmo de busca
gulosa, combinando duas funções:
f
(n) = g(n) + h(n)
Raiz
n
Meta g(n)
h(n)
Heurística utilizada
Os valores de h(n) são distâncias estimadas em linha reta
até Lages
Balneário Camboriú
275
Jaraguá do Sul
275
Blumenau
219
Joinville
316
Brusque
203
Lages
0
Caçador
162
Mafra
265
Garuva
353
Rio do Sul
134
Itajaí
266
São Bento do Sul
320
Em Prolog ...
distancia( Cidade,lages,H):-distancia( Cidade,H). distancia(bal_camboriu ,275). distancia(blumenau ,219). distancia(brusque ,203). distancia(cacador ,162). distancia(garuva ,353). distancia(itajai ,266). distancia(jaragua ,275). distancia(joinville ,310). distancia(mafra ,265). distancia(rio_do_sul ,134). distancia(sao_bento ,320). distancia(lages ,0). ←-VoltarEstágios que a busca realiza
←-Voltar
(c) Depois da expansão de Jaraguá do Sul
S. Bento Jaraguá
Itajaí Garuva
(b) Depois da expansão de Joinville
Joinville
(a) Estado inicial
316 = 0 + 316
389 = 36 + 353 360 = 94 + 266 328 = 53 + 275 388 = 68 + 320 Joinville
Joinville
Estágios que a busca realiza
S.Bento
Joinville
Jaraguá
Itajaí
Garuva
(d) Depois da expansão de Blumenau
Rio do Sul
Brusque
363 = 160 + 203 433 = 167 + 266 462 = 187 + 275 343 = 209 + 134
Caçador
Blumenau
Jaraguá
Itajaí
Joinville
S.Bento
Estágios que a busca realiza
(e) Depois da expansão de Rio do Sul
Lages
S.Bento
Joinville
Jaraguá
Itajaí
Garuva
Rio do Sul
Brusque
Caçador
Blumenau
Joinville
Itajaí
Jaraguá
S.Bento
Blumenau
Procedimento de Busca
a_estrela([[Objetivo|Rota]|_],Objetivo,Rota_final):-reverse([Objetivo|Rota], Rota_final).
a_estrela([Rota|Lista],Objetivo,Rota_final)
:-expandir(Rota,Expansao_caminho),
append(Lista,Expansao_caminho,Novo_caminho),
classifica(Novo_caminho,Objetivo,Lista_classificada),
a_estrela(Lista_classificada,Objetivo,Rota_final).
Código Fonte
rota :- a_estrela([[joinville]],lages, Rota), nl,
write(’Caminho:’),
imprima(Rota), nl,
write(’Dist{\ˆa}ncia de: ’),
g(Rota, Custo),
write(Custo), nl.
rota.
todas_rotas :- rota, fail.
imprima([]):- !.
imprima([lages|_]):-cidade(lages),!.
imprima([Cabeca|Cauda]):- !,cidade(Cabeca), write(’,’),
imprima(Cauda).
Código Fonte
cidade(bal_camboriu) :- write(’ Balneario Camboriu’).
cidade(blumenau)
:- write(’ Blumenau’).
cidade(brusque)
:- write(’ Brusque’).
cidade(cacador)
:- write(’ Cacador’).
cidade(garuva)
:- write(’ Garuva’).
cidade(itajai)
:- write(’ Itajai’).
cidade(jaragua)
:- write(’ Jaragua do Sul’).
cidade(joinville)
:- write(’ Joinville’).
cidade(mafra)
:- write(’ Mafra’).
cidade(rio_do_sul)
:- write(’ Rio do Sul’).
cidade(sao_bento)
:- write(’ Sao Bento do Sul’).
cidade(lages)
:- write(’ Lages’).
Código Fonte
g([Nodo1,Nodo2],Custo):-conexao(Nodo1,Nodo2,Custo).
g([Nodo1,
Nodo2|Caminho],Custo):-conexao(Nodo1,Nodo2,Custo1),
g([Nodo2|Caminho],Custo2),
Custo is Custo1 + Custo2.
h([Nodo|_],Objetivo,H) :- distancia(Nodo,Objetivo,H).
f(Rota,Objetivo,F)
:-g(Rota,G),
Código Fonte
a_estrela([[Objetivo|Rota]|_],Objetivo,Rota_final):-reverse([Objetivo|Rota], Rota_final).
a_estrela([Rota|Lista],Objetivo,Rota_final)
:-expandir(Rota,Expansao_caminho),
append(Lista,Expansao_caminho,Novo_caminho),
classifica(Novo_caminho,Objetivo,Lista_classificada),
a_estrela(Lista_classificada,Objetivo,Rota_final).
Código Fonte
classifica([],_,[]). classifica(Lista,Objetivo,[Menor_caminho|Lista_classificada]):-caminho_minimo(Lista,Objetivo,Menor_caminho,Novo_caminho), classifica(Novo_caminho,Objetivo, Lista_classificada). caminho_minimo([Caminho1|Lista],Objetivo,Caminho2, [Caminho1|Novo_caminho]):-caminho_minimo(Lista,Objetivo,Caminho2,Novo_caminho), f(Caminho1,Objetivo,F1), f(Caminho2,Objetivo,F2), F2<F1,!. caminho_minimo([Rota|Lista],_,Rota,Lista).Código Fonte
expandir([Nodo|Rota],Expansao_caminho) :-findall([Novo_nodo,Nodo|Rota],
(conexao(Nodo,Novo_nodo,_), \+ member(Novo_nodo,[Nodo|Rota])), Expansao_caminho).
Código Fonte
conexao(A,B,D) :- estrada(A,B,D). conexao(A,B,D) :- estrada(B,A,D). estrada(bal_camboriu, brusque, 43). estrada(bal_camboriu,itajai, 9). estrada(blumenau, brusque, 40). estrada(blumenau, itajai, 47). estrada(blumenau, jaragua, 67). estrada(blumenau, rio_do_sul, 89). estrada(cacador, jaragua, 301). estrada(cacador, mafra, 204). estrada(garuva, joinville, 36). estrada(garuva, sao_bento, 74). estrada(itajai, joinville, 94). estrada(jaragua, joinville, 53). estrada(jaragua, sao_bento, 45).Código Fonte
distancia(
Cidade,lages,H):-distancia( Cidade,H).
distancia(bal_camboriu
,275).
distancia(blumenau
,219).
distancia(brusque
,203).
distancia(cacador
,162).
distancia(garuva
,353).
distancia(itajai
,266).
distancia(jaragua
,275).
distancia(joinville
,310).
distancia(mafra
,265).
distancia(rio_do_sul
,134).
distancia(sao_bento
,320).
distancia(lages
,0).
Resultados
?- rota.
Caminho: Joinville, Jaraguá do Sul, Blumenau, Rio do Sul, Lages
Distância de: 343
Yes
?-Resultados
?- todas_rotas.
Caminho: Jlle, Jaraguá, Blumenau, Rio do Sul, Lages Distância de: 343
Caminho: Jlle, Itajaí, Blumenau, Rio do Sul, Lages Distância de: 364
Caminho: Jlle, São Bento, Jaraguá, Blumenau, Rio do Sul, Lages Distância de: 403
Caminho: Jlle, Itajaí, Balneário Camboriú, Brusque, Blumenau, Rio do Sul, Lages Distância de: 409
Caminho: Jlle, Garuva, São Bento, Jaraguá, Blumenau, Rio do Sul, Lages Distância de: 445
Caminho: Jlle, São Bento, Mafra, Caçador, Jaraguá, Blumenau, Rio do Sul, Lages Distância de: 928
Caminho: Jlle, Garuva, São Bento, Mafra, Caçador, Jaraguá, Blumenau, Rio do Sul, Lages Distância de: 970
No