void mis_permutation::construct(graph_access & G) { inconsistencies = 0; solution_size = 0; free_size = 0; total_size = G.number_of_nodes(); nodes.clear(); tightness.clear(); position.clear(); nodes.resize(total_size); tightness.resize(total_size); position.resize(total_size); onetight_all.init(G.number_of_nodes()); // Insert solution nodes forall_nodes(G, n) { nodes[n] = n; position[n] = n; unsigned int index = G.getPartitionIndex(n); // Maybe implement tightness calculations here if (index == 1) { move_to_solution(n, G); } else { int tight = calculate_tightness(n, G); tightness[n] = tight; if (tight == 0) move_to_free(n, G); else move_to_non_free(n, G); if (tight == 1) onetight_all.insert(n); } } endfor
void cycle_search::find_random_cycle(graph_access & G, std::vector<NodeID> & cycle) { //first perform a bfs starting from a random node and build the parent array std::deque<NodeID>* bfsqueue = new std::deque<NodeID>; NodeID v = random_functions::nextInt(0, G.number_of_nodes()-1); bfsqueue->push_back(v); std::vector<bool> touched(G.number_of_nodes(),false); std::vector<bool> is_leaf(G.number_of_nodes(),false); std::vector<NodeID> parent(G.number_of_nodes(),0); std::vector<NodeID> leafes; touched[v] = true; parent[v] = v; while(!bfsqueue->empty()) { NodeID source = bfsqueue->front(); bfsqueue->pop_front(); bool is_leaf = true; forall_out_edges(G, e, source) { NodeID target = G.getEdgeTarget(e); if(!touched[target]) { is_leaf = false; touched[target] = true; parent[target] = source; bfsqueue->push_back(target); } } endfor if(is_leaf) leafes.push_back(source); }
void topological_sort::sort( graph_access & G, std::vector<NodeID> & sorted_sequence) { std::vector<int> dfsnum(G.number_of_nodes(), -1); int dfscount = 0; std::vector<NodeID> nodes(G.number_of_nodes()); random_functions::permutate_vector_good(nodes, true); forall_nodes(G, node) { NodeID curNode = nodes[node]; if(dfsnum[curNode] == -1) { sort_dfs(curNode, G, dfsnum, dfscount, sorted_sequence); } } endfor
int wcycle_partitioner::perform_partitioning(const PartitionConfig & config, graph_access & G) { PartitionConfig cfg = config; if(config.stop_rule == STOP_RULE_SIMPLE) { m_coarsening_stop_rule = new simple_stop_rule(cfg, G.number_of_nodes()); } else { m_coarsening_stop_rule = new multiple_k_stop_rule(cfg, G.number_of_nodes()); } int improvement = (int) perform_partitioning_recursive(cfg, G, NULL); delete m_coarsening_stop_rule; return improvement; }
bool augmented_Qgraph_fabric::build_augmented_quotient_graph( PartitionConfig & config, graph_access & G, complete_boundary & boundary, augmented_Qgraph & aqg, unsigned & s, bool rebalance, bool plus) { graph_access G_bar; boundary.getUnderlyingQuotientGraph(G_bar); if(m_eligible.size() != G.number_of_nodes()) { m_eligible.resize(G.number_of_nodes()); forall_nodes(G, node) { m_eligible[node] = true; } endfor } else {
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 }
void parallel_mh_async::perform_partitioning(const PartitionConfig & partition_config, graph_access & G) { m_time_limit = partition_config.time_limit; m_island = new population(m_communicator, partition_config); m_best_global_map = new PartitionID[G.number_of_nodes()]; srand(partition_config.seed*m_size+m_rank); random_functions::setSeed(partition_config.seed*m_size+m_rank); PartitionConfig ini_working_config = partition_config; initialize( ini_working_config, G); m_t.restart(); exchanger ex(m_communicator); do { PartitionConfig working_config = partition_config; working_config.graph_allready_partitioned = false; if(!partition_config.strong) working_config.no_new_initial_partitioning = false; working_config.mh_pool_size = ini_working_config.mh_pool_size; if(m_rounds == 0 && working_config.mh_enable_quickstart) { ex.quick_start( working_config, G, *m_island ); } perform_local_partitioning( working_config, G ); if(m_rank == ROOT) { std::cout << "t left " << (m_time_limit - m_t.elapsed()) << std::endl; } //push and recv if( m_t.elapsed() <= m_time_limit && m_size > 1) { unsigned messages = ceil(log(m_size)); for( unsigned i = 0; i < messages; i++) { ex.push_best( working_config, G, *m_island ); ex.recv_incoming( working_config, G, *m_island ); } } m_rounds++; } while( m_t.elapsed() <= m_time_limit ); collect_best_partitioning(G, partition_config); m_island->print(); //print logfile (for convergence plots) if( partition_config.mh_print_log ) { std::stringstream filename_stream; filename_stream << "log_"<< partition_config.graph_filename << "_m_rank_" << m_rank << "_file_" << "_seed_" << partition_config.seed << "_k_" << partition_config.k; std::string filename(filename_stream.str()); m_island->write_log(filename); } delete m_island; }
void population_mis::set_mis_for_individuum(MISConfig & config, graph_access & G, individuum_mis & ind, bool secondary) { G.resizeSecondPartitionIndex(G.number_of_nodes()); forall_nodes(G, node) { if (!secondary) G.setPartitionIndex(node, ind.solution[node]); else G.setSecondPartitionIndex(node, ind.solution[node]); } endfor }
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 }
EdgeWeight tabu_search::perform_refinement(PartitionConfig & config, graph_access & G, complete_boundary & boundary) { quality_metrics qm; EdgeWeight input_cut = qm.edge_cut(G); EdgeWeight cur_cut = input_cut; EdgeWeight best_cut = input_cut; std::vector< PartitionID > bestmap(G.number_of_nodes(), 0); forall_nodes(G, node) { bestmap[node] = G.getPartitionIndex(node); } endfor
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 population_mis::mutate(MISConfig & config, graph_access & G, individuum_mis & ind) { set_mis_for_individuum(config, G, ind); delete [] ind.solution; ind.solution = NULL; ils iterate; iterate.perform_ils(config, G, config.ils_iterations); // Create solution for the individuum NodeID *solution = new NodeID[G.number_of_nodes()]; unsigned int solution_size = create_solution(G, solution); ind.solution = solution; ind.solution_size = solution_size; }
void graph_communication::broadcast_graph( graph_access & G, unsigned root) { int rank = MPI::COMM_WORLD.Get_rank(); //first B-Cast number of nodes and number of edges unsigned number_of_nodes = 0; unsigned number_of_edges = 0; std::vector< int > buffer(2,0); if(rank == (int)root) { buffer[0] = G.number_of_nodes(); buffer[1] = G.number_of_edges(); } MPI::COMM_WORLD.Bcast(&buffer[0], 2, MPI_INT, root); number_of_nodes = buffer[0]; number_of_edges = buffer[1]; int* xadj; int* adjncy; int* vwgt; int* adjwgt; if( rank == (int)root) { xadj = G.UNSAFE_metis_style_xadj_array(); adjncy = G.UNSAFE_metis_style_adjncy_array(); vwgt = G.UNSAFE_metis_style_vwgt_array(); adjwgt = G.UNSAFE_metis_style_adjwgt_array(); } else { xadj = new int[number_of_nodes+1]; adjncy = new int[number_of_edges]; vwgt = new int[number_of_nodes]; adjwgt = new int[number_of_edges]; } MPI::COMM_WORLD.Bcast(xadj, number_of_nodes+1, MPI_INT, root); MPI::COMM_WORLD.Bcast(adjncy, number_of_edges , MPI_INT, root); MPI::COMM_WORLD.Bcast(vwgt, number_of_nodes , MPI_INT, root); MPI::COMM_WORLD.Bcast(adjwgt, number_of_edges , MPI_INT, root); G.build_from_metis_weighted( number_of_nodes, xadj, adjncy, vwgt, adjwgt); delete[] xadj; delete[] adjncy; delete[] vwgt; delete[] adjwgt; }
void greedy_mis::initial_partition(const unsigned int seed, graph_access & G) { random_functions::setSeed(seed); NodePermutationMap permutation; generate_permutation(G, permutation); bucket_array *buckets = new bucket_array(G.number_of_nodes()); G.set_partition_count(2); // Initialize the priority queue forall_nodes (G, n) { NodeID node = permutation[n]; EdgeWeight node_degree = G.getNodeDegree(node); buckets->increment(node, node_degree); G.setPartitionIndex(node, 0); } endfor
EdgeWeight parallel_mh_async::collect_best_partitioning(graph_access & G) { //perform partitioning locally EdgeWeight min_objective = 0; m_island->apply_fittest(G, min_objective); int best_local_objective = min_objective; int best_global_objective = 0; PartitionID* best_local_map = new PartitionID[G.number_of_nodes()]; std::vector< NodeWeight > block_sizes(G.get_partition_count(),0); forall_nodes(G, node) { best_local_map[node] = G.getPartitionIndex(node); block_sizes[G.getPartitionIndex(node)]++; } 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
void population_mis::create_individuum(MISConfig & config, graph_access & G, individuum_mis & ind) { // Build solution int initial = random_functions::nextInt(0, 1); if (initial == 0) { random_mis init_solution; init_solution.initial_partition(config.seed, G); } else if (initial == 1) { greedy_mis init_solution; init_solution.initial_partition(config.seed, G); } // else if (initial == 2) { // greedy_vertex init_solution; // init_solution.initial_partition(config.seed, G); // } // Create solution for the individuum NodeID *solution = new NodeID[G.number_of_nodes()]; unsigned int solution_size = create_solution(G, solution); ind.solution = solution; ind.solution_size = solution_size; }
EdgeWeight kway_graph_refinement::perform_refinement(PartitionConfig & config, graph_access & G, complete_boundary & boundary) { commons = kway_graph_refinement_commons::getInstance(config); kway_graph_refinement_core refinement_core; EdgeWeight overall_improvement = 0; int max_number_of_swaps = (int)(G.number_of_nodes()); bool sth_changed = config.no_change_convergence; for( unsigned i = 0; i < config.kway_rounds || sth_changed; i++) { EdgeWeight improvement = 0; boundary_starting_nodes start_nodes; setup_start_nodes(config, G, boundary, start_nodes); if(start_nodes.size() == 0) return 0; // nothing to refine //metis steplimit int step_limit = (int)((config.kway_fm_search_limit/100.0)*max_number_of_swaps); step_limit = std::max(step_limit, 15); vertex_moved_hashtable moved_idx; improvement += refinement_core.single_kway_refinement_round(config, G, boundary, start_nodes, step_limit, moved_idx); sth_changed = improvement != 0 && config.no_change_convergence; if(improvement == 0) break; overall_improvement += improvement; } ASSERT_TRUE(overall_improvement >= 0); return (EdgeWeight) overall_improvement; }
void fast_construct_mapping::construct_initial_mapping_bottomup( PartitionConfig & config, graph_access & C, matrix & D, std::vector< NodeID > & perm_rank) { m_tmp_num_nodes = C.number_of_nodes(); construct_initial_mapping_bottomup_internal( config, C, D, 0, perm_rank); }
void local_optimizer::run_maxent_optimization_internal( const Config & config, graph_access & G ) { if(G.number_of_edges() == 0) return; std::vector< coord_t > new_coord(G.number_of_nodes()); CoordType alpha = config.maxent_alpha; int iterations = config.maxent_inner_iterations; CoordType q = config.q; std::vector<CoordType> distances(G.number_of_edges(),0); configure_distances( config, G, distances); for( int i = 0; i < config.maxent_outer_iterations; i++) { CoordType norm_coords = 0; CoordType norm_diff = 0; do { forall_nodes_parallel(G, node) { CoordType rho_i = 0; // assume graph is connected? if(G.getNodeDegree(node) == 0) continue; forall_out_edges(G, e, node) { CoordType distance = distances[e]; rho_i += 1/(distance*distance); } endfor rho_i = 1/rho_i; CoordType S_x = 0; CoordType S_y = 0; CoordType n_S_x = 0; CoordType n_S_y = 0; forall_out_edges(G, e, node) { NodeID target = G.getEdgeTarget(e); CoordType diffX = G.getX(node) - G.getX(target); CoordType diffY = G.getY(node) - G.getY(target); CoordType dist_square = diffX*diffX+diffY*diffY; CoordType distance = distances[e]; CoordType dist = sqrt(dist_square); CoordType scaled_distance = distance/dist; CoordType squared_distance = distance*distance; S_x += (G.getX(target) + scaled_distance*diffX)/(squared_distance); S_y += (G.getY(target) + scaled_distance*diffY)/(squared_distance); CoordType dist_q = pow(dist, q+2); n_S_x -= diffX/dist_q; n_S_y -= diffY/dist_q; } endfor S_x *= rho_i; S_y *= rho_i; forall_nodes(G, target) { if( node == target ) continue; CoordType diffX = G.getX(node) - G.getX(target); CoordType diffY = G.getY(node) - G.getY(target); CoordType dist_square = diffX*diffX+diffY*diffY; CoordType dist = sqrt(dist_square); CoordType dist_q = pow(dist, q+2); n_S_x += diffX/dist_q; n_S_y += diffY/dist_q; } endfor CoordType mult_factor = alpha*rho_i; n_S_x *= mult_factor; n_S_y *= mult_factor; new_coord[node].x = S_x + sgn(q)*n_S_x; new_coord[node].y = S_y + sgn(q)*n_S_y; } endfor
// implements our version of gal combine // compute a matching between blocks (greedily) // extend to partition // apply our refinements and tabu search void gal_combine::perform_gal_combine( PartitionConfig & config, graph_access & G) { //first greedily compute a matching of the partitions std::vector< std::unordered_map<PartitionID, unsigned> > counters(config.k); forall_nodes(G, node) { //boundary_pair bp; if(counters[G.getPartitionIndex(node)].find(G.getSecondPartitionIndex(node)) != counters[G.getPartitionIndex(node)].end()) { counters[G.getPartitionIndex(node)][G.getSecondPartitionIndex(node)] += 1; } else { counters[G.getPartitionIndex(node)][G.getSecondPartitionIndex(node)] = 1; } } endfor std::vector< PartitionID > permutation(config.k); for( unsigned i = 0; i < permutation.size(); i++) { permutation[i] = i; } random_functions::permutate_vector_good_small(permutation); std::vector<bool> rhs_matched(config.k, false); std::vector<PartitionID> bipartite_matching(config.k); for( unsigned i = 0; i < permutation.size(); i++) { PartitionID cur_partition = permutation[i]; PartitionID best_unassigned = config.k; NodeWeight best_value = 0; for( std::unordered_map<PartitionID, unsigned>::iterator it = counters[cur_partition].begin(); it != counters[cur_partition].end(); ++it) { if( rhs_matched[it->first] == false && it->second > best_value ) { best_unassigned = it->first; best_value = it->second; } } bipartite_matching[cur_partition] = best_unassigned; if( best_unassigned != config.k ) { rhs_matched[best_unassigned] = true; } } std::vector<bool> blocked_vertices(G.number_of_nodes(), false); forall_nodes(G, node) { if( bipartite_matching[G.getPartitionIndex(node)] == G.getSecondPartitionIndex(node) ){ blocked_vertices[node] = true; } else { // we will reassign this vertex since the partitions do not agree on it G.setPartitionIndex(node, config.k); } } endfor construct_partition cp; cp.construct_starting_from_partition( config, G ); refinement* refine = new mixed_refinement(); double real_epsilon = config.imbalance/100.0; double epsilon = random_functions::nextDouble(real_epsilon+0.005,real_epsilon+config.kabaE_internal_bal); PartitionConfig copy = config; copy.upper_bound_partition = (1+epsilon)*ceil(config.largest_graph_weight/(double)config.k); complete_boundary boundary(&G); boundary.build(); tabu_search ts; ts.perform_refinement( copy, G, boundary); //now obtain the quotient graph complete_boundary boundary2(&G); boundary2.build(); copy = config; copy.upper_bound_partition = (1+epsilon)*ceil(config.largest_graph_weight/(double)config.k); refine->perform_refinement( copy, G, boundary2); copy = config; cycle_refinement cr; cr.perform_refinement(config, G, boundary2); delete refine; }
int wcycle_partitioner::perform_partitioning_recursive( PartitionConfig & partition_config, graph_access & G, complete_boundary ** c_boundary) { //if graph not small enough // perform matching two times // perform coarsening two times // call rekursive //else // initial partitioning // //refinement NodeID no_of_coarser_vertices = G.number_of_nodes(); NodeID no_of_finer_vertices = G.number_of_nodes(); int improvement = 0; edge_ratings rating(partition_config); CoarseMapping* coarse_mapping = new CoarseMapping(); graph_access* finer = &G; matching* edge_matcher = NULL; contraction* contracter = new contraction(); PartitionConfig copy_of_partition_config = partition_config; graph_access* coarser = new graph_access(); Matching edge_matching; NodePermutationMap permutation; coarsening_configurator coarsening_config; coarsening_config.configure_coarsening(partition_config, &edge_matcher, m_level); rating.rate(*finer, m_level); edge_matcher->match(partition_config, *finer, edge_matching, *coarse_mapping, no_of_coarser_vertices, permutation); delete edge_matcher; if(partition_config.graph_allready_partitioned) { contracter->contract_partitioned(partition_config, *finer, *coarser, edge_matching, *coarse_mapping, no_of_coarser_vertices, permutation); } else { contracter->contract(partition_config, *finer, *coarser, edge_matching, *coarse_mapping, no_of_coarser_vertices, permutation); } coarser->set_partition_count(partition_config.k); complete_boundary* coarser_boundary = NULL; refinement* refine = NULL; if(!partition_config.label_propagation_refinement) { coarser_boundary = new complete_boundary(coarser); refine = new mixed_refinement(); } else { refine = new label_propagation_refinement(); } if(!m_coarsening_stop_rule->stop(no_of_finer_vertices, no_of_coarser_vertices)) { PartitionConfig cfg; cfg = partition_config; double factor = partition_config.balance_factor; cfg.upper_bound_partition = (factor +1.0)*partition_config.upper_bound_partition; initial_partitioning init_part; init_part.perform_initial_partitioning(cfg, *coarser); if(!partition_config.label_propagation_refinement) coarser_boundary->build(); //PRINT(std::cout << "upper bound " << cfg.upper_bound_partition << std::endl;) improvement += refine->perform_refinement(cfg, *coarser, *coarser_boundary); m_deepest_level = m_level + 1; } else { m_level++; improvement += perform_partitioning_recursive( partition_config, *coarser, &coarser_boundary); partition_config.graph_allready_partitioned = true; if(m_level % partition_config.level_split == 0 ) { if(!partition_config.use_fullmultigrid || m_have_been_level_down.find(m_level) == m_have_been_level_down.end()) { if(!partition_config.label_propagation_refinement) { delete coarser_boundary; coarser_boundary = new complete_boundary(coarser); } m_have_been_level_down[m_level] = true; // configurate the algorithm to use the same amount // of imbalance as was allowed on this level PartitionConfig cfg; cfg = partition_config; cfg.set_upperbound = false; double cur_factor = partition_config.balance_factor/(m_deepest_level-m_level); cfg.upper_bound_partition = ( (m_level != 0) * cur_factor+1.0)*partition_config.upper_bound_partition; // do the next arm of the F-cycle improvement += perform_partitioning_recursive( cfg, *coarser, &coarser_boundary); } } m_level--; } if(partition_config.use_balance_singletons && !partition_config.label_propagation_refinement) { coarser_boundary->balance_singletons( partition_config, *coarser ); } //project graph_access& fRef = *finer; graph_access& cRef = *coarser; forall_nodes(fRef, n) { NodeID coarser_node = (*coarse_mapping)[n]; PartitionID coarser_partition_id = cRef.getPartitionIndex(coarser_node); fRef.setPartitionIndex(n, coarser_partition_id); } endfor
EdgeWeight kway_graph_refinement_core::single_kway_refinement_round_internal(PartitionConfig & config, graph_access & G, complete_boundary & boundary, boundary_starting_nodes & start_nodes, int step_limit, vertex_moved_hashtable & moved_idx, bool compute_touched_partitions, std::unordered_map<PartitionID, PartitionID> & touched_blocks) { commons = kway_graph_refinement_commons::getInstance(config); refinement_pq* queue = NULL; if(config.use_bucket_queues) { EdgeWeight max_degree = G.getMaxDegree(); queue = new bucket_pq(max_degree); } else { queue = new maxNodeHeap(); } init_queue_with_boundary(config, G, start_nodes, queue, moved_idx); if(queue->empty()) {delete queue; return 0;} std::vector<NodeID> transpositions; std::vector<PartitionID> from_partitions; std::vector<PartitionID> to_partitions; int max_number_of_swaps = (int)(G.number_of_nodes()); int min_cut_index = -1; EdgeWeight cut = std::numeric_limits<int>::max()/2; // so we dont need to compute the edge cut EdgeWeight initial_cut = cut; //roll forwards EdgeWeight best_cut = cut; int number_of_swaps = 0; int movements = 0; kway_stop_rule* stopping_rule = NULL; switch(config.kway_stop_rule) { case KWAY_SIMPLE_STOP_RULE: stopping_rule = new kway_simple_stop_rule(config); break; case KWAY_ADAPTIVE_STOP_RULE: stopping_rule = new kway_adaptive_stop_rule(config); break; } for(number_of_swaps = 0, movements = 0; movements < max_number_of_swaps; movements++, number_of_swaps++) { if( queue->empty() ) break; if( stopping_rule->search_should_stop(min_cut_index, number_of_swaps, step_limit) ) break; Gain gain = queue->maxValue(); NodeID node = queue->deleteMax(); #ifndef NDEBUG PartitionID maxgainer; EdgeWeight ext_degree; ASSERT_TRUE(moved_idx[node].index == NOT_MOVED); ASSERT_EQ(gain, commons->compute_gain(G, node, maxgainer, ext_degree)); ASSERT_TRUE(ext_degree > 0); #endif PartitionID from = G.getPartitionIndex(node); bool successfull = move_node(config, G, node, moved_idx, queue, boundary); if(successfull) { cut -= gain; stopping_rule->push_statistics(gain); bool accept_equal = random_functions::nextBool(); if( cut < best_cut || ( cut == best_cut && accept_equal )) { best_cut = cut; min_cut_index = number_of_swaps; if(cut < best_cut) stopping_rule->reset_statistics(); } from_partitions.push_back(from); to_partitions.push_back(G.getPartitionIndex(node)); transpositions.push_back(node); } else { number_of_swaps--; //because it wasnt swaps } moved_idx[node].index = MOVED; ASSERT_TRUE(boundary.assert_bnodes_in_boundaries()); ASSERT_TRUE(boundary.assert_boundaries_are_bnodes()); } ASSERT_TRUE(boundary.assert_bnodes_in_boundaries()); ASSERT_TRUE(boundary.assert_boundaries_are_bnodes()); //roll backwards for(number_of_swaps--; number_of_swaps>min_cut_index; number_of_swaps--) { ASSERT_TRUE(transpositions.size() > 0); NodeID node = transpositions.back(); transpositions.pop_back(); PartitionID to = from_partitions.back(); from_partitions.pop_back(); to_partitions.pop_back(); move_node_back(config, G, node, to, moved_idx, queue, boundary); } //reconstruct the touched partitions if(compute_touched_partitions) { ASSERT_EQ(from_partitions.size(), to_partitions.size()); for(unsigned i = 0; i < from_partitions.size(); i++) { touched_blocks[from_partitions[i]] = from_partitions[i]; touched_blocks[to_partitions[i]] = to_partitions[i]; } } ASSERT_TRUE(boundary.assert_bnodes_in_boundaries()); ASSERT_TRUE(boundary.assert_boundaries_are_bnodes()); delete queue; delete stopping_rule; return initial_cut - best_cut; }
void graph_partitioner::perform_recursive_partitioning_internal(PartitionConfig & config, graph_access & G, PartitionID lb, PartitionID ub) { G.set_partition_count(2); // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // configuration of bipartitioning // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PartitionConfig bipart_config = config; bipart_config.k = 2; bipart_config.stop_rule = STOP_RULE_MULTIPLE_K; bipart_config.num_vert_stop_factor = 100; double epsilon = 0; bipart_config.rebalance = false; bipart_config.softrebalance = true; if(config.k < 64) { epsilon = m_rnd_bal/100.0; bipart_config.rebalance = false; bipart_config.softrebalance = false; } else { epsilon = 1/100.0; } if(m_global_k == 2) { epsilon = 3.0/100.0; } bipart_config.upper_bound_partition = ceil((1+epsilon)*config.largest_graph_weight/(double)bipart_config.k); bipart_config.corner_refinement_enabled = false; bipart_config.quotient_graph_refinement_disabled = false; bipart_config.refinement_scheduling_algorithm = REFINEMENT_SCHEDULING_ACTIVE_BLOCKS; bipart_config.kway_adaptive_limits_beta = log(G.number_of_nodes()); // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // end configuration // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% NodeID new_ub_lhs = floor((lb+ub)/2); NodeID new_lb_rhs = floor((lb+ub)/2+1); NodeID num_blocks_lhs = new_ub_lhs - lb + 1; NodeID num_blocks_rhs = ub - new_lb_rhs + 1; if(config.k % 2 != 0) { //otherwise the block weights have to be bipart_config.target_weights.clear(); bipart_config.target_weights.push_back((1+epsilon)*num_blocks_lhs/(double)(num_blocks_lhs+num_blocks_rhs)*config.largest_graph_weight); bipart_config.target_weights.push_back((1+epsilon)*num_blocks_rhs/(double)(num_blocks_lhs+num_blocks_rhs)*config.largest_graph_weight); bipart_config.initial_bipartitioning = true; bipart_config.refinement_type = REFINEMENT_TYPE_FM; // flows not supported for odd block weights } else { bipart_config.target_weights.clear(); bipart_config.target_weights.push_back(bipart_config.upper_bound_partition); bipart_config.target_weights.push_back(bipart_config.upper_bound_partition); bipart_config.initial_bipartitioning = false; } bipart_config.grow_target = ceil(num_blocks_lhs/(double)(num_blocks_lhs+num_blocks_rhs)*config.largest_graph_weight); perform_partitioning(bipart_config, G); if( config.k > 2 ) { graph_extractor extractor; graph_access extracted_block_lhs; graph_access extracted_block_rhs; std::vector<NodeID> mapping_extracted_to_G_lhs; // map the new nodes to the nodes in the old graph G std::vector<NodeID> mapping_extracted_to_G_rhs; // map the new nodes to the nodes in the old graph G NodeWeight weight_lhs_block = 0; NodeWeight weight_rhs_block = 0; extractor.extract_two_blocks(G, extracted_block_lhs, extracted_block_rhs, mapping_extracted_to_G_lhs, mapping_extracted_to_G_rhs, weight_lhs_block, weight_rhs_block); PartitionConfig rec_config = config; if(num_blocks_lhs > 1) { rec_config.k = num_blocks_lhs; rec_config.largest_graph_weight = weight_lhs_block; perform_recursive_partitioning_internal( rec_config, extracted_block_lhs, lb, new_ub_lhs); //apply partition forall_nodes(extracted_block_lhs, node) { G.setPartitionIndex(mapping_extracted_to_G_lhs[node], extracted_block_lhs.getPartitionIndex(node)); } endfor
void coarsening::perform_coarsening(const PartitionConfig & partition_config, graph_access & G, graph_hierarchy & hierarchy) { NodeID no_of_coarser_vertices = G.number_of_nodes(); NodeID no_of_finer_vertices = G.number_of_nodes(); edge_ratings rating(partition_config); CoarseMapping* coarse_mapping = NULL; graph_access* finer = &G; matching* edge_matcher = NULL; contraction* contracter = new contraction(); PartitionConfig copy_of_partition_config = partition_config; stop_rule* coarsening_stop_rule = NULL; if( partition_config.mode_node_separators ) { coarsening_stop_rule = new separator_simple_stop_rule(copy_of_partition_config, G.number_of_nodes()); } else { if(partition_config.stop_rule == STOP_RULE_SIMPLE) { coarsening_stop_rule = new simple_stop_rule(copy_of_partition_config, G.number_of_nodes()); } else if(partition_config.stop_rule == STOP_RULE_MULTIPLE_K) { coarsening_stop_rule = new multiple_k_stop_rule(copy_of_partition_config, G.number_of_nodes()); } else { coarsening_stop_rule = new strong_stop_rule(copy_of_partition_config, G.number_of_nodes()); } } coarsening_configurator coarsening_config; unsigned int level = 0; bool contraction_stop = false; do { graph_access* coarser = new graph_access(); coarse_mapping = new CoarseMapping(); Matching edge_matching; NodePermutationMap permutation; coarsening_config.configure_coarsening(copy_of_partition_config, &edge_matcher, level); rating.rate(*finer, level); edge_matcher->match(copy_of_partition_config, *finer, edge_matching, *coarse_mapping, no_of_coarser_vertices, permutation); delete edge_matcher; if(partition_config.graph_allready_partitioned) { contracter->contract_partitioned(copy_of_partition_config, *finer, *coarser, edge_matching, *coarse_mapping, no_of_coarser_vertices, permutation); } else { contracter->contract(copy_of_partition_config, *finer, *coarser, edge_matching, *coarse_mapping, no_of_coarser_vertices, permutation); } hierarchy.push_back(finer, coarse_mapping); contraction_stop = coarsening_stop_rule->stop(no_of_finer_vertices, no_of_coarser_vertices); no_of_finer_vertices = no_of_coarser_vertices; std::cout << "no of coarser vertices " << no_of_coarser_vertices << " and no of edges " << coarser->number_of_edges() << std::endl; finer = coarser; level++; } while( contraction_stop ); hierarchy.push_back(finer, NULL); // append the last created level delete contracter; delete coarsening_stop_rule; }
int wcycle_partitioner::perform_partitioning_recursive( PartitionConfig & partition_config, graph_access & G, complete_boundary ** c_boundary) { //if graph not small enough // perform matching two times // perform coarsening two times // call rekursive //else // initial partitioning // //refinement NodeID no_of_coarser_vertices = G.number_of_nodes(); NodeID no_of_finer_vertices = G.number_of_nodes(); int improvement = 0; edge_ratings rating(partition_config); CoarseMapping* coarse_mapping = new CoarseMapping(); graph_access* finer = &G; matching* edge_matcher = NULL; contraction* contracter = new contraction(); PartitionConfig copy_of_partition_config = partition_config; graph_access* coarser = new graph_access(); Matching edge_matching; NodePermutationMap permutation; coarsening_configurator coarsening_config; coarsening_config.configure_coarsening(partition_config, &edge_matcher, m_level); rating.rate(*finer, m_level); edge_matcher->match(partition_config, *finer, edge_matching, *coarse_mapping, no_of_coarser_vertices, permutation); delete edge_matcher; if(partition_config.graph_allready_partitioned) { contracter->contract_partitioned(partition_config, *finer, *coarser, edge_matching, *coarse_mapping, no_of_coarser_vertices, permutation); } else { contracter->contract(partition_config, *finer, *coarser, edge_matching, *coarse_mapping, no_of_coarser_vertices, permutation); } coarser->set_partition_count(partition_config.k); complete_boundary* coarser_boundary = NULL; refinement* refine = NULL; coarser_boundary = new complete_boundary(coarser); refine = new mixed_refinement(); if(!m_coarsening_stop_rule->stop(no_of_finer_vertices, no_of_coarser_vertices)) { initial_partitioning init_part; init_part.perform_initial_partitioning(partition_config, *coarser); coarser_boundary->build(); improvement += refine->perform_refinement(partition_config, *coarser, *coarser_boundary); } else { m_level++; improvement += perform_partitioning_recursive( partition_config, *coarser, &coarser_boundary); partition_config.graph_allready_partitioned = true; if(m_level % partition_config.level_split == 0 ) { if(!partition_config.use_fullmultigrid || m_have_been_level_down.find(m_level) == m_have_been_level_down.end()) { delete coarser_boundary; coarser_boundary = new complete_boundary(coarser); m_have_been_level_down[m_level] = true; improvement += perform_partitioning_recursive( partition_config, *coarser, &coarser_boundary); } } m_level--; } if(partition_config.use_balance_singletons) { coarser_boundary->balance_singletons( partition_config, *coarser ); } //project graph_access& fRef = *finer; graph_access& cRef = *coarser; forall_nodes(fRef, n) { NodeID coarser_node = (*coarse_mapping)[n]; PartitionID coarser_partition_id = cRef.getPartitionIndex(coarser_node); fRef.setPartitionIndex(n, coarser_partition_id); } endfor