Algoritmo A* » Histórico » Versão 2
Antonio de Souza Gomes Pereira, 08/03/2020 04:29 h
| 1 | 1 | Antonio de Souza Gomes Pereira | # Algoritmo A* |
|---|---|---|---|
| 2 | |||
| 3 | 2 | Antonio de Souza Gomes Pereira | ## Introdução |
| 4 | |||
| 5 | A* é um algoritmo para planejamento de trajetórias em um grid contendo o destino, caminhos livres e obstáculos. Sendo amplamente utilizado para encontrar o caminho mais curto (aproximação), de uma maneira rápida e inteligente. Antes de descrever o funcionamento do mesmo, começamos com o algoritmo de Dijkstra e depois como ele pode ser derivado no A*. |
||
| 6 | |||
| 7 | ## Algoritmo de Dijkstra |
||
| 8 | |||
| 9 | Dado um grafo e um vértice de origem, como podemos achar a mínima distância dele para todos os outros vértices? |
||
| 10 | Começamos a implementação criando uma lista aberta e uma lista fechada: |
||
| 11 | |||
| 12 | * A lista fechada terá como objetivo simplesmente armazenar o estado que o vértice possui, se sua miníma distância foi calculada ou não (True/False), podendo ser simplesmente um vetor de booleans ou uma hash table. |
||
| 13 | |||
| 14 | * A lista aberta conterá todos os outros vértices que já foram visitados e não estão na lista fechada, sendo composta de um par (distância, índice). Durante a execução do algoritmo, precisaremos várias vezes saber o vértice de menor distância na lista, por isso sendo de grande utilidade utilizar uma priority queue como lista fechada, pois o elemento de menor distância sempre ficará no topo da lista. |
||
| 15 | |||
| 16 | Podemos descrever o algoritmo da seguinte forma: |
||
| 17 | |||
| 18 | |||
| 19 | ``` |
||
| 20 | 1) Initialize distances of all vertices as infinite. |
||
| 21 | |||
| 22 | 2) Create an empty set. Every item of set is a pair |
||
| 23 | (weight, vertex). Weight (or distance) is used used |
||
| 24 | as first item of pair as first item is by default |
||
| 25 | used to compare two pairs. |
||
| 26 | |||
| 27 | 3) Insert source vertex into the set and make its |
||
| 28 | distance as 0. |
||
| 29 | |||
| 30 | 4) While Set doesn't become empty, do following |
||
| 31 | a) Extract minimum distance vertex from Set. |
||
| 32 | Let the extracted vertex be u. |
||
| 33 | b) Loop through all adjacent of u and do |
||
| 34 | following for every vertex v. |
||
| 35 | |||
| 36 | // If there is a shorter path to v |
||
| 37 | // through u. |
||
| 38 | If dist[v] > dist[u] + weight(u, v) |
||
| 39 | |||
| 40 | (i) Update distance of v, i.e., do |
||
| 41 | dist[v] = dist[u] + weight(u, v) |
||
| 42 | (i) If v is in set, update its distance |
||
| 43 | in set by removing it first, then |
||
| 44 | inserting with new distance |
||
| 45 | (ii) If v is not in set, then insert |
||
| 46 | it in set with new distance |
||
| 47 | |||
| 48 | 5) Print distance array dist[] to print all shortest |
||
| 49 | paths. |
||
| 50 | ``` |
||
| 51 | |||
| 52 | |||
| 53 | |||
| 54 | Vamos usar o grafo abaixo como exemplo do funcionamento: |
||
| 55 | |||
| 56 |  |
||
| 57 | |||
| 58 | A primeira coisa a se fazer é setar todas as distâncias para +INFINITO, excetuando a origem (vértice v1), que será inserida na lista aberta e terá sua distância como 0. |
||
| 59 | |||
| 60 | | LISTA ABERTA | |
||
| 61 | |--- | |
||
| 62 | | (0 , 1) | |
||
| 63 | |||
| 64 | |||
| 65 | | LISTA FECHADA | |
||
| 66 | |--- | |
||
| 67 | |||
| 68 | Após isso, retiraremos o vértice de menor valor da lista aberta e o inserimos na lista fechada, nesse caso o v1, e calculamos a distância de todos os vértices adjacentes ao recém retirado, os vértices v6, v3 e v2, respectivamente com distâncias 14, 9 e 7, inserindo-os na lista aberta. |
||
| 69 |  |
||
| 70 | |||
| 71 | | LISTA ABERTA | |
||
| 72 | |--- | |
||
| 73 | | (7 , 2) | |
||
| 74 | | (9 , 3) | |
||
| 75 | | (14 , 6) | |
||
| 76 | |||
| 77 | |||
| 78 | |||
| 79 | | LISTA FECHADA | |
||
| 80 | |--- | |
||
| 81 | | 1 | |
||
| 82 | |||
| 83 | |||
| 84 | |||
| 85 | Agora devemos repetir o processo, retirando o vértice de menor valor da lista aberta e o inserindo na fechada, nesse caso o v2, após isso devemos colocar na aberta o v4, que ainda não foi inicializado, e manter o valor de v3, pois a distância relativa ao v2 é de 17, sendo maior que 9, caso a distância calculada fosse menor que 9, o valor deveria ser substituído por esse. |
||
| 86 | |||
| 87 | |||
| 88 |  |
||
| 89 | |||
| 90 | | LISTA ABERTA | |
||
| 91 | |--- | |
||
| 92 | | (9 , 3) | |
||
| 93 | | (14 , 6) | |
||
| 94 | | (15 , 4) | |
||
| 95 | |||
| 96 | |||
| 97 | |||
| 98 | |||
| 99 | | LISTA FECHADA | |
||
| 100 | |--- | |
||
| 101 | | 1 | |
||
| 102 | | 2 | |
||
| 103 | |||
| 104 | Repetimos o processo até a lista aberta estar vazia e todos os vértices estejam na lista fechada, assim encontrando as menores distâncias de cada vértice. Veja que não encontramos o caminho específico que leva a menor distância, se quisermos fazer isso, basta criar um vetor com os índices dos vértices que sempre é atualizado quando o valor da distância também é atualizado. |
||
| 105 | |||
| 106 | ## Derivando o A* |
||
| 107 | |||
| 108 | |||
| 109 | |||
| 110 | ## Referências |