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); }
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 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
void separator_pool::generate_separators(MISConfig & config, graph_access & G) { internal_separators.clear(); internal_separators.resize(config.number_of_separators); for (unsigned int i = 0; i < separators_size; ++i) { diversifier div; div.diversify(config); // Add randomization to the imbalance config.imbalance = random_functions::nextDouble(0.05, 0.75); separator sep; forall_nodes(G, node) { G.setPartitionIndex(node, 0); } endfor create_separator(config, G, sep); sep.id = i; internal_separators[i] = sep; }
// 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; }
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
EdgeWeight edge_cut_flow_solver::convert_ds( const PartitionConfig & config, graph_access & G, PartitionID & lhs, PartitionID & rhs, std::vector<NodeID> & lhs_boundary_stripe, std::vector<NodeID> & rhs_boundary_stripe, std::vector<NodeID> & new_to_old_ids, long *n_ad, long* m_ad, node** nodes_ad, arc** arcs_ad, long ** cap_ad, node** source_ad, node** sink_ad, long* node_min_ad, EdgeID & no_edges_in_flow_graph) { //should soon be refactored #include "convert_ds_variables.h" //building up the graph as in parse.h of hi_pr code NodeID idx = 0; new_to_old_ids.resize(lhs_boundary_stripe.size() + rhs_boundary_stripe.size()); std::unordered_map<NodeID, NodeID> old_to_new; for( unsigned i = 0; i < lhs_boundary_stripe.size(); i++) { G.setPartitionIndex(lhs_boundary_stripe[i], BOUNDARY_STRIPE_NODE); new_to_old_ids[idx] = lhs_boundary_stripe[i]; old_to_new[lhs_boundary_stripe[i]] = idx++ ; } for( unsigned i = 0; i < rhs_boundary_stripe.size(); i++) { G.setPartitionIndex(rhs_boundary_stripe[i], BOUNDARY_STRIPE_NODE); new_to_old_ids[idx] = rhs_boundary_stripe[i]; old_to_new[rhs_boundary_stripe[i]] = idx++; } std::vector<NodeID> outer_lhs_boundary; std::vector<NodeID> outer_rhs_boundary; EdgeID no_edges = regions_no_edges(G, lhs_boundary_stripe, rhs_boundary_stripe, lhs, rhs, outer_lhs_boundary, outer_rhs_boundary); no_edges_in_flow_graph = no_edges; if(outer_lhs_boundary.size() == 0 || outer_rhs_boundary.size() == 0) return false; n = lhs_boundary_stripe.size() + rhs_boundary_stripe.size() + 2; //+source and target m = no_edges + outer_lhs_boundary.size() + outer_rhs_boundary.size(); nodes = (node*) calloc ( n+2, sizeof(node) ); arcs = (arc*) calloc ( 2*m+1, sizeof(arc) ); arc_tail = (long*) calloc ( 2*m, sizeof(long) ); arc_first= (long*) calloc ( n+2, sizeof(long) ); acap = (long*) calloc ( 2*m, sizeof(long) ); arc_current = arcs; node_max = 0; node_min = n; unsigned nodeoffset = 1; source = n - 2 + nodeoffset; sink = source+1; idx = 0; for( unsigned i = 0; i < lhs_boundary_stripe.size(); i++, idx++) { NodeID node = lhs_boundary_stripe[i]; NodeID sourceID = idx + nodeoffset; forall_out_edges(G, e, node) { if(G.getPartitionIndex(G.getEdgeTarget(e)) == BOUNDARY_STRIPE_NODE) { NodeID targetID = old_to_new[G.getEdgeTarget(e)] + nodeoffset; EdgeWeight capacity = G.getEdgeWeight(e); tail = sourceID; head = targetID; cap = capacity; createEdge() } } endfor }
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
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