Ejemplo n.º 1
0
def get_best_path(digraph, start, end, path, max_dist_outdoors, best_dist,
                  best_path):
    """
    Finds the shortest path between buildings.

    Returns:
        A tuple with the shortest-path from start to end, represented by
        a list of building numbers and the distance of that path.

        If there exists no path that satisfies max_total_dist and
        max_dist_outdoors constraints, then return None.
    """
    start = Node(start)
    end = Node(end)
    path[0].append(start.get_name())

    if start not in digraph.nodes or end not in digraph.nodes:
        raise ValueError
    elif start == end:
        return tuple([path[0].copy(), path[1]])
    else:
        for edge in digraph.edges[start]:
            if edge.get_destination().get_name() not in path[0]:
                if len(best_path) == 0 or len(path[0]) < len(best_path):
                    if path[2] + edge.get_outdoor_distance(
                    ) <= max_dist_outdoors:
                        path[1] += edge.get_total_distance()
                        path[2] += edge.get_outdoor_distance()
                        next_path = get_best_path(digraph,
                                                  edge.get_destination(), end,
                                                  path, max_dist_outdoors,
                                                  best_dist, best_path)
                        path[0].remove(edge.get_destination().get_name())
                        path[1] -= edge.get_total_distance()
                        path[2] -= edge.get_outdoor_distance()
                    else:
                        continue

                    if next_path is not None:
                        if best_dist == 0 or next_path[1] < best_dist:
                            best_path = next_path[0]
                            best_dist = next_path[1]

        if best_dist == 0:
            return None
        return tuple([best_path, best_dist])
Ejemplo n.º 2
0
def directed_dfs(digraph, start, end, max_total_dist, max_dist_outdoors):
    """
    Finds the shortest path from start to end using a directed depth-first
    search. The total distance traveled on the path must not
    exceed max_total_dist, and the distance spent outdoors on this path must
    not exceed max_dist_outdoors.

    Parameters:
        digraph: Digraph instance
            The graph on which to carry out the search
        start: string
            Building number at which to start
        end: string
            Building number at which to end
        max_total_dist: int
            Maximum total distance on a path
        max_dist_outdoors: int
            Maximum distance spent outdoors on a path

    Returns:
        The shortest-path from start to end, represented by
        a list of building numbers (in strings), [n_1, n_2, ..., n_k],
        where there exists an edge from n_i to n_(i+1) in digraph,
        for all 1 <= i < k

        If there exists no path that satisfies max_total_dist and
        max_dist_outdoors constraints, then raises a ValueError.
    """
    global Best_dist
    Best_dist = 99999
    start = Node(start)
    end = Node(end)
    if (not digraph.has_node(start)) or (not digraph.has_node(end)):
        raise ValueError("Bad test case!")
    path = [[start.get_name()], 0, 0]
    best_path = []
    ans = get_best_path(digraph, start, end, path, max_dist_outdoors,
                        max_total_dist, best_path)
    if best_path == None or len(best_path) == 0:
        raise ValueError("Bad test case!")
    return list(ans)
Ejemplo n.º 3
0
def get_best_path(digraph, start, end, path, max_dist_outdoors, best_dist,
                  best_path):
    """
    Finds the shortest path between buildings subject to constraints.

    Parameters:
        digraph: Digraph instance
            The graph on which to carry out the search
        start: string
            Building number at which to start
        end: string
            Building number at which to end
        path: list composed of [[list of strings], int, int]
            Represents the current path of nodes being traversed. Contains
            a list of node names, total distance traveled, and total
            distance outdoors.
        max_dist_outdoors: int
            Maximum distance spent outdoors on a path
        best_dist: int
            The smallest distance between the original start and end node
            for the initial problem that you are trying to solve
        best_path: list of strings
            The shortest path found so far between the original start
            and end node.

    Returns:
        A tuple with the shortest-path from start to end, represented by
        a list of building numbers (in strings), [n_1, n_2, ..., n_k],
        where there exists an edge from n_i to n_(i+1) in digraph,
        for all 1 <= i < k and the distance of that path.

        If there exists no path that satisfies max_total_dist and
        max_dist_outdoors constraints, then return None.
    """

    global edge
    path1 = path.copy()
    path1[0] = path[0].copy()

    start = Node(start)
    ##    print(start)
    ##    print(end)
    end = Node(end)
    if digraph.has_node(start) == False:
        raise ValueError("Node not in digraph")
    elif digraph.has_node(end) == False:
        raise ValueError("Node not in digraph")

    if len(path1[0]) != 0:
        path1[2] += int(edge.get_outdoor_distance())
        path1[1] += int(edge.get_total_distance())
        path1[0] = path1[0] + [str(edge.get_destination())]
    else:
        path1[0] = path1[0] + [str(start.get_name())]

##    print('start, ', path)

    if start == end and path1[2] <= max_dist_outdoors:
        ##        print('start == end', start)

        return path1

    r = digraph.get_edges_for_node(start)
    list1 = []

    for pedge in r:
        list1.append(pedge.get_destination())
##    print('edges', list1)

    for edge in digraph.get_edges_for_node(start):
        ##        print('edge', edge)

        start_node = str(edge.get_destination())
        ##        print('start2', start_node)
        ##        print('TEST', path1)

        if start_node not in path1[0]:
            if best_path == None or (path1[1] < best_dist
                                     and path1[2] <= max_dist_outdoors):
                ##                print('ent1')

                new_path = get_best_path(digraph, start_node, end, path1,
                                         max_dist_outdoors, best_dist,
                                         best_path)

                ##                print('new', new_path)

                if new_path != None:
                    if (new_path[2] <= max_dist_outdoors
                            and new_path[1] <= best_dist) or best_dist == 0:
                        ##                        print('ent2')

                        best_dist = new_path[1]

                        best_path = new_path.copy()

##    print('best path: ', best_path)
##    print(' ')

##    if str(edge.get_destination()) in path[0]:
##
##        path[2]   -= int(edge.get_outdoor_distance())
##        path[1]   -= int(edge.get_total_distance())
##        path[0].remove(str(edge.get_destination()))
    return best_path
def get_best_path(digraph, start, end, path, max_dist_outdoors, best_dist,
                  best_path):
    """
    Finds the shortest path between buildings subject to constraints.

    Parameters:
        digraph: Digraph instance
            The graph on which to carry out the search
        start: string
            Building number at which to start
        end: string
            Building number at which to end
        path: list composed of [[list of strings], int, int]
            Represents the current path of nodes being traversed. Contains
            a list of node names, total distance traveled, and total
            distance outdoors.
        max_dist_outdoors: int
            Maximum distance spent outdoors on a path
        best_dist: int
            The smallest distance between the original start and end node
            for the initial problem that you are trying to solve
        best_path: list of strings
            The shortest path found so far between the original start
            and end node.

    Returns:
        A tuple with the shortest-path from start to end, represented by
        a list of building numbers (in strings), [n_1, n_2, ..., n_k],
        where there exists an edge from n_i to n_(i+1) in digraph,
        for all 1 <= i < k and the distance of that path.

        If there exists no path that satisfies max_total_dist and
        max_dist_outdoors constraints, then return None.
    """
    start = Node(start)
    end = Node(end)
    path = path + [start]
    # print("path", path)

    if start == end:
        # print("s=e")
        return path

    # nodes = digraph.get_edges_for_node(start)
    # print("nodes:", end=" ")
    # for n in nodes:
    #     print(n, end=", ")
    # print("done")

    for node in digraph.get_edges_for_node(start):
        # print("node:", node)
        if node.get_destination() not in path:
            # print(node.get_destination(), "is node not in path")
            newPath = get_best_path(digraph,
                                    node.get_destination().get_name(),
                                    end.get_name(), path, max_dist_outdoors,
                                    best_dist, best_path)
            # print("new Path:", newPath)
            if newPath is not None:
                current_distance_outdoors = distance_outdoors(digraph, newPath)
                current_distance_total = current_distance(digraph, newPath)
                # print("current_distance_outdoors:", current_distance_outdoors)
                # print("current_distance:", current_distance_total)
                if (best_dist == 0) or (
                    (current_distance_outdoors <= max_dist_outdoors) and
                    (current_distance_total <= best_dist)):
                    # print("IN")
                    best_dist = current_distance_total
                    best_path = newPath
                    # print("best_dist:", best_dist)
                    # print("best_path:", best_path)

    # print("best_distance:", best_dist)
    if len(best_path) == 0:
        return None
    else:
        return best_path
Ejemplo n.º 5
0
def get_best_path(digraph, start, end, path, max_dist_outdoors, best_dist,
                  best_path):
    """
    Finds the shortest path between buildings subject to constraints.

    Parameters:
        digraph: Digraph instance
            The graph on which to carry out the search
        start: string
            Building number at which to start
        end: string
            Building number at which to end
        path: list composed of [[list of strings], int, int]
            Represents the current path of nodes being traversed. Contains
            a list of node names, total distance traveled, and total
            distance outdoors.
        max_dist_outdoors: int
            Maximum distance spent outdoors on a path
        best_dist: int
            The smallest distance between the original start and end node
            for the initial problem that you are trying to solve
        best_path: list of strings
            The shortest path found so far between the original start
            and end node.

    Returns:
        A tuple with the shortest-path from start to end, represented by
        a list of building numbers (in strings), [n_1, n_2, ..., n_k],
        where there exists an edge from n_i to n_(i+1) in digraph,
        for all 1 <= i < k and the distance of that path.

        If there exists no path that satisfies max_total_dist and
        max_dist_outdoors constraints, then return None.
    """
    # TODO
    #use dynamic programming and recursion
    #return none if all possible choice exceeds max_dist of max_outdoor_dist
    #update path
    path[0] = path[0] + [start]
    #Initialize Start and End both as Nodes
    start_n = Node(start)
    end_n = Node(end)
    if not digraph.has_node(start_n) or not digraph.has_node(end_n):
        raise ValueError('invalid start or end node')
    elif start == end:  #when reaches destination is when recusion should stop
        return (path[0], path[1])
    else:
        for edge in digraph.get_edges_for_node(start_n):
            next_node = Node(edge.get_destination())
            next_node_tot_dist = edge.get_total_distance()
            next_node_out_dist = edge.get_outdoor_distance()
            #get next node, total dist, and outdoor dist
            #make sure doesn't cycle i.e. come back to same node
            if next_node.get_name() not in path[0]:
                #check if max outdoor dist exceeded
                if next_node_out_dist + path[2] <= max_dist_outdoors:
                    #only have to keep going if path is going to be shorter than current best path
                    if best_path == None or next_node_tot_dist + path[
                            1] < best_dist:
                        path_update = [
                            path[0].copy(), path[1] + next_node_tot_dist,
                            path[2] + next_node_out_dist
                        ]
                        #updating original path with [list of node, total distance travelled, total dist outdoors]
                        #note that path[0] not updated here but rather within recursive function due to conderation of starting conditions
                        #the "start" parameter of get_best_path function is str, not Node object.
                        next_path = get_best_path(digraph,
                                                  next_node.get_name(), end,
                                                  path_update,
                                                  max_dist_outdoors, best_dist,
                                                  best_path)
                        #if all condition satisfied, traverse to next node
                        if next_path != None:
                            best_path = next_path
                            best_dist = next_path[1]
        return best_path