Fix: mutate starting node also
Perf: use reserve for containers, use const reference
This commit is contained in:
parent
476c221cc2
commit
c58f2de199
|
@ -63,12 +63,13 @@ public:
|
|||
const vector<node *> &node_list,
|
||||
int &return_index,
|
||||
const unordered_map<int, int> &node_id_to_pos);
|
||||
void mutated_DFS_visit(vector<node*> &dfsList,
|
||||
vector<node*> &node_list,
|
||||
void mutated_DFS_visit(vector<node *> &dfsList,
|
||||
vector<node *> &node_list,
|
||||
int &index,
|
||||
int &traversal_index,
|
||||
vector<int> rev_post_order,
|
||||
int mutate_point);
|
||||
const unordered_map<int, int> &node_id_to_pos,
|
||||
int mutate_point,
|
||||
mt19937 rng);
|
||||
|
||||
// custom comparator function to sort nodes according to order in given vector
|
||||
bool sortByOrder(const unordered_map<int, int>& node_id_to_pos, node* a, node* b);
|
||||
|
@ -164,11 +165,11 @@ public:
|
|||
// functions that prepare state
|
||||
void init_from_graph(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_guided_post_order(const ogdf::Graph &G, 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(vector<int> post_order);
|
||||
void mutatedPostOrderTraversal(vector<int> post_order, int mutate_point);
|
||||
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
|
||||
|
|
|
@ -52,12 +52,11 @@ vector<int> repeated_mutation(const ogdf::Graph &G, int k_max) {
|
|||
// 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) {
|
||||
// function compute new post_order and new_removed_size
|
||||
// temp_order and new_removed_size will be updated with new values
|
||||
compute_mps(G, mutate_point, temp_order, new_removed_size);
|
||||
compute_mps(G, dist(gen), temp_order, new_removed_size);
|
||||
// if there is an improvement
|
||||
// 1. update the removed size to use the new smaller size
|
||||
// 2. update the old_order to be the new_order
|
||||
|
|
|
@ -24,6 +24,8 @@ maximal_planar_subgraph_finder::get_new_node(node_type t) {
|
|||
vector<int>
|
||||
maximal_planar_subgraph_finder::return_post_order() {
|
||||
vector<int> post_order;
|
||||
// we have arg number of elements
|
||||
post_order.reserve(_post_order_list.size()); // reserve for decreased reallocation
|
||||
for (size_t i = 0; i < _post_order_list.size(); ++i) {
|
||||
post_order.push_back(_post_order_list[i]->node_id());
|
||||
}
|
||||
|
@ -48,7 +50,7 @@ maximal_planar_subgraph_finder::postOrderTraversal() {
|
|||
// take in a post-order argument then traces the graph in the same order
|
||||
// return is by reference via _post_order_list
|
||||
void
|
||||
maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector<int> post_order) {
|
||||
maximal_planar_subgraph_finder::guidedPostOrderTraversal(const vector<int> &post_order) {
|
||||
node::init_mark();
|
||||
|
||||
// // implementation 1: pass reversed vector
|
||||
|
@ -61,6 +63,7 @@ maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector<int> post_order)
|
|||
|
||||
// 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) {
|
||||
|
@ -73,6 +76,10 @@ maximal_planar_subgraph_finder::guidedPostOrderTraversal(vector<int> post_order)
|
|||
int start = post_order[post_order.size() - 1];
|
||||
int i = start;
|
||||
|
||||
// reserve for _post_order_list to decrease reallocation
|
||||
_post_order_list.reserve(_node_list.size());
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (((start > 0) && (i == (start - 1))) || ((start == 0 ) && (i == end_condition - 1)))
|
||||
|
@ -95,24 +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
|
||||
// return is by reference via _post_order_list
|
||||
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();
|
||||
|
||||
vector<int> rev_post_order;
|
||||
// // implementation 1: use vector
|
||||
// vector<int> rev_post_order;
|
||||
// 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) {
|
||||
rev_post_order.push_back(post_order[i]);
|
||||
node_id_to_pos[post_order[i]] = j++;
|
||||
}
|
||||
|
||||
int postOrderID = 0;
|
||||
int traversal_index = 0;
|
||||
|
||||
// Define the range [0, n]
|
||||
// int n = _node_list.size() - 1; // Change 'n' to your desired upper bound
|
||||
// setup random rng function
|
||||
std::random_device rd;
|
||||
std::mt19937 rng{rd()};
|
||||
|
||||
|
||||
int start = 0;
|
||||
// if we mutate first node, we will select a random starting node
|
||||
if (mutate_point == 0) {
|
||||
int first_value = 0;
|
||||
int last_value = post_order.size() - 1;
|
||||
std::uniform_int_distribution<> dist{first_value, last_value};
|
||||
start = post_order[dist(rng)];
|
||||
// if we don't mutate first, we just use the root node of the post_order
|
||||
} else {
|
||||
start = post_order[post_order.size() - 1];
|
||||
}
|
||||
|
||||
// set loop variables
|
||||
int start = rev_post_order[0];
|
||||
int i = start;
|
||||
|
||||
// reserve for _post_order_list to decrease reallocation
|
||||
_post_order_list.reserve(_node_list.size());
|
||||
|
||||
|
||||
int end_condition = _node_list.size();
|
||||
// this loop assumes start is not from 0
|
||||
|
@ -123,13 +156,13 @@ maximal_planar_subgraph_finder::mutatedPostOrderTraversal(vector<int> post_order
|
|||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <ogdf/fileformats/GraphIO.h>
|
||||
|
||||
// #define DEBUG
|
||||
#define DEBUG_2
|
||||
// #define DEBUG_2
|
||||
// #define TIME
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
@ -90,7 +90,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"
|
||||
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, const vector<int> &post_order, int mutate_point) {
|
||||
init_from_graph(G);
|
||||
|
||||
mutatedPostOrderTraversal(post_order, mutate_point);
|
||||
|
@ -104,7 +104,7 @@ vector<int> maximal_planar_subgraph_finder::generate_mutated_post_order(const og
|
|||
}
|
||||
|
||||
// result of this will be used as input to "compute_removed_edge_size"
|
||||
vector<int> maximal_planar_subgraph_finder::generate_guided_post_order(const ogdf::Graph &G, vector<int> post_order) {
|
||||
vector<int> maximal_planar_subgraph_finder::generate_guided_post_order(const ogdf::Graph &G, const vector<int> &post_order) {
|
||||
init_from_graph(G);
|
||||
guidedPostOrderTraversal(post_order);
|
||||
|
||||
|
@ -208,6 +208,7 @@ void maximal_planar_subgraph_finder::compute_mps(const ogdf::Graph &G, int mutat
|
|||
|
||||
void maximal_planar_subgraph_finder::init_from_graph(const ogdf::Graph &G) {
|
||||
// create nodes
|
||||
_node_list.reserve(G.numberOfNodes());
|
||||
for (int i = 0; i < G.numberOfNodes(); ++i) {
|
||||
_node_list.push_back(new node(P_NODE));
|
||||
_node_list[i]->set_id(i);
|
||||
|
|
|
@ -139,13 +139,13 @@ void node::guided_DFS_visit(vector<node *> &dfsList,
|
|||
++return_index;
|
||||
}
|
||||
|
||||
|
||||
void node::mutated_DFS_visit(vector<node*> &dfsList,
|
||||
vector<node*> &node_list,
|
||||
void node::mutated_DFS_visit(vector<node *> &dfsList,
|
||||
vector<node *> &node_list,
|
||||
int &return_index,
|
||||
int &traversal_index,
|
||||
vector<int> rev_post_order,
|
||||
int mutate_point)
|
||||
const unordered_map<int, int> &node_id_to_pos,
|
||||
int mutate_point,
|
||||
mt19937 rng)
|
||||
{
|
||||
|
||||
// mark current node
|
||||
|
@ -154,22 +154,37 @@ 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
|
||||
// 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
|
||||
std::unordered_set<int> neighbor_set;
|
||||
for (size_t i = 0; i < _adj_list.size(); ++i) {
|
||||
neighbor_set.insert(_adj_list[i]->node_id());
|
||||
}
|
||||
// when an element in rev_post_order is found in neighbor_set, we add that to neighbor_list
|
||||
// this produces a neighbor_list that follows the order by which they occur in the rev_post_order
|
||||
// it is ok if the neighbor was already visited before,
|
||||
// it would've been marked and will be subsequently ignored
|
||||
vector<node *> neighbor_list;
|
||||
for (size_t i = 0; i < rev_post_order.size(); ++i) {
|
||||
if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) {
|
||||
neighbor_list.push_back(node_list[rev_post_order[i]]);
|
||||
}
|
||||
// // implementation 1: naively check by running through all elements of rev_post_order
|
||||
// // create an unordered set to efficiently check for presence of an element
|
||||
// std::unordered_set<int> neighbor_set;
|
||||
// for (size_t i = 0; i < _adj_list.size(); ++i) {
|
||||
// neighbor_set.insert(_adj_list[i]->node_id());
|
||||
// }
|
||||
// // when an element in rev_post_order is found in neighbor_set, we add that to neighbor_list
|
||||
// // this produces a neighbor_list that follows the order by which they occur in the rev_post_order
|
||||
// // it is ok if the neighbor was already visited before,
|
||||
// // it would've been marked and will be subsequently ignored
|
||||
// vector<node *> neighbor_list;
|
||||
// for (size_t i = 0; i < rev_post_order.size(); ++i) {
|
||||
// if (neighbor_set.find(rev_post_order[i]) != neighbor_set.end()) {
|
||||
// neighbor_list.push_back(node_list[rev_post_order[i]]);
|
||||
// }
|
||||
// }
|
||||
|
||||
vector<node*> neighbor_list = _adj_list;
|
||||
// if the current index matches the mutate_point, then we know this is the cycle to mutate
|
||||
if (traversal_index == mutate_point) {
|
||||
// we shuffle the neighbor list
|
||||
std::shuffle(neighbor_list.begin(), neighbor_list.end(), rng);
|
||||
// otherwise just sort based on the order set by node_id_to_pos, which is
|
||||
// set by the reversed post_order
|
||||
} else {
|
||||
std::sort(neighbor_list.begin(), neighbor_list.end(), [this, &node_id_to_pos](node *a, node *b)
|
||||
{ return sortByOrder(node_id_to_pos, a, b); });
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG_MUTATION
|
||||
std::cout << "current node:" << this->node_id() << std::endl;
|
||||
for (size_t i = 0; i < neighbor_list.size(); ++i) {
|
||||
|
@ -179,17 +194,6 @@ void node::mutated_DFS_visit(vector<node*> &dfsList,
|
|||
#endif
|
||||
|
||||
|
||||
// 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) {
|
||||
// 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);
|
||||
|
||||
}
|
||||
|
||||
// increment traversal index after checking
|
||||
// next node will receive incremented index
|
||||
|
@ -200,7 +204,7 @@ void node::mutated_DFS_visit(vector<node*> &dfsList,
|
|||
if (!neighbor_list[i]->is_marked())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue