Exemplo n.º 1
0
void BidirectionalIBFS::IBFSInit()
{
    auto start = Clock::now();
    
    const int n = m_graph->NumNodes();

    m_source_layers = std::vector<NodeQueue>(n+1);
    m_sink_layers = std::vector<NodeQueue>(n+1);

    m_source_orphans.clear();
    m_sink_orphans.clear();

    auto& nodes = m_graph->GetNodes();
    auto& sNode = nodes[m_graph->GetS()];
    sNode.state = NodeState::S;
    sNode.dis = 0;
    m_source_layers[0].push_back(sNode);
    auto& tNode = nodes[m_graph->GetT()];
    tNode.state = NodeState::T;
    tNode.dis = 0;
    m_sink_layers[0].push_back(tNode);

    // saturate all s-i-t paths
    for (NodeId i = 0; i < n; ++i) {
        REAL min_cap = std::min(m_graph->m_c_si[i]-m_graph->m_phi_si[i],
                m_graph->m_c_it[i]-m_graph->m_phi_it[i]);
        m_graph->m_phi_si[i] += min_cap;
        m_graph->m_phi_it[i] += min_cap;
        if (m_graph->m_c_si[i] > m_graph->m_phi_si[i]) {
            auto& node = m_graph->node(i);
            node.state = NodeState::S;
            node.dis = 1;
            AddToLayer(i);
            node.parent_arc = m_graph->ArcsEnd(i);
            node.parent = m_graph->GetS();
        } else if (m_graph->m_c_it[i] > m_graph->m_phi_it[i]) {
            auto& node = m_graph->node(i);
            node.state = NodeState::T;
            node.dis = 1;
            AddToLayer(i);
            node.parent_arc = m_graph->ArcsEnd(i);
            node.parent = m_graph->GetT();
        } else {
            ASSERT(m_graph->m_c_si[i] == m_graph->m_phi_si[i] 
                && m_graph->m_c_it[i] == m_graph->m_phi_it[i]);
        }
    }
    m_initTime += Duration{ Clock::now() - start }.count();
}
Exemplo n.º 2
0
void BidirectionalIBFS::IBFS() {
    auto start = Clock::now();
    m_forward_search = false;
    m_source_tree_d = 1;
    m_sink_tree_d = 0;

    IBFSInit();

    // Set up initial current_q and search nodes to make it look like
    // we just finished scanning the sink node
    NodeQueue* current_q = &(m_sink_layers[0]);
    m_search_node_iter = current_q->end();
    m_search_node_end = current_q->end();

    while (!current_q->empty()) {
        if (m_search_node_iter == m_search_node_end) {
            // Swap queues and continue
            if (m_forward_search) {
                m_source_tree_d++;
                current_q = &(m_sink_layers[m_sink_tree_d]);
            } else {
                m_sink_tree_d++;
                current_q = &(m_source_layers[m_source_tree_d]);
            }
            m_search_node_iter = current_q->begin();
            m_search_node_end = current_q->end();
            m_forward_search = !m_forward_search;
            if (!current_q->empty()) {
                Node& n = *m_search_node_iter;
                NodeId nodeIdx = n.id;
                if (m_forward_search) {
                    ASSERT(n.state == NodeState::S || n.state == NodeState::S_orphan);
                    m_search_arc = m_graph->ArcsBegin(nodeIdx);
                    m_search_arc_end = m_graph->ArcsEnd(nodeIdx);
                } else {
                    ASSERT(n.state == NodeState::T || n.state == NodeState::T_orphan);
                    m_search_arc = m_graph->ArcsBegin(nodeIdx);
                    m_search_arc_end = m_graph->ArcsEnd(nodeIdx);
                }
            }
            continue;
        }
        Node& n = *m_search_node_iter;
        NodeId search_node = n.id;
        int distance;
        if (m_forward_search) {
            distance = m_source_tree_d;
        } else {
            distance = m_sink_tree_d;
        }
        ASSERT(n.dis == distance);
        // Advance m_search_arc until we find a residual arc
        while (m_search_arc != m_search_arc_end && !m_graph->NonzeroCap(m_search_arc, m_forward_search))
            ++m_search_arc;

        if (m_search_arc != m_search_arc_end) {
            NodeId neighbor = m_search_arc.Target();
            NodeState neighbor_state = m_graph->node(neighbor).state;
            if (neighbor_state == n.state) {
                ASSERT(m_graph->node(neighbor).dis <= n.dis + 1);
                if (m_graph->node(neighbor).dis == n.dis+1) {
                    auto reverseArc = m_search_arc.Reverse();
                    if (reverseArc < m_graph->node(neighbor).parent_arc) {
                        m_graph->node(neighbor).parent_arc = reverseArc;
                        m_graph->node(neighbor).parent = search_node;
                    }
                }
                ++m_search_arc;
            } else if (neighbor_state == NodeState::N) {
                // Then we found an unlabeled node, add it to the tree
                m_graph->node(neighbor).state = n.state;
                m_graph->node(neighbor).dis = n.dis + 1;
                AddToLayer(neighbor);
                auto reverseArc = m_search_arc.Reverse();
                m_graph->node(neighbor).parent_arc = reverseArc;
                ASSERT(m_graph->NonzeroCap(m_graph->node(neighbor).parent_arc, !m_forward_search));
                m_graph->node(neighbor).parent = search_node;
                ++m_search_arc;
            } else {
                // Then we found an arc to the other tree
                ASSERT(neighbor_state != NodeState::S_orphan && neighbor_state != NodeState::T_orphan);
                ASSERT(m_graph->NonzeroCap(m_search_arc, m_forward_search));
                Augment(m_search_arc);
                Adopt();
            }
        } else {
            // No more arcs to scan from this node, so remove from queue
            AdvanceSearchNode();
        }
    } // End while
    m_totalTime += Duration{ Clock::now() - start }.count();

    //std::cout << "Total time:      " << m_totalTime << "\n";
    //std::cout << "Init time:       " << m_initTime << "\n";
    //std::cout << "Augment time:    " << m_augmentTime << "\n";
    //std::cout << "Adopt time:      " << m_adoptTime << "\n";
}
Exemplo n.º 3
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();
}
Exemplo n.º 4
0
		        void FifoGap<TFLOW,TCAP>::GlobalUpdate()
		        {
                    Node *node, *head;
                    Layer *lay;
                    Arc *arc;

                    // Reset layers
                    for (Size i = 0; i <= m_max_rank; i++)
                    {
                        m_layer_list[i].m_first = NULL;
                    }

                    m_max_rank = 0;
                    m_fifo_first = NULL;
                    m_fifo_last = NULL;

                    // Initialize ranks, put nodes connected to the sink to the first layer
                    lay = &m_layer_list[1];

                    for (node = m_node_list.Begin(); node != m_node_list.End(); ++node)
                    {
                        if (node->m_excess < 0)
                        {
                            node->m_rank = 1;
                            node->m_current = node->m_first;
                            AddToLayer(lay, node);                        
                        }
                        else
                        {
                            node->m_rank = m_nodes;
                        }
                    }

                    // Breadth first search
                    for ( ; lay->m_first != NULL; lay++)
                    {
                        m_max_rank++;

                        // Check list of active nodes on this layer
                        for (node = lay->m_first; node != NULL; node = node->m_lay_next)
                        {
                            for (arc = node->m_first; arc != NULL; arc = arc->m_next)
                            {
                                head = arc->m_head;

                                if (head->m_rank == m_nodes && arc->m_sister->m_res_cap > 0)
                                {
                                    head->m_rank = node->m_rank + 1;
                                    head->m_current = head->m_first;

                                    AddToLayer(lay + 1, head);

                                    if (head->m_excess > 0)
                                    {
                                        // Add to queue - be careful to initialize the queue
                                        // here so the highest ranks are processed first.
                                        // It is much faster then.
                                        head->m_next_active = m_fifo_first;
                                        if (m_fifo_first == NULL)
                                        {
                                            m_fifo_last = head;
                                        }
                                        m_fifo_first = head;
                                    }
                                }
                            }
                        }
                    }
                }
Exemplo n.º 5
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;
		        }