Feat: combined mutation and flipping into a single procedure in
"compute_mps"
This commit is contained in:
parent
0e80061f44
commit
476c221cc2
|
@ -71,7 +71,7 @@ public:
|
||||||
int mutate_point);
|
int mutate_point);
|
||||||
|
|
||||||
// custom comparator function to sort nodes according to order in given vector
|
// custom comparator function to sort nodes according to order in given vector
|
||||||
bool sortByOrder(const std::unordered_map<int, int>& node_id_to_pos, node* a, node* b);
|
bool sortByOrder(const unordered_map<int, int>& node_id_to_pos, node* a, node* b);
|
||||||
|
|
||||||
//PARENT-CHILDREN
|
//PARENT-CHILDREN
|
||||||
void set_parent(node* n) ;
|
void set_parent(node* n) ;
|
||||||
|
@ -160,18 +160,26 @@ class maximal_planar_subgraph_finder
|
||||||
public:
|
public:
|
||||||
maximal_planar_subgraph_finder();
|
maximal_planar_subgraph_finder();
|
||||||
~maximal_planar_subgraph_finder();
|
~maximal_planar_subgraph_finder();
|
||||||
int find_mps(const ogdf::Graph &G);
|
|
||||||
int compute_removed_edge_size(const ogdf::Graph &G, vector<int> post_order);
|
// functions that prepare state
|
||||||
|
void init_from_graph(const ogdf::Graph &G);
|
||||||
vector<int> generate_post_order(const ogdf::Graph &G);
|
vector<int> generate_post_order(const ogdf::Graph &G);
|
||||||
vector<int> generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point);
|
vector<int> generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point);
|
||||||
vector<int> generate_guided_post_order(const ogdf::Graph &G, vector<int> post_order);
|
vector<int> generate_guided_post_order(const ogdf::Graph &G, vector<int> post_order);
|
||||||
node* get_new_node(node_type t);
|
|
||||||
void init_from_graph(const ogdf::Graph &G);
|
|
||||||
int output_removed_edge_size();
|
|
||||||
vector<int> return_post_order();
|
|
||||||
void postOrderTraversal();
|
void postOrderTraversal();
|
||||||
void guidedPostOrderTraversal(vector<int> post_order);
|
void guidedPostOrderTraversal(vector<int> post_order);
|
||||||
void mutatedPostOrderTraversal(vector<int> post_order, int mutate_point);
|
void mutatedPostOrderTraversal(vector<int> 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<int> &post_order, int &return_edge_size);
|
||||||
|
|
||||||
|
int find_mps(const ogdf::Graph &G);
|
||||||
|
int compute_removed_edge_size(const ogdf::Graph &G, vector<int> post_order);
|
||||||
|
node* get_new_node(node_type t);
|
||||||
|
void reset_state();
|
||||||
|
int output_removed_edge_size();
|
||||||
|
vector<int> return_post_order();
|
||||||
// void set_post_order(vector<int> post_order);
|
// void set_post_order(vector<int> post_order);
|
||||||
void print_post_order();
|
void print_post_order();
|
||||||
void sort_adj_list();
|
void sort_adj_list();
|
||||||
|
|
|
@ -25,6 +25,7 @@ ogdf::Graph read_from_gml(string input_file);
|
||||||
vector<int> generate_post_order(const ogdf::Graph &G);
|
vector<int> generate_post_order(const ogdf::Graph &G);
|
||||||
vector<int> generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point);
|
vector<int> generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point);
|
||||||
vector<int> generate_guided_post_order(const ogdf::Graph &G, vector<int> post_order);
|
vector<int> generate_guided_post_order(const ogdf::Graph &G, vector<int> post_order);
|
||||||
|
void compute_mps(const ogdf::Graph &G, int mutate_point, vector<int> &post_order, int &return_edge_size);
|
||||||
|
|
||||||
void vector_printer(const vector<int>& state) {
|
void vector_printer(const vector<int>& state) {
|
||||||
for (size_t i = 0; i < state.size(); ++i) {
|
for (size_t i = 0; i < state.size(); ++i) {
|
||||||
|
@ -34,53 +35,43 @@ void vector_printer(const vector<int>& state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vector<int> repeated_mutation(const ogdf::Graph &G, int k_max, int mutate_point) {
|
vector<int> repeated_mutation(const ogdf::Graph &G, int k_max) {
|
||||||
// generate first post order
|
// generate first post order
|
||||||
// std::cout << "generate first post order" << std::endl;
|
// std::cout << "generate first post order" << std::endl;
|
||||||
vector<int> state_old = generate_post_order(G);
|
vector<int> old_order = generate_post_order(G);
|
||||||
vector_printer(state_old);
|
vector_printer(old_order);
|
||||||
vector<int> state_new;
|
vector<int> temp_order = old_order;
|
||||||
|
int new_removed_size;
|
||||||
|
int old_removed_size = INT_MAX;
|
||||||
|
|
||||||
int old_edge_size = compute_removed_edge_size(G, state_old);
|
// prepare random selection
|
||||||
|
std::random_device rd;
|
||||||
int new_edge_size = old_edge_size;
|
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
|
||||||
|
int mutate_point = dist(gen); // generate number
|
||||||
|
|
||||||
for (int k = 0; k < k_max; ++k) {
|
for (int k = 0; k < k_max; ++k) {
|
||||||
// mutation produces rotated view
|
// function compute new post_order and new_removed_size
|
||||||
// state_new = generate_mutated_post_order(G, state_old, mutate_point);
|
// temp_order and new_removed_size will be updated with new values
|
||||||
// simulate a mutation
|
compute_mps(G, mutate_point, temp_order, new_removed_size);
|
||||||
// state_new = generate_guided_post_order(G, state_old);
|
// if there is an improvement
|
||||||
|
// 1. update the removed size to use the new smaller size
|
||||||
// another round of guided post order gives canonical representation
|
// 2. update the old_order to be the new_order
|
||||||
// state_new = generate_guided_post_order(G, state_new);
|
if (new_removed_size < old_removed_size) {
|
||||||
new_edge_size = compute_removed_edge_size(G, state_old);
|
old_removed_size = new_removed_size;
|
||||||
|
old_order = temp_order;
|
||||||
// if (new_edge_size < old_edge_size) {
|
// if there is no improvement, we revert the temp_order to the old_order
|
||||||
// state_old = state_new;
|
} else {
|
||||||
// }
|
temp_order = old_order;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// vector_printer(state_new);
|
return old_order;
|
||||||
return state_old;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_correctness(const ogdf::Graph &G) {
|
|
||||||
vector<int> state_old = generate_post_order(G);
|
|
||||||
compute_removed_edge_size(G, state_old);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int get_graph_size(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.numberOfNodes();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// Main function.
|
// Main function.
|
||||||
|
@ -90,20 +81,20 @@ 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]);
|
|
||||||
|
|
||||||
const ogdf::Graph G = read_from_gml(input_file);
|
const ogdf::Graph G = read_from_gml(input_file);
|
||||||
|
|
||||||
// generate order here
|
// generate order here
|
||||||
vector<int> post_order = repeated_mutation(G, k_max, mutate_point);
|
vector<int> post_order = repeated_mutation(G, k_max);
|
||||||
|
|
||||||
// test timing of function
|
// test timing of function
|
||||||
// test_correctness(G);
|
// test_correctness(G);
|
||||||
|
|
||||||
// // print final order and number of edges
|
// // print final order and number of edges
|
||||||
// // print post_order
|
std::cout << "---" << std::endl;
|
||||||
// std::copy(post_order.begin(), post_order.end(), std::ostream_iterator<int>(std::cout, ","));
|
std::cout << "final report" << std::endl;
|
||||||
// std::cout << std::endl;
|
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(G, post_order);
|
int removed_edges = compute_removed_edge_size(G, post_order);
|
||||||
std::cout << "Number of removed edges: " << removed_edges << std::endl;
|
std::cout << "Number of removed edges: " << removed_edges << std::endl;
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,8 @@ maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector<int> post_order
|
||||||
node::init_mark();
|
node::init_mark();
|
||||||
|
|
||||||
vector<int> rev_post_order;
|
vector<int> rev_post_order;
|
||||||
for (size_t i = post_order.size() - 1; i >= 0; --i) {
|
|
||||||
|
for (size_t i = post_order.size() - 1; i != std::numeric_limits<size_t>::max(); --i) {
|
||||||
rev_post_order.push_back(post_order[i]);
|
rev_post_order.push_back(post_order[i]);
|
||||||
}
|
}
|
||||||
int postOrderID = 0;
|
int postOrderID = 0;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <ogdf/fileformats/GraphIO.h>
|
#include <ogdf/fileformats/GraphIO.h>
|
||||||
|
|
||||||
// #define DEBUG
|
// #define DEBUG
|
||||||
|
#define DEBUG_2
|
||||||
// #define TIME
|
// #define TIME
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
@ -54,6 +55,12 @@ vector<int> generate_guided_post_order(const ogdf::Graph &G, vector<int> post_or
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void compute_mps(const ogdf::Graph &G, int mutate_point, vector<int> &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) {
|
int maximal_planar_subgraph_finder::find_mps(const ogdf::Graph &G) {
|
||||||
|
@ -85,6 +92,7 @@ vector<int> maximal_planar_subgraph_finder::generate_post_order(const ogdf::Grap
|
||||||
// result of this will be used as input to "compute_removed_edge_size"
|
// result of this will be used as input to "compute_removed_edge_size"
|
||||||
vector<int> maximal_planar_subgraph_finder::generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point) {
|
vector<int> maximal_planar_subgraph_finder::generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point) {
|
||||||
init_from_graph(G);
|
init_from_graph(G);
|
||||||
|
|
||||||
mutatedPostOrderTraversal(post_order, mutate_point);
|
mutatedPostOrderTraversal(post_order, mutate_point);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -164,6 +172,36 @@ int maximal_planar_subgraph_finder::compute_removed_edge_size(const ogdf::Graph
|
||||||
return output_removed_edge_size();
|
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<int> &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<int> temp_post_order = return_post_order();
|
||||||
|
#ifdef DEBUG_2
|
||||||
|
std::cout << "post_order pre-flip" << std::endl;
|
||||||
|
print_post_order();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
reset_state(); // clear the _post_order_list
|
||||||
|
// perform guided Post Order Traversal to flip the tree
|
||||||
|
guidedPostOrderTraversal(temp_post_order);
|
||||||
|
#ifdef DEBUG_2
|
||||||
|
std::cout << "post order post_flip" << std::endl;
|
||||||
|
print_post_order();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
post_order = return_post_order();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// Input, output
|
// Input, output
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
|
|
@ -119,7 +119,6 @@ void node::guided_DFS_visit(vector<node *> &dfsList,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cout << "current node:" << this->node_id() << std::endl;
|
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) {
|
for (int i = 0; i < neighbor_list.size(); ++i) {
|
||||||
std::cout << neighbor_list[i]->node_id() << "(" << neighbor_list[i]->is_marked() << ")" << ",";
|
std::cout << neighbor_list[i]->node_id() << "(" << neighbor_list[i]->is_marked() << ")" << ",";
|
||||||
}
|
}
|
||||||
|
@ -171,7 +170,14 @@ void node::mutated_DFS_visit(vector<node*> &dfsList,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
// since we increment the index before this line, the current index is "index - 1"
|
// 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 the current index matches the mutate_point, then we know this is the cycle to mutate
|
||||||
|
@ -183,13 +189,6 @@ void node::mutated_DFS_visit(vector<node*> &dfsList,
|
||||||
// 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);
|
||||||
|
|
||||||
#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
|
// increment traversal index after checking
|
||||||
|
|
Loading…
Reference in New Issue