Feat: optimized neighbor_list sorting

This commit is contained in:
Richard Wong 2024-03-03 23:53:21 +09:00
parent 996222ab60
commit 1c50e1fe86
Signed by: richard
GPG Key ID: 5BD36BA2E9EE33D0
4 changed files with 55 additions and 32 deletions

View File

@ -58,9 +58,9 @@ public:
void set_adj_list(vector<node*> vec); void set_adj_list(vector<node*> vec);
void DFS_visit(vector<node*> &dfsList, int &index); void DFS_visit(vector<node*> &dfsList, int &index);
void guided_DFS_visit(vector<node *> &dfsList, void guided_DFS_visit(vector<node *> &dfsList,
vector<node *> &node_list, const vector<node *> &node_list,
int &return_index, int &return_index,
vector<int> rev_post_order, const vector<int> &rev_post_order,
int prev_node); int prev_node);
void mutated_DFS_visit(vector<node*> &dfsList, void mutated_DFS_visit(vector<node*> &dfsList,
vector<node*> &node_list, vector<node*> &node_list,
@ -68,6 +68,9 @@ public:
int &traversal_index, int &traversal_index,
vector<int> rev_post_order, vector<int> rev_post_order,
int mutate_point); int mutate_point);
// custom comparator function to sort nodes according to order in given vector
bool sortByOrder(const std::vector<int>& vec_order, node* a, node* b);
//PARENT-CHILDREN //PARENT-CHILDREN
void set_parent(node* n) ; void set_parent(node* n) ;
@ -199,4 +202,4 @@ private:
vector<node*> _new_node_list; //Newly added nodes. vector<node*> _new_node_list; //Newly added nodes.
}; };
#endif #endif // for MPS_H

View File

@ -26,7 +26,7 @@ vector<int> generate_post_order(const ogdf::Graph &G);
vector<int> generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point); vector<int> generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point);
vector<int> generate_guided_post_order(const ogdf::Graph &G, vector<int> post_order); vector<int> generate_guided_post_order(const ogdf::Graph &G, vector<int> post_order);
void vector_printer(vector<int> state) { void vector_printer(const vector<int>& state) {
for (int i = 0; i < state.size(); ++i) { for (int i = 0; i < state.size(); ++i) {
std::cout << state[i] << ","; std::cout << state[i] << ",";
} }
@ -36,8 +36,9 @@ void vector_printer(vector<int> state) {
vector<int> repeated_mutation(const ogdf::Graph &G, int k_max, int mutate_point) { vector<int> repeated_mutation(const ogdf::Graph &G, int k_max, int mutate_point) {
// generate first post order // generate first post order
std::cout << "generate first post order" << std::endl; // std::cout << "generate first post order" << std::endl;
vector<int> state_old = generate_post_order(G); vector<int> state_old = generate_post_order(G);
vector_printer(state_old);
vector<int> state_new; vector<int> state_new;
int old_edge_size = compute_removed_edge_size(G, state_old); int old_edge_size = compute_removed_edge_size(G, state_old);
@ -46,7 +47,9 @@ vector<int> repeated_mutation(const ogdf::Graph &G, int k_max, int mutate_point)
for (int k = 0; k < k_max; ++k) { for (int k = 0; k < k_max; ++k) {
// mutation produces rotated view // mutation produces rotated view
state_new = generate_mutated_post_order(G, state_old, mutate_point); // state_new = generate_mutated_post_order(G, state_old, mutate_point);
// simulate a mutation
state_new = generate_guided_post_order(G, state_old);
// another round of guided post order gives canonical representation // another round of guided post order gives canonical representation
state_new = generate_guided_post_order(G, state_new); state_new = generate_guided_post_order(G, state_new);
@ -58,6 +61,7 @@ vector<int> repeated_mutation(const ogdf::Graph &G, int k_max, int mutate_point)
} }
vector_printer(state_new);
return state_new; return state_new;
} }
@ -92,18 +96,17 @@ int main(int argc, char* argv[]) {
const ogdf::Graph G = read_from_gml(input_file); const ogdf::Graph G = read_from_gml(input_file);
// generate order here // generate order here
// vector<int> post_order = repeated_mutation(input_file, k_max, mutate_point); vector<int> post_order = repeated_mutation(G, k_max, mutate_point);
// test_correctness(input_file);
// test timing of function // test timing of function
test_correctness(G); // test_correctness(G);
// // print final order and number of edges // // print final order and number of edges
// // print post_order // // print post_order
// std::copy(post_order.begin(), post_order.end(), std::ostream_iterator<int>(std::cout, ",")); // std::copy(post_order.begin(), post_order.end(), std::ostream_iterator<int>(std::cout, ","));
// std::cout << std::endl; // std::cout << std::endl;
// int removed_edges = compute_removed_edge_size(input_file, post_order); int removed_edges = compute_removed_edge_size(G, post_order);
// std::cout << "Number of removed edges: " << removed_edges << std::endl; std::cout << "Number of removed edges: " << removed_edges << std::endl;
return 0; return 0;
} }

View File

@ -9,7 +9,7 @@
// #define DEBUG // #define DEBUG
#define TIME // #define TIME
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// Finding MPS // Finding MPS
@ -127,6 +127,7 @@ int maximal_planar_subgraph_finder::compute_removed_edge_size(const ogdf::Graph
start = std::chrono::high_resolution_clock::now(); start = std::chrono::high_resolution_clock::now();
#endif #endif
guidedPostOrderTraversal(post_order); guidedPostOrderTraversal(post_order);
// postOrderTraversal();
#ifdef TIME #ifdef TIME
end = std::chrono::high_resolution_clock::now(); end = std::chrono::high_resolution_clock::now();
std::cout << "guidedPostOrderTraversal: " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << std::endl; std::cout << "guidedPostOrderTraversal: " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << std::endl;

View File

@ -70,10 +70,18 @@ void node::DFS_visit(vector<node*> &dfsList, int &index) {
} }
bool node::sortByOrder(const std::vector<int>& vec_order, node* a, node* b) {
auto itA = std::find(vec_order.begin(), vec_order.end(), a->node_id());
auto itB = std::find(vec_order.begin(), vec_order.end(), b->node_id());
return (std::distance(vec_order.begin(), itA) < std::distance(vec_order.begin(), itB));
}
void node::guided_DFS_visit(vector<node *> &dfsList, void node::guided_DFS_visit(vector<node *> &dfsList,
vector<node *> &node_list, const vector<node *> &node_list,
int &return_index, int &return_index,
vector<int> rev_post_order, const vector<int> &rev_post_order,
int prev_node) int prev_node)
{ {
@ -82,24 +90,32 @@ void node::guided_DFS_visit(vector<node *> &dfsList,
// purpose of this block: create list of neighbors ordered in the order they appear in rev_post_order // purpose of this block: create list of neighbors ordered in the order they appear in rev_post_order
// we want to select neighbors that match the rev_post_order at the specific traversal_index // we want to select neighbors that match the rev_post_order at the specific traversal_index
// create an unordered set to efficiently check for presence of an element // implementation 1: loop through all elements
std::unordered_set<int> neighbor_set; // // create an unordered set to efficiently check for presence of an element
for (int i = 0; i < _adj_list.size(); ++i) { // std::unordered_set<int> neighbor_set;
neighbor_set.insert(_adj_list[i]->node_id()); // for (int i = 0; i < _adj_list.size(); ++i) {
} // neighbor_set.insert(_adj_list[i]->node_id());
// when an element in rev_post_order is found in neighbor_set, we add that to neighbor_list // }
// this produces a neighbor_list that follows the order by which they occur in the rev_post_order // // when an element in rev_post_order is found in neighbor_set, we add that to neighbor_list
// it is ok if the neighbor was already visited before, // // this produces a neighbor_list that follows the order by which they occur in the rev_post_order
// it would've been marked and will be subsequently ignored // // it is ok if the neighbor was already visited before,
vector<node *> neighbor_list; // // it would've been marked and will be subsequently ignored
for (int i = 0; i < rev_post_order.size(); ++i) { // vector<node *> neighbor_list;
if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) { // for (int i = 0; i < rev_post_order.size(); ++i) {
// only add if newly encountered // if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) {
if (!node_list[rev_post_order[i]]->is_marked()) { // // only add if newly encountered
neighbor_list.push_back(node_list[rev_post_order[i]]); // if (!node_list[rev_post_order[i]]->is_marked()) {
} // neighbor_list.push_back(node_list[rev_post_order[i]]);
} // }
} // }
// }
// implementation 2: sort elements of _adj_list
vector<node*> neighbor_list = _adj_list;
std::sort(neighbor_list.begin(), neighbor_list.end(), [this, &rev_post_order](node* a, node* b) {
return sortByOrder(rev_post_order, a, b);
});
#ifdef DEBUG #ifdef DEBUG
std::cout << "current node:" << this->node_id() << std::endl; std::cout << "current node:" << this->node_id() << std::endl;