예제 #1
0
void bipartition::initial_partition( const PartitionConfig & config, 
                                     const unsigned int seed, 
                                     graph_access & G, 
                                     int* partition_map) {

        timer t;
        t.restart();
        unsigned iterations = config.bipartition_tries;
        EdgeWeight best_cut = std::numeric_limits<EdgeWeight>::max();
        int best_load       = std::numeric_limits<int>::max();

        for( unsigned i = 0; i < iterations; i++) {
                if(config.bipartition_algorithm == BIPARTITION_BFS)  {
                        grow_regions_bfs(config, G);
                } else if( config.bipartition_algorithm == BIPARTITION_FM) {
                        grow_regions_fm(config, G);
                } 

                G.set_partition_count(2);

                post_fm(config, G);

                quality_metrics qm;
                EdgeWeight curcut = qm.edge_cut(G); 

                int lhs_block_weight = 0;
                int rhs_block_weight = 0;

                forall_nodes(G, node) {
                        if(G.getPartitionIndex(node) == 0) {
                                lhs_block_weight += G.getNodeWeight(node);
                        } else {
                                rhs_block_weight += G.getNodeWeight(node);
                        }
                } endfor

                int lhs_overload = std::max(lhs_block_weight - config.target_weights[0],0);
                int rhs_overload = std::max(rhs_block_weight - config.target_weights[1],0);

                if(curcut < best_cut || (curcut == best_cut && lhs_overload + rhs_block_weight < best_load) ) {
                        //store it
                        best_cut  = curcut;
                        best_load = lhs_overload + rhs_overload;

                        forall_nodes(G, n) {
                                partition_map[n] =  G.getPartitionIndex(n);
                        } endfor
                } 
예제 #2
0
void graph_extractor::extract_block(graph_access & G, 
                                    graph_access & extracted_block, 
                                    PartitionID block, 
                                    std::vector<NodeID> & mapping) {

        // build reverse mapping
        std::vector<NodeID> reverse_mapping;
        NodeID nodes = 0;
        NodeID dummy_node = G.number_of_nodes() + 1;
        forall_nodes(G, node) {
                if(G.getPartitionIndex(node) == block) {
                        reverse_mapping.push_back(nodes++);
                } else {
                        reverse_mapping.push_back(dummy_node);
                }
        } endfor

        extracted_block.start_construction(nodes, G.number_of_edges());

        forall_nodes(G, node) {
                if(G.getPartitionIndex(node) == block) {
                        NodeID new_node = extracted_block.new_node();
                        mapping.push_back(node);
                        extracted_block.setNodeWeight( new_node, G.getNodeWeight(node));

                        forall_out_edges(G, e, node) {
                                NodeID target = G.getEdgeTarget(e);
                                if( G.getPartitionIndex( target ) == block ) {
                                        EdgeID new_edge = extracted_block.new_edge(new_node, reverse_mapping[target]);
                                        extracted_block.setEdgeWeight(new_edge, G.getEdgeWeight(e));
                                }
                        } endfor
                }
void fast_construct_mapping::construct_initial_mapping_bottomup_internal( PartitionConfig & config, graph_access & C, matrix & D, int idx,  std::vector< NodeID > & perm_rank) {

        PartitionID num_parts = C.number_of_nodes()/config.group_sizes[idx];
        partition_C_perfectly_balanced( config, C, num_parts);

        if( idx ==(int)(config.group_sizes.size() - 1) ) {
                // build initial offsets 
                int nodes_per_block = m_tmp_num_nodes / config.group_sizes[idx];
                perm_rank[0] = 0;
                for( unsigned int block = 1; block < perm_rank.size(); block++) {
                        perm_rank[block] = perm_rank[block-1]+nodes_per_block;
                }
        } else {
                //contract partitioned graph
                graph_access Q; complete_boundary bnd(&C);
                bnd.build();
                bnd.getUnderlyingQuotientGraph(Q);
               
                std::vector< NodeID > rec_ranks( num_parts, 0);
                construct_initial_mapping_bottomup_internal( config, Q, D, idx+1, rec_ranks);

                //recompute offsets 
                forall_nodes(C, node) {
                        PartitionID block = C.getPartitionIndex(node);
                        perm_rank[node]   = rec_ranks[block];
                        rec_ranks[block] += C.getNodeWeight(node);
                } endfor
        }
예제 #4
0
void kway_graph_refinement_core::move_node_back(PartitionConfig & config, 
                graph_access & G, 
                NodeID & node,
                PartitionID & to, 
                vertex_moved_hashtable & moved_idx, 
                refinement_pq * queue, 
                complete_boundary & boundary) {

        PartitionID from = G.getPartitionIndex(node);
        G.setPartitionIndex(node, to);        

        boundary_pair pair;
        pair.k   = config.k;
        pair.lhs = from;
        pair.rhs = to;

        //update all boundaries
        boundary.postMovedBoundaryNodeUpdates(node, &pair, true, true);

        NodeWeight this_nodes_weight = G.getNodeWeight(node);
        boundary.setBlockNoNodes(from, boundary.getBlockNoNodes(from)-1);
        boundary.setBlockNoNodes(to,   boundary.getBlockNoNodes(to)+1);
        boundary.setBlockWeight( from, boundary.getBlockWeight(from)-this_nodes_weight);
        boundary.setBlockWeight( to,   boundary.getBlockWeight(to)+this_nodes_weight);
}
예제 #5
0
int graph_io::writeGraphWeighted(graph_access & G, std::string filename) {
        std::ofstream f(filename.c_str());
        f << G.number_of_nodes() <<  " " <<  G.number_of_edges()/2 <<  " 11" <<  std::endl;

        forall_nodes(G, node) {
                f <<  G.getNodeWeight(node) ;
                forall_out_edges(G, e, node) {
                        f << " " <<   (G.getEdgeTarget(e)+1) <<  " " <<  G.getEdgeWeight(e) ;
                } endfor 
void most_balanced_minimum_cuts::compute_good_balanced_min_cut( graph_access & residualGraph, 
                                                                const PartitionConfig & config,
                                                                NodeWeight & perfect_rhs_weight, 
                                                                std::vector< NodeID > & new_rhs_nodes ) {

        strongly_connected_components scc;
        std::vector<int> components(residualGraph.number_of_nodes());
        int comp_count = scc.strong_components(residualGraph,components);
        
        std::vector< std::vector<NodeID> > comp_nodes(comp_count);
        std::vector< NodeWeight > comp_weights(comp_count, 0);
        
        forall_nodes(residualGraph, node) {
               comp_nodes[components[node]].push_back(node);
               comp_weights[components[node]] += residualGraph.getNodeWeight(node); 
        } endfor
예제 #7
0
// for documentation see technical reports of christian schulz  
void contraction::contract(const PartitionConfig & partition_config, 
                           graph_access & G, 
                           graph_access & coarser, 
                           const Matching & edge_matching,
                           const CoarseMapping & coarse_mapping,
                           const NodeID & no_of_coarse_vertices,
                           const NodePermutationMap & permutation) const {

        if(partition_config.combine) {
                coarser.resizeSecondPartitionIndex(no_of_coarse_vertices);
        }

        std::vector<NodeID> new_edge_targets(G.number_of_edges());
        forall_edges(G, e) {
                new_edge_targets[e] = coarse_mapping[G.getEdgeTarget(e)];
        } endfor

        std::vector<EdgeID> edge_positions(no_of_coarse_vertices, UNDEFINED_EDGE);

        //we dont know the number of edges jet, so we use the old number for 
        //construction of the coarser graph and then resize the field according
        //to the number of edges we really got
        coarser.start_construction(no_of_coarse_vertices, G.number_of_edges());

        NodeID cur_no_vertices = 0;

        forall_nodes(G, n) {
                NodeID node = permutation[n];
                //we look only at the coarser nodes
                if(coarse_mapping[node] != cur_no_vertices) 
                        continue;
                
                NodeID coarseNode = coarser.new_node();
                coarser.setNodeWeight(coarseNode, G.getNodeWeight(node));

                if(partition_config.combine) {
                        coarser.setSecondPartitionIndex(coarseNode, G.getSecondPartitionIndex(node));
                }

                // do something with all outgoing edges (in auxillary graph)
                forall_out_edges(G, e, node) {
                        visit_edge(G, coarser, edge_positions, coarseNode, e, new_edge_targets);                        
                } endfor
예제 #8
0
EdgeWeight cycle_refinement::greedy_ultra_model_plus(PartitionConfig & partition_config, 
                graph_access & G, 
                complete_boundary & boundary) {
        unsigned s             = partition_config.kaba_internal_no_aug_steps_aug;
        bool something_changed = false;
        bool overloaded        = false;
        
       
        augmented_Qgraph_fabric augmented_fabric;
        bool first_level = true;
        forall_nodes(G, node) {
                if(G.getNodeWeight(node) != 1) {
                        first_level = false;
                        break;
                }
        } endfor

        int unsucc_count = 0;
        do {
                augmented_Qgraph aqg;
                augmented_fabric.build_augmented_quotient_graph(partition_config, G, boundary, aqg, s, false, true);
                something_changed = m_advanced_modelling.compute_vertex_movements_ultra_model(partition_config, 
                                                                                              G, 
                                                                                              boundary, 
                                                                                              aqg, 
                                                                                              s,
                                                                                              false);

                if( something_changed ) {
                        unsucc_count = 0;
                } else {
                        unsucc_count++;
                }

                if(unsucc_count > 2 && unsucc_count < 19) {
                        something_changed = m_advanced_modelling.compute_vertex_movements_ultra_model(partition_config, 
                                                                                                      G, 
                                                                                                      boundary, 
                                                                                                      aqg, 
                                                                                                      s, true);
                }

                if(unsucc_count > 19 && first_level) {
                        graph_access G_bar;
                        boundary.getUnderlyingQuotientGraph(G_bar); 
                        overloaded = false;
                        forall_nodes(G_bar, block) {
                                if(boundary.getBlockWeight(block) > partition_config.upper_bound_partition ) {
                                        overloaded = true;
                                        break;
                                }
                        } endfor
                  
                        if(overloaded) {
                                augmented_Qgraph aqg_rebal;
                                bool moves_performed = augmented_fabric.build_augmented_quotient_graph(partition_config, 
                                                                                                       G, 
                                                                                                       boundary, 
                                                                                                       aqg_rebal, 
                                                                                                       s, true, true);
                                if(!moves_performed) {
                                        m_advanced_modelling.compute_vertex_movements_rebalance(partition_config, 
                                                                                                G, boundary, 
                                                                                                aqg_rebal, s);
                                } // else the fall back solution has been applied
                        }
                       
                }
        } while(unsucc_count < 20 || overloaded);

        return 0; 
}
예제 #9
0
void two_way_fm::move_node_back(const PartitionConfig & config, 
                                graph_access & G,
                                const NodeID & node,
                                vertex_moved_hashtable & moved_idx,
                                refinement_pq * from_queue,
                                refinement_pq * to_queue,
                                PartitionID from, 
                                PartitionID to,
                                boundary_pair * pair,         
                                NodeWeight * from_part_weight,
                                NodeWeight * to_part_weight,
                                complete_boundary & boundary) {

        ASSERT_NEQ(from, to);
        ASSERT_EQ(from, G.getPartitionIndex(node));

        //move node
        G.setPartitionIndex(node, to);         
        boundary.deleteNode(node, from, pair);

        EdgeWeight int_degree_node = 0;
        EdgeWeight ext_degree_node = 0;
        bool update_difficult = int_ext_degree(G, node, to, from, int_degree_node, ext_degree_node);

        if(ext_degree_node > 0) {
                boundary.insert(node, to, pair);
        }

        if(update_difficult) {
                boundary.postMovedBoundaryNodeUpdates(node, pair, true, false);
        }

        NodeWeight this_nodes_weight = G.getNodeWeight(node);
        (*from_part_weight) -= this_nodes_weight; 
        (*to_part_weight)   += this_nodes_weight; 

        //update neighbors
        forall_out_edges(G, e, node) {
                NodeID target = G.getEdgeTarget(e);
                PartitionID targets_partition = G.getPartitionIndex(target);

                if((targets_partition != from && targets_partition != to)) {
                        //at most difficult update nec.
                        continue; //they dont need to be updated during this refinement
                }

                EdgeWeight int_degree = 0;
                EdgeWeight ext_degree = 0;

                PartitionID other_partition = targets_partition == from ? to : from;
                int_ext_degree(G, target, targets_partition, other_partition, int_degree, ext_degree); 

                if(boundary.contains(target, targets_partition, pair)) {
                        if(ext_degree == 0) {
                                boundary.deleteNode(target, targets_partition, pair);
                        } 
                } else {
                        if(ext_degree > 0) {
                                boundary.insert(target, targets_partition, pair);
                        }
                }

        } endfor
예제 #10
0
void two_way_fm::move_node(const PartitionConfig & config, 
                           graph_access & G,
                           const NodeID & node,
                           vertex_moved_hashtable & moved_idx,
                           refinement_pq * from_queue,
                           refinement_pq * to_queue,
                           PartitionID from, 
                           PartitionID to,
                           boundary_pair * pair,         
                           NodeWeight * from_part_weight,
                           NodeWeight * to_part_weight,
                           complete_boundary & boundary) {
        //move node
        G.setPartitionIndex(node, to);        
        boundary.deleteNode(node, from, pair);

        EdgeWeight int_degree_node = 0;
        EdgeWeight ext_degree_node = 0;
        bool difficult_update      = int_ext_degree(G, node, to, from, int_degree_node, ext_degree_node);


        if(ext_degree_node > 0) {
                boundary.insert(node, to, pair);
        }

        if(difficult_update)
                boundary.postMovedBoundaryNodeUpdates(node, pair, true, false);


        NodeWeight this_nodes_weight = G.getNodeWeight(node);
        (*from_part_weight) -= this_nodes_weight; 
        (*to_part_weight)   += this_nodes_weight; 

        //update neighbors
        forall_out_edges(G, e, node) {
                NodeID target = G.getEdgeTarget(e);
                PartitionID targets_partition = G.getPartitionIndex(target);

                if((targets_partition != from && targets_partition != to)) {
                        continue; 
                }

                EdgeWeight int_degree = 0;
                EdgeWeight ext_degree = 0;

                PartitionID other_partition = targets_partition == from ? to : from;
                int_ext_degree(G, target, targets_partition, other_partition, int_degree, ext_degree); 

                refinement_pq * queue_to_update = 0;
                if(targets_partition == from) {
                        queue_to_update = from_queue;
                } else {
                        queue_to_update = to_queue;
                }

                Gain gain = ext_degree - int_degree;
                if(queue_to_update->contains(target)) {
                        if(ext_degree == 0) {
                                queue_to_update->deleteNode(target);
                                boundary.deleteNode(target, targets_partition, pair);
                        } else {
                                queue_to_update->changeKey(target, gain);
                        }
                } else {
                        if(ext_degree > 0) {
                                if(moved_idx[target].index == NOT_MOVED) {
                                        queue_to_update->insert(target, gain);
                                }
                                boundary.insert(target, targets_partition, pair);
                        } else {
                                boundary.deleteNode(target, targets_partition, pair);
                        }
                }

        } endfor