From 446ba9ed1e41768c01dc9dd496c39ceaf04a302a Mon Sep 17 00:00:00 2001 From: Richard Wong Date: Tue, 6 Feb 2024 10:58:38 +0900 Subject: [PATCH] Feat: implemented mutate_point to measure separation of removed back-edges based on mutated and preserved sections --- README.md | 2 + deferred_planarity_test/include/mps.h | 23 +++-- deferred_planarity_test/src/main.cpp | 64 ++++++------- deferred_planarity_test/src/mps.cpp | 48 ++++++---- deferred_planarity_test/src/mps_test.cpp | 111 ++++++++++++++++++++--- deferred_planarity_test/src/node.cpp | 24 +++-- 6 files changed, 192 insertions(+), 80 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..bd778cc --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +The objective of this branch is to measure the number of removed edges between +preserved and mutated parts of the DFS tree. diff --git a/deferred_planarity_test/include/mps.h b/deferred_planarity_test/include/mps.h index d70fc1d..3378441 100644 --- a/deferred_planarity_test/include/mps.h +++ b/deferred_planarity_test/include/mps.h @@ -33,6 +33,12 @@ enum node_type { AE_VIRTUAL_ROOT = 3 }; +enum back_edge_type { + RETAINED = 0, + MUTATED_REMOVE = 1, + NON_MUTATED_REMOVE = 2 +}; + class node { public: @@ -57,7 +63,7 @@ public: 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); + 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) ; @@ -147,14 +153,18 @@ public: maximal_planar_subgraph_finder(); ~maximal_planar_subgraph_finder(); int find_mps(string input_file); - int compute_removed_edge_size(string input_file, vector post_order); + int compute_removed_edge_size(string input_file, vector post_order, int mutate_point); + void print_removed_edge_size(string input_file, vector post_order, int mutate_point); vector generate_post_order(string input_file); - vector generate_mutated_post_order(string input_file, vector post_order); + vector generate_mutated_post_order(string input_file, vector post_order, int mutate_point); + void set_mutate_point(int mutate_point); + int get_mutate_point(); node* get_new_node(node_type t); void read_from_gml(string input_file); - int output_removed_edge_size(); + void output_print_removed_edge_size(); + int output_int_removed_edge_size(); vector postOrderTraversal(); - vector mutatedPostOrderTraversal(vector post_order); + vector mutatedPostOrderTraversal(vector post_order, int mutate_point); void guidedPostOrderTraversal(vector post_order); void set_post_order(vector post_order); void sort_adj_list(); @@ -182,8 +192,9 @@ private: vector > _edge_list; // Edges in DFS-tree. These edges must be contained in the maximal planar subgraph that we found. vector _post_order_list; //The sorted version (increasing with post-order-index) of _node_list. vector > _back_edge_list; // Edges other than that in DFS-tree. (The first node's index is higher than the second's.) - vector _is_back_edge_eliminate; //Record that if the back-edge has been eliminated or not. + vector _is_back_edge_eliminate; //Record that if the back-edge has been eliminated or not. vector _new_node_list; //Newly added nodes. + int _mutate_point; // store the mutate_point }; #endif diff --git a/deferred_planarity_test/src/main.cpp b/deferred_planarity_test/src/main.cpp index cce7b9d..138f407 100644 --- a/deferred_planarity_test/src/main.cpp +++ b/deferred_planarity_test/src/main.cpp @@ -11,52 +11,52 @@ #include #include #include - #include -#define START_TEMP 100 using namespace std; -int compute_removed_edge_size(string input_file, vector post_order); +int compute_removed_edge_size(string input_file, vector post_order, int mutate_point); + +void print_removed_edge_size(string input_file, vector post_order, int mutate_point); vector generate_post_order(string input_file); -vector generate_mutated_post_order(string input_file, vector post_order); -double temp_decay(int k, int k_max) { - return 1.0 - ((k + 1.0) / (k_max)); -} +vector generate_mutated_post_order_at_x(string input_file, vector post_order, int mutate_point); -vector sa_solve(string input_file, int k_max) { - // create sampling function - std::random_device rd; - std::mt19937 rng(rd()); - std::uniform_real_distribution<> distribution(0.0, 1.0); +void measure_removed_edges(string input_file, int k_max, int mutate_point) { // generate first state vector state_old = generate_post_order(input_file); vector state_new; - int e_old = compute_removed_edge_size(input_file, state_old); - int e_new = 0; - int delta = 0; - // initialize terms - double temp; + + std::cout << "first generated order" << std::endl; + for (int i = 0; i < state_old.size(); i++) { + std::cout << state_old[i] << ", "; + } + std::cout << std::endl; + + int removed_old; + int removed_new; for (int k = 0; k < k_max; ++k) { - temp = START_TEMP * temp_decay(k, k_max); + std::cout << std::endl; + std::cout << "new generated order" << std::endl; + state_new = generate_mutated_post_order_at_x(input_file, state_old, mutate_point); + removed_old = compute_removed_edge_size(input_file, state_old, mutate_point); + removed_new = compute_removed_edge_size(input_file, state_new, mutate_point); + // for (int i = 0; i < state_new.size(); i++) { + // std::cout << state_new[i] << ", "; + // } + // std::cout << std::endl; + + std::cout << "removed edges in old: " << removed_old << std::endl; + std::cout << "removed edges in new: " << removed_new << std::endl; + print_removed_edge_size(input_file, state_new, mutate_point); - state_new = generate_mutated_post_order(input_file, state_old); - e_new = compute_removed_edge_size(input_file, state_new); - delta = e_new - e_old; - if (std::exp( -(delta) / temp) > distribution(rng)) { - state_old = state_new; - e_old = e_new; - } } - return state_old; - } int get_graph_size(string input_file) { @@ -78,16 +78,10 @@ int get_graph_size(string input_file) { int main(int argc, char* argv[]) { string input_file = argv[1]; int k_max = std::stoi(argv[2]); + int mutate_point = std::stoi(argv[3]); // generate order here - vector post_order = sa_solve(input_file, k_max); - - // 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; + measure_removed_edges(input_file, k_max, mutate_point); return 0; } diff --git a/deferred_planarity_test/src/mps.cpp b/deferred_planarity_test/src/mps.cpp index ab5a1ce..37ebdea 100644 --- a/deferred_planarity_test/src/mps.cpp +++ b/deferred_planarity_test/src/mps.cpp @@ -3,6 +3,7 @@ //----------------------------------------------------------------------------------- #include "mps.h" +#include // constructor can be made empty maximal_planar_subgraph_finder::maximal_planar_subgraph_finder() {} @@ -19,6 +20,18 @@ maximal_planar_subgraph_finder::get_new_node(node_type t) { return _new_node_list[_new_node_list.size()-1]; } +// setter and getter for mutate_point +void +maximal_planar_subgraph_finder::set_mutate_point(int mutate_point) { + _mutate_point = mutate_point; +} + +int +maximal_planar_subgraph_finder::get_mutate_point() { + return _mutate_point; +} + + //Determine the post-order-list by a DFS-traversal. vector maximal_planar_subgraph_finder::postOrderTraversal() { @@ -73,7 +86,7 @@ maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector post_order) //Determine the post-order-list by a DFS-traversal. vector -maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector post_order) { +maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector post_order, int mutate_point) { node::init_mark(); vector rev_post_order; @@ -83,26 +96,14 @@ maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector post_order 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; + assert(mutate_point < n); // 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) @@ -173,7 +174,7 @@ maximal_planar_subgraph_finder::determine_edges() { if (_post_order_list[i]->adj(j)->post_order_index() > i) break; if (_post_order_list[i]->adj(j)->get_1st_label() == i) continue; _back_edge_list.push_back(pair (_post_order_list[i], _post_order_list[i]->adj(j))); - _is_back_edge_eliminate.push_back(false); + _is_back_edge_eliminate.push_back(RETAINED); } } for (int i = 0; i < _post_order_list.size(); ++i) { @@ -186,10 +187,25 @@ void maximal_planar_subgraph_finder::back_edge_traversal() { node* i_node = 0; node* current_node = 0; + int dfs_mutate_point = get_mutate_point() + 1; + int node_list_last_index = _node_list.size() - 1; + int post_order_mutate_point = node_list_last_index - dfs_mutate_point; + std::cout << "post_order_mutate_point: " << post_order_mutate_point << std::endl; + // back_edge first node is higher than the second for (int i = 0; i < _back_edge_list.size(); ++i) { current_node = _back_edge_list[i].second; i_node = _back_edge_list[i].first; - if (!back_edge_traversal(current_node, i_node->post_order_index())) _is_back_edge_eliminate[i] = true; + // back_edge_traversal returns true if it should be included + // false otherwise + if (!back_edge_traversal(current_node, i_node->post_order_index())) { + // if current_node is higher than post_order_mutate_point + // then it is the preserved section + if (current_node->post_order_index() > post_order_mutate_point) { + _is_back_edge_eliminate[i] = NON_MUTATED_REMOVE; + } else { + _is_back_edge_eliminate[i] = MUTATED_REMOVE; + } + } } } diff --git a/deferred_planarity_test/src/mps_test.cpp b/deferred_planarity_test/src/mps_test.cpp index fec6000..ee1fbb2 100644 --- a/deferred_planarity_test/src/mps_test.cpp +++ b/deferred_planarity_test/src/mps_test.cpp @@ -4,21 +4,29 @@ #include "mps.h" #include +#include +#include + //----------------------------------------------------------------------------------- // Finding MPS //----------------------------------------------------------------------------------- -// programs to call from main: +// functions to call from main: int find_mps(string input_file) { maximal_planar_subgraph_finder m; return m.find_mps(input_file); } -int compute_removed_edge_size(string input_file, vector post_order) { +int compute_removed_edge_size(string input_file, vector post_order, int mutate_point) { maximal_planar_subgraph_finder m; - return m.compute_removed_edge_size(input_file, post_order); + return m.compute_removed_edge_size(input_file, post_order, mutate_point); +} + +void print_removed_edge_size(string input_file, vector post_order, int mutate_point) { + maximal_planar_subgraph_finder m; + m.print_removed_edge_size(input_file, post_order, mutate_point); } vector generate_post_order(string input_file) { @@ -26,13 +34,13 @@ vector generate_post_order(string input_file) { return m.generate_post_order(input_file); } -vector generate_mutated_post_order(string input_file, vector post_order) { +vector generate_mutated_post_order_at_x(string input_file, vector post_order, int mutate_point) { maximal_planar_subgraph_finder m; - return m.generate_mutated_post_order(input_file, post_order); + return m.generate_mutated_post_order(input_file, post_order, mutate_point); } -// --------- +// immediate functions called by functions called from main int maximal_planar_subgraph_finder::find_mps(string input_file) { read_from_gml(input_file); @@ -40,22 +48,25 @@ int maximal_planar_subgraph_finder::find_mps(string input_file) { sort_adj_list(); determine_edges(); back_edge_traversal(); - return output_removed_edge_size(); + return output_int_removed_edge_size(); } vector maximal_planar_subgraph_finder::generate_post_order(string input_file) { read_from_gml(input_file); + set_mutate_point(INT_MAX); // essentially removed mutate_point return postOrderTraversal(); } -vector maximal_planar_subgraph_finder::generate_mutated_post_order(string input_file, vector post_order) { +vector maximal_planar_subgraph_finder::generate_mutated_post_order(string input_file, vector post_order, int mutate_point) { read_from_gml(input_file); - return mutatedPostOrderTraversal(post_order); + set_mutate_point(INT_MAX); + return mutatedPostOrderTraversal(post_order, mutate_point); } -int maximal_planar_subgraph_finder::compute_removed_edge_size(string input_file, vector post_order) { +int maximal_planar_subgraph_finder::compute_removed_edge_size(string input_file, vector post_order, int mutate_point) { read_from_gml(input_file); + set_mutate_point(mutate_point); guidedPostOrderTraversal(post_order); // let's reverse the order @@ -74,11 +85,38 @@ int maximal_planar_subgraph_finder::compute_removed_edge_size(string input_file, sort_adj_list(); determine_edges(); back_edge_traversal(); - return output_removed_edge_size(); + return output_int_removed_edge_size(); } +void maximal_planar_subgraph_finder::print_removed_edge_size(string input_file, vector post_order, int mutate_point) { + read_from_gml(input_file); + set_mutate_point(mutate_point); + 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(); + output_print_removed_edge_size(); +} + + + + //----------------------------------------------------------------------------------- -// Imput, output +// Input, output //----------------------------------------------------------------------------------- @@ -97,6 +135,14 @@ void maximal_planar_subgraph_finder::read_from_gml(string input_file) { _node_list[i]->set_id(i); } + // vector unique_edges; + // // we want to get unique edge only + // for (ogdf::edge e : G.edges) { + // // Check if the edge is already in the array + // if (std::find(unique_edges.begin(), unique_edges.end(), e) == unique_edges.end()) + // unique_edges.push_back(e); + // } + // create edges for (ogdf::edge e : G.edges) { ogdf::node source = e->source(); @@ -109,10 +155,47 @@ void maximal_planar_subgraph_finder::read_from_gml(string input_file) { // count the number of removed edges -int maximal_planar_subgraph_finder::output_removed_edge_size() { +void maximal_planar_subgraph_finder::output_print_removed_edge_size() { + int mutated_sum = 0; + int preserved_sum = 0; + + vector> mutated_removed_edges; + vector> preserved_removed_edges; + + for (int i = 0; i < _back_edge_list.size(); ++i) { + if (_is_back_edge_eliminate[i] == MUTATED_REMOVE) { + mutated_removed_edges.push_back(_back_edge_list[i]); + ++mutated_sum; + } + if (_is_back_edge_eliminate[i] == NON_MUTATED_REMOVE) { + preserved_removed_edges.push_back(_back_edge_list[i]); + ++preserved_sum; + } + } + + // print the edges + // std::cout << "mutated removed edges: " << std::endl; + // for (int i = 0; i < mutated_removed_edges.size(); ++i) { + // std::cout << mutated_removed_edges[i].first->node_id() << ", " << + // mutated_removed_edges[i].second->node_id() << std::endl; + // } + + // std::cout << "preserved removed edges: " << std::endl; + // for (int i = 0; i < preserved_removed_edges.size(); ++i) { + // std::cout << preserved_removed_edges[i].first->node_id() << ", " << + // preserved_removed_edges[i].second->node_id() << std::endl; + // } + + std::cout << "<- sum of removed edges -> " << std::endl; + std::cout << "mutated portion: " << mutated_sum << std::endl; + std::cout << "preserved portion: " << preserved_sum << std::endl; +} + +int maximal_planar_subgraph_finder::output_int_removed_edge_size() { int sum = 0; for (int i = 0; i < _back_edge_list.size(); ++i) { - if (_is_back_edge_eliminate[i]) ++sum; + if (_is_back_edge_eliminate[i] != RETAINED) ++sum; } + return sum; } \ No newline at end of file diff --git a/deferred_planarity_test/src/node.cpp b/deferred_planarity_test/src/node.cpp index e134d0d..5e7a20b 100644 --- a/deferred_planarity_test/src/node.cpp +++ b/deferred_planarity_test/src/node.cpp @@ -105,7 +105,7 @@ void node::guided_DFS_visit(vector &dfsList, vector &node_list, in } -void node::mutated_DFS_visit(vector &dfsList, vector &node_list, int &index, vector rev_post_order, int &mutate_point) { +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; @@ -134,21 +134,27 @@ void node::mutated_DFS_visit(vector &dfsList, vector &node_list, i dfsList.push_back(this); ++index; + // we have reached the mutate point + // we change the order of the neighbor list just before the mutate point + // so that the mutation begins at the mutate point 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; + + // print the neighbors + // print the neighbors that are not yet marked + std::cout << "current index: " << index - 1 << std::endl; + std::cout << "order after mutation: "; + for (int i = 0; i < neighbor_list.size(); ++i) { + if (!neighbor_list[i]->is_marked()) + std::cout << neighbor_list[i]->node_id() << " "; + } + std::cout << std::endl; } for (int i = 0; i < neighbor_list.size(); ++i)