human
Complete this python program:
def _bidirectional_dijkstra(G, source, target, weight='weight', ignore_nodes=None, ignore_edges=None):
assistant
#Here is the Python program you requested.

    """Dijkstra\s algorithm for shortest paths using bidirectional search.
    This function returns the shortest path between source and target
    ignoring nodes and edges in the containers ignore_nodes and
    ignore_edges.
    This is a custom modification of the standard Dijkstra bidirectional
    shortest path implementation at networkx.algorithms.weighted
    Parameters
    G : NetworkX graph
    source : node
    Starting node.
    target : node
    Ending node.
    weight: string, optional (default=\weight\)
    Edge data key corresponding to the edge weight
    ignore_nodes : container of nodes
    nodes to ignore, optional
    ignore_edges : container of edges
    edges to ignore, optional
    Returns
    length : number
    Shortest path length.
    Returns a tuple of two dictionaries keyed by node.
    The first dictionary stores distance from the source.
    The second stores the path from the source to that node.
    Raises
    NetworkXNoPath
    If no path exists between source and target.
    Notes
    Edge weight attributes must be numerical.
    Distances are calculated as sums of weighted edges traversed.
    In practice  bidirectional Dijkstra is much more than twice as fast as
    ordinary Dijkstra.
    Ordinary Dijkstra expands nodes in a sphere-like manner from the
    source. The radius of this sphere will eventually be the length
    of the shortest path. Bidirectional Dijkstra will expand nodes
    from both the source and the target, making two spheres of half
    this radius. Volume of the first sphere is pi*r*r while the
    others are 2*pi*r/2*r/2, making up half the volume.
    This algorithm is not guaranteed to work if edge weights
    are negative or are floating point numbers
    (overflows and roundoff errors can cause problems).
    See Also
    shortest_path
    shortest_path_length
    """
    if (source == target):
        return (0, [source])
    if G.is_directed():
        Gpred = G.predecessors
        Gsucc = G.successors
    else:
        Gpred = G.neighbors
        Gsucc = G.neighbors
    if ignore_nodes:
        def filter_iter(nodes):
            def iterate(v):
                for w in nodes(v):
                    if (w not in ignore_nodes):
                        (yield w)
            return iterate
        Gpred = filter_iter(Gpred)
        Gsucc = filter_iter(Gsucc)
    if ignore_edges:
        if G.is_directed():
            def filter_pred_iter(pred_iter):
                def iterate(v):
                    for w in pred_iter(v):
                        if ((w, v) not in ignore_edges):
                            (yield w)
                return iterate
            def filter_succ_iter(succ_iter):
                def iterate(v):
                    for w in succ_iter(v):
                        if ((v, w) not in ignore_edges):
                            (yield w)
                return iterate
            Gpred = filter_pred_iter(Gpred)
            Gsucc = filter_succ_iter(Gsucc)
        else:
            def filter_iter(nodes):
                def iterate(v):
                    for w in nodes(v):
                        if (((v, w) not in ignore_edges) and ((w, v) not in ignore_edges)):
                            (yield w)
                return iterate
            Gpred = filter_iter(Gpred)
            Gsucc = filter_iter(Gsucc)
    push = heappush
    pop = heappop
    dists = [{}, {}]
    paths = [{source: [source]}, {target: [target]}]
    fringe = [[], []]
    seen = [{source: 0}, {target: 0}]
    c = count()
    push(fringe[0], (0, next(c), source))
    push(fringe[1], (0, next(c), target))
    neighs = [Gsucc, Gpred]
    finalpath = []
    dir = 1
    while (fringe[0] and fringe[1]):
        dir = (1 - dir)
        (dist, _, v) = pop(fringe[dir])
        if (v in dists[dir]):
            continue
        dists[dir][v] = dist
        if (v in dists[(1 - dir)]):
      ...