• Nenhum resultado encontrado

Resolução de problemas por meio de busca

3.4 ESTRATÉGIAS DE BUSCA SEM INFORMAÇÃO

3.4.1 Busca em largura

A busca em largura (BrFS – Breadth-first search) é uma estratégia simples em que o nó raiz é expandido primeiro, em seguida todos os sucessores do nó raiz são expandidos, depois os sucessores

desses nós, e assim por diante. Em geral, todos os nós em dada profundidade na árvore de busca são

expandidos, antes que todos os nós no nível seguinte sejam expandidos.

A busca em largura é uma instância do algoritmo de busca em grafo (Figura 3.7), em que o nó mais raso não expandido é escolhido para expansão. Isso é conseguido simplesmente utilizando uma fila FIFO para a borda. Assim, novos nós (que são sempre mais profundos do que seus pais) vão para o fim da fila, e nós antigos, que são mais rasos que os novos, são expandidos primeiro. Há um ligeiro refinamento no algoritmo genérico de busca em grafos, pois o teste de objetivo é aplicado a cada nó quando é gerado e não quando é selecionado para expansão. Essa decisão será explicada a seguir, quando discutirmos a complexidade do tempo. Observe também que o algoritmo, que segue o modelo geral para a busca em grafos, descarta qualquer caminho novo para um estado já na borda ou no conjunto explorado; é fácil verificar que tal caminho deverá pelo menos ser tão profundo quanto aquele já encontrado. Assim, a busca em largura sempre terá o caminho mais raso para todo o nó na borda.

O pseudocódigo é apresentado na Figura 3.11. A Figura 3.12 mostra o progresso da busca em uma árvore binária simples.

função BUSCA-EM-LARGURA(problema) retorna uma solução ou falha

nó ← um nó com ESTADO = problema.ESTADO-INICIAL, CUSTO-DE-CAMINHO = 0 se problema.TESTE-DE-OBJETIVO(nó.ESTADO) senão retorne SOLUÇÃO(nó), borda ← uma fila FIFO com nó como elemento único

explorado ← conjunto vazio repita

se VAZIO?(borda), então retorne falha

nó ← POP(borda) / * escolhe o nó mais raso na borda */ adicione nó.ESTADO para explorado

para cada ação em problema.AÇÕES(nó.ESTADO) faça filho ← NÓ-FILHO(problema, nó, ação),

se (filho.ESTADO)não está em explorado ou borda então

se problema.TESTE-DE-OBJETIVO(filho.ESTADO) então retorne SOLUÇÃO(filho) borda ← INSIRA(filho, borda)

Figura 3.11 Busca em largura em um grafo.

Figura 3.12 Busca em largura em uma árvore binária simples. Em cada fase, o próximo nó a ser

expandido é indicado por um marcador.

Como avaliar a busca em largura de acordo com os quatro critérios da seção anterior? Podemos facilmente verificar que ela é completa — se o nó objetivo mais raso estiver em alguma profundidade finita d, a busca em largura acabará por encontrá-lo depois de gerar todos os nós mais rasos (desde que o fator de ramificação b seja finito). Observe que, logo que um nó objetivo é gerado, sabemos que é o nó objetivo mais raso porque todos os nós mais rasos já devem ter sido gerados e falhado no teste de objetivo. Agora, o nó objetivo mais raso não é necessariamente o

ótimo; tecnicamente, a busca em largura é ideal se o custo do caminho for uma função não

decrescente da profundidade do nó. O mais comum desse cenário é que todas as ações têm o mesmo custo.

Até aqui, o que se falou sobre busca em largura tem sido boas notícias. As notícias sobre o tempo e o espaço não são tão boas. Imagine a busca em uma árvore uniforme onde cada estado tenha b sucessores. A raiz da árvore de busca gera b nós no primeiro nível, cada um dos quais gera b outros nós, totalizando b2 no segundo nível. Cada um desses outros nós gera b outros nós, totalizando b3 nós

no terceiro nível, e assim por diante. Agora, suponha que a solução esteja na profundidade d. No pior caso, é o último nó gerado naquele nível. Então, o número total de nós gerados é:

b + b2 + b3 + … + bd = O(bd).

(Se o algoritmo fosse aplicar o teste de objetivo para nós ao serem selecionados para a expansão, em vez de ao serem gerados, toda a camada de nós na profundidade d seria expandida antes que o objetivo fosse detectado e a complexidade de tempo seria O (bd +1).).

Quanto à complexidade do espaço: para qualquer tipo de busca em grafos, que armazena todos os nós expandidos no conjunto explorado, a complexidade do espaço está sempre dentro de um fator de

b da complexidade do tempo. Em particular, para busca em largura em grafos, cada nó gerado

permanecerá na memória. Haverá O (bd−1) nós no conjunto explorado e O(bd) nós na borda; assim, a

complexidade de espaço será O(bd), ou seja, será dominada pelo tamanho da borda. Mudar para uma

busca em árvore não iria poupar muito espaço e, em um espaço de estados com muitos caminhos redundantes, a mudança poderia custar grande parte do tempo.

Um limite de complexidade exponencial tal como O(bd), é assustador. A Figura 3.13 mostra por

para uma busca em largura com fator de ramificação b = 10. A tabela assume a geração de um milhão de nós por segundo e o requisito de 1.000 bytes de armazenamento para um nó. Muitos problemas podem ser ajustados a essas suposições (de um fator de 100 para mais ou para menos), quando executados em um computador pessoal moderno.

Profundidade Nós Tempo Memória

2 110 0,11 milissegundo 107 kilobytes 4 11.110 11 milissegundos 10,6 megabytes 6 106 1,1 segundo 1 gigabyte 8 108 2 minutos 103 gigabytes 10 1010 3 horas 10 terabytes 12 1012 13 dias 1 petabyte 14 1014 3,5 anos 99 petabytes 16 1016 350 anos 10 exabytes

Figura 3.13 Requisitos de tempo e memória para a busca em largura. Os números mostrados

assumem fator de ramificação b = 10; um milhão de nós/segundo; 1.000 bytes/nó.

Duas lições podem ser aprendidas a partir da Figura 3.13. Em primeiro lugar, os requisitos de

memória são um problema maior para a busca em largura do que o tempo de execução . Deve-se

esperar 13 dias pela solução de um problema importante com profundidade de busca 12, mas nenhum computador pessoal tem a memória principal da ordem de petabytes que ele exigiria. Felizmente, existem outras estratégias de busca que exigem menos memória.

A segunda lição é que o tempo ainda é um fator importante. Se seu problema tem uma solução na profundidade 16, então (dadas nossas suposições) ele demorará 350 anos para que a busca em largura a encontre (ou, na realidade, qualquer busca sem informação). Em geral, os problemas de

busca de complexidade exponencial não podem ser resolvidos por métodos sem informação, para qualquer instância, exceto as menores.