From 850255fab2ecf13178b4257d878a4945f897a47d Mon Sep 17 00:00:00 2001 From: Richard Wong Date: Mon, 6 May 2024 16:21:09 +0900 Subject: [PATCH] Chore: re-organized to only have folders relevant to benchmarking --- .gitignore | 6 +- README.md | 1 - deferred_planarity_test/include/mps.h | 215 ------ deferred_planarity_test/makefile | 34 - deferred_planarity_test/src/main.cpp | 111 --- deferred_planarity_test/src/mps.cpp | 885 ----------------------- deferred_planarity_test/src/mps_test.cpp | 186 ----- deferred_planarity_test/src/node.cpp | 388 ---------- 8 files changed, 1 insertion(+), 1825 deletions(-) delete mode 100644 README.md delete mode 100644 deferred_planarity_test/include/mps.h delete mode 100644 deferred_planarity_test/makefile delete mode 100644 deferred_planarity_test/src/main.cpp delete mode 100644 deferred_planarity_test/src/mps.cpp delete mode 100644 deferred_planarity_test/src/mps_test.cpp delete mode 100644 deferred_planarity_test/src/node.cpp diff --git a/.gitignore b/.gitignore index 7cfc30d..69b046a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,7 @@ .vscode -deferred_planarity_test/build make_graphs/bin make_graphs/test_graphs make_planar/bin test_area dpt - -# remove build intermediate files -deferred_planarity_test/obj/ -deferred_planarity_test/bin/ +graph_datasets diff --git a/README.md b/README.md deleted file mode 100644 index 9ead933..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -This branch tests the idea of using fuzzing to choose the direction of mutation diff --git a/deferred_planarity_test/include/mps.h b/deferred_planarity_test/include/mps.h deleted file mode 100644 index ce2ebb7..0000000 --- a/deferred_planarity_test/include/mps.h +++ /dev/null @@ -1,215 +0,0 @@ -//----------------------------------------------------------------------------------- -// Header for modules: mps.cpp, mps_test.cpp, node.cpp. -//----------------------------------------------------------------------------------- - -#ifndef _MPS_H -#define _MPS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -class node; -class maximal_planar_subgraph_finder; - -enum label { - NOT_VISITED = 0, - ARTIFICIAL_EDGE = 1, - BOUNDARY_PATH = 2, - DELETED = 3 -}; - -enum node_type { - P_NODE = 0, - C_NODE = 1, - REPLICA_NODE = 2, - AE_VIRTUAL_ROOT = 3 -}; - -class node -{ -public: - //CONSTRUCTOR - node(node_type t); - - //DESTRUCTOR - ~node() {} - - //TYPE, ID, INDEX - node_type type(); - int post_order_index(); - void set_id(int i); - void set_post_order_index(int i); - void recursively_labeling(); - int node_id(); - - //DFS-TREE - void add_adj(node* n); - int degree(); - node* adj(int i); - void set_adj_list(vector vec); - void DFS_visit(vector &dfsList, int &index); - void guided_DFS_visit(vector &dfsList, - const vector &node_list, - int &return_index, - const unordered_map &node_id_to_pos); - void mutated_DFS_visit(vector &dfsList, - const vector &node_list, - int &index, - int &traversal_index, - const unordered_map &node_id_to_pos, - int mutate_point, - mt19937 rng); - - // custom comparator function to sort nodes according to order in given vector - bool sortByOrder(const unordered_map& node_id_to_pos, node* a, node* b); - - //PARENT-CHILDREN - void set_parent(node* n) ; - node* parent(); - int child_num(); - node* child(int i); - void add_child(node* n); - void clear_children(); - void remove_child(int i); - void remove_child(node* n); - vector* get_children_list(); - - //BOUNDARY_PATH - void set_to_boundary_path(node* n0, node* n1); - void set_neighbor(int i, node* n); - void set_neighbor(node* u, node* v); - node* neighbor(int i); - node* get_next(node* prev); - - //ARTIFICIAL EDGE - node* AE(int i); - void set_AE(int i, node* j); - void add_AE(node* j); - void inherit_AE(node* u); - void init_AE(node* u); - - //REPLICA - node* original_node(); - node* get_c_node(); - void set_c_node(node* c); - bool is_sentinel(); - static bool is_same(node* n1, node* n2); - void init_replica(node* u, node* c); - - //LABELING - void set_1st_label(int i); - void set_2nd_label(label i); - int get_1st_label(); - label get_2nd_label(); - - //C-NODE - node* get_a_list_node(); - int c_node_size(); - node* essential(int i); - void clear_essential(); - void add_essential(node* u); - - //MARK - void mark(); - static void init_mark(); - void un_mark(); - bool is_marked(); - -private: - //Basic information. - node_type _type; - pair _label; - - //Information about neighborhood. - node* _neighbor[2]; - node* _AE_root[2]; - - //Information about higher hierarchy. - node* _original_node; - node* _c_node; - - //Information about parent-children relation. - node* _parent; - vector _children; - - //Information about about p-nodes in DFS-tree - vector _adj_list; - int _post_order_index; - int _node_id; - - //List of essential nodes in c-node - vector _essential_list; - - //Mark - int _mark; - static int _ref_mark; -}; - -class maximal_planar_subgraph_finder -{ -public: - maximal_planar_subgraph_finder(); - ~maximal_planar_subgraph_finder(); - - // functions that prepare state - void init_from_graph(const ogdf::Graph &G); - vector generate_post_order(const ogdf::Graph &G); - vector generate_mutated_post_order(const ogdf::Graph &G, const vector &post_order, int mutate_point); - vector generate_guided_post_order(const ogdf::Graph &G, const vector &post_order); - void postOrderTraversal(); - void guidedPostOrderTraversal(const vector &post_order); - void mutatedPostOrderTraversal(const vector &post_order, int mutate_point); - - // compute_mps combines functionality to reduce repeating object initialization - // the results are returned by modifying mutable reference - void compute_mps(const ogdf::Graph &G, int mutate_point, vector &post_order, int &return_edge_size); - - int find_mps(const ogdf::Graph &G); - int compute_removed_edge_size(const ogdf::Graph &G, vector post_order); - node* get_new_node(node_type t); - void reset_state(); - int output_removed_edge_size(); - vector return_post_order(); - // void set_post_order(vector post_order); - void print_post_order(); - void sort_adj_list(); - void determine_edges(); - void back_edge_traversal(); - bool back_edge_traversal(node* traverse_node, int index); - void make_essential(node* p_node, node* c_node); - node* find(node* n); - void merge(pair, pair > boundary, node* list_node); - void eliminate(node* u); - void eliminate_AE(node* u, node* v); - pair, pair > trim(node* u); - void c_node_extension(node* c_node); - void recursively_shaving(node* u); - pair shave(node* x); - pair parallel_search_sentinel(node* x, node* &c); - pair parallel_search_sentinel(node* n0, node* n0_prev, node* n1, node* n1_prev, node* & c); - pair count_sentinel_elimination(pair sentinel_1, int num_sentinel); - node* construct(node* u); - node* construct(node* c, node* p); - void parenting_labeling_shaving(node* u, node* node_i) ; - -private: - vector _node_list; //List of nodes input. - 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 _new_node_list; //Newly added nodes. -}; - -#endif // for MPS_H diff --git a/deferred_planarity_test/makefile b/deferred_planarity_test/makefile deleted file mode 100644 index 934e95b..0000000 --- a/deferred_planarity_test/makefile +++ /dev/null @@ -1,34 +0,0 @@ -SRC_DIR := src -OBJ_DIR := obj -BIN_DIR := bin - -TARGET := $(BIN_DIR)/dpt_planarizer -SRCS := $(wildcard $(SRC_DIR)/*.cpp) -OBJS := $(SRCS:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o) -DEPS := $(OBJS:.o=.d) - -# compiler and flags -CXX := g++ -CPPFLAGS := -Iinclude -MMD -MP -CXXFLAGS := -std=c++14 -Wall -LDFLAGS := -lOGDF - -build: $(TARGET) - -# build target executable -$(TARGET): $(OBJS) | $(BIN_DIR) - $(CXX) $^ -o $@ $(LDFLAGS) - -# compile source to object files -$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ - -$(BIN_DIR) $(OBJ_DIR): - mkdir -p $@ - -# include dependency files --include $(DEPS) - -.PHONY: clean -clean: - rm -r $(OBJ_DIR) diff --git a/deferred_planarity_test/src/main.cpp b/deferred_planarity_test/src/main.cpp deleted file mode 100644 index f28306a..0000000 --- a/deferred_planarity_test/src/main.cpp +++ /dev/null @@ -1,111 +0,0 @@ -//----------------------------------------------------------------------------------- -// A simple code that test the MPS algorighm. -//----------------------------------------------------------------------------------- - -#include "mps.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#define START_TEMP 100 -// #define TIME - -using namespace std; - -int compute_removed_edge_size(const ogdf::Graph &G, vector post_order); - -// these functions are defined in mps_test.cpp -// but their signatures are not in mps.h, hence they are declared here -ogdf::Graph read_from_gml(string input_file); -vector generate_post_order(const ogdf::Graph &G); -vector generate_mutated_post_order(const ogdf::Graph &G, vector post_order, int mutate_point); -vector generate_guided_post_order(const ogdf::Graph &G, vector post_order); -void compute_mps(const ogdf::Graph &G, int mutate_point, vector &post_order, int &return_edge_size); - -void vector_printer(const vector& state) { - for (size_t i = 0; i < state.size(); ++i) { - std::cout << state[i] << ","; - } - std::cout << std::endl; -} - - -vector repeated_mutation(const ogdf::Graph &G, int k_max) { - // generate first post order - // std::cout << "generate first post order" << std::endl; - vector old_order = generate_post_order(G); - vector_printer(old_order); - vector temp_order = old_order; - int new_removed_size; - int old_removed_size = INT_MAX; - - // prepare random selection - std::random_device rd; - std::mt19937 gen{rd()}; // seed the generator - int first_value = 0; - // we want the index of the third last value - // at a given traversal index, only the next iteration has the mutated value - int last_value = (old_order.size() - 1) - 2; - std::uniform_int_distribution<> dist{first_value, last_value}; // set min and max - - for (int k = 0; k < k_max; ++k) { - // function compute new post_order and new_removed_size - // temp_order and new_removed_size will be updated with new values - - #ifdef TIME - auto start = std::chrono::high_resolution_clock::now(); - #endif - compute_mps(G, dist(gen), temp_order, new_removed_size); - #ifdef TIME - auto end = std::chrono::high_resolution_clock::now(); - std::cout << "compute_mps: " << std::chrono::duration_cast(end - start).count() << std::endl; - #endif - - // if there is an improvement - // 1. update the removed size to use the new smaller size - // 2. update the old_order to be the new_order - if (new_removed_size < old_removed_size) { - old_removed_size = new_removed_size; - old_order = temp_order; - // if there is no improvement, we revert the temp_order to the old_order - } else { - temp_order = old_order; - } - } - return old_order; -} - - -//----------------------------------------------------------------------------------- -// Main function. -//----------------------------------------------------------------------------------- - - -int main(int argc, char* argv[]) { - string input_file = argv[1]; - int k_max = std::stoi(argv[2]); - - const ogdf::Graph G = read_from_gml(input_file); - - // generate order here - vector post_order = repeated_mutation(G, k_max); - - // test timing of function - // test_correctness(G); - - // // print final order and number of edges - std::cout << "---" << std::endl; - std::cout << "final report" << std::endl; - std::copy(post_order.begin(), post_order.end(), std::ostream_iterator(std::cout, ",")); - std::cout << std::endl; - int removed_edges = compute_removed_edge_size(G, post_order); - std::cout << "Number of removed edges: " << removed_edges << std::endl; - - return 0; -} diff --git a/deferred_planarity_test/src/mps.cpp b/deferred_planarity_test/src/mps.cpp deleted file mode 100644 index 8c27ff9..0000000 --- a/deferred_planarity_test/src/mps.cpp +++ /dev/null @@ -1,885 +0,0 @@ -//----------------------------------------------------------------------------------- -// Implementation of a MPS algorithm via PC-tree. -//----------------------------------------------------------------------------------- - -#include "mps.h" - -// #define DEBUG - -// constructor can be made empty -maximal_planar_subgraph_finder::maximal_planar_subgraph_finder() {} - -//Destructor -maximal_planar_subgraph_finder::~maximal_planar_subgraph_finder() { - for (size_t i = 0; i < _node_list.size(); ++i) delete _node_list[i]; - for (size_t i = 0; i < _new_node_list.size(); ++i) delete _new_node_list[i]; -} - -node* -maximal_planar_subgraph_finder::get_new_node(node_type t) { - _new_node_list.push_back(new node(t)); - return _new_node_list[_new_node_list.size()-1]; -} - -vector -maximal_planar_subgraph_finder::return_post_order() { - vector post_order; - // we have arg number of elements - post_order.reserve(_post_order_list.size()); // reserve for decreased reallocation - for (size_t 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::postOrderTraversal() { - node::init_mark(); - // always start with node 0 - int postOrderID = 0; - for (size_t i = 0; i < _node_list.size(); ++i) { - if (!_node_list[i]->is_marked()) { - _node_list[i]->DFS_visit(_post_order_list, postOrderID); - } - } -} - - -// Determine the post-order-list by a DFS-traversal. -// take in a post-order argument then traces the graph in the same order -// return is by reference via _post_order_list -void -maximal_planar_subgraph_finder::guidedPostOrderTraversal(const vector &post_order) { - node::init_mark(); - - // // implementation 1: pass reversed vector - // vector rev_post_order; - // for (int i = post_order.size() - 1; i >= 0; --i) { - // rev_post_order.push_back(post_order[i]); - // } - // int start = rev_post_order[0]; - - - // implementation 2: use unordered_map to map node_id to position in reversed post_order - unordered_map node_id_to_pos; - node_id_to_pos.reserve(post_order.size()); - int j = 0; - // we flip the post_order vector around - for (size_t i = post_order.size() - 1; i != std::numeric_limits::max(); --i) { - node_id_to_pos[post_order[i]] = j++; - } - - int postOrderID = 0; - int end_condition = _node_list.size(); - // we start from the end of the post_order, which is the root node - int start = post_order[post_order.size() - 1]; - int i = start; - - // reserve for _post_order_list to decrease reallocation - _post_order_list.reserve(_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]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, node_id_to_pos); - } - break; - } - if (!_node_list[i]->is_marked()) - { - _node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, node_id_to_pos); - } - i = (i + 1) % end_condition; - } -} - -//Determine the post-order-list by a DFS-traversal. -// take in a post-order argument then traces the graph in the same order -// return is by reference via _post_order_list -void -maximal_planar_subgraph_finder::mutatedPostOrderTraversal(const vector &post_order, int mutate_point) { - node::init_mark(); - - // // implementation 1: use vector - // vector rev_post_order; - // for (size_t i = post_order.size() - 1; i != std::numeric_limits::max(); --i) { - // rev_post_order.push_back(post_order[i]); - // } - - // implementation 2: use unordered_map to map node_id to position in reversed post_order - unordered_map node_id_to_pos; - node_id_to_pos.reserve(post_order.size()); - int j = 0; - // we flip the post_order vector around - for (size_t i = post_order.size() - 1; i != std::numeric_limits::max(); --i) { - node_id_to_pos[post_order[i]] = j++; - } - - int postOrderID = 0; - int traversal_index = 0; - - // setup random rng function - std::random_device rd; - std::mt19937 rng{rd()}; - - - int start = 0; - // if we mutate first node, we will select a random starting node - if (mutate_point == 0) { - int first_value = 0; - int last_value = post_order.size() - 1; - std::uniform_int_distribution<> dist{first_value, last_value}; - start = post_order[dist(rng)]; - // if we don't mutate first, we just use the root node of the post_order - } else { - start = post_order[post_order.size() - 1]; - } - - // set loop variables - int i = start; - - // reserve for _post_order_list to decrease reallocation - _post_order_list.reserve(_node_list.size()); - - - int end_condition = _node_list.size(); - // this loop assumes start is not from 0 - // if starting index is not 0, it just increments and loops around until it encounters the element before it - 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, traversal_index, node_id_to_pos, mutate_point, rng); - } - break; - } - if (!_node_list[i]->is_marked()) - { - _node_list[i]->mutated_DFS_visit(_post_order_list, _node_list, postOrderID, traversal_index, node_id_to_pos, mutate_point, rng); - } - i = (i + 1) % end_condition; - } -} - -void -maximal_planar_subgraph_finder::print_post_order() { - int current_index; - for (size_t i = 0; i < _post_order_list.size(); ++i) { - current_index = _post_order_list[i]->node_id(); - std::cout << current_index << ","; - } - std::cout << std::endl; -} - - -// this function is not used anywhere -//Set the post-order-list via given list -// void -// maximal_planar_subgraph_finder::set_post_order(vector post_order) { -// for (int i = 0; i < _node_list.size(); ++i) { -// _node_list[i]->set_post_order_index(post_order[i]); -// } -// } - -//Sort the adj-list of every node increasingly according to post-order-index. -void -maximal_planar_subgraph_finder::sort_adj_list() { - vector > vecList; - vecList.resize(_post_order_list.size()); - for (size_t i = 0; i < _post_order_list.size(); ++i) { - for (int j = 0; j < _post_order_list[i]->degree(); ++j) { - vecList[_post_order_list[i]->adj(j)->post_order_index()].push_back(_post_order_list[i]); - } - } - for (size_t i = 0; i < _post_order_list.size(); ++i) { - _post_order_list[i]->set_adj_list(vecList[i]); - } -} - -//Determine edge-list, and back-edge-list. -//Order the edges properly. -void -maximal_planar_subgraph_finder::determine_edges() { - for (size_t i = 0; i < _post_order_list.size(); ++i) { - if (_post_order_list[i]->parent() == 0) continue; - _post_order_list[i]->set_1st_label(_post_order_list[i]->parent()->post_order_index()); - _edge_list.push_back(pair (_post_order_list[i]->parent(), _post_order_list[i])); - } - for (size_t i = 0; i < _post_order_list.size(); ++i) { - for (int j = 0; j < _post_order_list[i]->degree(); ++j) { - if (_post_order_list[i]->adj(j)->post_order_index() > static_cast(i)) break; - if (_post_order_list[i]->adj(j)->get_1st_label() == static_cast(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); - } - } - for (size_t i = 0; i < _post_order_list.size(); ++i) { - _post_order_list[i]->set_1st_label(INT_MAX); - } -} - -//The main part of the whole algorithm: Back-edge-traversal -void -maximal_planar_subgraph_finder::back_edge_traversal() { - node* i_node = 0; - node* current_node = 0; - for (size_t 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; - } -} - -//sub-function for the for-loop of back_edge_traversal(). -bool maximal_planar_subgraph_finder::back_edge_traversal(node* traverse_node, int index) { - node* parent_node; //The next node to traverse. - //If the node has been deleted. - if (traverse_node == 0 || traverse_node->get_2nd_label() == DELETED) { - return false; - } - //We have reached the i-node, stop. - if (traverse_node->post_order_index() == index) { - return true; - } - //Case 1 - if (traverse_node->get_2nd_label() == NOT_VISITED) { - //1.1 - if (traverse_node->get_1st_label() == INT_MAX) { - traverse_node->set_1st_label(index); - parent_node = traverse_node->parent(); - } - //1.2 - else if (traverse_node->get_1st_label() == index) { - return true; - } - //1.3 - else if (traverse_node->get_1st_label() < index) { - parent_node = construct(traverse_node); - traverse_node->set_1st_label(index); - } - } - //Case 2: Find the top-tier c-node. - else { - node* my_c_node = find(traverse_node); - make_essential(traverse_node, my_c_node); - //2.1 - if (my_c_node->get_1st_label() == index) { - parent_node = my_c_node; - } - //2.2 - else if (my_c_node->get_1st_label() < index) { - node* my_c_node_2 = construct(my_c_node, traverse_node); - parent_node = my_c_node_2; - } - traverse_node->set_1st_label(index); - traverse_node->set_2nd_label(NOT_VISITED); - } - if (back_edge_traversal(parent_node, index)) { - if (parent_node != _post_order_list[index]) parent_node->add_child(traverse_node); - return true; - } - else { - eliminate(traverse_node); - return false; - } -} - -//The p_node is originally a normal node in c_node's boundary cycle. -//Now we transfer it to be an essential node by the following steps: -//1. Create a replica-node of p_node to be representative of p_node in c_node. -//2. Take out the p_node from c_node, and then set the parent of p_node to be c_node. -//Note: We are not adding p_node to the c_node's children-list. -void -maximal_planar_subgraph_finder::make_essential(node* p_node, node* c_node) { - node* sentinel = get_new_node(REPLICA_NODE); - node* n0 = p_node->neighbor(0); - node* n1 = p_node->neighbor(1); - sentinel->init_replica(p_node, c_node); - c_node->add_essential(sentinel); - sentinel->set_to_boundary_path(n0, n1); - sentinel->inherit_AE(p_node); - n0->set_neighbor(n0->get_next(p_node), sentinel); - n1->set_neighbor(n1->get_next(p_node), sentinel); - p_node->set_neighbor((node*)0, (node*)0); - p_node->set_parent(c_node); -} - -//Find the top-tier c-node of the input node. -//Note: We don't set the input node to be essential node of the top-tier c-node. -//When terminated, the input node will be in the boundary cycle of top-tier c-node. -node* maximal_planar_subgraph_finder::find(node* n) { - pair, pair > boundary; - node* c_node_new = 0; - int c_node_size = 0; - node* return_node = 0; - if (n->parent() == 0) { - //If n is already a node in boundary cycle. - //Note: n must not be an essential node, otherwise it will never enter the function. - //Find the first(nearest to n) essential node. - boundary.first = parallel_search_sentinel(n, c_node_new); - } - else { - //If n is not a node in boundary cycle. - //It is in an Artificial edge. - //Trim it. - boundary = trim(n); - //Find the first(nearest to n) essential node. - boundary.first = parallel_search_sentinel(boundary.first.first, boundary.first.second, boundary.second.first, boundary.second.second, c_node_new); - } - //Find the c-node in the current hierachy . - //If it is top-tier, return it. - if (c_node_new != 0) return c_node_new; - c_node_new = (boundary.first).first->get_c_node(); - - //If not, find the two nearest essential node, eliminate the rest nodes. - c_node_size = c_node_new->c_node_size(); - boundary.second = count_sentinel_elimination(boundary.first, c_node_size); - //Go to the higher hierachy, and continue to find. - if (c_node_new->get_2nd_label() == ARTIFICIAL_EDGE) { - //A peculiar technic: - //Remove all the children of c_node_new but the one that should remains(Let it be u). - //Remove all other essential nodes, pretend to be a c-node of size equals 2. - //Call find(u). - node* u = 0; - for (int i = 0; i < c_node_new->child_num(); ++i) { - if (node::is_same(boundary.first.first, c_node_new->child(i)) || node::is_same(boundary.second.first, c_node_new->child(i))) { - u = c_node_new->child(i); - } - else eliminate(c_node_new->child(i)); - } - c_node_new->clear_children(); - c_node_new->add_child(u); - c_node_new->clear_essential(); - c_node_new->add_essential(boundary.first.first); - c_node_new->add_essential(boundary.second.first); - return_node = find(u); - } - else return_node = find(c_node_new); - //Merge the part of boundary cycle remains in current hierachy to the top-tier c-node. - merge(boundary, c_node_new); - return return_node; -} - -//The list_node is a c-node. -//The boundary indicates the part of the boundary cycle of c-node needs to be merge to the higher hierachy. -//Replace the list_node by boundary. -//Set list_node to be DELETED. -//Note: We do not eliminate anything in this function. -void -maximal_planar_subgraph_finder::merge(pair, pair > boundary, node* list_node) { - node* n0 = list_node->neighbor(0); - node* n1 = list_node->neighbor(1); - node* s0, * s0_prev; - node* s1, * s1_prev; - if (node::is_same(boundary.first.first, n0)) { - s0 = boundary.first.first; - s0_prev = boundary.first.second; - s1 = boundary.second.first; - s1_prev = boundary.second.second; - } - else { - s0 = boundary.second.first; - s0_prev = boundary.second.second; - s1 = boundary.first.first; - s1_prev = boundary.first.second; - } - if (s0_prev == s1 && s1_prev == s0) { - n0->set_neighbor(n0->get_next(list_node), n1); - n1->set_neighbor(n1->get_next(list_node), n0); - } - else { - n0->set_neighbor(n0->get_next(list_node), s0_prev); - n1->set_neighbor(n1->get_next(list_node), s1_prev); - s0_prev->set_neighbor(s0_prev->get_next(s0), n0); - s1_prev->set_neighbor(s1_prev->get_next(s1), n1); - } - //Inherit AE. - n0->inherit_AE(s0); - n1->inherit_AE(s1); - //Delete c-node - list_node->set_2nd_label(DELETED); -} - -//Set u and its subtree to be DELETED. -//If u has some AE, eliminate them. -//We don't do anything about u's parent, neighborhood.(Only children are affected.) -//If u is a p-node, we don't eliminate anything in the lower hierachy that corresponds to the same p-node. -//If u is a c-node, we eliminate all nodes in u's boundary cycle. -void -maximal_planar_subgraph_finder::eliminate(node* u) { - if (u->get_2nd_label() == DELETED) return; - u->set_2nd_label(DELETED); - if (u->type() == C_NODE) { - node* list_node = u->get_a_list_node(); - node* n0, * n0_prev;; - node* temp = 0; - n0 = list_node; - n0_prev = list_node->neighbor(0); - while (true) { - eliminate(n0); - temp = n0; - n0 = n0->get_next(n0_prev); - n0_prev = temp; - if (n0 == list_node) break; - } - } - else if (u->type() == P_NODE) { - for (int i = 0; i < u->degree(); ++i) { - if (u->adj(i)->post_order_index() < u->post_order_index() && u->adj(i)->get_1st_label() == INT_MAX) eliminate(u->adj(i)); - } - } - if (u->AE(0) != 0) eliminate(u->AE(0)); - if (u->AE(1) != 0) eliminate(u->AE(1)); - for (int i = 0; i < u->child_num(); ++i) { - eliminate(u->child(i)); - } -} - -//Eliminate the AE of(u,v)-link that points to u.(If exists) -void -maximal_planar_subgraph_finder::eliminate_AE(node* u, node* v) { - int v_index = v->post_order_index(); - if (u->AE(0) != 0 && u->AE(0)->get_1st_label() == v_index) { - eliminate (u->AE(0)); - u->set_AE(0, 0); - } - if (u->AE(1) != 0 && u->AE(1)->get_1st_label() == v_index) { - eliminate (u->AE(1)); - u->set_AE(1, 0); - } -} - -//The input node u must not be c-node. -//The traversed node is in the AE = (up <- down). -//The returned boundary = [up, up_prev ..., down_prev, down]. -//Direction: up it higher than down. -pair, pair > -maximal_planar_subgraph_finder::trim(node* u) { - node* up = 0; - node* down = 0; - //Since we may do c-node extension in the future, we need to memorize next in order to deduce prev. - node* up_next = 0; - node* down_next = 0; - node* new_AE_root = 0; - //The index from small to large indicates the path that we traversed, note that u = node_list[0]. - vector node_list; - node* curr = u; - node_list.push_back(u); - //Traverse upward. - while (true) { - curr = curr->parent(); - if (curr->type() == AE_VIRTUAL_ROOT) { - up = curr->parent(); - //case 1: We are in a newly created c-node. - //It has only one AE, and the two neighbor-pointer point to the same one. - if (up->neighbor(0) == up->neighbor(1)) { - down = up->neighbor(0); - up->set_neighbor(down, node_list[node_list.size()-1]); - down->set_neighbor(up, node_list[0]); - curr->remove_child(node_list[node_list.size()-1]); - //There's no other child, just delete the AE. - if (curr->child_num() == 0) { - up->set_AE(0, 0); - up->set_AE(1, 0); - } - } - //case 2: General case. - else { - if (up->neighbor(0)->post_order_index() == curr->get_1st_label()) down = up->neighbor(0); - else down = up->neighbor(1); - up->set_neighbor(up->get_next(down), node_list[node_list.size()-1]); - down->set_neighbor(down->get_next(up), node_list[0]); - curr->remove_child(node_list[node_list.size()-1]); - eliminate_AE(up, down); - } - break; - } - node_list.push_back(curr); - } - //Set the "downward" AE of node_list[0]. - new_AE_root = get_new_node(AE_VIRTUAL_ROOT); - new_AE_root->init_AE(node_list[0]); - //Eliminate the children other than the path. - for (size_t i = 1; i < node_list.size(); ++i) { - for (int j = 0; j < node_list[i]->child_num(); ++j) { - if (node_list[i]->child(j) != node_list[i-1]) eliminate(node_list[i]->child(j)); - } - } - //Set to the boundary path. - if (node_list.size() == 1) node_list[0]->set_to_boundary_path(up, down); - else { - node_list[0]->set_to_boundary_path(down, node_list[1]); - node_list[node_list.size()-1]->set_to_boundary_path(up, node_list[node_list.size()-2]); - for (size_t i = 1; i < node_list.size()-1; ++i) { - node_list[i]->set_to_boundary_path(node_list[i-1], node_list[i+1]); - } - } - //Set the next of up and down. - up_next = up->get_next(node_list[node_list.size()-1]); - down_next = down->get_next(node_list[0]); - //Unfold the c-nodes in the node_list. - for (size_t i = 0; i < node_list.size(); ++i) { - if (node_list[i]->type() == C_NODE) c_node_extension(node_list[i]); - } - //Return the new boundary. - return pair, pair > (pair(up, up->get_next(up_next)), pair(down, down->get_next(down_next))); -} - -//The trim's sub-function. -//The input c-node does not contain any children nor parent, but it has two neighbors, which is originally c-node's parent and one child. -//If c-node's size equals 2, then we don't need to unfold it. -//Otherwise, it must has size equals 3. -//And then we find that redundent essential node, and remove the nodes that need not remains. -//Merge the remain part to the higher hierachy. -void -maximal_planar_subgraph_finder::c_node_extension(node* c_node) { - //size == 2 - if (c_node->c_node_size() == 2) return; - //size == 3 - node* sentinel = 0; - for (int i = 0; i < c_node->c_node_size(); ++i) { - if (!node::is_same(c_node->essential(i), c_node->neighbor(0)) && !node::is_same(c_node->essential(i), c_node->neighbor(1))) { - sentinel = c_node->essential(i); - break; - } - } - eliminate(sentinel); - //The two other essential nodes and their subsequent neighbor. - pair sentinel_0; - pair sentinel_1; - node* n0, * n0_prev = sentinel; - node* n1, * n1_prev = sentinel; - node* temp = 0; - n0 = sentinel->neighbor(0); - n1 = sentinel->neighbor(1); - while (true) {//Toward the direction of n0. - if (n0->is_sentinel()) {//If we meet a essential node, stop, don't remove it. - sentinel_0 = pair (n0, n0->get_next(n0_prev)); - break; - } - eliminate(n0); - temp = n0; - n0 = n0->get_next(n0_prev); - n0_prev = temp; - } - while (true) {//Toward the direction of n0. - if (n1->is_sentinel()) {//If we meet a essential node, stop, don't remove it. - sentinel_1 = pair (n1, n1->get_next(n1_prev)); - break; - } - eliminate(n1); - temp = n1; - n1 = n1->get_next(n1_prev); - n1_prev = temp; - } - - //Remember to remove the AE toward two essential nodes that is in the delete region. - eliminate_AE(sentinel_0.first, sentinel_0.first->get_next(sentinel_0.second)); - eliminate_AE(sentinel_1.first, sentinel_1.first->get_next(sentinel_1.second)); - //Reset the neighborhood of two essential nodes. - sentinel_0.first->set_neighbor(sentinel_1.first, sentinel_0.second); - sentinel_1.first->set_neighbor(sentinel_0.first, sentinel_1.second); - //Merge to upper boundary cycle. - merge(pair, pair >(sentinel_0, sentinel_1), c_node); -} - -//u is a normal p-node. -//We'll do the work of elimination, and renewing of children-list. -void -maximal_planar_subgraph_finder::recursively_shaving(node* u) { - node* parent_node = 0; - node* node_x = 0; - pair new_two_child; - vector new_child_list; - //p-node - if (u->type() == P_NODE) { - for (int i = 0; i < u->child_num(); ++i) recursively_shaving(u->child(i)); - } - //c-node - else { - //We don't need to shave if u has only one child. - if (u->child_num() == 1) { - recursively_shaving(u->child(0)); - return; - } - //More than one child. - parent_node = u->parent(); - //Find node_x, and shave it. - for (int i = 0; i < u->c_node_size(); ++i) { - if (node::is_same(u->essential(i), parent_node)) { - node_x = u->essential(i); - new_two_child = shave(node_x); - break; - } - } - //Reset children-list and essential node. - for (int i = 0; i < u->child_num(); ++i) { - if (node::is_same(u->child(i), new_two_child.first) || node::is_same(u->child(i), new_two_child.second)) new_child_list.push_back(u->child(i)); - else eliminate(u->child(i)); - } - u->clear_children(); - u->clear_essential(); - u->add_essential(node_x); - u->add_essential(new_two_child.first); - u->add_essential(new_two_child.second); - u->add_child(new_child_list[0]); - u->add_child(new_child_list[1]); - for (int i = 0; i < u->child_num(); ++i) recursively_shaving(u->child(i)); - } -} - -//In this function, we only deal with inner part of c-node. -//x,y,z are essential nodes, let y,z be x's nearest essential nodes in w's boundary cycle. -//Anything outside [x,y], and[x,z] will be eliminated. -//Definition of y_prev, z_prev: ..., y, y_prev, ..., x, ..., z_prev, z, ... -//Return pair = (y,z). Note: What we return is the replica-node in the inner part of c-node. -//The work of deleting children will be done by recursively_shaving(). -pair -maximal_planar_subgraph_finder::shave(node* x) { - //c-node. - node* c_node = x->get_c_node(); - //No need to shave if child_num == 1. - if (c_node->child_num() == 1) return pair((node*)0, (node*)0); - //sentinel_1 = (y, y_prev). Note: At this time, c-node must has type equals ARTIFICIAL_EDGE, so no problem here. - pair sentinel_1 = parallel_search_sentinel(x, c_node); - //sentinel_2 = (z, z_prev). Same as above. - pair sentinel_2 = count_sentinel_elimination(sentinel_1, c_node->child_num()); - return pair(sentinel_1.first, sentinel_2.first); -} - -//Use parallel_search to find essential nodes. Return (essential nodes that we find, its prev). -//x is not in the searching region. -//If the c-node found is top-tier, then set all the nodes during searching a pointer to c-node, set c to be that c-node, and return pair be all null. -pair -maximal_planar_subgraph_finder::parallel_search_sentinel(node* x, node* &c) { - node* n0, * n0_prev = x; - node* n1, * n1_prev = x; - n0 = x->neighbor(0); - n1 = x->neighbor(1); - return parallel_search_sentinel(n0, n0_prev, n1, n1_prev, c); -} - -//Another version of parallel search: n0, n0_prev, ..., n1_prev, n1 -//searching region = (...n0] [n1...). Find the nearest essential node. -//return (essential nodes that we find, its prev). -pair -maximal_planar_subgraph_finder::parallel_search_sentinel(node* n0, node* n0_prev, node* n1, node* n1_prev, node* & c) { - node* temp = 0; - vector traversed; - while (true) { - //If c-node is top-tier. - //note: If c points to a c-node traversed in some previous iteration, then it must not be top-tier, so it'll not pass the if-condition. - if (n0->get_c_node() != 0 && n0->get_c_node()->get_2nd_label() == NOT_VISITED) { - c = n0->get_c_node(); - break; - } - if (n1->get_c_node() != 0 && n1->get_c_node()->get_2nd_label() == NOT_VISITED) { - c = n1->get_c_node(); - break; - } - //If an essential-node found. - if (n0->is_sentinel()) return pair(n0, n0_prev); - if (n1->is_sentinel()) return pair(n1, n1_prev); - //Just a normal node.. - traversed.push_back(n0); - traversed.push_back(n1); - temp = n0; - n0 = n0->get_next(n0_prev); - n0_prev = temp; - temp = n1; - n1 = n1->get_next(n1_prev); - n1_prev = temp; - } - - //If the c-node found is top-tier, then assign all the traversed node a pointer to c-node. - for (size_t i = 0; i < traversed.size(); ++i) traversed[i]->set_c_node(c); - return pair((node*)0, (node*)0); -} - -// sentinel_1= (y, y_prev) -// return pair = (z, z_prev) -// ..., y_prev, y,[ ...(contains num_sentinel-2 essential nodes)...], z, z_prev, ... : eliminate the [...] part. -// Which means, num_sentinel = Number of essential nodes in the region [y, z]. -// Note: y, z(Of course, and their prev,) will not be eliminated. -// Note: All the node that correspond to the same one as deleted node in higher hierachy will not be affected. -// The boundary cycle of c-node will be re-connected, AE be properly handled. -// Do nothing outside the c-node. -pair maximal_planar_subgraph_finder::count_sentinel_elimination(pair sentinel_1, int num_sentinel) { - pair sentinel_2; //(z, z_prev) - int count = 1;//Count the essential nodes traversed. - node* n0 = sentinel_1.first->get_next(sentinel_1.second), * n0_prev = sentinel_1.first;//Going one step further. - node* temp = 0; - while (true) { - if (n0->is_sentinel()) { - ++count;//counter - if (count == num_sentinel) {//We have reached y. Note: We will not eleminate y. - sentinel_2.first = n0; - sentinel_2.second = n0->get_next(n0_prev); - break; - } - } - eliminate(n0); - temp = n0; - n0 = n0->get_next(n0_prev); - n0_prev = temp; - } - //Remember to eliminate AE toward two essential nodes that is in the deleted region. - eliminate_AE(sentinel_2.first, sentinel_2.first->get_next(sentinel_2.second)); - eliminate_AE(sentinel_1.first, sentinel_1.first->get_next(sentinel_1.second)); - //Reset neighborhood of two essential nodes. - sentinel_2.first->set_neighbor(sentinel_1.first, sentinel_2.second); - sentinel_1.first->set_neighbor(sentinel_2.first, sentinel_1.second); - return sentinel_2; -} - -//Used when u has label equals , i c-node -> node_i). -//We don't create child-link here. -//Default label of newly contructed c-node is (INT_MAX, NOT_VISITED). -node* -maximal_planar_subgraph_finder::construct(node* u) { - //Basic works. - // int i_label = u->get_1st_label(); // unused - node* node_i = _post_order_list[u->get_1st_label()]; - parenting_labeling_shaving(u, node_i); - - //Get some new nodes. - node* i_sentinel = get_new_node(REPLICA_NODE); - node* u_sentinel = get_new_node(REPLICA_NODE); - node* new_c_node = get_new_node(C_NODE); - node* new_AE_root = get_new_node(AE_VIRTUAL_ROOT); - - //Setting of replica-nodes. - i_sentinel->init_replica(node_i, new_c_node); - u_sentinel->init_replica(u, new_c_node); - for (int i = 0; i < u->child_num(); ++i) { - u_sentinel->add_child(u->child(i)); - } - new_AE_root->init_AE(u_sentinel); - - //Neighborhood setting of replica-nodes in c-node. - i_sentinel->set_to_boundary_path(u_sentinel, u_sentinel); - u_sentinel->set_to_boundary_path(i_sentinel, i_sentinel); - - //Default label of c-node. - new_c_node->set_1st_label(INT_MAX); - new_c_node->set_2nd_label(NOT_VISITED); - - //Set essential node of c-node. - new_c_node->add_essential(i_sentinel); - new_c_node->add_essential(u_sentinel); - - //Parenting - new_c_node->set_parent(node_i); - u->set_parent(new_c_node); - - //Clear children-list of u_node. (which has benn transfered to AE inside c-node.) - u->clear_children(); - - return new_c_node; - } - -//The case when the first explored node is c-node (The input parameter c). -//The p-node that trigger c(The input parameter p), has p->c parent-link already, and p is essential(not essential before triggered). -//But we don't have c->p child-link yet. -//We are not going to establish that child-link in this function. (Will be done in BET's main loop.) -//Set c to be DELETED. -node* -maximal_planar_subgraph_finder::construct(node* c, node* p) { - //Basic works. - // int i_label = c->get_1st_label(); // unused var - node* node_i = _post_order_list[c->get_1st_label()]; - parenting_labeling_shaving(p, node_i); - //note: Now, c must have exactly two children left, and c has a parent-link to p, p has achild link to c, too. - //Remember to handle them later. - - //Get some new nodes. - node* i_sentinel = get_new_node(REPLICA_NODE); - node* new_c_node = get_new_node(C_NODE); - i_sentinel->init_replica(node_i, new_c_node); - - //Strategy: Build thisboundary cycle first: (i, child(0), c, child(1), i). - //And then find the two replica-node corresponding to the two children in c, and merge. - node* ch0 = c->child(0); - node* ch1 = c->child(1); - node* AE_root_0 = get_new_node(AE_VIRTUAL_ROOT); - node* AE_root_1 = get_new_node(AE_VIRTUAL_ROOT); - AE_root_0->init_AE(ch0); - AE_root_1->init_AE(ch1); - i_sentinel->set_to_boundary_path(ch0, ch1); - ch0->set_to_boundary_path(i_sentinel, c); - ch1->set_to_boundary_path(i_sentinel, c); - c->set_to_boundary_path(ch0, ch1); - - //find the boundary in c, merge! - node* sent_0; - node* sent_1; - node* sent_p; - for (int i = 0; i < c->c_node_size(); ++i) { - if (node::is_same(c->essential(i), ch0)) sent_0 = c->essential(i); - else if (node::is_same(c->essential(i), ch1)) sent_1 = c->essential(i); - else if (node::is_same(c->essential(i), p)) sent_p = c->essential(i); - } - merge(pair, pair > (pair(sent_0, sent_0->get_next(sent_1)), pair(sent_1, sent_1->get_next(sent_0))), c); - - //Set essential-node of c-node. - new_c_node->add_essential(i_sentinel); - new_c_node->add_essential(sent_p); - - //Default label of c-node. - new_c_node->set_1st_label(INT_MAX); - new_c_node->set_2nd_label(NOT_VISITED); - - //Parenting. - new_c_node->set_parent(node_i); - - //p-node, p_sent. - sent_p->set_c_node(new_c_node); - p->clear_children(); - p->set_parent(new_c_node); - - //Delete c-node - c->set_2nd_label(DELETED); - - return new_c_node; -} - -//Some basic works in constructing c-node. -//u is the first explored node in the newly constructed c-node. -//In the case of newly constructed c-node itself is c-node, u will be the p-node that trigger the c-node. -//And in this case, p->c parent-link has been established, but c->p child-link not. -void -maximal_planar_subgraph_finder::parenting_labeling_shaving(node* u, node* node_i) { - //reverse parent-children relation in [u, node_i] as following. - //(u-> ... ->y->i) -> (u<- ... <-y , i). - vector u_i_path; - u_i_path.push_back(u); - while (true) { - u_i_path.push_back(u_i_path[u_i_path.size()-1]->parent()); - if (u_i_path[u_i_path.size()-1] == node_i) break; - } - for (size_t i = 0; i < u_i_path.size()-2; ++i) { - u_i_path[i]->add_child(u_i_path[i+1]); - u_i_path[i+1]->set_parent(u_i_path[i]); - } - for (size_t i = 0; i < u_i_path.size()-2; ++i) { - for (int j = 0; j < u_i_path[i+1]->child_num(); ++j) { - if (u_i_path[i+1]->child(j) == u_i_path[i]) { - u_i_path[i+1]->remove_child(j); - } - } - } - u_i_path[0]->set_parent(0); - - //BFS-traversal, all labeled to , and then shave the c-node. - u->recursively_labeling(); - recursively_shaving(u); -} diff --git a/deferred_planarity_test/src/mps_test.cpp b/deferred_planarity_test/src/mps_test.cpp deleted file mode 100644 index a514816..0000000 --- a/deferred_planarity_test/src/mps_test.cpp +++ /dev/null @@ -1,186 +0,0 @@ -//----------------------------------------------------------------------------------- -// Implementation of a MPS algorithm via PC-tree. -//----------------------------------------------------------------------------------- - -#include -#include "mps.h" - -#include - -// #define DEBUG -// #define DEBUG_2 -// #define TIME - -//----------------------------------------------------------------------------------- -// Finding MPS -//----------------------------------------------------------------------------------- - -// programs to call from main: - -// read input file of gml format -ogdf::Graph read_from_gml(string input_file) { - ogdf::Graph G; - - // utilize OGDF readGML - if (!ogdf::GraphIO::read(G, input_file, ogdf::GraphIO::readGML)) { - std::cerr << "Could not read " << input_file << ".gml" << std::endl; - } - return G; -} - - -int find_mps(const ogdf::Graph &G) { - maximal_planar_subgraph_finder m; - return m.find_mps(G); -} - -int compute_removed_edge_size(const ogdf::Graph &G, vector post_order) { - maximal_planar_subgraph_finder m; - return m.compute_removed_edge_size(G, post_order); -} - -vector generate_post_order(const ogdf::Graph &G) { - maximal_planar_subgraph_finder m; - return m.generate_post_order(G); -} - -vector generate_mutated_post_order(const ogdf::Graph &G, vector post_order, int mutate_point) { - maximal_planar_subgraph_finder m; - return m.generate_mutated_post_order(G, post_order, mutate_point); -} - -vector generate_guided_post_order(const ogdf::Graph &G, vector post_order) { - maximal_planar_subgraph_finder m; - return m.generate_guided_post_order(G, post_order); -} - - -void compute_mps(const ogdf::Graph &G, int mutate_point, vector &post_order, int &return_edge_size) { - maximal_planar_subgraph_finder m; - m.compute_mps(G, mutate_point, post_order, return_edge_size); -} - - -// --------- - -int maximal_planar_subgraph_finder::find_mps(const ogdf::Graph &G) { - init_from_graph(G); - postOrderTraversal(); - - #ifdef DEBUG - print_post_order(); - #endif - - sort_adj_list(); - determine_edges(); - back_edge_traversal(); - return output_removed_edge_size(); -} - -vector maximal_planar_subgraph_finder::generate_post_order(const ogdf::Graph &G) { - init_from_graph(G); - postOrderTraversal(); - - #ifdef DEBUG - std::cout << "standard post order traversal" << std::endl; - print_post_order(); - #endif - - return return_post_order(); -} - -// result of this will be used as input to "compute_removed_edge_size" -vector maximal_planar_subgraph_finder::generate_mutated_post_order(const ogdf::Graph &G, const vector &post_order, int mutate_point) { - init_from_graph(G); - - mutatedPostOrderTraversal(post_order, mutate_point); - - #ifdef DEBUG - std::cout << "mutated post order traversal" << std::endl; - print_post_order(); - #endif - - return return_post_order(); -} - -// result of this will be used as input to "compute_removed_edge_size" -vector maximal_planar_subgraph_finder::generate_guided_post_order(const ogdf::Graph &G, const vector &post_order) { - init_from_graph(G); - guidedPostOrderTraversal(post_order); - - // #ifdef DEBUG - // std::cout << "guided post order traversal" << std::endl; - // print_post_order(); - // #endif - - return return_post_order(); -} - - - -int maximal_planar_subgraph_finder::compute_removed_edge_size(const ogdf::Graph &G, vector post_order) { - // read_from_gml - init_from_graph(G); - - // guidedPostOrderTraversal - guidedPostOrderTraversal(post_order); - sort_adj_list(); - determine_edges(); - back_edge_traversal(); - - return output_removed_edge_size(); -} - -void maximal_planar_subgraph_finder::reset_state() { - _post_order_list.clear(); -} - -void maximal_planar_subgraph_finder::compute_mps(const ogdf::Graph &G, int mutate_point, vector &post_order, int &return_edge_size) { - init_from_graph(G); - mutatedPostOrderTraversal(post_order, mutate_point); - sort_adj_list(); - determine_edges(); - back_edge_traversal(); - return_edge_size = output_removed_edge_size(); - - // now we get the canonical representation of the post order - vector temp_post_order = return_post_order(); - - reset_state(); // clear the _post_order_list - // perform guided Post Order Traversal to flip the tree - guidedPostOrderTraversal(temp_post_order); - - post_order = return_post_order(); -} - -//----------------------------------------------------------------------------------- -// Input, output -//----------------------------------------------------------------------------------- - -void maximal_planar_subgraph_finder::init_from_graph(const ogdf::Graph &G) { - // create nodes - _node_list.reserve(G.numberOfNodes()); - for (int i = 0; i < G.numberOfNodes(); ++i) { - _node_list.push_back(new node(P_NODE)); - _node_list[i]->set_id(i); - } - - // create edges - for (ogdf::edge e : G.edges) { - ogdf::node source = e->source(); - ogdf::node target = e->target(); - _node_list[source->index()]->add_adj(_node_list[target->index()]); - _node_list[target->index()]->add_adj(_node_list[source->index()]); - } -} - - - -// count the number of removed edges -int maximal_planar_subgraph_finder::output_removed_edge_size() { - int sum = 0; - for (size_t i = 0; i < _back_edge_list.size(); ++i) { - if (_is_back_edge_eliminate[i]) ++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 deleted file mode 100644 index 0b43207..0000000 --- a/deferred_planarity_test/src/node.cpp +++ /dev/null @@ -1,388 +0,0 @@ -//----------------------------------------------------------------------------------- -// Implementation of a MPS algorithm via PC-tree. -//----------------------------------------------------------------------------------- - -#include "mps.h" - -// #define DEBUG -// #define DEBUG_MUTATION - -//----------------------------------------------------------------------------------- -// CONSTRUCTOR -//----------------------------------------------------------------------------------- -node::node(node_type t) { - _type = t; - _label = pair(INT_MAX, NOT_VISITED); - _neighbor[0] = _neighbor[1] = 0; - _AE_root[0] = _AE_root[1] = 0; - _original_node = 0; - _c_node = 0; - _parent = 0; - _post_order_index = INT_MAX; - _node_id = INT_MAX; - _mark = 0; -} - -//----------------------------------------------------------------------------------- -// TYPE, ID, INDEX -//----------------------------------------------------------------------------------- -node_type node::type() {return _type;} - -int node::post_order_index() {return _post_order_index;} - -void node::set_id(int i) {_node_id = i;} - -void node::set_post_order_index(int i) {_post_order_index = i;} - -//Only used when consturcting c-node -//The first node calling this function would not be labeled. -void node::recursively_labeling() { - for (size_t i = 0; i < _children.size(); ++i) { - _children[i]->_label.second = ARTIFICIAL_EDGE; - _children[i]->recursively_labeling(); - } -} - -int node::node_id() {return _node_id;} - -//----------------------------------------------------------------------------------- -// DFS-TREE -//----------------------------------------------------------------------------------- -void node::add_adj(node* n) {_adj_list.push_back(n);} - -int node::degree() {return _adj_list.size();} - -node* node::adj(int i) {return _adj_list[i];} - -void node::set_adj_list(vector vec) {_adj_list = vec;} - -void node::DFS_visit(vector &dfsList, int &index) { - mark(); - for (size_t i = 0; i < _adj_list.size(); ++i) { - if (!_adj_list[i]->is_marked()) { - _adj_list[i]->_parent = this; - _adj_list[i]->DFS_visit(dfsList, index); - } - } - set_post_order_index(index); - dfsList.push_back(this); - ++index; -} - - -bool node::sortByOrder(const std::unordered_map& node_id_to_pos, node* a, node* b) { - auto iter_a = node_id_to_pos.find(a->node_id()); - auto iter_b = node_id_to_pos.find(b->node_id()); - - // second yields the position - return iter_a->second < iter_b->second; -} - - -void node::guided_DFS_visit(vector &dfsList, - const vector &node_list, - int &return_index, - const unordered_map &node_id_to_pos) -{ - - mark(); - - // 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 - - // implementation 1: loop through all elements - // // create an unordered set to efficiently check for presence of an element - // std::unordered_set neighbor_set; - // 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 - // // it is ok if the neighbor was already visited before, - // // it would've been marked and will be subsequently ignored - // vector neighbor_list; - // for (int i = 0; i < rev_post_order.size(); ++i) { - // if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) { - // // only add if newly encountered - // 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 neighbor_list = _adj_list; - std::sort(neighbor_list.begin(), neighbor_list.end(), [this, &node_id_to_pos](node* a, node* b) { - return sortByOrder(node_id_to_pos, a, b); - }); - - - #ifdef DEBUG - std::cout << "current node:" << this->node_id() << std::endl; - for (int i = 0; i < neighbor_list.size(); ++i) { - std::cout << neighbor_list[i]->node_id() << "(" << neighbor_list[i]->is_marked() << ")" << ","; - } - std::cout << std::endl; - #endif - - - - for (size_t 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, return_index, node_id_to_pos); - } - } - - set_post_order_index(return_index); - dfsList.push_back(this); - ++return_index; -} - -void node::mutated_DFS_visit(vector &dfsList, - const vector &node_list, - int &return_index, - int &traversal_index, - const unordered_map &node_id_to_pos, - int mutate_point, - mt19937 rng) -{ - - // mark current node - mark(); - - // 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 - - // // implementation 1: naively check by running through all elements of rev_post_order - // // create an unordered set to efficiently check for presence of an element - // std::unordered_set neighbor_set; - // for (size_t 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 - // // it is ok if the neighbor was already visited before, - // // it would've been marked and will be subsequently ignored - // vector neighbor_list; - // for (size_t 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]]); - // } - // } - - vector neighbor_list = _adj_list; - // if the current index matches the mutate_point, then we know this is the cycle to mutate - if (traversal_index == mutate_point) { - // we shuffle the neighbor list - std::shuffle(neighbor_list.begin(), neighbor_list.end(), rng); - // otherwise just sort based on the order set by node_id_to_pos, which is - // set by the reversed post_order - } else { - std::sort(neighbor_list.begin(), neighbor_list.end(), [this, &node_id_to_pos](node *a, node *b) - { return sortByOrder(node_id_to_pos, a, b); }); - } - - - - #ifdef DEBUG_MUTATION - std::cout << "current node:" << this->node_id() << std::endl; - for (size_t i = 0; i < neighbor_list.size(); ++i) { - std::cout << neighbor_list[i]->node_id() << "(" << neighbor_list[i]->is_marked() << ")" << ","; - } - std::cout << std::endl; - #endif - - - - // increment traversal index after checking - // next node will receive incremented index - traversal_index++; - - for (size_t 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, return_index, traversal_index, node_id_to_pos, mutate_point, rng); - } - } - - set_post_order_index(return_index); - dfsList.push_back(this); - ++return_index; -} - -//----------------------------------------------------------------------------------- -// PARENT-CHILDREN -//----------------------------------------------------------------------------------- -int node::child_num() {return _children.size();} - -node* node::child(int i) {return _children[i];} - -node* node::parent() {return _parent;} - -void node::clear_children() { - _children.clear(); -} - -void node::remove_child(int i) { - _children[i] = _children[_children.size()-1]; - _children.resize(_children.size()-1); -} - -void node::remove_child(node* n) { - for (size_t i = 0; i < _children.size(); ++i) { - if (_children[i] == n) { - _children[i] = _children[_children.size()-1]; - _children.resize(_children.size()-1); - } - } -} - -void node::add_child(node* n) { - _children.push_back(n); -} - -vector* node::get_children_list() { - vector* ptr = new vector(_children); - return ptr; -} - -void node::set_parent(node* n) { - _parent= n; -} - -//----------------------------------------------------------------------------------- -// BOUNDARY_PATH -//----------------------------------------------------------------------------------- -void node::set_to_boundary_path(node* n0, node* n1) { - _parent = 0; - _children.clear(); - _neighbor[0] = n0; - _neighbor[1] = n1; - set_2nd_label(BOUNDARY_PATH); -} - -node* node::get_next(node* prev) { - if (_neighbor[0] != prev) return _neighbor[0]; - else return _neighbor[1]; -} - -node* node::neighbor(int i) {return _neighbor[i];} - -void node::set_neighbor(int i, node* n) {_neighbor[i] = n;} - -void node::set_neighbor(node* u, node* v) { - _neighbor[0] = u; - _neighbor[1] = v; -} - -//----------------------------------------------------------------------------------- -// ARTIFICIAL EDGE -//----------------------------------------------------------------------------------- -node* node::AE(int i) {return _AE_root[i];} - -void node::set_AE(int i, node* j) { - _AE_root[i] = j; - if (j != 0) j->set_parent(this); -} - -void node::add_AE(node* j) { - if (j == 0) return; - if (_AE_root[0] == 0) set_AE(0, j); - else if (_AE_root[1] == 0) set_AE(1, j); -} - -//Inherit u's artificial edge. -void node::inherit_AE(node* u) { - if (u->_AE_root[0] != 0) add_AE(u->_AE_root[0]); - if (u->_AE_root[1] != 0) add_AE(u->_AE_root[1]); - u->_AE_root[0] = u->_AE_root[1] = 0; -} - -//Set itself to be an AE-root-node in u. -//Inherite u's chilren-list. -//Do nothing if u does not have any children. -void node::init_AE(node* u) { - if (u->child_num() == 0) return; - _children = u->_children; - u->clear_children(); - for (size_t i = 0; i < _children.size(); ++i) { - _children[i]->set_parent(this); - } - set_parent(u); - set_1st_label(_children[0]->get_1st_label()); - set_2nd_label(ARTIFICIAL_EDGE); - u->add_AE(this); -} - -//----------------------------------------------------------------------------------- -// REPLICA -//----------------------------------------------------------------------------------- -node* node::original_node() {return _original_node;} - -node* node::get_c_node() {return _c_node;} - -void node::set_c_node(node* c) {_c_node = c;} - -bool node::is_sentinel() {return type() == REPLICA_NODE;} - -//Check if n1 and n2 correspond to the same node -bool node::is_same(node* n1, node* n2) { - node* s1 = (n1->type() == REPLICA_NODE)? n1->original_node() : n1; - node* s2 = (n2->type() == REPLICA_NODE)? n2->original_node() : n2; - return s1 == s2; -} - -//Set itself to be a replica-node of u in c. -//Only inherit some basic setting, not including info about neighborhood. -void node::init_replica(node* u, node* c) { - set_post_order_index(u->post_order_index()); - set_2nd_label(BOUNDARY_PATH); - _original_node = (u->type() == REPLICA_NODE)? u->original_node() : u; - _c_node = c; -} - -//----------------------------------------------------------------------------------- -// LABELING -//----------------------------------------------------------------------------------- -void node::set_1st_label(int i) {_label.first = i;} - -void node::set_2nd_label(label i) {_label.second = i;} - -int node::get_1st_label() {return _label.first;} - -label node::get_2nd_label() {return _label.second;} - -//----------------------------------------------------------------------------------- -// C-NODE -//----------------------------------------------------------------------------------- -node* node::get_a_list_node() { - return _essential_list[0]; -} - -int node::c_node_size() { - return _essential_list.size(); -} - -node* node::essential(int i) { - return _essential_list[i]; -} - -void node::clear_essential() {_essential_list.clear();} - -void node::add_essential(node* u) {_essential_list.push_back(u);} - -//----------------------------------------------------------------------------------- -// MARK -//----------------------------------------------------------------------------------- -void node::mark() {_mark = _ref_mark;} - -void node::init_mark() {++_ref_mark;} - -void node::un_mark() {_mark = 0;} - -bool node::is_marked() {return _mark == _ref_mark;} - -int node::_ref_mark = 1;