diff --git a/deferred_planarity_test/main.cpp b/deferred_planarity_test/main.cpp index c713148..e31a6f8 100644 --- a/deferred_planarity_test/main.cpp +++ b/deferred_planarity_test/main.cpp @@ -18,6 +18,9 @@ using namespace std; int compute_removed_edge_size(string input_file, vector post_order); +vector generate_post_order(string input_file); +vector generate_mutated_post_order(string input_file, vector post_order); + int get_graph_size(string input_file) { ogdf::Graph G; @@ -36,25 +39,23 @@ int get_graph_size(string input_file) { int main(int argc, char* argv[]) { string input_file = argv[1]; - int num_runs = stoi(argv[2]); - // find the size of the graph here - int node_size = get_graph_size(input_file); - // generate order here - vector post_order; - for (int i=0; i < node_size; ++i) { - post_order.push_back(i); - } - for (int i=0; i< num_runs; ++i) { - std::random_device rd; - std::mt19937 g(rd()); - - std::shuffle(post_order.begin(), post_order.end(), g); - // print order - std::copy(post_order.begin(), post_order.end(), std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - std::cout << "Number of removed edges: " << compute_removed_edge_size(input_file, post_order) << std::endl; - } + // generate order here + vector post_order = generate_post_order(input_file); + std::copy(post_order.begin(), post_order.end(), std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // generate mutated order + vector mutated_order = generate_mutated_post_order(input_file, post_order); + post_order = mutated_order; + std::copy(post_order.begin(), post_order.end(), std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + + // print order + int removed_edges = compute_removed_edge_size(input_file, post_order); + std::cout << "Number of removed edges: " << removed_edges << std::endl; + return 0; } diff --git a/deferred_planarity_test/mps.cpp b/deferred_planarity_test/mps.cpp index 0dc746c..3f9d389 100644 --- a/deferred_planarity_test/mps.cpp +++ b/deferred_planarity_test/mps.cpp @@ -20,7 +20,7 @@ maximal_planar_subgraph_finder::get_new_node(node_type t) { } //Determine the post-order-list by a DFS-traversal. -void +vector maximal_planar_subgraph_finder::postOrderTraversal() { node::init_mark(); int postOrderID = 0; @@ -29,8 +29,113 @@ maximal_planar_subgraph_finder::postOrderTraversal() { _node_list[i]->DFS_visit(_post_order_list, postOrderID); } } + + vector post_order; + for (int i = 0; i < _post_order_list.size(); ++i) { + post_order.push_back(_post_order_list[i]->node_id()); + } + return post_order; } + +//Determine the post-order-list by a DFS-traversal. +void +maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector post_order) { + node::init_mark(); + + vector rev_post_order; + for (int i = post_order.size() - 1; i >= 0; --i) { + rev_post_order.push_back(post_order[i]); + } + int postOrderID = 0; + + int end_condition = _node_list.size(); + int start = rev_post_order[0]; + int i = start; + while (true) + { + if (((start > 0) && (i == (start - 1))) || ((start == 0 ) && (i == end_condition - 1))) + { + if (!_node_list[i]->is_marked()) + { + _node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order); + } + break; + } + // std::cout << _node_list[i]->node_id() << ", " << !_node_list[i]->is_marked() << std::endl; + if (!_node_list[i]->is_marked()) + { + _node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order); + } + i = (i + 1) % end_condition; + } +} + +//Determine the post-order-list by a DFS-traversal. +vector +maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector post_order) { + node::init_mark(); + + vector rev_post_order; + for (int i = post_order.size() - 1; i >= 0; --i) { + rev_post_order.push_back(post_order[i]); + } + int postOrderID = 0; + + // introduce random selection + std::random_device rd; + std::mt19937 rng(rd()); + // Define the range [0, n] + int n = _node_list.size() - 1; // Change 'n' to your desired upper bound + // Create a uniform distribution for the range [0, n] + std::uniform_int_distribution distribution(0, n); + // Generate a random number between 0 and n (inclusive) + int mutate_point = distribution(rng); + std::cout << "the mutate point: " << mutate_point << std::endl; + + // set loop variables + int start = rev_post_order[0]; + int i = start; + + // if mutate_point = 0 + if (mutate_point == 0) { + // generate another point + start = distribution(rng); + } + + + int end_condition = _node_list.size(); + while (true) + { + if (((start > 0) && (i == (start - 1))) || ((start == 0 ) && (i == end_condition - 1))) + { + if (!_node_list[i]->is_marked()) + { + _node_list[i]->mutated_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order, mutate_point); + } + break; + } + // std::cout << _node_list[i]->node_id() << ", " << !_node_list[i]->is_marked() << std::endl; + if (!_node_list[i]->is_marked()) + { + _node_list[i]->mutated_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order, mutate_point); + } + i = (i + 1) % end_condition; + } + + vector return_order; + for (int i = 0; i < _post_order_list.size(); ++i) { + return_order.push_back(_post_order_list[i]->node_id()); + } + + // we have to reverse the order as we add to list in the forward direction of recursion + // unlike that of previous methods where we add to list in the return direction of recursion + std::reverse(return_order.begin(), return_order.end()); + return return_order; +} + + + //Set the post-order-list via given list void maximal_planar_subgraph_finder::set_post_order(vector post_order) { diff --git a/deferred_planarity_test/mps.h b/deferred_planarity_test/mps.h index 8a9dd6c..d70fc1d 100644 --- a/deferred_planarity_test/mps.h +++ b/deferred_planarity_test/mps.h @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include using namespace std; @@ -53,6 +56,8 @@ public: node* adj(int i); void set_adj_list(vector vec); void DFS_visit(vector &dfsList, int &index); + void guided_DFS_visit(vector &dfsList, vector &node_list, int &index, vector rev_post_order); + void mutated_DFS_visit(vector &dfsList, vector &node_list, int &index, vector rev_post_order, int &mutate_point); //PARENT-CHILDREN void set_parent(node* n) ; @@ -143,10 +148,14 @@ public: ~maximal_planar_subgraph_finder(); int find_mps(string input_file); int compute_removed_edge_size(string input_file, vector post_order); + vector generate_post_order(string input_file); + vector generate_mutated_post_order(string input_file, vector post_order); node* get_new_node(node_type t); void read_from_gml(string input_file); int output_removed_edge_size(); - void postOrderTraversal(); + vector postOrderTraversal(); + vector mutatedPostOrderTraversal(vector post_order); + void guidedPostOrderTraversal(vector post_order); void set_post_order(vector post_order); void sort_adj_list(); void determine_edges(); diff --git a/deferred_planarity_test/mps_test.cpp b/deferred_planarity_test/mps_test.cpp index 795ca0c..b8bc828 100644 --- a/deferred_planarity_test/mps_test.cpp +++ b/deferred_planarity_test/mps_test.cpp @@ -8,6 +8,9 @@ //----------------------------------------------------------------------------------- // Finding MPS //----------------------------------------------------------------------------------- + +// programs to call from main: + int find_mps(string input_file) { maximal_planar_subgraph_finder m; return m.find_mps(input_file); @@ -18,6 +21,19 @@ int compute_removed_edge_size(string input_file, vector post_order) { return m.compute_removed_edge_size(input_file, post_order); } +vector generate_post_order(string input_file) { + maximal_planar_subgraph_finder m; + return m.generate_post_order(input_file); +} + +vector generate_mutated_post_order(string input_file, vector post_order) { + maximal_planar_subgraph_finder m; + return m.generate_mutated_post_order(input_file, post_order); +} + + +// --------- + int maximal_planar_subgraph_finder::find_mps(string input_file) { read_from_gml(input_file); postOrderTraversal(); @@ -27,10 +43,34 @@ int maximal_planar_subgraph_finder::find_mps(string input_file) { return output_removed_edge_size(); } +vector maximal_planar_subgraph_finder::generate_post_order(string input_file) { + read_from_gml(input_file); + return postOrderTraversal(); +} + +vector maximal_planar_subgraph_finder::generate_mutated_post_order(string input_file, vector post_order) { + read_from_gml(input_file); + return mutatedPostOrderTraversal(post_order); +} + int maximal_planar_subgraph_finder::compute_removed_edge_size(string input_file, vector post_order) { read_from_gml(input_file); - set_post_order(post_order); + guidedPostOrderTraversal(post_order); + + // let's reverse the order + std::reverse(_post_order_list.begin(), _post_order_list.end()); + // then set post_order_index + for (int i = 0; i < _post_order_list.size(); ++i) { + _node_list[_post_order_list[i]->node_id()]->set_post_order_index(i); + } + + std::cout << "check order of duplicated traversal" << std::endl; + for (int i = 0; i < _post_order_list.size(); ++i) { + std::cout << _post_order_list[i]->node_id() << " "; + } + + std::cout << std::endl; sort_adj_list(); determine_edges(); back_edge_traversal(); diff --git a/deferred_planarity_test/node.cpp b/deferred_planarity_test/node.cpp index 8e36f4f..0433ecf 100644 --- a/deferred_planarity_test/node.cpp +++ b/deferred_planarity_test/node.cpp @@ -66,6 +66,103 @@ void node::DFS_visit(vector &dfsList, int &index) { ++index; } + +void node::guided_DFS_visit(vector &dfsList, vector &node_list, int &index, vector rev_post_order) { + mark(); + // you will want to sort the neighbor nodes by the order they appear in the rev_post_order + vector neighbor_list; + std::unordered_set neighbor_set; + + // create an unordered set to efficiently check for presence of an element + 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 + for (int i = 0; i < rev_post_order.size(); ++i) { + if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) { + neighbor_list.push_back(node_list[rev_post_order[i]]); + } + } + + // print the neighbors + // std::cout << "current index: " << this->node_id() << std::endl; + // for (int i = 0; i < neighbor_list.size(); ++i) { + // std::cout << neighbor_list[i]->node_id() << " "; + // } + // std::cout << std::endl; + + set_post_order_index(index); + dfsList.push_back(this); + ++index; + + for (int i = 0; i < neighbor_list.size(); ++i) { + if (!neighbor_list[i]->is_marked()) { + neighbor_list[i]->_parent = this; + neighbor_list[i]->guided_DFS_visit(dfsList, node_list, index, rev_post_order); + } + } +} + + +void node::mutated_DFS_visit(vector &dfsList, vector &node_list, int &index, vector rev_post_order, int &mutate_point) { + mark(); + // you will want to sort the neighbor nodes by the order they appear in the rev_post_order + vector neighbor_list; + std::unordered_set neighbor_set; + + // create an unordered set to efficiently check for presence of an element + 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 + for (int i = 0; i < rev_post_order.size(); ++i) { + if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) { + neighbor_list.push_back(node_list[rev_post_order[i]]); + } + } + + // print the neighbors + std::cout << "current index: " << this->node_id() << std::endl; + for (int i = 0; i < neighbor_list.size(); ++i) { + std::cout << neighbor_list[i]->node_id() << " "; + } + std::cout << std::endl; + + set_post_order_index(index); + dfsList.push_back(this); + ++index; + + if (index - 1 == mutate_point) { + // Create a random number generator and seed it + std::cout << "mutated at index: " << index - 1<< "and at mutate point: " << mutate_point << std::endl; + std::random_device rd; + std::mt19937 rng(rd()); + // Use std::shuffle to shuffle the elements in the vector + std::shuffle(neighbor_list.begin(), neighbor_list.end(), rng); + // print the neighbors + std::cout << "order after mutation: " << std::endl; + std::cout << "current index: " << this->node_id() << std::endl; + for (int i = 0; i < neighbor_list.size(); ++i) + { + std::cout << neighbor_list[i]->node_id() << " "; + } + std::cout << std::endl; + } + + for (int i = 0; i < neighbor_list.size(); ++i) + { + if (!neighbor_list[i]->is_marked()) + { + neighbor_list[i]->_parent = this; + neighbor_list[i]->mutated_DFS_visit(dfsList, node_list, index, rev_post_order, mutate_point); + } + } +} + + + //----------------------------------------------------------------------------------- // PARENT-CHILDREN //-----------------------------------------------------------------------------------