def max_flow_preflowpush(self, source, sink, algo = 'FIFO', display = None):
        '''
        API: max_flow_preflowpush(self, source, sink, algo = 'FIFO',
                                  display = None)
        Description:
        Finds maximum flow from source to sink by a depth-first search based
        augmenting path algorithm.
        Pre:
             Assumes a directed graph in which each arc has a 'capacity'
             attribute and for which there does does not exist both arcs (i,j)
             and (j,i) for any pair of nodes i and j.
        Input:
            source: Source node name.
            sink: Sink node name.
            algo: Algorithm choice, 'FIFO', 'SAP' or 'HighestLabel'.
            display: display method.
        Post:
            The 'flow' attribute of each arc gives a maximum flow.
        '''
        if display == None:
            display = self.attr['display']
        else:
            self.set_display_mode(display)
        nl = self.get_node_list()
        # set excess of all nodes to 0
        for n in nl:
            self.set_node_attr(n, 'excess', 0)
        # set flow of all edges to 0
        for e in self.edge_attr:
            self.edge_attr[e]['flow'] = 0
            if 'capacity' in self.edge_attr[e]:
                capacity = self.edge_attr[e]['capacity']
                self.edge_attr[e]['label'] = str(capacity)+'/0'
            else:
                self.edge_attr[e]['capacity'] = INF
                self.edge_attr[e]['label'] = 'INF/0'
        self.display()
        self.set_display_mode('off')
        self.search(sink, algo = 'UnweightedSPT', reverse = True)
        self.set_display_mode(display)
        disconnect = False
        for n in nl:
            if self.get_node_attr(n, 'distance') is None:
                disconnect = True
                self.set_node_attr(n, 'distance',
                                   2*len(nl) + 1)
        if disconnect:
            print('Warning: graph contains nodes not connected to the sink...')
        if algo == 'FIFO':
            q = Queue()
        elif algo == 'SAP':
            q = Stack()
        elif algo == 'HighestLabel':
            q = PriorityQueue()
        for n in self.get_neighbors(source):
            capacity = self.get_edge_attr(source, n, 'capacity')
            self.set_edge_attr(source, n, 'flow', capacity)
            self.set_node_attr(n, 'excess', capacity)
            excess = self.get_node_attr(source, 'excess')
            self.set_node_attr(source, 'excess', excess - capacity)
            if algo == 'FIFO' or algo == 'SAP':
                q.push(n)
            elif algo == 'HighestLabel':
                q.push(n, -1)
        self.set_node_attr(source, 'distance', len(nl))
        self.show_flow()
        while not q.isEmpty():
            relabel = True
            current = q.peek()
            neighbors = (self.get_neighbors(current) +
                         self.get_in_neighbors(current))
            for n in neighbors:
                pushed = self.process_edge_flow(source, sink, current, n, algo,
                                                q)
                if pushed:
                    self.show_flow()
                    if algo == 'FIFO':
                        '''With FIFO, we need to add the neighbors to the queue
                        before the current is added back in or the nodes will
                        be out of order
                        '''
                        if q.peek(n) is None and n != source and n != sink:
                            q.push(n)
                        '''Keep pushing while there is excess'''
                        if self.get_node_attr(current, 'excess') > 0:
                            continue
                    '''If we were able to push, then there we should not
                    relabel
                    '''
                    relabel = False
                    break
            q.remove(current)
            if current != sink:
                if relabel:
                    self.relabel(current)
                    self.show_flow()
                if self.get_node_attr(current, 'excess') > 0:
                    if algo == 'FIFO' or algo == 'SAP':
                        q.push(current)
                    elif algo == 'HighestLabel':
                        q.push(current, -self.get_node_attr(current,
                                                            'distance'))
            if pushed and q.peek(n) is None and n != source:
                if algo == 'SAP':
                    q.push(n)
                elif algo == 'HighestLabel':
                    q.push(n, -self.get_node_attr(n, 'distance'))