Пример #1
0
void BidirectionalIBFS::Adopt() {
    auto start = Clock::now();
    while (!m_source_orphans.empty()) {
        Node& n = m_source_orphans.front();
        NodeId i = n.id;
        m_source_orphans.pop_front();
        int old_dist = n.dis;
        while (n.parent_arc != m_graph->ArcsEnd(i)
                && (m_graph->node(n.parent).state == NodeState::T
                    || m_graph->node(n.parent).state == NodeState::T_orphan
                    || m_graph->node(n.parent).state == NodeState::N
                    || m_graph->node(n.parent).dis != old_dist - 1
                    || !m_graph->NonzeroCap(n.parent_arc, false))) {
            ++n.parent_arc;
            if (n.parent_arc != m_graph->ArcsEnd(i))
                n.parent = n.parent_arc.Target();
        }
        if (n.parent_arc == m_graph->ArcsEnd(i)) {
            RemoveFromLayer(i);
            // We didn't find a new parent with the same label, so do a relabel
            n.dis = std::numeric_limits<int>::max()-1;
            for (auto newParentArc = m_graph->ArcsBegin(i); newParentArc != m_graph->ArcsEnd(i); ++newParentArc) {
                auto target = newParentArc.Target();
                if (m_graph->node(target).dis < n.dis
                        && (m_graph->node(target).state == NodeState::S
                            || m_graph->node(target).state == NodeState::S_orphan)
                        && m_graph->NonzeroCap(newParentArc, false)) {
                    n.dis = m_graph->node(target).dis;
                    n.parent_arc = newParentArc;
                    ASSERT(m_graph->NonzeroCap(n.parent_arc, false));
                    n.parent = target;
                }
            }
            n.dis++;
            int cutoff_distance = m_source_tree_d;
            if (m_forward_search) cutoff_distance += 1;
            if (n.dis > cutoff_distance) {
                n.state = NodeState::N;
            } else {
                n.state = NodeState::S;
                AddToLayer(i);
            }
            // FIXME(afix) Should really assert that n.dis > old_dis
            // but current-arc heuristic isn't watertight at the moment...
            if (n.dis > old_dist) {
                for (auto arc = m_graph->ArcsBegin(i); arc != m_graph->ArcsEnd(i); ++arc) {
                    if (m_graph->node(arc.Target()).parent == i)
                        MakeOrphan(arc.Target());
                }
            }
        } else {
            ASSERT(m_graph->NonzeroCap(n.parent_arc, false));
            n.state = NodeState::S;
        }
    }
    while (!m_sink_orphans.empty()) {
        Node& n = m_sink_orphans.front();
        NodeId i = n.id;
        m_sink_orphans.pop_front();
        int old_dist = n.dis;
        while (n.parent_arc != m_graph->ArcsEnd(i)
                && (m_graph->node(n.parent).state == NodeState::S
                    || m_graph->node(n.parent).state == NodeState::S_orphan
                    || m_graph->node(n.parent).state == NodeState::N
                    || m_graph->node(n.parent).dis != old_dist - 1
                    || !m_graph->NonzeroCap(n.parent_arc, true))) {
            ++n.parent_arc;
            if (n.parent_arc != m_graph->ArcsEnd(i))
                n.parent = n.parent_arc.Target();
        }
        if (n.parent_arc == m_graph->ArcsEnd(i)) {
            RemoveFromLayer(i);
            // We didn't find a new parent with the same label, so do a relabel
            n.dis = std::numeric_limits<int>::max()-1;
            for (auto newParentArc = m_graph->ArcsBegin(i); newParentArc != m_graph->ArcsEnd(i); ++newParentArc) {
                auto target = newParentArc.Target();
                if (m_graph->node(target).dis < n.dis
                        && (m_graph->node(target).state == NodeState::T
                            || m_graph->node(target).state == NodeState::T_orphan)
                        && m_graph->NonzeroCap(newParentArc, true)) {
                    n.dis = m_graph->node(target).dis;
                    n.parent_arc = newParentArc;
                    ASSERT(m_graph->NonzeroCap(n.parent_arc, true));
                    n.parent = target;
                }
            }
            n.dis++;
            int cutoff_distance = m_sink_tree_d;
            if (!m_forward_search) cutoff_distance += 1;
            if (n.dis > cutoff_distance) {
                n.state = NodeState::N;
            } else {
                n.state = NodeState::T;
                AddToLayer(i);
            }
            // FIXME(afix) Should really assert that n.dis > old_dis
            // but current-arc heuristic isn't watertight at the moment...
            if (n.dis > old_dist) {
                for (auto arc = m_graph->ArcsBegin(i); arc != m_graph->ArcsEnd(i); ++arc) {
                    if (m_graph->node(arc.Target()).parent == i)
                        MakeOrphan(arc.Target());
                }
            }
        } else {
            ASSERT(m_graph->NonzeroCap(n.parent_arc, true));
            n.state = NodeState::T;
        }
    }
    m_adoptTime += Duration{ Clock::now() - start }.count();
}
Пример #2
0
		        TFLOW FifoGap<TFLOW,TCAP>::FindMaxFlow()
		        {
                    if (m_stage != 1)
                    {
                        throw System::InvalidOperationException(__FUNCTION__, __LINE__,
                            "Call Init method before computing maximum flow.");
                    }              

                    Size rl_count = 0, rl_threshold = (Size) (m_glob_rel_freq * m_nodes);
                    Size next_layer_rank, min_rank;
                    Node *node, *head;
                    Arc *arc, *min_arc = NULL;
                    Layer *lay;
                    TCAP bottleneck;

                    GlobalUpdate();

                    while (m_fifo_first != NULL)
                    {
                        // Pop node from the queue
                        node = m_fifo_first;
                        m_fifo_first = node->m_next_active;

                        if (node->m_rank == m_nodes)
                        {
                            // The node was removed during gap relabeling
                            continue;
                        }

                        RemoveFromLayer(&m_layer_list[node->m_rank], node);

                        // DISCHARGE node
                        while (node->m_rank < m_nodes)
                        {
                            lay = &m_layer_list[node->m_rank];
                            next_layer_rank = node->m_rank - 1;

                            // PUSH excess
                            for (arc = node->m_current; arc != NULL; arc = arc->m_next)
                            {
                                if (arc->m_res_cap > 0)
                                {
                                    head = arc->m_head;

                                    if (head->m_rank == next_layer_rank)
                                    {
                                        bottleneck = Math::Min(node->m_excess, arc->m_res_cap);

                                        arc->m_res_cap -= bottleneck;
                                        arc->m_sister->m_res_cap += bottleneck;

                                        if (head->m_excess <= 0)
                                        {
                                            if (head->m_excess + bottleneck > 0)
                                            {
                                                // Add node to active queue
                                                if (m_fifo_first == NULL)
                                                {
                                                    m_fifo_first = head;
                                                }
                                                else
                                                {
                                                    m_fifo_last->m_next_active = head;
                                                }

                                                m_fifo_last = head;
                                                head->m_next_active = NULL;
                                                m_flow -= head->m_excess;
                                            }
                                            else
                                            {
                                                m_flow += bottleneck;
                                            }
                                        }

                                        head->m_excess += bottleneck;
                                        node->m_excess -= bottleneck;

                                        if (node->m_excess == 0)
                                        {
                                            break;
                                        }
                                    }
                                }
                            }

                            if (arc != NULL)
                            {
                                // All excess pushed away, the node becomes inactive
                                AddToLayer(lay, node);
                                node->m_current = arc;
                                break;
                            }

                            // RELABEL node
                            node->m_rank = min_rank = m_nodes;
                            
                            if (lay->m_first == NULL)
                            {
                                // Gap relabeling
                                GapRelabeling(lay, next_layer_rank);
                            }
                            else
                            {
                                // Node relabeling
                                for (arc = node->m_first; arc != NULL; arc = arc->m_next)
                                {
                                    if (arc->m_res_cap > 0 && arc->m_head->m_rank < min_rank)
                                    {
                                        min_rank = arc->m_head->m_rank;
                                        min_arc = arc;
                                    }
                                }

                                rl_count++;

                                if (++min_rank < m_nodes)
                                {
                                    node->m_rank = min_rank;
                                    node->m_current = min_arc;

                                    if (min_rank > m_max_rank)
                                    {
                                        m_max_rank = min_rank;
                                    }
                                }
                            }
                        }

                        // Check if global relabeling should be done
                        if (rl_count > rl_threshold && m_fifo_first != NULL)
                        {
                            GlobalUpdate();
                            rl_count = 0;
                        }
                    }

                    // Find nodes that are connected to the sink after the last step.
                    // This is IMPORTANT, because it allows us to find which nodes are
                    // connected to the source and which to the sink.
                    GlobalUpdate();

                    m_stage = 2;

                    return m_flow;
		        }