Esempio n. 1
0
def hill_climbing(labyrinth, start, end):

    # Guardam os tempos da função
    begin_time = None
    found_time = None

    # Guarda as dimensões do labirinto
    x = len(labyrinth)
    y = len(labyrinth[0])

    # Matriz que guarda os antecessores das posições já visitadas
    prev = [[[-1, -1] for i in range(y)] for j in range(x)]

    # Marca o elemento inicial para ser verificado primeiro
    cur = start

    # Marca a melhor heuristica encontrada até agora (inicia-se com um valor
    # maior que qualquer um que poderia ser retornado pela função)
    cur_dist = 2 * x * y

    # Marca o tempo de início e executa o hill climbing
    begin_time = time.time()
    while cur != None:

        # Verifica se um caminho foi encontrado
        # Se ele foi a busca encerra e o tempo é anotado
        if lb.is_end(labyrinth, cur):
            found = True
            found_time = time.time()
            break

        # Checa as adjacências do elemento e busca qual "colina subir"

        # Guarda o melhor elemento e seu valor na heuristica (inicia-se com um valor
        # maior que qualquer um que poderia ser retornado pela função)
        best = None

        # Direita
        next = lb.get_right(labyrinth, cur, prev)  # [cur[0], cur[1] + 1]
        if next != None:
            # Escolhe esse nó se ele for melhor que o atual e melhor que os outros adjacentes (checado abaixo)
            next_dist = manhattan_distance(next, end)
            if next_dist < cur_dist:
                best = next
                # Já atualiza a distância atual para usa-la nas checagens abaixo
                cur_dist = next_dist

        # Baixo
        next = lb.get_bottom(labyrinth, cur, prev)  # [cur[0] + 1, cur[1]]
        if next != None:
            next_dist = manhattan_distance(next, end)
            if next_dist < cur_dist:
                best = next
                cur_dist = next_dist

        # Esquerda
        next = lb.get_left(labyrinth, cur, prev)  # [cur[0], cur[1] - 1]
        if next != None:
            next_dist = manhattan_distance(next, end)
            if next_dist < cur_dist:
                best = next
                cur_dist = next_dist

        # Cima
        next = lb.get_top(labyrinth, cur, prev)  # [cur[0] - 1, cur[1]]
        if next != None:
            next_dist = manhattan_distance(next, end)
            if next_dist < cur_dist:
                best = next
                cur_dist = next_dist

        # "Sobe para a colina mais alta", se best for igual a None é porque o algoritmo
        # chegou em um melhor local, como não estamos usando backtracking ele deve parar
        if best != None:
            # Marca o antecessor do proximo elemento como sendo o atual
            prev[best[0]][best[1]] = [cur[0], cur[1]]
            cur = best
        else:
            # Marca o tempo que o algoritmo finalizou
            found_time = time.time()
            break

    # Gera o caminho a partir da matriz de predecessores
    # Nota-se que passamos cur ao invés de end para a função,
    # Isso é feito para podermos checar o melhor local encontrado
    # pelo algoritmo, já que muitas vezes ele não é capaz de achar
    # o melhor global
    path = lb.prev_to_path(prev, start, cur)

    # Retorna um objeto com os resultados
    return lb.Result(path, found_time - begin_time)
Esempio n. 2
0
def bfs(labyrinth, start, end):
    
    # Guardam os tempos da função
    begin_time = None
    found_time = None

    # Queue usada para a BFS
    queue = [start]

    # Guarda as dimensões do labirinto
    x = len(labyrinth)
    y = len(labyrinth[0])

    # Matriz que guarda os antecessores das posições já visitadas
    prev = [[[-1, -1] for i in range(y)] for j in range(x)]

    # Marca se um caminho foi encontrado
    found = False

    # Marca o tempo de início e executa a BFS
    begin_time = time.time()
    while len(queue) != 0:

        # Remove o primeiro elemento da fila
        cur = queue.pop(0)

        # Verifica se um caminho foi encontrado
        # Se ele foi a busca encerra e o tempo é anotado
        if lb.is_end(labyrinth, cur):
            found = True
            found_time = time.time()
            break

        # Checa as adjacências do elemento e as coloca na pilha se não foram visitadas

        # Direita
        next = lb.get_right(labyrinth, cur, prev) # [cur[0], cur[1] + 1]
        if next != None:
            queue.append(next) # Adiciona na fila
            prev[next[0]][next[1]] = cur # Marca o antecessor do proximo elemento como sendo o atual

        # Baixo
        next = lb.get_bottom(labyrinth, cur, prev) # [cur[0] + 1, cur[1]]
        if next != None:
            queue.append(next)
            prev[next[0]][next[1]] = cur

        # Esquerda
        next = lb.get_left(labyrinth, cur, prev) # [cur[0], cur[1] - 1]
        if next != None:
            queue.append(next)
            prev[next[0]][next[1]] = cur

        # Cima
        next = lb.get_top(labyrinth, cur, prev) # [cur[0] - 1, cur[1]]
        if next != None:
            queue.append(next)
            prev[next[0]][next[1]] = cur

    # Gera o caminho a partir da matriz de predecessores
    path = lb.prev_to_path(prev, start, end)

    # Retorna um objeto com os resultados
    if found:
        return lb.Result(path, found_time - begin_time)
    return lb.Result(None, None)
def best_first_search(labyrinth, start, end):
    
    # Marca o final do labirinto de forma que seja acessível à função de ordenação
    global global_end
    global_end = end

    # Guardam os tempos da função
    begin_time = None
    found_time = None

    # Priority queue usada para a best-first search
    p_queue = [start]

    # Guarda as dimensões do labirinto
    x = len(labyrinth)
    y = len(labyrinth[0])

    # Matriz que guarda os antecessores das posições já visitadas
    prev = [[[-1, -1] for i in range(y)] for j in range(x)]

    # Marca se um caminho foi encontrado
    found = False

    # Marca o tempo de início e executa a best-first search
    begin_time = time.time()
    while len(p_queue) != 0:

        # Ordena a fila baseada em uma heuristica
        p_queue.sort(key=manhattan_distance)

        # Remove o primeiro elemento da fila
        cur = p_queue.pop(0)

        # Verifica se um caminho foi encontrado
        # Se ele foi a busca encerra e o tempo é anotado
        if lb.is_end(labyrinth, cur):
            found = True
            found_time = time.time()
            break

        # Checa as adjacências do elemento e as coloca na priority queue se não foram visitadas

        # Direita
        next = lb.get_right(labyrinth, cur, prev) # [cur[0], cur[1] + 1]
        if next != None:
            p_queue.append(next) # Adiciona na fila
            prev[next[0]][next[1]] = cur # Marca o antecessor do proximo elemento como sendo o atual

        # Baixo
        next = lb.get_bottom(labyrinth, cur, prev) # [cur[0] + 1, cur[1]]
        if next != None:
            p_queue.append(next)
            prev[next[0]][next[1]] = cur

        # Esquerda
        next = lb.get_left(labyrinth, cur, prev) # [cur[0], cur[1] - 1]
        if next != None and prev[next[0]][next[1]] == [-1, -1]:
            p_queue.append(next)
            prev[next[0]][next[1]] = cur

        # Cima
        next = lb.get_top(labyrinth, cur, prev) # [cur[0] - 1, cur[1]]
        if next != None and prev[next[0]][next[1]] == [-1, -1]:
            p_queue.append(next)
            prev[next[0]][next[1]] = cur

    # Gera o caminho a partir da matriz de predecessores
    path = lb.prev_to_path(prev, start, end)

    # Retorna um objeto com os resultados
    if found:
        return lb.Result(path, found_time - begin_time)
    return lb.Result(None, None)