Compare commits

..

2 Commits

Author SHA1 Message Date
Richard Wong 8ca09dbf9e
Bug: fixed broken guided traversal. Discovered that guided traversal
rotates the dfs tree.
2024-02-22 10:52:36 +09:00
Richard Wong 54b51b002d
Fix: changed logic in modified-postOrderTraversal to match default
postOrderTraversal
Refactor: make postOrderTraversal functions single responsibility only
2024-02-20 17:00:51 +09:00
7 changed files with 222 additions and 259 deletions

View File

@ -1,2 +1 @@
The objective of this branch is to measure the number of removed edges between This branch tests the idea of using fuzzing to choose the direction of mutation
preserved and mutated parts of the DFS tree.

View File

@ -33,12 +33,6 @@ enum node_type {
AE_VIRTUAL_ROOT = 3 AE_VIRTUAL_ROOT = 3
}; };
enum back_edge_type {
RETAINED = 0,
MUTATED_REMOVE = 1,
NON_MUTATED_REMOVE = 2
};
class node class node
{ {
public: public:
@ -62,10 +56,11 @@ public:
node* adj(int i); node* adj(int i);
void set_adj_list(vector<node*> vec); void set_adj_list(vector<node*> vec);
void DFS_visit(vector<node*> &dfsList, int &index); void DFS_visit(vector<node*> &dfsList, int &index);
void guided_DFS_visit(vector<node*> &dfsList, void guided_DFS_visit(vector<node *> &dfsList,
vector<node*> &node_list, vector<node *> &node_list,
int &return_index, int &return_index,
vector<int> rev_post_order); vector<int> rev_post_order,
int prev_node);
void mutated_DFS_visit(vector<node*> &dfsList, void mutated_DFS_visit(vector<node*> &dfsList,
vector<node*> &node_list, vector<node*> &node_list,
int &index, int &index,
@ -161,22 +156,19 @@ public:
maximal_planar_subgraph_finder(); maximal_planar_subgraph_finder();
~maximal_planar_subgraph_finder(); ~maximal_planar_subgraph_finder();
int find_mps(string input_file); int find_mps(string input_file);
int compute_removed_edge_size(string input_file, vector<int> post_order, int mutate_point); int compute_removed_edge_size(string input_file, vector<int> post_order);
void print_removed_edge_stats(string input_file, vector<int> post_order, int mutate_point);
vector<int> generate_post_order(string input_file); vector<int> generate_post_order(string input_file);
vector<int> generate_mutated_post_order(string input_file, vector<int> post_order);
vector<int> generate_guided_post_order(string input_file, vector<int> post_order); vector<int> generate_guided_post_order(string input_file, vector<int> post_order);
vector<int> generate_mutated_post_order(string input_file, vector<int> post_order, int mutate_point);
void set_mutate_point(int mutate_point);
int get_mutate_point();
node* get_new_node(node_type t); node* get_new_node(node_type t);
void read_from_gml(string input_file); void read_from_gml(string input_file);
void output_print_removed_edge_stats(); int output_removed_edge_size();
int output_int_removed_edge_size();
vector<int> return_post_order(); vector<int> return_post_order();
void postOrderTraversal(); void postOrderTraversal();
void mutatedPostOrderTraversal(vector<int> post_order, int mutate_point);
void guidedPostOrderTraversal(vector<int> post_order); void guidedPostOrderTraversal(vector<int> post_order);
void set_post_order(vector<int> post_order); void mutatedPostOrderTraversal(vector<int> post_order);
// void set_post_order(vector<int> post_order);
void print_post_order();
void sort_adj_list(); void sort_adj_list();
void determine_edges(); void determine_edges();
void back_edge_traversal(); void back_edge_traversal();
@ -202,9 +194,8 @@ private:
vector<pair<node*, node*> > _edge_list; // Edges in DFS-tree. These edges must be contained in the maximal planar subgraph that we found. vector<pair<node*, node*> > _edge_list; // Edges in DFS-tree. These edges must be contained in the maximal planar subgraph that we found.
vector<node*> _post_order_list; //The sorted version (increasing with post-order-index) of _node_list. vector<node*> _post_order_list; //The sorted version (increasing with post-order-index) of _node_list.
vector<pair<node*, node*> > _back_edge_list; // Edges other than that in DFS-tree. (The first node's index is higher than the second's.) vector<pair<node*, node*> > _back_edge_list; // Edges other than that in DFS-tree. (The first node's index is higher than the second's.)
vector<back_edge_type> _is_back_edge_eliminate; //Record that if the back-edge has been eliminated or not. vector<bool> _is_back_edge_eliminate; //Record that if the back-edge has been eliminated or not.
vector<node*> _new_node_list; //Newly added nodes. vector<node*> _new_node_list; //Newly added nodes.
int _mutate_point; // store the mutate_point
}; };
#endif #endif

View File

@ -31,4 +31,4 @@ $(BIN_DIR) $(OBJ_DIR):
.PHONY: clean .PHONY: clean
clean: clean:
rm -r $(OBJ_DIR) rm -r $(BIN_DIR) $(OBJ_DIR)

View File

@ -11,60 +11,52 @@
#include <iterator> #include <iterator>
#include <random> #include <random>
#include <vector> #include <vector>
#include <ogdf/fileformats/GraphIO.h> #include <ogdf/fileformats/GraphIO.h>
#define START_TEMP 100
using namespace std; using namespace std;
int compute_removed_edge_size(string input_file, vector<int> post_order);
// functions defined in mps_test.cpp
int compute_removed_edge_size(string input_file, vector<int> post_order, int mutate_point);
void print_removed_edge_stats(string input_file, vector<int> post_order, int mutate_point);
vector<int> generate_post_order(string input_file); vector<int> generate_post_order(string input_file);
vector<int> generate_mutated_post_order(string input_file, vector<int> post_order);
vector<int> generate_guided_post_order(string input_file, vector<int> post_order); vector<int> generate_guided_post_order(string input_file, vector<int> post_order);
vector<int> generate_mutated_post_order_at_x(string input_file, vector<int> post_order, int mutate_point);
void vector_printer(vector<int> state) { vector<int> repeated_mutation(string input_file, int k_max) {
for (int i = 0; i < state.size(); ++i) { // generate first post order
std::cout << state[i] << ","; std::cout << "generate first post order" << std::endl;
}
std::cout << std::endl;
}
void measure_removed_edges(string input_file, int k_max, int mutate_point) {
// generate first state
vector<int> state_old = generate_post_order(input_file); vector<int> state_old = generate_post_order(input_file);
vector<int> state_new; vector<int> state_new;
int num_removed_edges;
int removed_old = compute_removed_edge_size(input_file, state_old, mutate_point);
int removed_new;
for (int k = 0; k < k_max; ++k) { for (int k = 0; k < k_max; ++k) {
std::cout << "first post order" << std::endl; // rotate it first
vector_printer(state_old); std::cout << "cycle:" << k << std::endl;
std::cout << "rotate the dfs tree" << std::endl;
// run mutation on canonical representation directly state_new = generate_guided_post_order(input_file, state_old);
state_new = generate_mutated_post_order_at_x(input_file, state_old, mutate_point); // then the next traversal will rotate it back
// rotate output of mutated state to canonical representation std::cout << "mutate the dfs tree" << std::endl;
state_new = generate_mutated_post_order(input_file, state_new);
// num_removed_edges = compute_removed_edge_size(input_file, state_new);
// first time will rotate the tree
std::cout << "rotate the dfs tree" << std::endl;
state_new = generate_guided_post_order(input_file, state_new); state_new = generate_guided_post_order(input_file, state_new);
// tree produced should be the same as tree from mutation // second time will rotate back the rotated tree
removed_new = compute_removed_edge_size(input_file, state_new, mutate_point); std::cout << "print the mutated tree again" << std::endl;
state_new = generate_guided_post_order(input_file, state_new);
std::cout << "mutated post order" << std::endl; std::cout << std::endl;
vector_printer(state_new);
// std::cout << "removed edges in old: " << removed_old << std::endl;
// std::cout << "removed edges in new: " << removed_new << std::endl;
print_removed_edge_stats(input_file, state_new, mutate_point);
} }
return state_new;
} }
void test_correctness(string input_file) {
vector<int> state_old = generate_post_order(input_file);
int num_removed_edges;
num_removed_edges = compute_removed_edge_size(input_file, state_old);
}
int get_graph_size(string input_file) { int get_graph_size(string input_file) {
ogdf::Graph G; ogdf::Graph G;
@ -84,10 +76,17 @@ int get_graph_size(string input_file) {
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
string input_file = argv[1]; string input_file = argv[1];
int k_max = std::stoi(argv[2]); int k_max = std::stoi(argv[2]);
int mutate_point = std::stoi(argv[3]);
// generate order here // generate order here
measure_removed_edges(input_file, k_max, mutate_point); vector<int> post_order = repeated_mutation(input_file, k_max);
// test_correctness(input_file);
// // print final order and number of edges
// // print post_order
// std::copy(post_order.begin(), post_order.end(), std::ostream_iterator<int>(std::cout, ","));
// std::cout << std::endl;
// int removed_edges = compute_removed_edge_size(input_file, post_order);
// std::cout << "Number of removed edges: " << removed_edges << std::endl;
return 0; return 0;
} }

View File

@ -3,7 +3,9 @@
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
#include "mps.h" #include "mps.h"
#include <cassert> #include <iterator>
// #define DEBUG
// constructor can be made empty // constructor can be made empty
maximal_planar_subgraph_finder::maximal_planar_subgraph_finder() {} maximal_planar_subgraph_finder::maximal_planar_subgraph_finder() {}
@ -20,17 +22,6 @@ maximal_planar_subgraph_finder::get_new_node(node_type t) {
return _new_node_list[_new_node_list.size()-1]; 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;
}
vector<int> vector<int>
maximal_planar_subgraph_finder::return_post_order() { maximal_planar_subgraph_finder::return_post_order() {
vector<int> post_order; vector<int> post_order;
@ -40,11 +31,11 @@ maximal_planar_subgraph_finder::return_post_order() {
return post_order; return post_order;
} }
//Determine the post-order-list by a DFS-traversal. //Determine the post-order-list by a DFS-traversal.
void void
maximal_planar_subgraph_finder::postOrderTraversal() { maximal_planar_subgraph_finder::postOrderTraversal() {
node::init_mark(); node::init_mark();
// always start with node 0
int postOrderID = 0; int postOrderID = 0;
for (int i = 0; i < _node_list.size(); ++i) { for (int i = 0; i < _node_list.size(); ++i) {
if (!_node_list[i]->is_marked()) { if (!_node_list[i]->is_marked()) {
@ -54,7 +45,9 @@ maximal_planar_subgraph_finder::postOrderTraversal() {
} }
//Determine the post-order-list by a DFS-traversal. // 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 void
maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector<int> post_order) { maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector<int> post_order) {
node::init_mark(); node::init_mark();
@ -68,31 +61,33 @@ maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector<int> post_order)
int end_condition = _node_list.size(); int end_condition = _node_list.size();
int start = rev_post_order[0]; int start = rev_post_order[0];
int i = start; int i = start;
int prev_node = INT_MAX;
while (true) while (true)
{ {
if (((start > 0) && (i == (start - 1))) || ((start == 0 ) && (i == end_condition - 1))) if (((start > 0) && (i == (start - 1))) || ((start == 0 ) && (i == end_condition - 1)))
{ {
if (!_node_list[i]->is_marked()) if (!_node_list[i]->is_marked())
{ {
_node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order); _node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order, prev_node);
} }
break; break;
} }
// std::cout << _node_list[i]->node_id() << ", " << !_node_list[i]->is_marked() << std::endl;
if (!_node_list[i]->is_marked()) if (!_node_list[i]->is_marked())
{ {
_node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order); _node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order, prev_node);
} }
i = (i + 1) % end_condition; i = (i + 1) % end_condition;
} }
} }
//Determine the post-order-list by a DFS-traversal. //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 void
maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector<int> post_order, int mutate_point) { maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector<int> post_order) {
node::init_mark(); node::init_mark();
// reverse post_order because reversed post_order is the traversal of the DFS tree from the starting node
vector<int> rev_post_order; vector<int> rev_post_order;
for (int i = post_order.size() - 1; i >= 0; --i) { for (int i = post_order.size() - 1; i >= 0; --i) {
rev_post_order.push_back(post_order[i]); rev_post_order.push_back(post_order[i]);
@ -101,16 +96,30 @@ maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector<int> post_order
int traversal_index = 0; int traversal_index = 0;
// introduce random selection // introduce random selection
std::random_device rd;
std::mt19937 rng(rd());
// Define the range [0, n] // Define the range [0, n]
int n = _node_list.size() - 1; // Change 'n' to your desired upper bound int n = _node_list.size() - 1; // Change 'n' to your desired upper bound
// assert(mutate_point < n); // Create a uniform distribution for the range [0, n]
std::uniform_int_distribution<int> 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 // set loop variables
int start = rev_post_order[0]; int start = rev_post_order[0];
int i = start; int i = start;
// if mutate_point = 0
if (mutate_point == 0) {
// generate another point
start = distribution(rng);
}
int end_condition = _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) while (true)
{ {
if (((start > 0) && (i == (start - 1))) || ((start == 0 ) && (i == end_condition - 1))) if (((start > 0) && (i == (start - 1))) || ((start == 0 ) && (i == end_condition - 1)))
@ -121,7 +130,6 @@ maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector<int> post_order
} }
break; break;
} }
// std::cout << _node_list[i]->node_id() << ", " << !_node_list[i]->is_marked() << std::endl;
if (!_node_list[i]->is_marked()) if (!_node_list[i]->is_marked())
{ {
_node_list[i]->mutated_DFS_visit(_post_order_list, _node_list, postOrderID, traversal_index, rev_post_order, mutate_point); _node_list[i]->mutated_DFS_visit(_post_order_list, _node_list, postOrderID, traversal_index, rev_post_order, mutate_point);
@ -130,16 +138,26 @@ maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector<int> post_order
} }
} }
//Set the post-order-list via given list
void void
maximal_planar_subgraph_finder::set_post_order(vector<int> post_order) { maximal_planar_subgraph_finder::print_post_order() {
for (int i = 0; i < _node_list.size(); ++i) { int current_index;
_node_list[i]->set_post_order_index(post_order[i]); for (int 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<int> 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. //Sort the adj-list of every node increasingly according to post-order-index.
void void
maximal_planar_subgraph_finder::sort_adj_list() { maximal_planar_subgraph_finder::sort_adj_list() {
@ -169,7 +187,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)->post_order_index() > i) break;
if (_post_order_list[i]->adj(j)->get_1st_label() == i) continue; if (_post_order_list[i]->adj(j)->get_1st_label() == i) continue;
_back_edge_list.push_back(pair<node*, node*> (_post_order_list[i], _post_order_list[i]->adj(j))); _back_edge_list.push_back(pair<node*, node*> (_post_order_list[i], _post_order_list[i]->adj(j)));
_is_back_edge_eliminate.push_back(RETAINED); _is_back_edge_eliminate.push_back(false);
} }
} }
for (int i = 0; i < _post_order_list.size(); ++i) { for (int i = 0; i < _post_order_list.size(); ++i) {
@ -180,35 +198,13 @@ maximal_planar_subgraph_finder::determine_edges() {
//The main part of the whole algorithm: Back-edge-traversal //The main part of the whole algorithm: Back-edge-traversal
void void
maximal_planar_subgraph_finder::back_edge_traversal() { maximal_planar_subgraph_finder::back_edge_traversal() {
node* i_node = nullptr; node* i_node = 0;
node* current_node = nullptr; node* current_node = 0;
int dfs_mutate_point = get_mutate_point();
int node_list_last_index = _node_list.size() - 1;
// dfs_mutate_point starts counting from the DFS head
// post_order starts from the last leaf of the DFS tree
// hence we start counting from the post_order last index
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) { for (int i = 0; i < _back_edge_list.size(); ++i) {
// current node is the lower
current_node = _back_edge_list[i].second; current_node = _back_edge_list[i].second;
i_node = _back_edge_list[i].first; i_node = _back_edge_list[i].first;
// back_edge_traversal returns true if it should be included if (!back_edge_traversal(current_node, i_node->post_order_index())) _is_back_edge_eliminate[i] = true;
// 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) {
std::cout << "(" << current_node->node_id() << "[" << current_node->post_order_index() << "]"
<< "," << i_node->node_id() << "[" << i_node->post_order_index() << "]" << ") ";
_is_back_edge_eliminate[i] = NON_MUTATED_REMOVE;
} else {
_is_back_edge_eliminate[i] = MUTATED_REMOVE;
} }
}
}
std::cout << std::endl;
} }
//sub-function for the for-loop of back_edge_traversal(). //sub-function for the for-loop of back_edge_traversal().

View File

@ -4,29 +4,23 @@
#include "mps.h" #include "mps.h"
#include <ogdf/fileformats/GraphIO.h> #include <ogdf/fileformats/GraphIO.h>
#include <algorithm>
#include <vector>
#define DEBUG
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// Finding MPS // Finding MPS
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// functions to call from main: // programs to call from main:
int find_mps(string input_file) { int find_mps(string input_file) {
maximal_planar_subgraph_finder m; maximal_planar_subgraph_finder m;
return m.find_mps(input_file); return m.find_mps(input_file);
} }
int compute_removed_edge_size(string input_file, vector<int> post_order, int mutate_point) { int compute_removed_edge_size(string input_file, vector<int> post_order) {
maximal_planar_subgraph_finder m; maximal_planar_subgraph_finder m;
return m.compute_removed_edge_size(input_file, post_order, mutate_point); return m.compute_removed_edge_size(input_file, post_order);
}
void print_removed_edge_stats(string input_file, vector<int> post_order, int mutate_point) {
maximal_planar_subgraph_finder m;
m.print_removed_edge_stats(input_file, post_order, mutate_point);
} }
vector<int> generate_post_order(string input_file) { vector<int> generate_post_order(string input_file) {
@ -34,78 +28,90 @@ vector<int> generate_post_order(string input_file) {
return m.generate_post_order(input_file); return m.generate_post_order(input_file);
} }
vector<int> generate_mutated_post_order(string input_file, vector<int> post_order) {
maximal_planar_subgraph_finder m;
return m.generate_mutated_post_order(input_file, post_order);
}
vector<int> generate_guided_post_order(string input_file, vector<int> post_order) { vector<int> generate_guided_post_order(string input_file, vector<int> post_order) {
maximal_planar_subgraph_finder m; maximal_planar_subgraph_finder m;
return m.generate_guided_post_order(input_file, post_order); return m.generate_guided_post_order(input_file, post_order);
} }
vector<int> generate_mutated_post_order_at_x(string input_file, vector<int> post_order, int mutate_point) {
maximal_planar_subgraph_finder m;
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) { int maximal_planar_subgraph_finder::find_mps(string input_file) {
read_from_gml(input_file); read_from_gml(input_file);
postOrderTraversal(); postOrderTraversal();
#ifdef DEBUG
print_post_order();
#endif
sort_adj_list(); sort_adj_list();
determine_edges(); determine_edges();
back_edge_traversal(); back_edge_traversal();
return output_int_removed_edge_size(); return output_removed_edge_size();
} }
vector<int> maximal_planar_subgraph_finder::generate_post_order(string input_file) { vector<int> maximal_planar_subgraph_finder::generate_post_order(string input_file) {
read_from_gml(input_file); read_from_gml(input_file);
set_mutate_point(INT_MAX); // essentially removed mutate_point
postOrderTraversal(); postOrderTraversal();
#ifdef DEBUG
std::cout << "standard post order traversal" << std::endl;
print_post_order();
#endif
return return_post_order(); return return_post_order();
} }
// result of this will be used as input to "compute_removed_edge_size"
vector<int> maximal_planar_subgraph_finder::generate_mutated_post_order(string input_file, vector<int> post_order) {
read_from_gml(input_file);
mutatedPostOrderTraversal(post_order);
#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<int> maximal_planar_subgraph_finder::generate_guided_post_order(string input_file, vector<int> post_order) { vector<int> maximal_planar_subgraph_finder::generate_guided_post_order(string input_file, vector<int> post_order) {
read_from_gml(input_file); read_from_gml(input_file);
set_mutate_point(INT_MAX); // essentially remove mutate point
guidedPostOrderTraversal(post_order); guidedPostOrderTraversal(post_order);
#ifdef DEBUG
std::cout << "guided post order traversal" << std::endl;
print_post_order();
#endif
return return_post_order(); return return_post_order();
} }
vector<int> maximal_planar_subgraph_finder::generate_mutated_post_order(string input_file, vector<int> post_order, int mutate_point) {
read_from_gml(input_file);
set_mutate_point(INT_MAX);
mutatedPostOrderTraversal(post_order, mutate_point);
return return_post_order();
}
int maximal_planar_subgraph_finder::compute_removed_edge_size(string input_file, vector<int> post_order) {
int maximal_planar_subgraph_finder::compute_removed_edge_size(string input_file, vector<int> post_order, int mutate_point) {
read_from_gml(input_file); read_from_gml(input_file);
set_mutate_point(mutate_point);
guidedPostOrderTraversal(post_order); guidedPostOrderTraversal(post_order);
#ifdef DEBUG
std::cout << "guided post order traversal" << std::endl;
print_post_order();
#endif
sort_adj_list(); sort_adj_list();
determine_edges(); determine_edges();
back_edge_traversal(); back_edge_traversal();
return output_int_removed_edge_size(); return output_removed_edge_size();
} }
void maximal_planar_subgraph_finder::print_removed_edge_stats(string input_file, vector<int> post_order, int mutate_point) {
read_from_gml(input_file);
set_mutate_point(mutate_point);
guidedPostOrderTraversal(post_order);
sort_adj_list();
determine_edges();
back_edge_traversal();
output_print_removed_edge_stats();
}
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// Input, output // Imput, output
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
@ -124,14 +130,6 @@ void maximal_planar_subgraph_finder::read_from_gml(string input_file) {
_node_list[i]->set_id(i); _node_list[i]->set_id(i);
} }
// vector<ogdf::edge> 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 // create edges
for (ogdf::edge e : G.edges) { for (ogdf::edge e : G.edges) {
ogdf::node source = e->source(); ogdf::node source = e->source();
@ -144,47 +142,10 @@ void maximal_planar_subgraph_finder::read_from_gml(string input_file) {
// count the number of removed edges // count the number of removed edges
void maximal_planar_subgraph_finder::output_print_removed_edge_stats() { int maximal_planar_subgraph_finder::output_removed_edge_size() {
int mutated_sum = 0;
int preserved_sum = 0;
vector<pair<node*, node*>> mutated_removed_edges;
vector<pair<node*, node*>> 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; int sum = 0;
for (int i = 0; i < _back_edge_list.size(); ++i) { for (int i = 0; i < _back_edge_list.size(); ++i) {
if (_is_back_edge_eliminate[i] != RETAINED) ++sum; if (_is_back_edge_eliminate[i]) ++sum;
} }
return sum; return sum;
} }

View File

@ -4,6 +4,8 @@
#include "mps.h" #include "mps.h"
// #define DEBUG
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// CONSTRUCTOR // CONSTRUCTOR
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
@ -53,8 +55,6 @@ node* node::adj(int i) {return _adj_list[i];}
void node::set_adj_list(vector<node*> vec) {_adj_list = vec;} void node::set_adj_list(vector<node*> vec) {_adj_list = vec;}
// original DFS visit implementation
// it just uses _adj_list directly as list of neighbors
void node::DFS_visit(vector<node*> &dfsList, int &index) { void node::DFS_visit(vector<node*> &dfsList, int &index) {
mark(); mark();
for (int i = 0; i < _adj_list.size(); ++i) { for (int i = 0; i < _adj_list.size(); ++i) {
@ -63,17 +63,19 @@ void node::DFS_visit(vector<node*> &dfsList, int &index) {
_adj_list[i]->DFS_visit(dfsList, index); _adj_list[i]->DFS_visit(dfsList, index);
} }
} }
// head recursion: function call before returning result
set_post_order_index(index); set_post_order_index(index);
dfsList.push_back(this); dfsList.push_back(this);
++index; ++index;
} }
void node::guided_DFS_visit(vector<node *> &dfsList, void node::guided_DFS_visit(vector<node *> &dfsList,
vector<node *> &node_list, vector<node *> &node_list,
int &return_index, int &return_index,
vector<int> rev_post_order) vector<int> rev_post_order,
int prev_node)
{ {
mark(); mark();
// purpose of this block: create list of neighbors ordered in the order they appear in rev_post_order // purpose of this block: create list of neighbors ordered in the order they appear in rev_post_order
@ -91,29 +93,46 @@ void node::guided_DFS_visit(vector<node *> &dfsList,
vector<node *> neighbor_list; vector<node *> neighbor_list;
for (int i = 0; i < rev_post_order.size(); ++i) { for (int i = 0; i < rev_post_order.size(); ++i) {
if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) { 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]]); neighbor_list.push_back(node_list[rev_post_order[i]]);
} }
} }
}
#ifdef DEBUG
std::cout << "current node:" << this->node_id() << std::endl;
std::cout << "prev node:" << prev_node << 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 (int i = 0; i < neighbor_list.size(); ++i) { for (int i = 0; i < neighbor_list.size(); ++i) {
if (!neighbor_list[i]->is_marked()) { if (!neighbor_list[i]->is_marked()) {
neighbor_list[i]->_parent = this; neighbor_list[i]->_parent = this;
neighbor_list[i]->guided_DFS_visit(dfsList, node_list, return_index, rev_post_order); neighbor_list[i]->guided_DFS_visit(dfsList, node_list, return_index, rev_post_order, this->node_id());
} }
} }
// head recursion
set_post_order_index(return_index); set_post_order_index(return_index);
dfsList.push_back(this); dfsList.push_back(this);
++return_index; ++return_index;
} }
void node::mutated_DFS_visit(vector<node*> &dfsList, void node::mutated_DFS_visit(vector<node*> &dfsList,
vector<node*> &node_list, vector<node*> &node_list,
int &return_index, int &return_index,
int &traversal_index, int &traversal_index,
vector<int> rev_post_order, vector<int> rev_post_order,
int mutate_point) { int mutate_point)
{
// mark current node
mark(); mark();
// purpose of this block: create list of neighbors ordered in the order they appear in rev_post_order // purpose of this block: create list of neighbors ordered in the order they appear in rev_post_order
@ -136,13 +155,14 @@ void node::mutated_DFS_visit(vector<node*> &dfsList,
} }
// introduce mutation at mutate_point
// since we increment the index before this line, the current index is "index - 1"
// if the current index matches the mutate_point, then we know this is the cycle to mutate
if (traversal_index == mutate_point) { if (traversal_index == mutate_point) {
// Create a random number generator and seed it // Create a random number generator and seed it
// std::cout << "mutated at index: " << index - 1<< "and at mutate point: " << mutate_point << std::endl; // std::cout << "mutated at index: " << index - 1<< "and at mutate point: " << mutate_point << std::endl;
std::random_device rd; std::random_device rd;
std::mt19937 rng(rd()); std::mt19937 rng(rd());
// Use std::shuffle to shuffle the elements in the vector // Use std::shuffle to shuffle the elements in the vector
std::shuffle(neighbor_list.begin(), neighbor_list.end(), rng); std::shuffle(neighbor_list.begin(), neighbor_list.end(), rng);
} }
@ -160,14 +180,11 @@ void node::mutated_DFS_visit(vector<node*> &dfsList,
} }
} }
// head recursion like the initial dfs visit implementation
set_post_order_index(return_index); set_post_order_index(return_index);
dfsList.push_back(this); dfsList.push_back(this);
++return_index; ++return_index;
} }
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// PARENT-CHILDREN // PARENT-CHILDREN
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------