Exemplo n.º 1
0
    def _setup_heap(self, heap):
        """before _find_min_augument_path start, this function sets up heap
           as the source nodes should be treated as single node. Basically,
           all the nodes but source nodes will be inserted into heap with
           appropriate weights and prev_nodes.
        """
        min_weight_right_nodes = [sys.maxint] * len(self.table_weight)
        prev_of_right_nodes = [None] * len(self.table_weight)

        num_left_exposed_node = 0

        # insert nodes in left category
        for i in range(0, len(self.map_match_left_to_right)):
            if self.map_match_left_to_right[i] == None:
                num_left_exposed_node += 1
                left_exposed_node = HeapNode(self._global_node_id(i, True), 0)

                for j in range(0, len(self.table_weight)):
                    if min_weight_right_nodes[j] > self.table_weight[i][j]:
                        min_weight_right_nodes[j] = self.table_weight[i][j]
                        prev_of_right_nodes[j] = left_exposed_node
            else:
                heappush(heap,
                         HeapNode(self._global_node_id(i, True), sys.maxint))

        if num_left_exposed_node == 0:
            heap = []
            return

        for j in range(0, len(self.table_weight)):
            heappush(
                heap,
                HeapNode(self._global_node_id(j, False),
                         min_weight_right_nodes[j], prev_of_right_nodes[j]))
Exemplo n.º 2
0
 def test_insert_nodes_with_descending_values(self):
     binary_heap = BinaryHeap()
     binary_heap.insert(HeapNode({'name': 'A', 'value': 0.91}, 'value'))
     self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [0.91])
     binary_heap.insert(HeapNode({'name': 'B', 'value': 0.57}, 'value'))
     self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [0.57, 0.91])
     binary_heap.insert(HeapNode({'name': 'B', 'value': 0.34}, 'value'))
     self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [0.34, 0.91, 0.57])
Exemplo n.º 3
0
 def merge_nodes(self):
     # if the tree has more than one node
     while (len(self.heap) > 1):
         node_1 = heapq.heappop(self.heap)
         node_2 = heapq.heappop(self.heap)
         # merge to  one upper node
         merged = HeapNode(None, node_1.freq + node_2.freq)
         merged.left = node_1
         merged.right = node_2
         heapq.heappush(self.heap, merged)
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    def _get_neighbors_aug_path(self, global_id_node, heap):
        """return neighbors in alternate path."""

        assert global_id_node >= 0 and \
                 global_id_node < ( len(self.table_weight) * 2 ), \
               "unexpected global_id: %d" % global_id

        if self._is_node_left_category(global_id_node):  # left category
            if self.map_match_left_to_right[
                    global_id_node] == None:  # exposed node
                return self.list_all_node_ids_right_category
            else:  # node with match
                list = []
                for global_id_right_node in self.list_all_node_ids_right_category:
                    if global_id_right_node != \
                        self.map_match_left_to_right[global_id_node] and \
                       heap.count( HeapNode(global_id_right_node, 0, None, False) ) > 0:
                        list.append(global_id_right_node)
                return list

        else:  # right category
            # return the node in left category which can be reached through
            # matched edge
            idx = self._local_node_id(global_id_node)
            assert (self.map_match_right_to_left[idx] != None), \
                    "there is no neighbor for node %d" % global_id_node
            return [self.map_match_right_to_left[idx]]
Exemplo n.º 6
0
    def trees_merge(self):

        # We pick the 2 trees with the smallest frequency
        # Combine them into a new tree with a new parent node with the frequency of both of its children
        # Until you have no more trees to merge

        while (len(self.heap) > 1):
            node1 = heapq.heappop(
                self.heap
            )  #Pop and return the smallest item from the heap, maintaining the heap invariant
            node2 = heapq.heappop(self.heap)

            tree_merged = HeapNode(None, node1.frequency + node2.frequency)
            tree_merged.left = node1
            tree_merged.right = node2

            heapq.heappush(self.heap, tree_merged)
Exemplo n.º 7
0
    def heap_creation(self, frequency):

        #We use our class HeapNode to create the binary tree

        for key in frequency:
            node = HeapNode(key, frequency[key])
            heapq.heappush(
                self.heap, node
            )  #Push the value of the node onto the heap, maintaining the heap invariant
Exemplo n.º 8
0
    def _find_min_augument_path(self):
        """return augument path with minimum weight given match. dijkistra's
           shortest path is used to find the path.
        """

        path, heap = [], []
        self._setup_heap(heap)

        while heap:
            node_entry = heappop(heap)

            if self._is_node_exposed_right_category(node_entry.id):
                tmp_node_entry = node_entry
                while True:
                    path.append(tmp_node_entry.id)
                    tmp_node_entry = tmp_node_entry.prev_node
                    if (tmp_node_entry == None):
                        break
                return path

            list_neighbor_node_id = \
                self._get_neighbors_aug_path(node_entry.id, heap)

            local_id_entry_node = self._local_node_id(node_entry.id)
            for neighbor_node_id in list_neighbor_node_id:
                local_id_neighbor_node = self._local_node_id(neighbor_node_id)

                if self._is_node_left_category(node_entry.id):
                    alt = node_entry.priority + \
                    self.table_weight[local_id_entry_node][local_id_neighbor_node]
                else:
                    alt = node_entry.priority - \
                    self.table_weight[local_id_neighbor_node][local_id_entry_node]

                node_neighbor = HeapNode.get_entry(neighbor_node_id)

                if alt < node_neighbor.priority:
                    node_neighbor.priority = alt
                    node_neighbor.prev_node = node_entry
                    heapify(heap)
        # end of  while heap

        assert len(path) == 0, "path with element(s) not expected."
        return path
    def _find_min_augument_path(self):
        """return augument path with minimum weight given match. dijkistra's
           shortest path is used to find the path.
        """
        
        path, heap = [], []
        self._setup_heap(heap)

        while heap:
            node_entry = heappop(heap)
            
            if self._is_node_exposed_right_category(node_entry.id):
                tmp_node_entry = node_entry
                while True:
                    path.append(tmp_node_entry.id)
                    tmp_node_entry = tmp_node_entry.prev_node
                    if (tmp_node_entry == None):
                        break
                return path

            list_neighbor_node_id = \
                self._get_neighbors_aug_path(node_entry.id, heap)

            local_id_entry_node = self._local_node_id(node_entry.id)
            for neighbor_node_id in list_neighbor_node_id:
                local_id_neighbor_node = self._local_node_id(neighbor_node_id)

                if self._is_node_left_category(node_entry.id):
                    alt = node_entry.priority + \
                    self.table_weight[local_id_entry_node][local_id_neighbor_node]
                else:
                    alt = node_entry.priority - \
                    self.table_weight[local_id_neighbor_node][local_id_entry_node]

                node_neighbor = HeapNode.get_entry(neighbor_node_id)

                if alt < node_neighbor.priority:
                    node_neighbor.priority = alt
                    node_neighbor.prev_node = node_entry
                    heapify(heap)
        # end of  while heap

        assert len(path) == 0, "path with element(s) not expected."
        return path
Exemplo n.º 10
0
 def priority_queue(self, frequency):
     # make a prio queue based on the fequency
     for key in frequency:
         node = HeapNode(key, frequency[key])
         heapq.heappush(self.heap, node)
Exemplo n.º 11
0
 def setup(self, names, values):
     return [HeapNode({'name': n[0], 'value': n[1]}, 'value') for n in zip(names, values)]