Feat: introduced mutation and allow re-traversing of previous post-order

This commit is contained in:
Richard Wong 2023-09-11 12:21:02 +09:00
parent 46a3810af5
commit f2ba57b57f
Signed by: richard
GPG Key ID: 5BD36BA2E9EE33D0
5 changed files with 273 additions and 21 deletions

View File

@ -18,6 +18,9 @@ using namespace std;
int compute_removed_edge_size(string input_file, vector<int> post_order); int compute_removed_edge_size(string input_file, vector<int> post_order);
vector<int> generate_post_order(string input_file);
vector<int> generate_mutated_post_order(string input_file, vector<int> post_order);
int get_graph_size(string input_file) { int get_graph_size(string input_file) {
ogdf::Graph G; ogdf::Graph G;
@ -36,25 +39,23 @@ 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 num_runs = stoi(argv[2]);
// find the size of the graph here
int node_size = get_graph_size(input_file);
// generate order here // generate order here
vector<int> post_order; vector<int> post_order = generate_post_order(input_file);
for (int i=0; i < node_size; ++i) { std::copy(post_order.begin(), post_order.end(), std::ostream_iterator<int>(std::cout, " "));
post_order.push_back(i); std::cout << std::endl;
}
for (int i=0; i< num_runs; ++i) { // generate mutated order
std::random_device rd; vector<int> mutated_order = generate_mutated_post_order(input_file, post_order);
std::mt19937 g(rd()); post_order = mutated_order;
std::copy(post_order.begin(), post_order.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// print order
int removed_edges = compute_removed_edge_size(input_file, post_order);
std::cout << "Number of removed edges: " << removed_edges << std::endl;
std::shuffle(post_order.begin(), post_order.end(), g);
// print order
std::copy(post_order.begin(), post_order.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
std::cout << "Number of removed edges: " << compute_removed_edge_size(input_file, post_order) << std::endl;
}
return 0; return 0;
} }

View File

@ -20,7 +20,7 @@ maximal_planar_subgraph_finder::get_new_node(node_type t) {
} }
//Determine the post-order-list by a DFS-traversal. //Determine the post-order-list by a DFS-traversal.
void vector<int>
maximal_planar_subgraph_finder::postOrderTraversal() { maximal_planar_subgraph_finder::postOrderTraversal() {
node::init_mark(); node::init_mark();
int postOrderID = 0; int postOrderID = 0;
@ -29,8 +29,113 @@ maximal_planar_subgraph_finder::postOrderTraversal() {
_node_list[i]->DFS_visit(_post_order_list, postOrderID); _node_list[i]->DFS_visit(_post_order_list, postOrderID);
} }
} }
vector<int> post_order;
for (int i = 0; i < _post_order_list.size(); ++i) {
post_order.push_back(_post_order_list[i]->node_id());
}
return post_order;
} }
//Determine the post-order-list by a DFS-traversal.
void
maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector<int> post_order) {
node::init_mark();
vector<int> rev_post_order;
for (int i = post_order.size() - 1; i >= 0; --i) {
rev_post_order.push_back(post_order[i]);
}
int postOrderID = 0;
int end_condition = _node_list.size();
int start = rev_post_order[0];
int i = start;
while (true)
{
if (((start > 0) && (i == (start - 1))) || ((start == 0 ) && (i == end_condition - 1)))
{
if (!_node_list[i]->is_marked())
{
_node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order);
}
break;
}
// std::cout << _node_list[i]->node_id() << ", " << !_node_list[i]->is_marked() << std::endl;
if (!_node_list[i]->is_marked())
{
_node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order);
}
i = (i + 1) % end_condition;
}
}
//Determine the post-order-list by a DFS-traversal.
vector<int>
maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector<int> post_order) {
node::init_mark();
vector<int> rev_post_order;
for (int i = post_order.size() - 1; i >= 0; --i) {
rev_post_order.push_back(post_order[i]);
}
int postOrderID = 0;
// introduce random selection
std::random_device rd;
std::mt19937 rng(rd());
// Define the range [0, n]
int n = _node_list.size() - 1; // Change 'n' to your desired upper bound
// Create a uniform distribution for the range [0, n]
std::uniform_int_distribution<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
int start = rev_post_order[0];
int i = start;
// if mutate_point = 0
if (mutate_point == 0) {
// generate another point
start = distribution(rng);
}
int end_condition = _node_list.size();
while (true)
{
if (((start > 0) && (i == (start - 1))) || ((start == 0 ) && (i == end_condition - 1)))
{
if (!_node_list[i]->is_marked())
{
_node_list[i]->mutated_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order, mutate_point);
}
break;
}
// std::cout << _node_list[i]->node_id() << ", " << !_node_list[i]->is_marked() << std::endl;
if (!_node_list[i]->is_marked())
{
_node_list[i]->mutated_DFS_visit(_post_order_list, _node_list, postOrderID, rev_post_order, mutate_point);
}
i = (i + 1) % end_condition;
}
vector<int> return_order;
for (int i = 0; i < _post_order_list.size(); ++i) {
return_order.push_back(_post_order_list[i]->node_id());
}
// we have to reverse the order as we add to list in the forward direction of recursion
// unlike that of previous methods where we add to list in the return direction of recursion
std::reverse(return_order.begin(), return_order.end());
return return_order;
}
//Set the post-order-list via given list //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::set_post_order(vector<int> post_order) {

View File

@ -10,6 +10,9 @@
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <climits> #include <climits>
#include <random>
#include <algorithm>
#include <unordered_set>
using namespace std; using namespace std;
@ -53,6 +56,8 @@ 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, vector<node*> &node_list, int &index, vector<int> rev_post_order);
void mutated_DFS_visit(vector<node*> &dfsList, vector<node*> &node_list, int &index, vector<int> rev_post_order, int &mutate_point);
//PARENT-CHILDREN //PARENT-CHILDREN
void set_parent(node* n) ; void set_parent(node* n) ;
@ -143,10 +148,14 @@ public:
~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 compute_removed_edge_size(string input_file, vector<int> post_order);
vector<int> generate_post_order(string input_file);
vector<int> generate_mutated_post_order(string input_file, vector<int> post_order);
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);
int output_removed_edge_size(); int output_removed_edge_size();
void postOrderTraversal(); vector<int> postOrderTraversal();
vector<int> mutatedPostOrderTraversal(vector<int> post_order);
void guidedPostOrderTraversal(vector<int> post_order);
void set_post_order(vector<int> post_order); void set_post_order(vector<int> post_order);
void sort_adj_list(); void sort_adj_list();
void determine_edges(); void determine_edges();

View File

@ -8,6 +8,9 @@
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// Finding MPS // Finding MPS
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// 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);
@ -18,6 +21,19 @@ int compute_removed_edge_size(string input_file, vector<int> post_order) {
return m.compute_removed_edge_size(input_file, post_order); return m.compute_removed_edge_size(input_file, post_order);
} }
vector<int> generate_post_order(string input_file) {
maximal_planar_subgraph_finder m;
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);
}
// ---------
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();
@ -27,10 +43,34 @@ int maximal_planar_subgraph_finder::find_mps(string input_file) {
return output_removed_edge_size(); return output_removed_edge_size();
} }
vector<int> maximal_planar_subgraph_finder::generate_post_order(string input_file) {
read_from_gml(input_file);
return postOrderTraversal();
}
vector<int> maximal_planar_subgraph_finder::generate_mutated_post_order(string input_file, vector<int> post_order) {
read_from_gml(input_file);
return mutatedPostOrderTraversal(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) {
read_from_gml(input_file); read_from_gml(input_file);
set_post_order(post_order); guidedPostOrderTraversal(post_order);
// let's reverse the order
std::reverse(_post_order_list.begin(), _post_order_list.end());
// then set post_order_index
for (int i = 0; i < _post_order_list.size(); ++i) {
_node_list[_post_order_list[i]->node_id()]->set_post_order_index(i);
}
std::cout << "check order of duplicated traversal" << std::endl;
for (int i = 0; i < _post_order_list.size(); ++i) {
std::cout << _post_order_list[i]->node_id() << " ";
}
std::cout << std::endl;
sort_adj_list(); sort_adj_list();
determine_edges(); determine_edges();
back_edge_traversal(); back_edge_traversal();

View File

@ -66,6 +66,103 @@ void node::DFS_visit(vector<node*> &dfsList, int &index) {
++index; ++index;
} }
void node::guided_DFS_visit(vector<node*> &dfsList, vector<node*> &node_list, int &index, vector<int> rev_post_order) {
mark();
// you will want to sort the neighbor nodes by the order they appear in the rev_post_order
vector<node *> neighbor_list;
std::unordered_set<int> neighbor_set;
// create an unordered set to efficiently check for presence of an element
for (int i = 0; i < _adj_list.size(); ++i) {
neighbor_set.insert(_adj_list[i]->node_id());
}
// when an element in rev_post_order is found in neighbor_set, we add that to neighbor_list
for (int i = 0; i < rev_post_order.size(); ++i) {
if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) {
neighbor_list.push_back(node_list[rev_post_order[i]]);
}
}
// print the neighbors
// std::cout << "current index: " << this->node_id() << std::endl;
// for (int i = 0; i < neighbor_list.size(); ++i) {
// std::cout << neighbor_list[i]->node_id() << " ";
// }
// std::cout << std::endl;
set_post_order_index(index);
dfsList.push_back(this);
++index;
for (int i = 0; i < neighbor_list.size(); ++i) {
if (!neighbor_list[i]->is_marked()) {
neighbor_list[i]->_parent = this;
neighbor_list[i]->guided_DFS_visit(dfsList, node_list, index, rev_post_order);
}
}
}
void node::mutated_DFS_visit(vector<node*> &dfsList, vector<node*> &node_list, int &index, vector<int> rev_post_order, int &mutate_point) {
mark();
// you will want to sort the neighbor nodes by the order they appear in the rev_post_order
vector<node *> neighbor_list;
std::unordered_set<int> neighbor_set;
// create an unordered set to efficiently check for presence of an element
for (int i = 0; i < _adj_list.size(); ++i) {
neighbor_set.insert(_adj_list[i]->node_id());
}
// when an element in rev_post_order is found in neighbor_set, we add that to neighbor_list
for (int i = 0; i < rev_post_order.size(); ++i) {
if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) {
neighbor_list.push_back(node_list[rev_post_order[i]]);
}
}
// print the neighbors
std::cout << "current index: " << this->node_id() << std::endl;
for (int i = 0; i < neighbor_list.size(); ++i) {
std::cout << neighbor_list[i]->node_id() << " ";
}
std::cout << std::endl;
set_post_order_index(index);
dfsList.push_back(this);
++index;
if (index - 1 == mutate_point) {
// Create a random number generator and seed it
std::cout << "mutated at index: " << index - 1<< "and at mutate point: " << mutate_point << std::endl;
std::random_device rd;
std::mt19937 rng(rd());
// Use std::shuffle to shuffle the elements in the vector
std::shuffle(neighbor_list.begin(), neighbor_list.end(), rng);
// print the neighbors
std::cout << "order after mutation: " << std::endl;
std::cout << "current index: " << this->node_id() << std::endl;
for (int i = 0; i < neighbor_list.size(); ++i)
{
std::cout << neighbor_list[i]->node_id() << " ";
}
std::cout << std::endl;
}
for (int i = 0; i < neighbor_list.size(); ++i)
{
if (!neighbor_list[i]->is_marked())
{
neighbor_list[i]->_parent = this;
neighbor_list[i]->mutated_DFS_visit(dfsList, node_list, index, rev_post_order, mutate_point);
}
}
}
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// PARENT-CHILDREN // PARENT-CHILDREN
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------