Feat: merge with read_once branch
- performance improvements from optimizing multiple procedures
This commit is contained in:
parent
e35462ef2d
commit
aa3c3e3b20
|
@ -10,9 +10,12 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <limits>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <ogdf/fileformats/GraphIO.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -57,16 +60,19 @@ public:
|
||||||
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,
|
const vector<node *> &node_list,
|
||||||
int &return_index,
|
int &return_index,
|
||||||
vector<int> rev_post_order,
|
const unordered_map<int, int> &node_id_to_pos);
|
||||||
int prev_node);
|
|
||||||
void mutated_DFS_visit(vector<node *> &dfsList,
|
void mutated_DFS_visit(vector<node *> &dfsList,
|
||||||
vector<node*> &node_list,
|
const vector<node *> &node_list,
|
||||||
int &index,
|
int &index,
|
||||||
int &traversal_index,
|
int &traversal_index,
|
||||||
vector<int> rev_post_order,
|
const unordered_map<int, int> &node_id_to_pos,
|
||||||
int mutate_point);
|
int mutate_point,
|
||||||
|
mt19937 rng);
|
||||||
|
|
||||||
|
// custom comparator function to sort nodes according to order in given vector
|
||||||
|
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) ;
|
||||||
|
@ -155,18 +161,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(string input_file);
|
|
||||||
int compute_removed_edge_size(string input_file, vector<int> post_order);
|
// functions that prepare state
|
||||||
vector<int> generate_post_order(string input_file);
|
void init_from_graph(const ogdf::Graph &G);
|
||||||
vector<int> generate_mutated_post_order(string input_file, vector<int> post_order, int mutate_point);
|
vector<int> generate_post_order(const ogdf::Graph &G);
|
||||||
vector<int> generate_guided_post_order(string input_file, vector<int> post_order);
|
vector<int> generate_mutated_post_order(const ogdf::Graph &G, const vector<int> &post_order, int mutate_point);
|
||||||
|
vector<int> generate_guided_post_order(const ogdf::Graph &G, const vector<int> &post_order);
|
||||||
|
void postOrderTraversal();
|
||||||
|
void guidedPostOrderTraversal(const vector<int> &post_order);
|
||||||
|
void mutatedPostOrderTraversal(const 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);
|
node* get_new_node(node_type t);
|
||||||
void read_from_gml(string input_file);
|
void reset_state();
|
||||||
int output_removed_edge_size();
|
int output_removed_edge_size();
|
||||||
vector<int> return_post_order();
|
vector<int> return_post_order();
|
||||||
void postOrderTraversal();
|
|
||||||
void guidedPostOrderTraversal(vector<int> post_order);
|
|
||||||
void mutatedPostOrderTraversal(vector<int> post_order, int mutate_point);
|
|
||||||
// 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();
|
||||||
|
@ -198,4 +212,4 @@ private:
|
||||||
vector<node*> _new_node_list; //Newly added nodes.
|
vector<node*> _new_node_list; //Newly added nodes.
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // for MPS_H
|
||||||
|
|
|
@ -31,4 +31,4 @@ $(BIN_DIR) $(OBJ_DIR):
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -r $(BIN_DIR) $(OBJ_DIR)
|
rm -r $(OBJ_DIR)
|
||||||
|
|
|
@ -14,68 +14,73 @@
|
||||||
|
|
||||||
#include <ogdf/fileformats/GraphIO.h>
|
#include <ogdf/fileformats/GraphIO.h>
|
||||||
#define START_TEMP 100
|
#define START_TEMP 100
|
||||||
|
// #define TIME
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int compute_removed_edge_size(string input_file, vector<int> post_order);
|
int compute_removed_edge_size(const ogdf::Graph &G, vector<int> post_order);
|
||||||
|
|
||||||
// these functions are defined in mps_test.cpp
|
// these functions are defined in mps_test.cpp
|
||||||
// but their signatures are not in mps.h, hence they are declared here
|
// but their signatures are not in mps.h, hence they are declared here
|
||||||
vector<int> generate_post_order(string input_file);
|
ogdf::Graph read_from_gml(string input_file);
|
||||||
vector<int> generate_mutated_post_order(string input_file, vector<int> post_order, int mutate_point);
|
vector<int> generate_post_order(const ogdf::Graph &G);
|
||||||
vector<int> generate_guided_post_order(string input_file, vector<int> post_order);
|
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);
|
||||||
|
void compute_mps(const ogdf::Graph &G, int mutate_point, vector<int> &post_order, int &return_edge_size);
|
||||||
|
|
||||||
void vector_printer(vector<int> state) {
|
void vector_printer(const vector<int>& state) {
|
||||||
for (int i = 0; i < state.size(); ++i) {
|
for (size_t i = 0; i < state.size(); ++i) {
|
||||||
std::cout << state[i] << ",";
|
std::cout << state[i] << ",";
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vector<int> repeated_mutation(string input_file, 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(input_file);
|
vector<int> old_order = generate_post_order(G);
|
||||||
vector<int> state_new;
|
vector_printer(old_order);
|
||||||
|
vector<int> 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) {
|
for (int k = 0; k < k_max; ++k) {
|
||||||
std::cout << "cycle:" << k << std::endl;
|
// function compute new post_order and new_removed_size
|
||||||
|
// temp_order and new_removed_size will be updated with new values
|
||||||
|
|
||||||
vector_printer(state_old);
|
#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<std::chrono::microseconds>(end - start).count() << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// if there is an improvement
|
||||||
// mutation produces rotated view
|
// 1. update the removed size to use the new smaller size
|
||||||
state_new = generate_mutated_post_order(input_file, state_old, mutate_point);
|
// 2. update the old_order to be the new_order
|
||||||
vector_printer(state_new);
|
if (new_removed_size < old_removed_size) {
|
||||||
|
old_removed_size = new_removed_size;
|
||||||
// another round of guided post order gives canonical representation
|
old_order = temp_order;
|
||||||
state_new = generate_guided_post_order(input_file, state_new);
|
// if there is no improvement, we revert the temp_order to the old_order
|
||||||
vector_printer(state_new);
|
} else {
|
||||||
|
temp_order = old_order;
|
||||||
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
return state_new;
|
}
|
||||||
|
return old_order;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
|
||||||
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.
|
||||||
|
@ -85,18 +90,22 @@ 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);
|
||||||
|
|
||||||
// generate order here
|
// generate order here
|
||||||
vector<int> post_order = repeated_mutation(input_file, k_max, mutate_point);
|
vector<int> post_order = repeated_mutation(G, k_max);
|
||||||
// test_correctness(input_file);
|
|
||||||
|
// test timing of function
|
||||||
|
// 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, ","));
|
||||||
// int removed_edges = compute_removed_edge_size(input_file, post_order);
|
std::cout << std::endl;
|
||||||
// std::cout << "Number of removed edges: " << removed_edges << std::endl;
|
int removed_edges = compute_removed_edge_size(G, post_order);
|
||||||
|
std::cout << "Number of removed edges: " << removed_edges << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "mps.h"
|
#include "mps.h"
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
// #define DEBUG
|
// #define DEBUG
|
||||||
|
|
||||||
|
@ -12,8 +11,8 @@ maximal_planar_subgraph_finder::maximal_planar_subgraph_finder() {}
|
||||||
|
|
||||||
//Destructor
|
//Destructor
|
||||||
maximal_planar_subgraph_finder::~maximal_planar_subgraph_finder() {
|
maximal_planar_subgraph_finder::~maximal_planar_subgraph_finder() {
|
||||||
for (int i = 0; i < _node_list.size(); ++i) delete _node_list[i];
|
for (size_t i = 0; i < _node_list.size(); ++i) delete _node_list[i];
|
||||||
for (int i = 0; i < _new_node_list.size(); ++i) delete _new_node_list[i];
|
for (size_t i = 0; i < _new_node_list.size(); ++i) delete _new_node_list[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
node*
|
node*
|
||||||
|
@ -25,7 +24,9 @@ maximal_planar_subgraph_finder::get_new_node(node_type t) {
|
||||||
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;
|
||||||
for (int i = 0; i < _post_order_list.size(); ++i) {
|
// 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());
|
post_order.push_back(_post_order_list[i]->node_id());
|
||||||
}
|
}
|
||||||
return post_order;
|
return post_order;
|
||||||
|
@ -37,7 +38,7 @@ maximal_planar_subgraph_finder::postOrderTraversal() {
|
||||||
node::init_mark();
|
node::init_mark();
|
||||||
// always start with node 0
|
// always start with node 0
|
||||||
int postOrderID = 0;
|
int postOrderID = 0;
|
||||||
for (int i = 0; i < _node_list.size(); ++i) {
|
for (size_t i = 0; i < _node_list.size(); ++i) {
|
||||||
if (!_node_list[i]->is_marked()) {
|
if (!_node_list[i]->is_marked()) {
|
||||||
_node_list[i]->DFS_visit(_post_order_list, postOrderID);
|
_node_list[i]->DFS_visit(_post_order_list, postOrderID);
|
||||||
}
|
}
|
||||||
|
@ -49,33 +50,49 @@ maximal_planar_subgraph_finder::postOrderTraversal() {
|
||||||
// take in a post-order argument then traces the graph in the same order
|
// take in a post-order argument then traces the graph in the same order
|
||||||
// return is by reference via _post_order_list
|
// return is by reference via _post_order_list
|
||||||
void
|
void
|
||||||
maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector<int> post_order) {
|
maximal_planar_subgraph_finder::guidedPostOrderTraversal(const vector<int> &post_order) {
|
||||||
node::init_mark();
|
node::init_mark();
|
||||||
|
|
||||||
vector<int> rev_post_order;
|
// // implementation 1: pass reversed vector
|
||||||
for (int i = post_order.size() - 1; i >= 0; --i) {
|
// vector<int> rev_post_order;
|
||||||
rev_post_order.push_back(post_order[i]);
|
// for (int i = post_order.size() - 1; i >= 0; --i) {
|
||||||
}
|
// rev_post_order.push_back(post_order[i]);
|
||||||
int postOrderID = 0;
|
// }
|
||||||
|
// int start = rev_post_order[0];
|
||||||
|
|
||||||
|
|
||||||
|
// implementation 2: use unordered_map to map node_id to position in reversed post_order
|
||||||
|
unordered_map<int, int> 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<size_t>::max(); --i) {
|
||||||
|
node_id_to_pos[post_order[i]] = j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int postOrderID = 0;
|
||||||
int end_condition = _node_list.size();
|
int end_condition = _node_list.size();
|
||||||
int start = rev_post_order[0];
|
// 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;
|
int i = start;
|
||||||
|
|
||||||
int prev_node = INT_MAX;
|
// reserve for _post_order_list to decrease reallocation
|
||||||
|
_post_order_list.reserve(_node_list.size());
|
||||||
|
|
||||||
|
|
||||||
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, prev_node);
|
_node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, node_id_to_pos);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
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, prev_node);
|
_node_list[i]->guided_DFS_visit(_post_order_list, _node_list, postOrderID, node_id_to_pos);
|
||||||
}
|
}
|
||||||
i = (i + 1) % end_condition;
|
i = (i + 1) % end_condition;
|
||||||
}
|
}
|
||||||
|
@ -85,23 +102,50 @@ maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector<int> post_order)
|
||||||
// take in a post-order argument then traces the graph in the same order
|
// take in a post-order argument then traces the graph in the same order
|
||||||
// return is by reference via _post_order_list
|
// 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(const vector<int> &post_order, int mutate_point) {
|
||||||
node::init_mark();
|
node::init_mark();
|
||||||
|
|
||||||
vector<int> rev_post_order;
|
// // implementation 1: use vector
|
||||||
for (int i = post_order.size() - 1; i >= 0; --i) {
|
// vector<int> rev_post_order;
|
||||||
rev_post_order.push_back(post_order[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]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// implementation 2: use unordered_map to map node_id to position in reversed post_order
|
||||||
|
unordered_map<int, int> 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<size_t>::max(); --i) {
|
||||||
|
node_id_to_pos[post_order[i]] = j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int postOrderID = 0;
|
int postOrderID = 0;
|
||||||
int traversal_index = 0;
|
int traversal_index = 0;
|
||||||
|
|
||||||
// Define the range [0, n]
|
// setup random rng function
|
||||||
int n = _node_list.size() - 1; // Change 'n' to your desired upper bound
|
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
|
// set loop variables
|
||||||
int start = rev_post_order[0];
|
|
||||||
int i = start;
|
int i = start;
|
||||||
|
|
||||||
|
// reserve for _post_order_list to decrease reallocation
|
||||||
|
_post_order_list.reserve(_node_list.size());
|
||||||
|
|
||||||
|
|
||||||
int end_condition = _node_list.size();
|
int end_condition = _node_list.size();
|
||||||
// this loop assumes start is not from 0
|
// this loop assumes start is not from 0
|
||||||
|
@ -112,13 +156,13 @@ maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector<int> post_order
|
||||||
{
|
{
|
||||||
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, node_id_to_pos, mutate_point, rng);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
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, node_id_to_pos, mutate_point, rng);
|
||||||
}
|
}
|
||||||
i = (i + 1) % end_condition;
|
i = (i + 1) % end_condition;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +171,7 @@ maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector<int> post_order
|
||||||
void
|
void
|
||||||
maximal_planar_subgraph_finder::print_post_order() {
|
maximal_planar_subgraph_finder::print_post_order() {
|
||||||
int current_index;
|
int current_index;
|
||||||
for (int i = 0; i < _post_order_list.size(); ++i) {
|
for (size_t i = 0; i < _post_order_list.size(); ++i) {
|
||||||
current_index = _post_order_list[i]->node_id();
|
current_index = _post_order_list[i]->node_id();
|
||||||
std::cout << current_index << ",";
|
std::cout << current_index << ",";
|
||||||
}
|
}
|
||||||
|
@ -149,12 +193,12 @@ void
|
||||||
maximal_planar_subgraph_finder::sort_adj_list() {
|
maximal_planar_subgraph_finder::sort_adj_list() {
|
||||||
vector<vector<node*> > vecList;
|
vector<vector<node*> > vecList;
|
||||||
vecList.resize(_post_order_list.size());
|
vecList.resize(_post_order_list.size());
|
||||||
for (int i = 0; i < _post_order_list.size(); ++i) {
|
for (size_t i = 0; i < _post_order_list.size(); ++i) {
|
||||||
for (int j = 0; j < _post_order_list[i]->degree(); ++j) {
|
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]);
|
vecList[_post_order_list[i]->adj(j)->post_order_index()].push_back(_post_order_list[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < _post_order_list.size(); ++i) {
|
for (size_t i = 0; i < _post_order_list.size(); ++i) {
|
||||||
_post_order_list[i]->set_adj_list(vecList[i]);
|
_post_order_list[i]->set_adj_list(vecList[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,20 +207,20 @@ maximal_planar_subgraph_finder::sort_adj_list() {
|
||||||
//Order the edges properly.
|
//Order the edges properly.
|
||||||
void
|
void
|
||||||
maximal_planar_subgraph_finder::determine_edges() {
|
maximal_planar_subgraph_finder::determine_edges() {
|
||||||
for (int i = 0; i < _post_order_list.size(); ++i) {
|
for (size_t i = 0; i < _post_order_list.size(); ++i) {
|
||||||
if (_post_order_list[i]->parent() == 0) continue;
|
if (_post_order_list[i]->parent() == 0) continue;
|
||||||
_post_order_list[i]->set_1st_label(_post_order_list[i]->parent()->post_order_index());
|
_post_order_list[i]->set_1st_label(_post_order_list[i]->parent()->post_order_index());
|
||||||
_edge_list.push_back(pair<node*, node*> (_post_order_list[i]->parent(), _post_order_list[i]));
|
_edge_list.push_back(pair<node*, node*> (_post_order_list[i]->parent(), _post_order_list[i]));
|
||||||
}
|
}
|
||||||
for (int i = 0; i < _post_order_list.size(); ++i) {
|
for (size_t i = 0; i < _post_order_list.size(); ++i) {
|
||||||
for (int j = 0; j < _post_order_list[i]->degree(); ++j) {
|
for (int j = 0; j < _post_order_list[i]->degree(); ++j) {
|
||||||
if (_post_order_list[i]->adj(j)->post_order_index() > i) break;
|
if (_post_order_list[i]->adj(j)->post_order_index() > static_cast<int>(i)) break;
|
||||||
if (_post_order_list[i]->adj(j)->get_1st_label() == i) continue;
|
if (_post_order_list[i]->adj(j)->get_1st_label() == static_cast<int>(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(false);
|
_is_back_edge_eliminate.push_back(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < _post_order_list.size(); ++i) {
|
for (size_t i = 0; i < _post_order_list.size(); ++i) {
|
||||||
_post_order_list[i]->set_1st_label(INT_MAX);
|
_post_order_list[i]->set_1st_label(INT_MAX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,7 +230,7 @@ void
|
||||||
maximal_planar_subgraph_finder::back_edge_traversal() {
|
maximal_planar_subgraph_finder::back_edge_traversal() {
|
||||||
node* i_node = 0;
|
node* i_node = 0;
|
||||||
node* current_node = 0;
|
node* current_node = 0;
|
||||||
for (int i = 0; i < _back_edge_list.size(); ++i) {
|
for (size_t i = 0; i < _back_edge_list.size(); ++i) {
|
||||||
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;
|
||||||
if (!back_edge_traversal(current_node, i_node->post_order_index())) _is_back_edge_eliminate[i] = true;
|
if (!back_edge_traversal(current_node, i_node->post_order_index())) _is_back_edge_eliminate[i] = true;
|
||||||
|
@ -463,7 +507,7 @@ maximal_planar_subgraph_finder::trim(node* u) {
|
||||||
new_AE_root = get_new_node(AE_VIRTUAL_ROOT);
|
new_AE_root = get_new_node(AE_VIRTUAL_ROOT);
|
||||||
new_AE_root->init_AE(node_list[0]);
|
new_AE_root->init_AE(node_list[0]);
|
||||||
//Eliminate the children other than the path.
|
//Eliminate the children other than the path.
|
||||||
for (int i = 1; i < node_list.size(); ++i) {
|
for (size_t i = 1; i < node_list.size(); ++i) {
|
||||||
for (int j = 0; j < node_list[i]->child_num(); ++j) {
|
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));
|
if (node_list[i]->child(j) != node_list[i-1]) eliminate(node_list[i]->child(j));
|
||||||
}
|
}
|
||||||
|
@ -473,7 +517,7 @@ maximal_planar_subgraph_finder::trim(node* u) {
|
||||||
else {
|
else {
|
||||||
node_list[0]->set_to_boundary_path(down, node_list[1]);
|
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]);
|
node_list[node_list.size()-1]->set_to_boundary_path(up, node_list[node_list.size()-2]);
|
||||||
for (int i = 1; i < node_list.size()-1; ++i) {
|
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]);
|
node_list[i]->set_to_boundary_path(node_list[i-1], node_list[i+1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -481,7 +525,7 @@ maximal_planar_subgraph_finder::trim(node* u) {
|
||||||
up_next = up->get_next(node_list[node_list.size()-1]);
|
up_next = up->get_next(node_list[node_list.size()-1]);
|
||||||
down_next = down->get_next(node_list[0]);
|
down_next = down->get_next(node_list[0]);
|
||||||
//Unfold the c-nodes in the node_list.
|
//Unfold the c-nodes in the node_list.
|
||||||
for (int i = 0; i < node_list.size(); ++i) {
|
for (size_t i = 0; i < node_list.size(); ++i) {
|
||||||
if (node_list[i]->type() == C_NODE) c_node_extension(node_list[i]);
|
if (node_list[i]->type() == C_NODE) c_node_extension(node_list[i]);
|
||||||
}
|
}
|
||||||
//Return the new boundary.
|
//Return the new boundary.
|
||||||
|
@ -655,7 +699,7 @@ maximal_planar_subgraph_finder::parallel_search_sentinel(node* n0, node* n0_prev
|
||||||
}
|
}
|
||||||
|
|
||||||
//If the c-node found is top-tier, then assign all the traversed node a pointer to c-node.
|
//If the c-node found is top-tier, then assign all the traversed node a pointer to c-node.
|
||||||
for (int i = 0; i < traversed.size(); ++i) traversed[i]->set_c_node(c);
|
for (size_t i = 0; i < traversed.size(); ++i) traversed[i]->set_c_node(c);
|
||||||
return pair<node*, node*>((node*)0, (node*)0);
|
return pair<node*, node*>((node*)0, (node*)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,7 +747,7 @@ pair<node*, node*> maximal_planar_subgraph_finder::count_sentinel_elimination(pa
|
||||||
node*
|
node*
|
||||||
maximal_planar_subgraph_finder::construct(node* u) {
|
maximal_planar_subgraph_finder::construct(node* u) {
|
||||||
//Basic works.
|
//Basic works.
|
||||||
int i_label = u->get_1st_label();
|
// int i_label = u->get_1st_label(); // unused
|
||||||
node* node_i = _post_order_list[u->get_1st_label()];
|
node* node_i = _post_order_list[u->get_1st_label()];
|
||||||
parenting_labeling_shaving(u, node_i);
|
parenting_labeling_shaving(u, node_i);
|
||||||
|
|
||||||
|
@ -751,7 +795,7 @@ maximal_planar_subgraph_finder::construct(node* u) {
|
||||||
node*
|
node*
|
||||||
maximal_planar_subgraph_finder::construct(node* c, node* p) {
|
maximal_planar_subgraph_finder::construct(node* c, node* p) {
|
||||||
//Basic works.
|
//Basic works.
|
||||||
int i_label = c->get_1st_label();
|
// int i_label = c->get_1st_label(); // unused var
|
||||||
node* node_i = _post_order_list[c->get_1st_label()];
|
node* node_i = _post_order_list[c->get_1st_label()];
|
||||||
parenting_labeling_shaving(p, node_i);
|
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.
|
//note: Now, c must have exactly two children left, and c has a parent-link to p, p has achild link to c, too.
|
||||||
|
@ -822,11 +866,11 @@ maximal_planar_subgraph_finder::parenting_labeling_shaving(node* u, node* node_i
|
||||||
u_i_path.push_back(u_i_path[u_i_path.size()-1]->parent());
|
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;
|
if (u_i_path[u_i_path.size()-1] == node_i) break;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < u_i_path.size()-2; ++i) {
|
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]->add_child(u_i_path[i+1]);
|
||||||
u_i_path[i+1]->set_parent(u_i_path[i]);
|
u_i_path[i+1]->set_parent(u_i_path[i]);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < u_i_path.size()-2; ++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) {
|
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]) {
|
if (u_i_path[i+1]->child(j) == u_i_path[i]) {
|
||||||
u_i_path[i+1]->remove_child(j);
|
u_i_path[i+1]->remove_child(j);
|
||||||
|
|
|
@ -2,10 +2,14 @@
|
||||||
// Implementation of a MPS algorithm via PC-tree.
|
// Implementation of a MPS algorithm via PC-tree.
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include "mps.h"
|
#include "mps.h"
|
||||||
|
|
||||||
#include <ogdf/fileformats/GraphIO.h>
|
#include <ogdf/fileformats/GraphIO.h>
|
||||||
|
|
||||||
// #define DEBUG
|
// #define DEBUG
|
||||||
|
// #define DEBUG_2
|
||||||
|
// #define TIME
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// Finding MPS
|
// Finding MPS
|
||||||
|
@ -13,36 +17,54 @@
|
||||||
|
|
||||||
// programs to call from main:
|
// programs to call from main:
|
||||||
|
|
||||||
int find_mps(string input_file) {
|
// read input file of gml format
|
||||||
maximal_planar_subgraph_finder m;
|
ogdf::Graph read_from_gml(string input_file) {
|
||||||
return m.find_mps(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 compute_removed_edge_size(string input_file, vector<int> post_order) {
|
|
||||||
|
int find_mps(const ogdf::Graph &G) {
|
||||||
maximal_planar_subgraph_finder m;
|
maximal_planar_subgraph_finder m;
|
||||||
return m.compute_removed_edge_size(input_file, post_order);
|
return m.find_mps(G);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int> generate_post_order(string input_file) {
|
int compute_removed_edge_size(const ogdf::Graph &G, vector<int> post_order) {
|
||||||
maximal_planar_subgraph_finder m;
|
maximal_planar_subgraph_finder m;
|
||||||
return m.generate_post_order(input_file);
|
return m.compute_removed_edge_size(G, post_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int> generate_mutated_post_order(string input_file, vector<int> post_order, int mutate_point) {
|
vector<int> generate_post_order(const ogdf::Graph &G) {
|
||||||
maximal_planar_subgraph_finder m;
|
maximal_planar_subgraph_finder m;
|
||||||
return m.generate_mutated_post_order(input_file, post_order, mutate_point);
|
return m.generate_post_order(G);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int> generate_guided_post_order(string input_file, vector<int> post_order) {
|
vector<int> generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point) {
|
||||||
maximal_planar_subgraph_finder m;
|
maximal_planar_subgraph_finder m;
|
||||||
return m.generate_guided_post_order(input_file, post_order);
|
return m.generate_mutated_post_order(G, post_order, mutate_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<int> generate_guided_post_order(const ogdf::Graph &G, vector<int> 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<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(string input_file) {
|
int maximal_planar_subgraph_finder::find_mps(const ogdf::Graph &G) {
|
||||||
read_from_gml(input_file);
|
init_from_graph(G);
|
||||||
postOrderTraversal();
|
postOrderTraversal();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -55,8 +77,8 @@ 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) {
|
vector<int> maximal_planar_subgraph_finder::generate_post_order(const ogdf::Graph &G) {
|
||||||
read_from_gml(input_file);
|
init_from_graph(G);
|
||||||
postOrderTraversal();
|
postOrderTraversal();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -68,8 +90,9 @@ vector<int> maximal_planar_subgraph_finder::generate_post_order(string input_fil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(string input_file, vector<int> post_order, int mutate_point) {
|
vector<int> maximal_planar_subgraph_finder::generate_mutated_post_order(const ogdf::Graph &G, const vector<int> &post_order, int mutate_point) {
|
||||||
read_from_gml(input_file);
|
init_from_graph(G);
|
||||||
|
|
||||||
mutatedPostOrderTraversal(post_order, mutate_point);
|
mutatedPostOrderTraversal(post_order, mutate_point);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -81,8 +104,8 @@ vector<int> maximal_planar_subgraph_finder::generate_mutated_post_order(string i
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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_guided_post_order(string input_file, vector<int> post_order) {
|
vector<int> maximal_planar_subgraph_finder::generate_guided_post_order(const ogdf::Graph &G, const vector<int> &post_order) {
|
||||||
read_from_gml(input_file);
|
init_from_graph(G);
|
||||||
guidedPostOrderTraversal(post_order);
|
guidedPostOrderTraversal(post_order);
|
||||||
|
|
||||||
// #ifdef DEBUG
|
// #ifdef DEBUG
|
||||||
|
@ -95,36 +118,48 @@ vector<int> maximal_planar_subgraph_finder::generate_guided_post_order(string in
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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(const ogdf::Graph &G, vector<int> post_order) {
|
||||||
read_from_gml(input_file);
|
// read_from_gml
|
||||||
|
init_from_graph(G);
|
||||||
|
|
||||||
|
// guidedPostOrderTraversal
|
||||||
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_removed_edge_size();
|
return output_removed_edge_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
void maximal_planar_subgraph_finder::reset_state() {
|
||||||
// Imput, output
|
_post_order_list.clear();
|
||||||
//-----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// read input file of gml format
|
|
||||||
void maximal_planar_subgraph_finder::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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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
|
// create nodes
|
||||||
|
_node_list.reserve(G.numberOfNodes());
|
||||||
for (int i = 0; i < G.numberOfNodes(); ++i) {
|
for (int i = 0; i < G.numberOfNodes(); ++i) {
|
||||||
_node_list.push_back(new node(P_NODE));
|
_node_list.push_back(new node(P_NODE));
|
||||||
_node_list[i]->set_id(i);
|
_node_list[i]->set_id(i);
|
||||||
|
@ -144,7 +179,7 @@ void maximal_planar_subgraph_finder::read_from_gml(string input_file) {
|
||||||
// count the number of removed edges
|
// count the number of removed edges
|
||||||
int maximal_planar_subgraph_finder::output_removed_edge_size() {
|
int maximal_planar_subgraph_finder::output_removed_edge_size() {
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
for (int i = 0; i < _back_edge_list.size(); ++i) {
|
for (size_t i = 0; i < _back_edge_list.size(); ++i) {
|
||||||
if (_is_back_edge_eliminate[i]) ++sum;
|
if (_is_back_edge_eliminate[i]) ++sum;
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "mps.h"
|
#include "mps.h"
|
||||||
|
|
||||||
// #define DEBUG
|
// #define DEBUG
|
||||||
#define DEBUG_MUTATION
|
// #define DEBUG_MUTATION
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// CONSTRUCTOR
|
// CONSTRUCTOR
|
||||||
|
@ -37,7 +37,7 @@ void node::set_post_order_index(int i) {_post_order_index = i;}
|
||||||
//Only used when consturcting c-node
|
//Only used when consturcting c-node
|
||||||
//The first node calling this function would not be labeled.
|
//The first node calling this function would not be labeled.
|
||||||
void node::recursively_labeling() {
|
void node::recursively_labeling() {
|
||||||
for (int i = 0; i < _children.size(); ++i) {
|
for (size_t i = 0; i < _children.size(); ++i) {
|
||||||
_children[i]->_label.second = ARTIFICIAL_EDGE;
|
_children[i]->_label.second = ARTIFICIAL_EDGE;
|
||||||
_children[i]->recursively_labeling();
|
_children[i]->recursively_labeling();
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ void node::set_adj_list(vector<node*> vec) {_adj_list = vec;}
|
||||||
|
|
||||||
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 (size_t i = 0; i < _adj_list.size(); ++i) {
|
||||||
if (!_adj_list[i]->is_marked()) {
|
if (!_adj_list[i]->is_marked()) {
|
||||||
_adj_list[i]->_parent = this;
|
_adj_list[i]->_parent = this;
|
||||||
_adj_list[i]->DFS_visit(dfsList, index);
|
_adj_list[i]->DFS_visit(dfsList, index);
|
||||||
|
@ -70,11 +70,19 @@ void node::DFS_visit(vector<node*> &dfsList, int &index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool node::sortByOrder(const std::unordered_map<int, int>& 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<node *> &dfsList,
|
void node::guided_DFS_visit(vector<node *> &dfsList,
|
||||||
vector<node *> &node_list,
|
const vector<node *> &node_list,
|
||||||
int &return_index,
|
int &return_index,
|
||||||
vector<int> rev_post_order,
|
const unordered_map<int, int> &node_id_to_pos)
|
||||||
int prev_node)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
mark();
|
mark();
|
||||||
|
@ -82,28 +90,35 @@ void node::guided_DFS_visit(vector<node *> &dfsList,
|
||||||
// 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
|
||||||
// we want to select neighbors that match the rev_post_order at the specific traversal_index
|
// we want to select neighbors that match the rev_post_order at the specific traversal_index
|
||||||
|
|
||||||
// create an unordered set to efficiently check for presence of an element
|
// implementation 1: loop through all elements
|
||||||
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) {
|
// std::unordered_set<int> neighbor_set;
|
||||||
neighbor_set.insert(_adj_list[i]->node_id());
|
// 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
|
// // when an element in rev_post_order is found in neighbor_set, we add that to neighbor_list
|
||||||
// it is ok if the neighbor was already visited before,
|
// // this produces a neighbor_list that follows the order by which they occur in the rev_post_order
|
||||||
// it would've been marked and will be subsequently ignored
|
// // it is ok if the neighbor was already visited before,
|
||||||
vector<node *> neighbor_list;
|
// // it would've been marked and will be subsequently ignored
|
||||||
for (int i = 0; i < rev_post_order.size(); ++i) {
|
// vector<node *> neighbor_list;
|
||||||
if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) {
|
// for (int i = 0; i < rev_post_order.size(); ++i) {
|
||||||
// only add if newly encountered
|
// if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) {
|
||||||
if (!node_list[rev_post_order[i]]->is_marked()) {
|
// // only add if newly encountered
|
||||||
neighbor_list.push_back(node_list[rev_post_order[i]]);
|
// 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<node*> 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
|
#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() << ")" << ",";
|
||||||
}
|
}
|
||||||
|
@ -112,10 +127,10 @@ void node::guided_DFS_visit(vector<node *> &dfsList,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < neighbor_list.size(); ++i) {
|
for (size_t 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, this->node_id());
|
neighbor_list[i]->guided_DFS_visit(dfsList, node_list, return_index, node_id_to_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,13 +139,13 @@ void node::guided_DFS_visit(vector<node *> &dfsList,
|
||||||
++return_index;
|
++return_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void node::mutated_DFS_visit(vector<node *> &dfsList,
|
void node::mutated_DFS_visit(vector<node *> &dfsList,
|
||||||
vector<node*> &node_list,
|
const vector<node *> &node_list,
|
||||||
int &return_index,
|
int &return_index,
|
||||||
int &traversal_index,
|
int &traversal_index,
|
||||||
vector<int> rev_post_order,
|
const unordered_map<int, int> &node_id_to_pos,
|
||||||
int mutate_point)
|
int mutate_point,
|
||||||
|
mt19937 rng)
|
||||||
{
|
{
|
||||||
|
|
||||||
// mark current node
|
// mark current node
|
||||||
|
@ -139,53 +154,57 @@ void node::mutated_DFS_visit(vector<node*> &dfsList,
|
||||||
// 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
|
||||||
// we want to select neighbors that match the rev_post_order at the specific traversal_index
|
// we want to select neighbors that match the rev_post_order at the specific traversal_index
|
||||||
|
|
||||||
// create an unordered set to efficiently check for presence of an element
|
// // implementation 1: naively check by running through all elements of rev_post_order
|
||||||
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) {
|
// std::unordered_set<int> neighbor_set;
|
||||||
neighbor_set.insert(_adj_list[i]->node_id());
|
// 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
|
// // when an element in rev_post_order is found in neighbor_set, we add that to neighbor_list
|
||||||
// it is ok if the neighbor was already visited before,
|
// // this produces a neighbor_list that follows the order by which they occur in the rev_post_order
|
||||||
// it would've been marked and will be subsequently ignored
|
// // it is ok if the neighbor was already visited before,
|
||||||
vector<node *> neighbor_list;
|
// // it would've been marked and will be subsequently ignored
|
||||||
for (int i = 0; i < rev_post_order.size(); ++i) {
|
// vector<node *> neighbor_list;
|
||||||
if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) {
|
// for (size_t i = 0; i < rev_post_order.size(); ++i) {
|
||||||
neighbor_list.push_back(node_list[rev_post_order[i]]);
|
// if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) {
|
||||||
}
|
// neighbor_list.push_back(node_list[rev_post_order[i]]);
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
vector<node*> neighbor_list = _adj_list;
|
||||||
|
|
||||||
// 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
|
||||||
if (traversal_index == mutate_point) {
|
if (traversal_index == mutate_point) {
|
||||||
// Create a random number generator and seed it
|
// we shuffle the neighbor list
|
||||||
// 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);
|
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
|
#ifdef DEBUG_MUTATION
|
||||||
std::cout << "current node:" << this->node_id() << std::endl;
|
std::cout << "current node:" << this->node_id() << std::endl;
|
||||||
for (int i = 0; i < neighbor_list.size(); ++i) {
|
for (size_t 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() << ")" << ",";
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// increment traversal index after checking
|
// increment traversal index after checking
|
||||||
// next node will receive incremented index
|
// next node will receive incremented index
|
||||||
traversal_index++;
|
traversal_index++;
|
||||||
|
|
||||||
for (int i = 0; i < neighbor_list.size(); ++i)
|
for (size_t 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]->mutated_DFS_visit(dfsList, node_list, return_index, traversal_index, rev_post_order, mutate_point);
|
neighbor_list[i]->mutated_DFS_visit(dfsList, node_list, return_index, traversal_index, node_id_to_pos, mutate_point, rng);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +232,7 @@ void node::remove_child(int i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void node::remove_child(node* n) {
|
void node::remove_child(node* n) {
|
||||||
for (int i = 0; i < _children.size(); ++i) {
|
for (size_t i = 0; i < _children.size(); ++i) {
|
||||||
if (_children[i] == n) {
|
if (_children[i] == n) {
|
||||||
_children[i] = _children[_children.size()-1];
|
_children[i] = _children[_children.size()-1];
|
||||||
_children.resize(_children.size()-1);
|
_children.resize(_children.size()-1);
|
||||||
|
@ -289,7 +308,7 @@ void node::init_AE(node* u) {
|
||||||
if (u->child_num() == 0) return;
|
if (u->child_num() == 0) return;
|
||||||
_children = u->_children;
|
_children = u->_children;
|
||||||
u->clear_children();
|
u->clear_children();
|
||||||
for (int i = 0; i < _children.size(); ++i) {
|
for (size_t i = 0; i < _children.size(); ++i) {
|
||||||
_children[i]->set_parent(this);
|
_children[i]->set_parent(this);
|
||||||
}
|
}
|
||||||
set_parent(u);
|
set_parent(u);
|
||||||
|
|
Loading…
Reference in New Issue