Пример #1
0
 def test_update_with_lower_value_for_leaf_node(self):
     values = [1, 3, 5, 7, 9, 10, 11]
     names = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
     binary_heap = BinaryHeap(self.setup(names, values))
     binary_heap.build_heap()
     binary_heap.update(6, 4)
     self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [1, 3, 4, 7, 9, 5, 11])
Пример #2
0
 def test_delete_min(self):
     names = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
     values = [5, 3, 7, 1, 9, 10, 11]
     binary_heap = BinaryHeap(self.setup(names, values))
     binary_heap.build_heap()
     self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [1, 3, 7, 5, 9, 10, 11])
     self.assertEqual(binary_heap.delete_min().get_value_attribute(), 1)
Пример #3
0
def test_heap_delete_min_build_heap(benchmark, dsa_, values):
    nums = deepcopy(values)
    dsa_obj = BinaryHeap()
    dsa_obj.build_heap(values)
    to_del = values[len(values) // 2]

    benchmark(dsa_obj.delete_min)
Пример #4
0
 def test_correctness(self):
     for case in cases:
         bheap = BinaryHeap()
         bheap.build_heap(case)
         retrieved = []
         while len(bheap) > 0:
             retrieved.append(bheap.delete_min())
         self.assertEqual(retrieved, sorted(case))
Пример #5
0
def task_1ab():
    task_list = deepcopy(TASK_ONE_A)

    _, bh_obj = create_heap_for_loop_insert(task_list)  # for-loop, insert()
    bh_linear = BinaryHeap()  # New bh-obj for linear insertion
    bh_linear.build_heap(task_list)  # Build with linear insertion

    # HeapList
    bh_list = ", ".join([str(l) for l in bh_obj.heapList[1::]])
    bh_linear_list = ", ".join([str(l) for l in bh_linear.heapList[1::]])

    # "For-loop"-obj walks
    xa, a = travers_tree_inorder(bh_obj)
    xb, b = travers_tree_postorder(bh_obj)
    xc, c = travers_tree_preorder(bh_obj)
    xd, d = level_order(bh_obj)

    # "Linear"-obj walks
    ignore, aa = travers_tree_inorder(bh_linear)
    ignore, bb = travers_tree_postorder(bh_linear)
    ignore, cc = travers_tree_preorder(bh_linear)
    ignore, dd = level_order(bh_linear)

    table = Table("Task", "Array", "Insert Method")

    table.add_row("1a, algorithm 1", bh_list, "for-loop")
    table.add_row("1b, algorithm 2", bh_linear_list, "Linear")

    table.add_row("", "", "")
    table.add_row("1c, " + xa, ", ".join([str(l) for l in a]), "for-loop")
    table.add_row("1c, " + xb, ", ".join([str(l) for l in b]), "for-loop")
    table.add_row("1c, " + xc, ", ".join([str(l) for l in c]), "for-loop")
    table.add_row("1c, " + xd, ", ".join([str(l) for l in d]), "for-loop")
    table.add_row("", "", "")
    table.add_row("1c, " + xa, ", ".join([str(l) for l in aa]), "Linear")
    table.add_row("1c, " + xb, ", ".join([str(l) for l in bb]), "Linear")
    table.add_row("1c, " + xc, ", ".join([str(l) for l in cc]), "Linear")
    table.add_row("1c, " + xd, ", ".join([str(l) for l in dd]), "Linear")

    console = Console()
    console.print(table)
Пример #6
0
 def test_build_heap_with_sorted_list(self):
     values = [1, 3, 5, 7, 9, 10, 11]
     names = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
     binary_heap = BinaryHeap(self.setup(names, values))
     binary_heap.build_heap()
     self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [1, 3, 5, 7, 9, 10, 11])
Пример #7
0
def test_heap_build():
    bh_bh = BinaryHeap()
    bh_bh.build_heap(mock_lists[1])
    return bh_bh
Пример #8
0
class AStar():
    """
    Paramaters:
        map: Reference to map object
        start_node_id: Index of start node
        dest_node_id: Index of destination node
    """
    def __init__(self, map):
        self.map = map
        # Hash set to keep track of open intersections. The hash set will contain intersection IDs only
        # and will be used to find out if an intersection ID is already there is the set
        self.open = set()
        # Hash set to keep track of closed intersection ID. The hash set will contain intersection IDs only
        # and will be used to find out
        self.closed = set()
        # Dictionary to keep track of cost. The dictionary is keyed by intersection id
        # Cost will have three components.
        # g = true of cost of getting from source node to current node
        # h = estimated cost of getting from current node to destination node
        # f = total cost = g + h
        self.cost = {}

        # List used to store the actual path from destination path back to source intersection.
        # Once the shortest path to destination intersection is found, this will be reversed and returned as path from
        # source to destination
        self.nodes_in_path = []
        # Dictionary to keep track of parent intersection. It is keyed by current intersection id.
        # Parent intersection ID is the intersection from where the current intersection is reached
        self.parent = {}
        # Initialize min binary heap. This will be used to get the intersection with minimum cost
        self.cost_heap = BinaryHeap()

    # Private method to get the intersection with minimum total cost
    def _get_node_with_min_cost(self):
        min_value_node = self.cost_heap.delete_min()
        # Remove the intersection with min cost from list of open intersections
        self.open.remove(min_value_node.id)
        # Put that intersection into closed intersections
        self.closed.add(min_value_node.id)
        return min_value_node

    # Returns the list of intersections that can be reached from the current intersection
    def _get_next_nodes(self, current_node_id):
        return self.map.roads[current_node_id]

    # Method that performs A-star search
    def search(self, start_node_id, dest_node_id):
        # Initialize the cost structure of first intersection
        self.cost[start_node_id] = {
            'g': 0, # True cost of getting from start node to this node. This is calculated in terms of number of hops (edges)
            'h': 0, # Estimated cost of getting this node to destination node
            'f': 0  # Total cost. It is a computed field f = g + h
        }
        # Put the start node as the first open node where the search starts
        self.open.add(start_node_id)
        self.cost_heap.insert(HeapNode({'id': start_node_id, 'f': 0, 'g': 0, 'h' : 0}, 'f'))
        iteration = 1
        while len(self.open) > 0:
            # Among all nodes which are open find the node with minimum total cost
            # This will be the nest node to explore
            current_node = self._get_node_with_min_cost()
            if current_node.id == dest_node_id:
                end_node = current_node.id
                while end_node is not None:
                    self.nodes_in_path.append(end_node)
                    end_node = self.parent.get(end_node, None)
                self.nodes_in_path.reverse()
                return self.nodes_in_path
            children = self._get_next_nodes(current_node.id)
            for child in children:
                # If the intersection is already in closed set then there is no need to explore it
                if child in self.closed: continue
                g = self.cost[current_node.id]['g'] + \
                    math.sqrt(
                        math.pow(self.map.intersections[current_node.id][0] - self.map.intersections[child][0], 2) + \
                        math.pow(self.map.intersections[current_node.id][1] - self.map.intersections[child][1], 2))

                # Estimate distance to destination intersection. This is pre euclidean distance.
                # This heuristic will always be less than or equal to the true distance of the road
                # connecting the two intersections
                h = math.sqrt(
                    math.pow(self.map.intersections[child][0] - self.map.intersections[dest_node_id][0], 2) + \
                    math.pow(self.map.intersections[child][1] - self.map.intersections[dest_node_id][1], 2))
                # If the child intersection is not in open set then put it in the list to explore
                # Compute the cost (cost to reach this intersection, estimated cost to reach destination
                # from here and total cost for this intersection
                # The child intersection may already be there if there way another intersection leading to this one
                # Update the cost values if cost of reaching this child intersection is lower than cost value
                # associated with the intersection
                if child not in self.open:
                    self.cost[child] = {'g' : g, 'h' : h, 'f' : g + h}
                    self.parent[child] = current_node.id
                    self.open.add(child)
                    self.cost_heap.insert(HeapNode({'id': child, 'f': g + h, 'g': g, 'h' : h}, 'f'))
                elif self.cost[child]['f'] > g + h:
                    self.cost[child] = {'g' : g, 'h' : h, 'f' : g + h}
                    self.parent[child] = current_node.id
                    self.cost_heap.build_heap()
            #if iteration >= 1:
            #    sys.exit(0)
            iteration += 1

    # Generates SVG diagram for the graph and the shortest path found using A* search
    def draw_astar_map(self, path, colors, output_file):
        graph = pydot.Dot(graph_type='graph', rankdir="LR")
        nodes = {}
        edges = set()

        for k, v in self.map.intersections.items():
            n = pydot.Node(k, shape="circle", style="filled", fillcolor="cyan" if k not in path else colors[0], tooltip="(%f,%f)" % (v[0], v[1]))
            nodes[k] = n
            graph.add_node(n)
        for src, dst in enumerate(self.map.roads):
            for d in dst:
                if (src,d) not in edges:
                    distance = math.sqrt(math.pow(self.map.intersections[src][0] - self.map.intersections[d][0], 2) + \
                                         math.pow(self.map.intersections[src][1] - self.map.intersections[d][1], 2))
                    edges.add((src,d))
                    edges.add((d,src))
                    if src in path and d in path:
                        color = colors[1]
                        style="bold"
                    else:
                        color = "black"
                        style = "dashed"
                    graph.add_edge(pydot.Edge(nodes[src], nodes[d], style=style, label="%0.2f" % distance, color=color, tooltip="%0.2f" % distance))
        graph.write_svg(output_file)