Matéria das aulas T3 (procura cega) e T4 (procura informada). O exercício 1 é resolvido no quadro; os restantes são para trabalho autónomo, individualmente ou em grupos de dois. Os exercícios que ficarem por resolver na aula devem ser resolvidos em casa.
Toda a terminologia é a do AIMA, 4.ª edição (capítulo 3) e a dos slides T3 e T4.

Figura 1 — Estado inicial S, objectivo G.
(a) Aplique a procura em largura primeiro, preenchendo passo a passo uma tabela com quatro colunas: #, nó retirado, fronteira (FIFO) depois e atingidos depois. Indique o caminho devolvido e o seu custo.
(b) Aplique o A*. Mesma tabela, escrevendo cada nó da fronteira na forma X(g+h=f) e ordenando a fronteira por f. Caminho e custo.
(c) No passo em que se expande B, o estado D já estava em atingidos. O que faz a BEST-FIRST-SEARCH, e porquê? Que linhas do pseudocódigo são responsáveis?
(d) A procura em largura devolveu o caminho com menos acções; o A* devolveu o de menor custo. Porque é que não são o mesmo caminho? O que teria de acontecer aos custos para que fossem sempre o mesmo?
(e) Verifique que h é admissível. É consistente?
Ainda sobre o grafo da Figura 1.
(a) Aplique a procura de custo uniforme, com a tabela do exercício 1 (escreva X(g)). Caminho e custo.
(b) Aplique a procura sôfrega, escrevendo X(h). Caminho e custo.
(c) Complete:
Algoritmo |
Nós expandidos |
Caminho devolvido |
Custo |
Óptimo em custo? |
|---|---|---|---|---|
| Largura primeiro | ||||
| Custo uniforme | ||||
| Sôfrega | ||||
| A* |
(d) A sôfrega expande menos nós do que o A*. Porque é que isso não faz dela o melhor algoritmo?
(e) Na procura de custo uniforme, G entra em atingidos com g = 22 e, mais tarde, com g = 20. Se o teste de objectivo fosse feito ao gerar — como na procura em largura — que caminho teria sido devolvido? Relacione com o slide «Porque é que o teste tem de ser ao retirar».
Um drone de entregas opera sobre uma cidade representada por uma grelha de N × M células. O drone parte do depósito, numa célula fixa e conhecida.
Há P pacotes. Cada pacote i está numa célula de recolha fixa e conhecida e tem uma célula de entrega, também fixa e conhecida. Todas estas células são distintas entre si e distintas do depósito. O drone transporta no máximo um pacote de cada vez.
Acções: mover para uma das células adjacentes na horizontal ou na vertical (custo 1); recolher o pacote da célula onde está, se não levar nenhum (custo 1); entregar o pacote que leva, se estiver na célula de entrega desse pacote (custo 1); recarregar, só no depósito (custo 5).
O drone tem uma bateria com E unidades de carga, que começa cheia. Cada mover gasta uma unidade; recolher e entregar não gastam; recarregar repõe a bateria em E. Com a bateria a zero o drone não se pode mover. O objectivo é ter os P pacotes entregues.
(a) Formalize o problema indicando os seis componentes do AIMA: espaço de estados, estado inicial, estados objectivo (IS-GOAL), acções (ACTIONS), modelo de transição (RESULT) e custo das acções (ACTION-COST).
(b) Qual é o tamanho do espaço de estados, em função de N, M, P e E? Justifique a contagem.
(c) Qual é o factor de ramificação máximo a partir de um estado qualquer? Justifique.
(d) Suponha agora que o drone pode transportar até dois pacotes ao mesmo tempo. Qual passa a ser o tamanho do espaço de estados?
(e) Apresente uma heurística admissível não trivial e justifique a admissibilidade. Sugestão: pense num problema relaxado.
(f) Considere h2(n) = (número de pacotes ainda não entregues). É admissível? É consistente? Domina a heurística da alínea (e), ou é dominada por ela?

Figura 2 — Estado inicial S, objectivo G. O grafo é acíclico.
Para cada um dos algoritmos seguintes, preencha a tabela passo a passo (nó retirado, fronteira depois, atingidos depois) e indique o caminho devolvido, o seu custo e a lista de nós expandidos.
(a) Procura em largura primeiro.
(b) Procura em profundidade primeiro (tipo-árvore, pilha LIFO, com IS-CYCLE). Nesta não há tabela de atingidos.
(c) Procura de custo uniforme.
(d) A procura em largura expandiu muito menos estados do que a de custo uniforme e devolveu um caminho muito pior. Explique as duas coisas ao mesmo tempo.
(e) O grafo é acíclico, e por isso a procura em profundidade tipo-árvore termina mesmo sem o teste IS-CYCLE. Se existisse também o arco H → A com custo 1, o que aconteceria à procura em profundidade sem IS-CYCLE? E com IS-CYCLE?
Ainda sobre o grafo da Figura 2.
(a) Aplique a procura de profundidade limitada com ℓ = 1 e com ℓ = 2. Para cada limite indique os nós retirados da fronteira, pela ordem, e o resultado (failure, cutoff ou um nó solução).
(b) Aplique o aprofundamento progressivo. A que limite ℓ encontra solução? Qual é o caminho e o custo?
(c) Some os nós expandidos em todas as iterações do aprofundamento progressivo e compare com os da procura em largura primeiro sobre o mesmo grafo. Comente.
(d) Com ℓ = 3, o estado H é retirado da fronteira duas vezes. Porquê? O que é que o evitaria, e a que preço?
(e) A procura em largura precisa de O(bd) de memória e o aprofundamento progressivo de O(bd). Com b = 10 e d = 8, e supondo 1 kbyte por nó, quanta memória é isso em cada caso?
Ainda sobre o grafo da Figura 2.
(a) Aplique a procura sôfrega. Tabela, caminho, custo, nós expandidos.
(b) Aplique o A*. Tabela com X(g+h=f), caminho, custo, nós expandidos.
(c) O A* e a procura de custo uniforme devolveram o mesmo caminho, mas o A* expandiu metade dos estados. Explique com a ideia dos contornos do slide «Contornos de procura».
(d) Quais são os nós que o A* nunca expande? Diga, para cada um, qual é o valor de f que o impede, e relacione com o critério «o A* nunca expande nós com f(n) > C*».
(e) Neste grafo o A* não substituiu nenhuma entrada em atingidos. Diga porquê: repare em que estados é que chega mais do que um caminho e verifique se ambos os caminhos chegaram sequer a ser gerados.
Complete a tabela para o grafo da Figura 2 (use os resultados dos exercícios 4 a 6):
Algoritmo |
Nós expandidos |
Caminho |
Custo |
Óptimo? |
Memória |
|---|---|---|---|---|---|
| Largura primeiro | |||||
| Profundidade primeiro (tipo-árvore) | |||||
| Aprofundamento progressivo | |||||
| Custo uniforme | |||||
| Sôfrega | |||||
| A* |
E responda:
(a) Três algoritmos expandiram apenas três estados, e devolveram caminhos de custo 19, 19 e 11. Que conclusão se tira daqui sobre «expandir poucos nós»?
(b) A procura em largura e o aprofundamento progressivo devolveram o mesmo caminho. Isso é coincidência? Em que condições é que o aprofundamento progressivo devolve sempre o mesmo caminho que a procura em largura?
(c) A procura em profundidade devolveu um caminho melhor do que a de largura. Isso contraria alguma garantia dada nas aulas?
(d) Dos seis, quais são completos neste grafo e quais seriam completos num espaço de estados infinito?
Ainda sobre o grafo da Figura 2.
(a) Calcule h*(n) — o custo do caminho óptimo de n até G — para A, C, D e E, e verifique que h é admissível nesses estados.
(b) Verifique a consistência de h nos arcos S → C, A → F, C → E e F → H. Em quais deles é que a desigualdade fica justa (com igualdade)?
(c) Substitua h(C) = 4 por um valor x, mantendo tudo o resto.
(d) Repita a alínea (c) para h(B) = 8, substituído por y. Os dois intervalos coincidem. Explique porquê, olhando para os arcos que entram e saem de B.
(e) Sejam h1 e h2 duas heurísticas admissíveis. Mostre que h(n) = max{h1(n), h2(n)} é admissível. Se ambas forem consistentes, h é consistente?
(f) E o mínimo? Se h1 for consistente e h2 admissível, min{h1, h2} é necessariamente admissível? E consistente?
(g) Diz-se que h2 domina h1 se h2(n) ≥ h1(n) para todo o n, sendo ambas admissíveis. Porque é que dominar é ser melhor? Qual é o preço a pagar?
Um colega diz que as duas últimas linhas do corpo do if da BEST-FIRST-SEARCH são redundantes e apagou-as, ficando com isto:
function A*(problem) returns a solution node or failure
node ← NODE(STATE = problem.INITIAL)
frontier ← a priority queue ordered by g + h, with node as an element
reached ← a lookup table, with one entry with key
problem.INITIAL and value node
while not IS-EMPTY(frontier) do
node ← POP(frontier)
if problem.IS-GOAL(node.STATE) then return node
for each child in EXPAND(problem, node) do
s ← child.STATE
if s is not in reached then ⟵ sem comparar PATH-COST
reached[s] ← child
add child to frontier
return failure
(a) Execute este algoritmo sobre o grafo da Figura 1. Que caminho devolve, e com que custo? Compare com o A* do livro.
(b) Identifique o passo exacto em que o caminho óptimo é perdido, e diga porquê.
(c) Construa uma instância com no máximo 5 estados e uma heurística admissível em que este algoritmo devolve um caminho sub-óptimo. Desenhe o grafo e indique h.
(d) [difícil] Consegue construir uma instância em que a heurística seja, além de admissível, também consistente, e em que o algoritmo continue a devolver um caminho sub-óptimo?
Se sim, há um erro no raciocínio que levou o colega a apagar as duas linhas:
«Os slides dizem que, com h consistente, nenhum estado já expandido volta a ser atingido por um caminho melhor. Então a condição child.PATH-COST < reached[s].PATH-COST nunca se verifica, e posso apagá-la.»
Identifique a premissa, que é verdadeira, e a conclusão, que é falsa, e diga porque é que a segunda não se segue da primeira.
(e) Este algoritmo não é a procura tipo-árvore. Aplique ao mesmo grafo o A* tipo-árvore — sem tabela atingidos nenhuma — e diga que caminho devolve. Como é possível que guardar atingidos, e nunca o actualizar, seja pior do que não guardar nada?
(f) [difícil] A demonstração de optimalidade do A* dada na aula usa apenas a admissibilidade de h, e não fala de atingidos em lado nenhum. Identifique o passo da demonstração que deixa de ser válido neste algoritmo, e diga porque é que esse passo continua válido na procura tipo-árvore.
Ainda sobre o grafo da Figura 2.
(a) Aplique o IDA*. Para cada iteração indique o f-limite, os nós expandidos e os estados cortados (com o f que os cortou). Quantas iterações são precisas?
(b) Quantas vezes é que S e C são expandidos ao longo de toda a execução? Porque é que isso não é catastrófico?
(c) Aplique o RBFS. Identifique a primeira mudança de ideias: qual é o nó que a provoca, qual era o seu f e qual passa a ser. Explique de onde vem o novo valor (backed-up value).
(d) Compare a memória usada pelo A*, pelo IDA* e pelo RBFS neste grafo. E o número de expansões.
(a) Num espaço de estados com factor de ramificação b = 4 e solução mais rasa à profundidade d = 6: quantos nós gera a procura em largura primeiro? E o aprofundamento progressivo? Calcule o rácio e explique porque é que não é catastrófico.
(b) O A* encontrou uma solução à profundidade d = 5 tendo gerado 52 nós. Qual é o factor de ramificação efectivo b*? O que é que um b* próximo de 1 significa?
(c) Para cada afirmação, indique se é verdadeira (V) ou falsa (F). Justifique em uma linha as que forem falsas.