Inteligência Artificial

Pseudo-código para os algoritmos de busca.

Última ocorrência: 2024-04-15 em Universidade LaSalle Canoas

Posts Relacionados

Busca em Profundidade

Para este algoritmo:

def DFS(Grafo, start, goal):
    assert(start in Grafo.vertices)
    assert(goal in Grafo.vertices)
    S = Stack()
    S.push(start)
    while not S.is_empty():
        v = S.pop()
        if goal == v:
            return  # encontrou o caminho
        if not visited(v):
            # processa o caminho "até v"
            processa_caminho(v)
            set_visited(v)
            for u in Grafo.neighbors(v):
                S.push(u)

Busca em Largura

def BFS(Grafo, start, goal):
    assert(start in Grafo.vertices)
    assert(goal in Grafo.vertices)
    Q = Queue()
    Q.enqueue(start)
    while not Q.is_empty():
        v = Q.dequeue()
        if goal == v:
            return  # encontrou o caminho
        if not visited(v):
            # processa o caminho até v
            processa_caminho(v)
            set_visited(v)
            for u in Grafo.neighbors(v):
                Q.enqueue(u)

Branch and Bound

O algoritmo Branch and Bound leva em consideração o caminho até o momento e se este caminho não pode levar a um resultado melhor, não segue criando divisões a partir daquele vértice.

def branch_and_bound(Grafo, start, goal):
    assert(start in Grafo.vertices)
    assert(goal in Grafo.vertices)
    best_so_far = (None, +INF)
    Q = Queue()
    Q.enqueue(start)
    while not Q.is_empty():
        v = Q.dequeue()
        if goal == v:
            # 'candidate' é o comprimento atual do caminho
            new_path, candidate = processa_caminho(v)
            path, limit = best_so_far
            if candidate < limit:
                best_so_far = (new_path, candidate)
        else:
            ajusta_caminho(start, v)
            for u in Grafo.neighbors(v):
                # Só adiciona caminhos que podem ser melhores
                if caminho_ate_aqui(start, u) < best_so_far:
                    Q.enqueue(u)

A*

Para o algoritmo $A^*$, será necessária a criação de uma heurística admissível, ou, melhor ainda, uma heurística consistente.

Sobre o algoritmo $A^*$:

frontier = PriorityQueue()
frontier.put(start, 0)
came_from = {}
cost_so_far = {}
came_from[start] = None
cost_so_far[start] = 0

def heuristic(a, b):
   """Manhattan distance on a square grid."""
   return abs(a.x - b.x) + abs(a.y - b.y)

while not frontier.empty():
   current = frontier.get()

   if current == goal:
      break
   
   for next in graph.neighbors(current):
      new_cost = cost_so_far[current] + graph.cost(current, next)
      if next not in cost_so_far or new_cost < cost_so_far[next]:
         cost_so_far[next] = new_cost
         priority = new_cost + heuristic(goal, next)
         frontier.put(next, priority)
         came_from[next] = current

Algoritmo de Dijkstra

O pseudocódigo para a implementação do algoritmo de Dijkstra:


function Dijkstra(Graph, source, goal):
    for each vertex v in Graph.Vertices:
        dist[v] = INFINITY
        prev[v] = UNDEFINED
        add v to Q
    dist[source] = 0
   
    while Q is not empty:
        u = vertex in Q with min dist[u]
        remove u from Q
       
        for each neighbor v of u still in Q:
            alt = dist[u] + Graph.edge(u, v)
            if alt < dist[v]:
                dist[v] = alt
                prev[v] = u

    return dist[], prev[]

Para uma implementação eficiente do algoritmo, deve ser utilizada uma fila de prioridades (priority queue), que pode ser implementada como um heap mínimo.

Recursos para essa aula