Esempio n. 1
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
                }
Esempio n. 2
0
void kway_graph_refinement::setup_start_nodes(PartitionConfig & config, graph_access & G, complete_boundary & boundary,  boundary_starting_nodes & start_nodes) {
        QuotientGraphEdges quotient_graph_edges;
        boundary.getQuotientGraphEdges(quotient_graph_edges);

        unordered_map<NodeID, bool> allready_contained;

        for( unsigned i = 0; i < quotient_graph_edges.size(); i++) {
                boundary_pair & ret_value = quotient_graph_edges[i];
                PartitionID lhs           = ret_value.lhs;
                PartitionID rhs           = ret_value.rhs;

                PartialBoundary & partial_boundary_lhs = boundary.getDirectedBoundary(lhs, lhs, rhs);
                forall_boundary_nodes(partial_boundary_lhs, cur_bnd_node) {
                        ASSERT_EQ(G.getPartitionIndex(cur_bnd_node), lhs);
                        if(allready_contained.find(cur_bnd_node) == allready_contained.end() ) { 
                                start_nodes.push_back(cur_bnd_node);
                                allready_contained[cur_bnd_node] = true;
                        }
                } endfor

                PartialBoundary & partial_boundary_rhs = boundary.getDirectedBoundary(rhs, lhs, rhs);
                forall_boundary_nodes(partial_boundary_rhs, cur_bnd_node) {
                        ASSERT_EQ(G.getPartitionIndex(cur_bnd_node), rhs);
                        if(allready_contained.find(cur_bnd_node) == allready_contained.end()) { 
                                start_nodes.push_back(cur_bnd_node);
                                allready_contained[cur_bnd_node] = true;
                        }
                } endfor
Esempio n. 3
0
EdgeWeight quality_metrics::edge_cut(graph_access & G) {
        EdgeWeight edgeCut = 0;
        forall_nodes(G, n) { 
                PartitionID partitionIDSource = G.getPartitionIndex(n);
                forall_out_edges(G, e, n) {
                        NodeID targetNode = G.getEdgeTarget(e);
                        PartitionID partitionIDTarget = G.getPartitionIndex(targetNode);

                        if (partitionIDSource != partitionIDTarget) {
                                edgeCut += G.getEdgeWeight(e);
                        }
                } endfor 
Esempio n. 4
0
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
Esempio n. 5
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
                } 
Esempio n. 6
0
void two_way_fm::init_queue_with_boundary(const PartitionConfig & config,
                                          graph_access & G,
                                          std::vector<NodeID> & bnd_nodes,
                                          refinement_pq * queue,                     
                                          PartitionID partition_of_boundary, 
                                          PartitionID other) {

        if(config.permutation_during_refinement == PERMUTATION_QUALITY_FAST) {
                random_functions::permutate_vector_fast(bnd_nodes, false);
        } else if(config.permutation_during_refinement == PERMUTATION_QUALITY_GOOD) {
                random_functions::permutate_vector_good(bnd_nodes, false);
        }


        for( unsigned int i = 0, end = bnd_nodes.size(); i < end; i++) {
                NodeID cur_bnd_node = bnd_nodes[i];
                //compute gain
                EdgeWeight int_degree = 0;
                EdgeWeight ext_degree = 0;

                int_ext_degree(G, cur_bnd_node, partition_of_boundary, other, int_degree, ext_degree);

                Gain gain = ext_degree - int_degree;
                queue->insert(cur_bnd_node, gain);
                ASSERT_TRUE(ext_degree > 0);
                ASSERT_EQ(partition_of_boundary, G.getPartitionIndex(cur_bnd_node));
        }
}
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 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 initial_partition_bipartition::initial_partition( const PartitionConfig & config, 
                                                       const unsigned int seed,  
                                                       graph_access & G, int* partition_map) {
        graph_partitioner gp;
        PartitionConfig rec_config                  = config;
        rec_config.initial_partitioning_type        = INITIAL_PARTITIONING_BIPARTITION;
        rec_config.initial_partitioning_repetitions = 0;
        rec_config.global_cycle_iterations          = 1;
        rec_config.use_wcycles                      = false;
        rec_config.use_fullmultigrid                = false;
        rec_config.fm_search_limit                  = config.bipartition_post_ml_limits;
        rec_config.matching_type                    = MATCHING_GPA;
        //rec_config.matching_type                    = CLUSTER_COARSENING;
        rec_config.permutation_quality              = PERMUTATION_QUALITY_GOOD;

        rec_config.initial_partitioning             = true;

        std::streambuf* backup = std::cout.rdbuf();
        std::ofstream ofs;
        ofs.open("/dev/null");
        std::cout.rdbuf(ofs.rdbuf()); 

        gp.perform_recursive_partitioning(rec_config, G); 

        ofs.close();
        std::cout.rdbuf(backup);

        forall_nodes(G, n) {
                partition_map[n] =  G.getPartitionIndex(n);
        } endfor
bool vertex_separator_flow_solver::construct_flow_pb( const PartitionConfig & config, 
                                                      graph_access & G, 
                                                      PartitionID & lhs, 
                                                      PartitionID & rhs, 
                                                      std::vector<NodeID> & lhs_nodes,
                                                      std::vector<NodeID> & rhs_nodes,
                                                      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) { 
        
        //very dirty for loading variables :). some time this should all be refactored. for now we can focus on the important stuff.
        #include "../refinement/quotient_graph_refinement/flow_refinement/flow_solving_kernel/convert_ds_variables.h"

        //building up the graph as in parse.h of hi_pr code
        //first we have to count the number of edges 
        // s to lhs + rhs to t + lhs to rhs 
        unsigned no_edges = 0;
        for( unsigned i = 0; i < lhs_nodes.size(); i++) {
                NodeID node = lhs_nodes[i];
                forall_out_edges(G, e, node) {
                        NodeID target = G.getEdgeTarget(e);
                        if(rhs == G.getPartitionIndex(target)) {
                                ++no_edges;
                        }
                } endfor
        }
Esempio n. 11
0
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
Esempio n. 12
0
void partition_snapshooter::addSnapshot(graph_access & G) {
        std::cout <<  "idx " << m_partition_map_buffer.size() << std::endl;
        std::vector<PartitionID>* partition_map = new std::vector<PartitionID>();
        m_partition_map_buffer.push_back(partition_map);

        forall_nodes(G, node) {
               partition_map->push_back(G.getPartitionIndex(node)); 
        } endfor
Esempio n. 13
0
int mis_permutation::calculate_tightness(NodeID node, graph_access & G) {
    int tightness = 0;
    forall_out_edges(G, edge, node) {
        NodeID target = G.getEdgeTarget(edge);
        bool target_index = G.getPartitionIndex(target);
        if (target_index == 1) {
            tightness++;
        }
    } endfor
Esempio n. 14
0
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
Esempio n. 15
0
unsigned int population_mis::create_solution(graph_access & G, NodeID *solution) {
    unsigned int solution_size = 0;    
    forall_nodes(G, node) {
        if (G.getPartitionIndex(node) == 1) {
            solution[node] = 1;
            solution_size++;
        } 
        else solution[node] = 0;
    } endfor
    return solution_size;
}
Esempio n. 16
0
EdgeID edge_cut_flow_solver::regions_no_edges( graph_access & G,
                                               std::vector<NodeID> & lhs_boundary_stripe,
                                               std::vector<NodeID> & rhs_boundary_stripe,
                                               PartitionID & lhs, 
                                               PartitionID & rhs,
                                               std::vector<NodeID> & outer_lhs_boundary_nodes,
                                               std::vector<NodeID> & outer_rhs_boundary_nodes ) {

        EdgeID no_of_edges = 0;
        unsigned idx = 0;
        for( unsigned i = 0; i < lhs_boundary_stripe.size(); i++, idx++) {
                NodeID node = lhs_boundary_stripe[i];
                bool is_outer_boundary = false;
                forall_out_edges(G, e, node) {
                        if(G.getPartitionIndex(G.getEdgeTarget(e)) == BOUNDARY_STRIPE_NODE) no_of_edges++;
                        else is_outer_boundary = true;
                } endfor
                if(is_outer_boundary) {
                        outer_lhs_boundary_nodes.push_back(idx);
                }
        }

        for( unsigned i = 0; i < rhs_boundary_stripe.size(); i++, idx++) {
                NodeID node = rhs_boundary_stripe[i];
                bool is_outer_boundary = false;
                forall_out_edges(G, e, node) {
                        if(G.getPartitionIndex(G.getEdgeTarget(e)) == BOUNDARY_STRIPE_NODE) no_of_edges++;
                        else is_outer_boundary = true;
                } endfor
                if(is_outer_boundary) {
                        outer_rhs_boundary_nodes.push_back(idx);
                }
        }

        return no_of_edges; 
}
Esempio n. 17
0
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; 
}
Esempio n. 18
0
bool population_mis::insert(MISConfig & config, graph_access & G, individuum_mis & ind) {
    ASSERT_TRUE(is_mis(config, G, ind));
    bool successful_insertion = false;

    if (internal_population.size() < population_size) {
        ind.id = internal_population.size();
        internal_population.push_back(ind);
    } else {

        unsigned int worst_solution = std::numeric_limits<unsigned int>::max();
        unsigned int worst_id = 0;
        // Get worst solution
        for (unsigned int i = 0; i < internal_population.size(); ++i) {
            if (internal_population[i].solution_size < worst_solution) {
                worst_solution = internal_population[i].solution_size;            
                worst_id = i;
            }
        }
        individuum_mis worst = internal_population[worst_id];

        // Should the solution be inserted by force?
        if (insert_no_change > config.insert_threshold) {
            // std::cout << "Force" << std::endl;
            set_mis_for_individuum(config, G, ind);
            ils iterate;
            iterate.perform_ils(config, G, config.ils_iterations);

            ind.solution_size = 0;
            forall_nodes(G, node) {
                if (G.getPartitionIndex(node) == 1) ind.solution_size++; 
                ind.solution[node] = G.getPartitionIndex(node);
            } endfor
            replace(worst, ind);
            insert_no_change = 0;
            return true;
        }

        // Is the solution bigger than any so far?
        if (ind.solution_size <= worst_solution) {
            // std::cout << "Worse" << std::endl;
            insert_no_change++;
            delete [] ind.solution;
            ind.solution = NULL;
            return false;
        }

        // Else perform ILS and search most similar
        set_mis_for_individuum(config, G, ind);
        ils iterate;
        iterate.perform_ils(config, G, config.ils_iterations);

        ind.solution_size = 0;
        forall_nodes(G, node) {
            if (G.getPartitionIndex(node) == 1) ind.solution_size++;
            ind.solution[node] = G.getPartitionIndex(node);
        } endfor

        individuum_mis remove;
        bool valid_replacement = get_most_similar_replacement(config, G, ind, remove); 

        if (!valid_replacement) {
            // std::cout << "Not Valid" << ind.solution_size << std::endl;
            insert_no_change++;
            delete [] ind.solution;
            ind.solution = NULL;
            return false;
        } 
        else {
            // std::cout << "Valid: " << ind.solution_size << std::endl;
            replace(remove, ind);
            successful_insertion = true;
            insert_no_change = 0;
        }

    }
Esempio n. 19
0
// 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;

        
}
Esempio n. 20
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
Esempio n. 21
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
Esempio n. 22
0
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;
}
Esempio n. 23
0
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
        }