resolução de problemas com procura - técnico lisboa · exemplo: roménia inexistência de mapa...
TRANSCRIPT
Sumário
Agentes que resolvem problemas Tipos de problemas Formulação de problemas Exemplos de problemas Algoritmos de procura básicos Eliminação de estados repetidos Procura com informação parcial
Exemplo: Roménia
Férias na Roménia; actualmente em Arad Voo parte amanhã de Bucareste Formulação do objectivo:
Estar em Bucareste
Formulação do problema: Estados: várias cidades Acções: conduzir entre cidades
Encontrar solução: Sequência de cidades E.g., Arad, Sibiu, Fagaras, Bucareste
Exemplo: Roménia
Inexistência de mapa Escolhas aleatórias…
Existência de mapa Possibilidade de considerar sequência de estados Uma vez encontrada uma solução, basta executar uma
sequência de acções para atingir o objectivo Procura = encontrar uma solução Execução = sequência de acções que permitem
alcançar o objectivo
Agente = Formular + Procurar + Executar
Agentes que resolvem problemas
Função AgenteResolveProblemas (percep) devolve acção Argumento: percep, uma percepção Estático: seq, sequência de acções inicialmente vazia estado, descrição do estado actual obj, objectivo inicialmente vazio prob, formulação do problema
estado ← ActualizaEstado(estado,percep) se seq vazia então obj ← FormulaObjectivo(estado) prob ← FormulaProblema(estado,obj) seq ← Procura(prob) acção ← FIRST(seq) seq ← REST(seq)
devolve acção
Tipo de ambiente/problema
Estático (vs. dinâmico) Ambiente não é alterado enquanto agente efectua
formulação e resolução do problema
Observável (vs. parcialmente observável) Sensores dão acesso ao estado completo do ambiente
Discreto (vs. contínuo) Número limitado de percepções e acções distintas
claramente definidas
Determinístico (vs. estocástico) Estado seguinte é determinado em função do estado
actual e da acção executada pelo agente; fase de execução independente das percepções!
Formulação do Problema (1/2)
Estado inicial em que se encontra o agente Em(Arad)
Descrição das acções possíveis Função sucessor-fn: estado <acção,sucessor>* sucessor-fn(Em(Arad)) = {<Ir(Sibiu),Em(Sibiu)>,
<Ir(Timisoara),Em(Timisoara)>, <Ir(Zerind),Em(Zerind)>}
Estado inicial e sucessor-fn definem implicitamente o espaço de estados do problema (mapa pode ser interpretado como espaço de estados)
Um caminho num espaço de estados é uma sequência de estados resultantes de uma sequência de acções
Formulação do Problema (2/2)
Teste objectivo que determina se um estado é um estado objectivo Os estados objectivo podem ser explícitos (Em(Bucareste)) ou
implícitos (checkmate)
Função de custo que atribui um custo numérico a cada caminho Escolhida em função do desempenho pretendido para o agente
(rapidez km)
Formulação do Problema = estado inicial + acções/sucessor-fn + teste objectivo + função de custo
Solução = sequência de acções que permitem ir desde o estado inicial até um estado objectivo
Espaço de Estados: grafo
estados? sujidade e localização do robot acções? Esquerda, Direita, Aspirar teste objectivo? não haver sujidade em nenhuma
posição
função de custo? 1 por acção
Exemplo: 8-puzzle
estados? Localização das peças acções? Mover espaço esq, dir, cima, baixo teste objectivo? = estado objectivo (dado) função de custo? 1 por movimento
[Nota: solução óptima para a família n-Puzzle é NP-difícil]
Exemplo: montagem
estados?: coordenadas das posições chave do robot e do objecto a ser montado
acções?: movimentos do robot teste objectivo?: montagem completa função de custo?: tempo de execução
Exercício: 8-rainhas
Colocar 8 rainhas num tabuleiro 8x8 tal que nenhuma rainha ataca outra rainha (uma rainha ataca outra rainha se estiver na mesma linha, na mesma coluna ou na mesma diagonal)
Solução: 8-rainhas
Estados: qualquer tabuleiro de 8x8 com 8 rainhas Acções: movimentar uma rainha para uma posição vazia Teste objectivo: 8 rainhas no tabuleiro, nenhuma atacada Função de custo: 1 por movimento
Árvores de Procura (1/2)
Algoritmo: Simulação da expansão do espaço de procura a
partir da geração dos sucessores dos estados já gerados (expansão de estados)
Vs. espaço de estados O mesmo estado pode estar em nós diferentes Caminho bem definido
Árvores de Procura (2/2)
Função ArvoreDeProcura (problema, estratégia) devolve solução ou nãohásolução
InicializaArvoreDeProcuraComEstadoInicial(problema) loop se não há candidatos para expansão então devolve nãohásolução EscolheNóFolhaDaArvoreParaExpansao(estratégia) se o nó contém um estado objectivo então devolve solução senão expande o nó e
adiciona novos nós à árvore de procura
Existe um único nó folha que pode ser expandido: Arad Nós resultantes da expansão do nó Arad: Sibiu, Timisoara,
Zerind
Árvore de Procura: exemplo
Árvore de Procura: exemplo
Existem três nós folha que podem ser expandidos: Sibiu, Timisoara, Zerind
Nó Sibiu é escolhido pela estratégia de procura como o próximo nó a ser expandido
Nós resultantes da expansão do nó Sibiu são adicionados ao conjunto de nós folha
Implementação: estados vs. nós
Um estado é a representação de uma configuração física Um nó é uma estrutura de dados que constitui parte de
uma árvore de procura e que inclui estado, nó pai, acção, custo do caminho g(x), profundidade
A função Expande cria novos nós, preenche os vários campos da estrutura nó e usa a função successor-fn do problema para criar os estados correspondentes.
Implementação (1/4)
Considerem-se definidos os seguintes campos para o tipo NÓ: Estado PaiNó Acção CustoCaminho Profundidade
Implementação (2/4)
Considerem-se definidas as seguintes funções para o tipo FILA: CriaFila(elemento, …) Vazia?(fila) RemovePrimeiro(fila) Insere(elemento,fila) InsereTodos(elementos,fila)
Implementação (3/4)
Função ArvoreDeProcura (problema, filafolhas) devolve solução ou nãohásolução
filafolhas ← Insere(CriaNó(EstadoInicial[problema]),filafolhas)
loop se Vazia?(filafolhas) então devolve nãohásolução nó ← RemovePrimeiro(filafolhas) se TesteObjectivo[problema](nó) então devolve solução(nó) filafolhas ←
InsereTodos(Expande(nó,problema),filafolhas)
Implementação (4/4)
Função Expande (nó, problema) devolve sucessores (conjunto de nós)
sucessores ← conjunto vazio paracada <acção,resultado> em sucessor-fn[problema](Estado(nó)) s ← novo Nó Estado(s) ← resultado PaiNó(s) ← nó Acção(s) ← acção CustoCaminho(s) ← CustoCaminho(nó) + CustoRamo(Estado(nó),
acção, resultado) Profundidade(s) ← Profundidade(nó) +1 adiciona s aos sucessores devolve sucessores
Estratégias de Procura
Uma estratégia de procura é caracterizada por escolher a ordem de expansão dos nós Ou em alternativa a ordem de inserção dos nós na
fila de folhas
Estratégias de Procura
As estratégias são avaliadas de acordo com 4 aspectos: Completude: encontra sempre uma solução caso exista (se não
existir diz que não há solução) Complexidade temporal: número de nós gerados Complexidade espacial: número máximo de nós em memória Optimalidade: encontra a solução de menor custo
Complexidade temporal e espacial são medidas em termos de: r: máximo factor de ramificação da árvore de procura p: profundidade da solução de menor custo (nó com estado
inicial tem profundidade 0) m: máxima profundidade do espaço de estados (pode ser ∞)
Procura Não Informada
Estratégias de procura não informada usam apenas a informação disponível na definição do problema
Largura Primeiro Custo Uniforme Profundidade Primeiro Profundidade Limitada Profundidade Iterativa Bi-Direccional
Também chamadas estratégias de procura cega
Largura Primeiro
Expande nó folha de menor profundidade Implementação:
folhas colocadas numa fila (FIFO), i.e., novos sucessores são colocadas no fim da lista
Largura Primeiro
Nó A é expandido: novos nós B e C B está no início da fila: próximo nó a expandir
A ordem é irrelevante para nós com a mesma profundidade (pode usar-se ordem alfabética para desempate)
Largura Primeiro
Nó B é expandido: novos nós D e E C está no início da fila; os outros nós folha (D e E)
têm maior profundidade
Largura Primeiro
Estado actual Fila nós folha: D, E, F, G nós abertos
Nós gerados mas ainda não expandidos
Nós expandidos: A, B, C nós fechados
Largura Primeiro: propriedades
Completa? Sim (se r é finito) Tempo? 1+r+r2+r3+… +rp + (rp+1-r) = O(rp+1), i.e.
exponencial em p Espaço? O(rp+1) (todos os nós por expandir em memória) Óptima? Sim (se custo = 1 por acção); logo não é óptima
no caso geral
r: máximo factor de ramificação da árvore de procura p: profundidade da solução de menor custo
Espaço é o maior problema (mais do que tempo) Se forem gerados nós a 100MB/s então 24h = 8640GB ≈ 8.4TB
Complexidade: exemplo
Estado objectivo G Factor de ramificação r=2 Profundidade da solução p=2 Tempo
1+21+22+(23-2) O(23), i.e, O(rp+1)
Espaço 23-2 O(23) i.e, O(rp+1)
A
C
E
H
G F D
I J L M N
B
p=0
p=1
p=2
p=3
Exemplo: Roménia
Profundidade da Solução? Nº mínimo de nós expandidos até solução? Obs: teste objectivo é feito antes da expansão do nó!
Exemplo: solução
Profundidade da solução: 3 Nº mínimo de nós expandidos: 12
Obs: estados iguais correspondem a nós diferentes (Arad, Oradea,…)
Custo Uniforme
Expandir nó folha n que tem menor custo g(n) Implementação:
folhas = fila ordenada por custo do caminho Equivalente à procura por largura primeiro se todos os
ramos tiverem o mesmo custo Completa? Sim, se custo do ramo ≥ ε
ε é uma constante > 0, para evitar ciclos em ramos com custo 0 Custo do caminho aumenta sempre com a profundidade
Tempo? # de nós com g ≤ custo da solução óptima, O(r1+C*/ε) onde C* é o custo da solução óptima Todos os ramos com o mesmo custo O(r1+C*/ε) = O(rp+1)
Espaço? # de nós com g ≤ custo da solução óptima, O(r1+C*/ε)
Óptima? Sim – nós expandidos por ordem crescente de g
Custo Uniforme: exemplo
Custo associado a cada ramo
Ordem de expansão dos nós? Desempate: ordem
alfabética
Solução encontrada?
A
C
E G F D
J L M N
B
2
2 1 1 5
1 2 3 1
3
Custo Uniforme: exemplo
Ordem de expansão dos nós? A(0), B(2), C(3), E(3),
F(4), J(4) Nós folha: G(5), L(5),
N(5), D(7), M(7)
Solução encontrada? J (custo 4)
A
C
E G F D
J L M N
B 2
5 4 3 7
4 5 7 5
3
0
Complexidade: exemplo
Todos os ramos com custo ε, com excepção do ramo assinalado
Objectivo G (C*=3.1ε)
Factor de ramificação r=2 Tempo e Espaço
1+21+22+(23-2)+(24-4) O(24), i.e, O(r1+C*/ε)
A
C
E
H
G F D
I J L M N
B
p=0
p=1
p=2
p=3
p=4
2.1 ε
Profundidade Primeiro
Expandir nó folha com a maior profundidade Implementação:
listafolhas = fila LIFO (pilha), i.e., sucessores colocados no início da fila
Profundidade Primeiro: propriedades
Completa? Não: não encontra a solução em espaços de estados com profundidade infinita/com ciclos Modificação para evitar estados repetidos ao longo do
caminho completa em espaços finitos
Tempo? O(rm): problemático se máxima profundidade do espaço de estados m é muito maior do que profundidade da solução de menor custo p
Espaço? O(r*m) - espaço linear (só um caminho) Óptima? Não
Profundidade Primeiro
Implementação: habitualmente recursiva Nós deixam de ser guardados em memória quando
todos os seus sucessores são gerados Variante: procura por retrocesso
Usa ainda menos memória: O(m) vs. O(r*m) Só é gerado um sucessor de cada vez
Profundidade Limitada
Profundidade primeiro com limite de profundidade l, i.e., nós com profundidade l não têm sucessores
Resolve problema da profundidade infinita Limite pode ser determinado em função do tipo de
problema Diâmetro do espaço de estados define máxima
profundidade da solução
Se p > l não é encontrada solução Complexidade temporal O(rl) Complexidade espacial O(rl)
Implementação Recursiva
Função ProcuraProfundidadeLimitada (prob,limite) devolve solução ou nãohásolução/corta
devolve PPLrecursiva (CriaNó(EstadoInicial[problema]),prob,limite)
Função PPLrecursiva (nó,prob,limite) devolve solução ou nãohásolução/corta
atingiu_limite? ← falso se TesteObjectivo[problema](nó) então devolve solução(nó) senão se Profundidade(nó)=limite então devolve corta senão para cada sucessor em Expande(nó,prob) resultado ← PPLrecursiva (sucessor,prob,limite) se resultado = corta então atingiu_limite ← verdadeiro senão se resultado ≠ corta então devolve resultado se atingiu_limite? então devolve corta senão devolve nãohásolução
Implementação Recursiva
Algoritmo ProcuraProfundidadeLimitada tem 3 outputs possíveis: Solução: se encontra solução Corta: se não encontra solução mas não chegou
a expandir toda a árvore devido ao limite de profundidade
Não há solução: se não encontrou solução e expandiu toda a árvore
Profundidade Limitada: exemplo
Solução encontrada? Profundidade Primeiro Profundidade Limitada
l =1
l =2
A
C
E G F D
J L M N
B
Profundidade Iterativa
Profundidade limitada com limite incremental: l=0, l=1, l=2, l=3, …, l=p
Combina vantagens da largura primeiro e da profundidade primeiro
Função ProcuraProfundidadeIterativa (prob) devolve solução ou nãohásolução
ciclo limite ← 0 até ∞ resultado ← ProcuraProfundidadeLimitada(prob,limite) se resultado ≠ corta então devolve resultado
Profundidade Iterativa
Número de nós gerados na procura em profundidade limitada com profundidade p e factor de ramificação r:
NPPL = r0 + r1 + r2 + … + rp-2 + rp-1 + rp
Número de nós gerados na procura em profundidade iterativa com profundidade p e factor de ramificação r: NPPI=(p+1)r0 + pr^1 + (p-1)r^2 + … + 3rp-2 +2rp-1 + 1rp
Para r = 10, p = 5, NPPL = 1 + 10 + 100 + 1,000 + 10,000 + 100,000 = 111,111 NPPI = 6 + 50 + 400 + 3,000 + 20,000 + 100,000 = 123,456
Esforço adicional = (123,456 - 111,111)/111,111 = 11%
Profundidade Iterativa: propriedades
Completa? Sim Tempo? (p+1)r0 + pr1 + (p-1)r2 + … + rp =
O(rp) Espaço? O(r*p) Óptima? Sim, se custo de cada ramo = 1
Procura Bi-Direccional
Executar duas procuras em largura em simultâneo Uma a partir do estado inicial (forward, para a frente) Outra a partir do estado final (backward, para trás)
Procura termina quando as duas procuras se encontram (têm um estado em comum)
Motivação: rp/2 + rp/2 << rp
Necessidade de calcular eficientemente os predecessores de um nó
Problemática quando estados objectivos são descritos implicitamente (por exº, checkmate)
Procura Bi-Direccional: propriedades
Completa? Sim, se p é finito e se executa procura em largura primeiro em ambas as direcções
Tempo? O(rp/2) Espaço? O(rp/2) Óptima? Sim, se custo de cada ramo = 1 e se
executa procura em largura primeiro em ambas as direcções
Resumo dos algoritmos
a completa se r é finito b completa se custo de cada ramo > 0 c óptima se todos os ramos têm o mesmo custo d se ambas as direcções executam procura em largura primeiro
Largura Primeiro
Custo Uniforme
Profund. Primeiro
Profund. Limitada
Profund. Iterativa
Bi-direc-cional
Completa? Sima Sima,b Não Não Sima Sima,d
Tempo O(r p+1) O(r1+C*/ε) O(r m) O(r l) O(r p) O(r p/2)
Espaço O(r p+1) O(r1+C*/ε) O(rm) O(r l) O(rp) O(r p/2)
Óptima? Simc Sim Não Não Simc Simc,d
Eliminação de Estados Repetidos
Não detecção de estados repetidos pode transformar um problema linear em exponencial!
Alterar procura em árvore para procura em grafo com análise de nós fechados Optimalidade pode ser afectada se usarmos nós abertos
Procura em grafo
Função GrafoDeProcura (problema, filafolhas) devolve solução ou nãohásolução
fechados ← conjunto vazio filafolhas ←
Insere(CriaNó(EstadoInicial[problema]),filafolhas) loop se Vazia?(filafolhas) então devolve nãohásolução nó ← RemovePrimeiro(filafolhas) se TesteObjectivo[problema](nó) então devolve solução(nó) se nó não está em fechados então adiciona Estado(nó) a fechados nó ← InsereTodos(Expande(nó,problema),filafolhas)
Procura com Informação Parcial
Problemas nos sensores O estado actual consiste num conjunto de estados acreditados O resultado das acções é conhecido transição entre conjuntos de
estados acreditados
Problemas de contingência Ambiente parcialmente observável ou resultado das acções é incerto
nova informação depois de cada acção Solução dada ao agente é um plano de contingência: acções
dependem de condições
Problemas de exploração Estados e acções do ambiente são desconhecidos Caso extremo de problema de contingência