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); }
EdgeWeight two_way_fm::perform_refinement(PartitionConfig & cfg, graph_access& G, complete_boundary & boundary, std::vector<NodeID> & lhs_start_nodes, std::vector<NodeID> & rhs_start_nodes, boundary_pair * pair, NodeWeight & lhs_part_weight, NodeWeight & rhs_part_weight, EdgeWeight & cut, bool & something_changed) { PartitionConfig config = cfg;//copy it since we make changes on that if(lhs_start_nodes.size() == 0 or rhs_start_nodes.size() == 0) return 0; // nothing to refine quality_metrics qm; ASSERT_NEQ(pair->lhs, pair->rhs); ASSERT_TRUE(assert_directed_boundary_condition(G, boundary, pair->lhs, pair->rhs)); ASSERT_EQ( cut, qm.edge_cut(G, pair->lhs, pair->rhs)); refinement_pq* lhs_queue = NULL; refinement_pq* rhs_queue = NULL; if(config.use_bucket_queues) { EdgeWeight max_degree = G.getMaxDegree(); lhs_queue = new bucket_pq(max_degree); rhs_queue = new bucket_pq(max_degree); } else { lhs_queue = new maxNodeHeap(); rhs_queue = new maxNodeHeap(); } init_queue_with_boundary(config, G, lhs_start_nodes, lhs_queue, pair->lhs, pair->rhs); init_queue_with_boundary(config, G, rhs_start_nodes, rhs_queue, pair->rhs, pair->lhs); queue_selection_strategy* topgain_queue_select = new queue_selection_topgain(config); queue_selection_strategy* diffusion_queue_select = new queue_selection_diffusion(config); queue_selection_strategy* diffusion_queue_select_block_target = new queue_selection_diffusion_block_targets(config); vertex_moved_hashtable moved_idx; std::vector<NodeID> transpositions; EdgeWeight inital_cut = cut; int max_number_of_swaps = (int)(boundary.getBlockNoNodes(pair->lhs) + boundary.getBlockNoNodes(pair->rhs)); int step_limit = (int)((config.fm_search_limit/100.0)*max_number_of_swaps); step_limit = std::max(step_limit, 15); int min_cut_index = -1; refinement_pq* from_queue = 0; refinement_pq* to_queue = 0; PartitionID from = 0; PartitionID to = 0; NodeWeight * from_part_weight = 0; NodeWeight * to_part_weight = 0; stop_rule* st_rule = new easy_stop_rule(); partition_accept_rule* accept_partition = NULL; if(config.initial_bipartitioning) { accept_partition = new ip_partition_accept_rule(config, cut,lhs_part_weight, rhs_part_weight, pair->lhs, pair->rhs); } else { accept_partition = new normal_partition_accept_rule(config, cut,lhs_part_weight, rhs_part_weight); } queue_selection_strategy* q_select; if(config.softrebalance || config.rebalance || config.initial_bipartitioning) { if(config.initial_bipartitioning) { q_select = diffusion_queue_select_block_target; } else { q_select = diffusion_queue_select; } } else { q_select = topgain_queue_select; } //roll forwards EdgeWeight best_cut = cut; int number_of_swaps = 0; for(number_of_swaps = 0; number_of_swaps < max_number_of_swaps; number_of_swaps++) { if(st_rule->search_should_stop(min_cut_index, number_of_swaps, step_limit)) break; if(lhs_queue->empty() && rhs_queue->empty()) { break; } q_select->selectQueue(lhs_part_weight, rhs_part_weight, pair->lhs, pair->rhs, from,to, lhs_queue, rhs_queue, &from_queue, &to_queue); if(!from_queue->empty()) { Gain gain = from_queue->maxValue(); NodeID node = from_queue->deleteMax(); ASSERT_TRUE(moved_idx[node].index == NOT_MOVED); boundary.setBlockNoNodes(from, boundary.getBlockNoNodes(from)-1); boundary.setBlockNoNodes(to, boundary.getBlockNoNodes(to)+1); if(from == pair->lhs) { from_part_weight = &lhs_part_weight; to_part_weight = &rhs_part_weight; } else { from_part_weight = &rhs_part_weight; to_part_weight = &lhs_part_weight; } move_node(config, G, node, moved_idx, from_queue, to_queue, from, to, pair, from_part_weight, to_part_weight, boundary); cut -= gain; if( accept_partition->accept_partition(config, cut, lhs_part_weight, rhs_part_weight, pair->lhs, pair->rhs, config.rebalance)) { ASSERT_TRUE( cut <= best_cut || config.rebalance); if( cut < best_cut ) { something_changed = true; } best_cut = cut; min_cut_index = number_of_swaps; } transpositions.push_back(node); moved_idx[node].index = MOVED; } else { break; } } ASSERT_TRUE(assert_directed_boundary_condition(G, boundary, pair->lhs, pair->rhs)); ASSERT_EQ( cut, qm.edge_cut(G, pair->lhs, pair->rhs)); //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 nodes_partition = G.getPartitionIndex(node); if(nodes_partition == pair->lhs) { from_queue = lhs_queue; to_queue = rhs_queue; from = pair->lhs; to = pair->rhs; from_part_weight = &lhs_part_weight; to_part_weight = &rhs_part_weight; } else { from_queue = rhs_queue; to_queue = lhs_queue; from = pair->rhs; to = pair->lhs; from_part_weight = &rhs_part_weight; to_part_weight = &lhs_part_weight; } boundary.setBlockNoNodes(from, boundary.getBlockNoNodes(from)-1); boundary.setBlockNoNodes(to, boundary.getBlockNoNodes(to)+1); move_node_back(config, G, node, moved_idx, from_queue, to_queue, from, to, pair, from_part_weight, to_part_weight, boundary); } //clean up cut = best_cut; boundary.setEdgeCut(pair, best_cut); boundary.setBlockWeight(pair->lhs, lhs_part_weight); boundary.setBlockWeight(pair->rhs, rhs_part_weight); delete lhs_queue; delete rhs_queue; delete topgain_queue_select; delete diffusion_queue_select; delete diffusion_queue_select_block_target; delete st_rule; delete accept_partition; ASSERT_EQ( cut, qm.edge_cut(G, pair->lhs, pair->rhs)); ASSERT_TRUE(assert_directed_boundary_condition(G, boundary, pair->lhs, pair->rhs)); ASSERT_TRUE( (int)inital_cut-(int)best_cut >= 0 || cfg.rebalance); // the computed partition shouldnt have a edge cut which is worse than the initial one return inital_cut-best_cut; }