234 lines
7.2 KiB
C++
234 lines
7.2 KiB
C++
//-----------------------------------------------------------------------------------
|
|
// Implementation of a MPS algorithm via PC-tree.
|
|
//-----------------------------------------------------------------------------------
|
|
|
|
#include <chrono>
|
|
#include "mps.h"
|
|
|
|
#include <ogdf/fileformats/GraphIO.h>
|
|
|
|
// #define DEBUG
|
|
#define DEBUG_2
|
|
// #define TIME
|
|
|
|
//-----------------------------------------------------------------------------------
|
|
// Finding MPS
|
|
//-----------------------------------------------------------------------------------
|
|
|
|
// programs to call from main:
|
|
|
|
// read input file of gml format
|
|
ogdf::Graph 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;
|
|
}
|
|
return G;
|
|
}
|
|
|
|
|
|
int find_mps(const ogdf::Graph &G) {
|
|
maximal_planar_subgraph_finder m;
|
|
return m.find_mps(G);
|
|
}
|
|
|
|
int compute_removed_edge_size(const ogdf::Graph &G, vector<int> post_order) {
|
|
maximal_planar_subgraph_finder m;
|
|
return m.compute_removed_edge_size(G, post_order);
|
|
}
|
|
|
|
vector<int> generate_post_order(const ogdf::Graph &G) {
|
|
maximal_planar_subgraph_finder m;
|
|
return m.generate_post_order(G);
|
|
}
|
|
|
|
vector<int> generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point) {
|
|
maximal_planar_subgraph_finder m;
|
|
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(const ogdf::Graph &G) {
|
|
init_from_graph(G);
|
|
postOrderTraversal();
|
|
|
|
#ifdef DEBUG
|
|
print_post_order();
|
|
#endif
|
|
|
|
sort_adj_list();
|
|
determine_edges();
|
|
back_edge_traversal();
|
|
return output_removed_edge_size();
|
|
}
|
|
|
|
vector<int> maximal_planar_subgraph_finder::generate_post_order(const ogdf::Graph &G) {
|
|
init_from_graph(G);
|
|
postOrderTraversal();
|
|
|
|
#ifdef DEBUG
|
|
std::cout << "standard post order traversal" << std::endl;
|
|
print_post_order();
|
|
#endif
|
|
|
|
return return_post_order();
|
|
}
|
|
|
|
// result of this will be used as input to "compute_removed_edge_size"
|
|
vector<int> maximal_planar_subgraph_finder::generate_mutated_post_order(const ogdf::Graph &G, vector<int> post_order, int mutate_point) {
|
|
init_from_graph(G);
|
|
|
|
mutatedPostOrderTraversal(post_order, mutate_point);
|
|
|
|
#ifdef DEBUG
|
|
std::cout << "mutated post order traversal" << std::endl;
|
|
print_post_order();
|
|
#endif
|
|
|
|
return return_post_order();
|
|
}
|
|
|
|
// result of this will be used as input to "compute_removed_edge_size"
|
|
vector<int> maximal_planar_subgraph_finder::generate_guided_post_order(const ogdf::Graph &G, vector<int> post_order) {
|
|
init_from_graph(G);
|
|
guidedPostOrderTraversal(post_order);
|
|
|
|
// #ifdef DEBUG
|
|
// std::cout << "guided post order traversal" << std::endl;
|
|
// print_post_order();
|
|
// #endif
|
|
|
|
return return_post_order();
|
|
}
|
|
|
|
|
|
|
|
int maximal_planar_subgraph_finder::compute_removed_edge_size(const ogdf::Graph &G, vector<int> post_order) {
|
|
// read_from_gml
|
|
#ifdef TIME
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
#endif
|
|
init_from_graph(G);
|
|
#ifdef TIME
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
std::cout << "init from G: " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << std::endl;
|
|
#endif
|
|
|
|
// guidedPostOrderTraversal
|
|
#ifdef TIME
|
|
start = std::chrono::high_resolution_clock::now();
|
|
#endif
|
|
guidedPostOrderTraversal(post_order);
|
|
// postOrderTraversal();
|
|
#ifdef TIME
|
|
end = std::chrono::high_resolution_clock::now();
|
|
std::cout << "guidedPostOrderTraversal: " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << std::endl;
|
|
#endif
|
|
|
|
// remaining procedure
|
|
#ifdef TIME
|
|
start = std::chrono::high_resolution_clock::now();
|
|
#endif
|
|
sort_adj_list();
|
|
#ifdef TIME
|
|
end = std::chrono::high_resolution_clock::now();
|
|
std::cout << "sort_adj_list: " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << std::endl;
|
|
#endif
|
|
|
|
#ifdef TIME
|
|
start = std::chrono::high_resolution_clock::now();
|
|
#endif
|
|
determine_edges();
|
|
#ifdef TIME
|
|
end = std::chrono::high_resolution_clock::now();
|
|
std::cout << "determine edges: " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << std::endl;
|
|
#endif
|
|
|
|
#ifdef TIME
|
|
start = std::chrono::high_resolution_clock::now();
|
|
#endif
|
|
back_edge_traversal();
|
|
#ifdef TIME
|
|
end = std::chrono::high_resolution_clock::now();
|
|
std::cout << "back edge traversal: " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << std::endl;
|
|
#endif
|
|
|
|
|
|
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
|
|
//-----------------------------------------------------------------------------------
|
|
|
|
void maximal_planar_subgraph_finder::init_from_graph(const ogdf::Graph &G) {
|
|
// create nodes
|
|
for (int i = 0; i < G.numberOfNodes(); ++i) {
|
|
_node_list.push_back(new node(P_NODE));
|
|
_node_list[i]->set_id(i);
|
|
}
|
|
|
|
// create edges
|
|
for (ogdf::edge e : G.edges) {
|
|
ogdf::node source = e->source();
|
|
ogdf::node target = e->target();
|
|
_node_list[source->index()]->add_adj(_node_list[target->index()]);
|
|
_node_list[target->index()]->add_adj(_node_list[source->index()]);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// count the number of removed edges
|
|
int maximal_planar_subgraph_finder::output_removed_edge_size() {
|
|
int sum = 0;
|
|
for (size_t i = 0; i < _back_edge_list.size(); ++i) {
|
|
if (_is_back_edge_eliminate[i]) ++sum;
|
|
}
|
|
return sum;
|
|
} |