Feat: accept gml as input file
Chore: included make_graphs and make_planar
This commit is contained in:
parent
7f277b1768
commit
1e86ec5b1e
|
@ -0,0 +1,3 @@
|
||||||
|
Deferred Planarity Test implementation is from
|
||||||
|
https://code.google.com/archive/p/planarity-algorithms/. The original code is
|
||||||
|
licensed under the "New BSD License".
|
|
@ -1,2 +1,6 @@
|
||||||
.vscode
|
.vscode
|
||||||
deferred_planarity_test/bin
|
deferred_planarity_test/bin
|
||||||
|
make_graphs/bin
|
||||||
|
make_graphs/test_graphs
|
||||||
|
make_planar/bin
|
||||||
|
test_area
|
||||||
|
|
|
@ -3,33 +3,14 @@
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <string>
|
||||||
#include "mps.h"
|
#include "mps.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void find_mps(ifstream*, ofstream*);
|
int find_mps(string input_file);
|
||||||
|
|
||||||
//n nodes, with the probability of existence of each edge being p.
|
|
||||||
void random_graph_generator(int n, double p, ofstream* out) {
|
|
||||||
(*out) << n << endl;
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
for (int j = i+1; j < n; ++j) {
|
|
||||||
if ((double)rand()/RAND_MAX <= p) (*out) << i << " " << j << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Complete graph K_n.
|
|
||||||
void complete_graph_generator(int n, ofstream* out) {
|
|
||||||
(*out) << n << endl;
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
for (int j = i+1; j < n; ++j) {
|
|
||||||
(*out) << i << " " << j << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// Main function.
|
// Main function.
|
||||||
|
@ -37,34 +18,8 @@ void complete_graph_generator(int n, ofstream* out) {
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (argc == 1) {
|
string input_file = argv[1];
|
||||||
cout << "Usages:" << endl;
|
std::cout << "Number of removed edges: " << find_mps(input_file) << std::endl;
|
||||||
cout << "======================" << endl;
|
|
||||||
cout << "mps_testing -mps <infile> <outfile>" << endl;
|
|
||||||
cout << " Process the infile, and output the resulting maximal" << endl
|
|
||||||
<< " planar subgraph in the outfile." << endl;
|
|
||||||
cout << "mps_testing -gen <infile> <outfile>" << endl;
|
|
||||||
cout << " Generate a random graph as the spec given in the infile." << endl;
|
|
||||||
while (true) {
|
|
||||||
int x = 0;
|
|
||||||
cin >> x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ifstream in;
|
|
||||||
in.open(argv[2]);
|
|
||||||
ofstream out;
|
|
||||||
out.open(argv[3]);
|
|
||||||
if (!in.is_open() || !out.is_open()) {
|
|
||||||
cout << "An error occurs when opening file." << endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (argv[1][1] == 'm') find_mps(&in, &out);
|
|
||||||
else if (argv[1][1] == 'g') {
|
|
||||||
int n;
|
|
||||||
double p;
|
|
||||||
in >> n;
|
|
||||||
in >> p;
|
|
||||||
random_graph_generator(n, p, &out);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,11 +141,10 @@ class maximal_planar_subgraph_finder
|
||||||
public:
|
public:
|
||||||
maximal_planar_subgraph_finder();
|
maximal_planar_subgraph_finder();
|
||||||
~maximal_planar_subgraph_finder();
|
~maximal_planar_subgraph_finder();
|
||||||
void find_mps(ifstream* in, ofstream* out);
|
int find_mps(string input_file);
|
||||||
node* get_new_node(node_type t);
|
node* get_new_node(node_type t);
|
||||||
void read_from_file(ifstream* in);
|
void read_from_gml(string input_file);
|
||||||
void output(ofstream* out);
|
int output_removed_edge_size();
|
||||||
void output_deleted_edges(ofstream* out);
|
|
||||||
void postOrderTraversal();
|
void postOrderTraversal();
|
||||||
void sort_adj_list();
|
void sort_adj_list();
|
||||||
void determine_edges();
|
void determine_edges();
|
||||||
|
|
|
@ -3,62 +3,61 @@
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "mps.h"
|
#include "mps.h"
|
||||||
|
#include <ogdf/fileformats/GraphIO.h>
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// Finding MPS
|
// Finding MPS
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
void find_mps(ifstream* in, ofstream* out) {
|
int find_mps(string input_file) {
|
||||||
maximal_planar_subgraph_finder m;
|
maximal_planar_subgraph_finder m;
|
||||||
m.find_mps(in, out);
|
return m.find_mps(input_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void maximal_planar_subgraph_finder::find_mps(ifstream* in, ofstream* out) {
|
int maximal_planar_subgraph_finder::find_mps(string input_file) {
|
||||||
read_from_file(in);
|
read_from_gml(input_file);
|
||||||
postOrderTraversal();
|
postOrderTraversal();
|
||||||
sort_adj_list();
|
sort_adj_list();
|
||||||
determine_edges();
|
determine_edges();
|
||||||
back_edge_traversal();
|
back_edge_traversal();
|
||||||
output(out);
|
return output_removed_edge_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// Imput, output
|
// Imput, output
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
//First line: a single integer indicates the number of nodes.
|
|
||||||
//The rest: a pair of integers (i, j) represents an edge (i, j)
|
|
||||||
//0 <= i, j < n-1, where n is number of nodes.
|
// read input file of gml format
|
||||||
void maximal_planar_subgraph_finder::read_from_file(ifstream* in) {
|
void maximal_planar_subgraph_finder::read_from_gml(string input_file) {
|
||||||
int node_num, n1, n2;
|
ogdf::Graph G;
|
||||||
//Number of nodes.
|
|
||||||
(*in) >> node_num;
|
// utilize OGDF readGML
|
||||||
//initialize all the nodes.
|
if (!ogdf::GraphIO::read(G, input_file, ogdf::GraphIO::readGML)) {
|
||||||
for (int i = 0; i < node_num; ++i) {
|
std::cerr << "Could not read " << input_file << ".gml" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create nodes
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
//Set the adj-list.
|
|
||||||
while ((*in) >> n1 >> n2) {
|
// create edges
|
||||||
_node_list[n1]->add_adj(_node_list[n2]);
|
for (ogdf::edge e : G.edges) {
|
||||||
_node_list[n2]->add_adj(_node_list[n1]);
|
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()]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Output a maximal planar subgraph in the same format as input.
|
//Output a maximal planar subgraph in the same format as input.
|
||||||
void maximal_planar_subgraph_finder::output(ofstream* out) {
|
int maximal_planar_subgraph_finder::output_removed_edge_size() {
|
||||||
(*out) << _node_list.size() << endl;
|
int sum = 0;
|
||||||
for (int i = 0; i < _edge_list.size(); ++i) {
|
for (int i = 0; i < _back_edge_list.size(); ++i) {
|
||||||
(*out) << _edge_list[i].first->node_id() << " " << _edge_list[i].second->node_id() << endl;
|
if (_is_back_edge_eliminate[i]) ++sum;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < _back_edge_list.size(); ++i) {
|
return sum;
|
||||||
if (_is_back_edge_eliminate[i]) continue;
|
}
|
||||||
(*out) << _back_edge_list[i].first->node_id() << " " << _back_edge_list[i].second->node_id() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void maximal_planar_subgraph_finder::output_deleted_edges(ofstream* out) {
|
|
||||||
(*out) << _node_list.size() << endl;
|
|
||||||
for (int i = 0; i < _back_edge_list.size(); ++i) {
|
|
||||||
if (!_is_back_edge_eliminate[i]) continue;
|
|
||||||
(*out) << _back_edge_list[i].first->node_id() << " " << _back_edge_list[i].second->node_id() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include <ogdf/basic/basic.h>
|
||||||
|
#include <ogdf/basic/Graph.h>
|
||||||
|
#include <ogdf/fileformats/GraphIO.h>
|
||||||
|
#include <ogdf/basic/graph_generators.h>
|
||||||
|
|
||||||
|
using namespace ogdf;
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int nodeCount = std::stoi(argv[1]);
|
||||||
|
int edgeCount = std::stoi(argv[2]);
|
||||||
|
int copies = std::stoi(argv[3]);
|
||||||
|
int seed = std::stoi(argv[4]);
|
||||||
|
bool enforcePlanar = std::stoi(argv[5]);
|
||||||
|
std::string outputFolder = argv[6];
|
||||||
|
|
||||||
|
setSeed(seed);
|
||||||
|
for (int i = 0; i < copies; i++) {
|
||||||
|
Graph G;
|
||||||
|
if (enforcePlanar) {
|
||||||
|
randomPlanarBiconnectedGraph(G, nodeCount, edgeCount, false);
|
||||||
|
} else {
|
||||||
|
randomBiconnectedGraph(G, nodeCount, edgeCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << outputFolder << "/graphn" << nodeCount << "e" << edgeCount << "s" << seed << "i" << i
|
||||||
|
<< (enforcePlanar ? "planar" : "") << ".gml";
|
||||||
|
std::string s = ss.str();
|
||||||
|
GraphIO::write(G, s, GraphIO::writeGML);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,328 @@
|
||||||
|
#include <PCTree/PCTree.h>
|
||||||
|
|
||||||
|
// #include "hsuPC/include/PCTree.h"
|
||||||
|
// #include "hsuPC/include/PCNode.h"
|
||||||
|
|
||||||
|
#include <ogdf/basic/STNumbering.h>
|
||||||
|
#include <ogdf/basic/graph_generators.h>
|
||||||
|
#include <ogdf/basic/GraphCopy.h>
|
||||||
|
#include <ogdf/fileformats/GraphIO.h>
|
||||||
|
#include <ogdf/planarity/BoothLueker.h>
|
||||||
|
#include <ogdf/planarity/BoyerMyrvold.h>
|
||||||
|
#include <ogdf/basic/extended_graph_alg.h>
|
||||||
|
|
||||||
|
#include <ogdf/planarity/booth_lueker/IndInfo.h>
|
||||||
|
#include <ogdf/planarity/booth_lueker/PlanarPQTree.h>
|
||||||
|
#include <ogdf/planarity/planar_subgraph_fast/PlanarSubgraphPQTree.h>
|
||||||
|
#include <ogdf/planarity/PlanarSubgraphFast.h>
|
||||||
|
#include <ogdf/planarity/PlanarSubgraphBoyerMyrvold.h>
|
||||||
|
#include <ogdf/planarity/PlanarSubgraphPC.h>
|
||||||
|
#include <ogdf/planarity/MaximumPlanarSubgraph.h>
|
||||||
|
#include <ogdf/planarity/MaximalPlanarSubgraphSimple.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <chrono>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
using namespace ogdf;
|
||||||
|
|
||||||
|
using std::chrono::time_point;
|
||||||
|
using std::chrono::high_resolution_clock;
|
||||||
|
using std::chrono::duration_cast;
|
||||||
|
using std::chrono::nanoseconds;
|
||||||
|
|
||||||
|
|
||||||
|
void planarizePQ(const Graph &G, NodeArray<int> &numbering, List<edge> &delEdges) {
|
||||||
|
using PlanarLeafKey = booth_lueker::PlanarLeafKey<whaInfo*>;
|
||||||
|
|
||||||
|
NodeArray<SListPure<PlanarLeafKey*>> inLeaves(G);
|
||||||
|
NodeArray<SListPure<PlanarLeafKey*>> outLeaves(G);
|
||||||
|
Array<node> table(G.numberOfNodes()+1);
|
||||||
|
|
||||||
|
for(node v : G.nodes) {
|
||||||
|
for(adjEntry adj : v->adjEntries) {
|
||||||
|
edge e = adj->theEdge();
|
||||||
|
if (numbering[e->opposite(v)] > numbering[v]) { // sideeffect: ignores selfloops
|
||||||
|
PlanarLeafKey* L = new PlanarLeafKey(e);
|
||||||
|
inLeaves[v].pushFront(L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table[numbering[v]] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(node v : G.nodes) {
|
||||||
|
for (PlanarLeafKey *L : inLeaves[v]) {
|
||||||
|
outLeaves[L->userStructKey()->opposite(v)].pushFront(L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SList<PQLeafKey<edge,whaInfo*,bool>*> totalEliminatedKeys;
|
||||||
|
|
||||||
|
PlanarSubgraphPQTree T;
|
||||||
|
T.Initialize(inLeaves[table[1]]);
|
||||||
|
for (int i = 2; i < G.numberOfNodes(); i++) {
|
||||||
|
SList<PQLeafKey<edge,whaInfo*,bool>*> eliminatedKeys; // handle key elimination
|
||||||
|
T.Reduction(outLeaves[table[i]], eliminatedKeys); // handle key elimination
|
||||||
|
totalEliminatedKeys.conc(eliminatedKeys); // handle key elimination
|
||||||
|
T.ReplaceRoot(inLeaves[table[i]]);
|
||||||
|
T.emptyAllPertinentNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
// append eliminated edges to delEdges
|
||||||
|
for (PQLeafKey<edge, whaInfo*, bool> *key : totalEliminatedKeys) {
|
||||||
|
edge e = key->userStructKey();
|
||||||
|
delEdges.pushBack(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
for(node v : G.nodes) {
|
||||||
|
while (!inLeaves[v].empty()) {
|
||||||
|
PlanarLeafKey *L = inLeaves[v].popFrontRet();
|
||||||
|
delete L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T.Cleanup(); // Explicit call for destructor necessary. This allows to call virtual
|
||||||
|
// function CleanNode for freeing node information class.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename PCT, typename PCN, typename PCNT>
|
||||||
|
void planarizePC(const Graph &G, const NodeArray<int> &numbering, List<edge> &delEdges) {
|
||||||
|
// initialize PCTree instance
|
||||||
|
PCT T;
|
||||||
|
|
||||||
|
// vector to store nodes of graph in order specified in numbering
|
||||||
|
std::vector<node> order(G.numberOfNodes(), nullptr);
|
||||||
|
for (node n : G.nodes) {
|
||||||
|
order.at(numbering[n] - 1) = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store leaf representations of edges in PCTree
|
||||||
|
std::vector<PCN *> leafRepresentation(G.maxEdgeIndex() + 1, nullptr);
|
||||||
|
// vectors declared for later use
|
||||||
|
std::vector<edge> outEdges;
|
||||||
|
std::vector<PCN *> consecutiveLeaves;
|
||||||
|
|
||||||
|
// iterates over nodes in the 'order' vector
|
||||||
|
for (node n : order) {
|
||||||
|
// quit condition: if current node is last node
|
||||||
|
if (n == order[G.numberOfNodes() - 1]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear both vectors in for each node in iteration
|
||||||
|
consecutiveLeaves.clear();
|
||||||
|
outEdges.clear();
|
||||||
|
|
||||||
|
// leafToEdge
|
||||||
|
// create a map of PCN to edge
|
||||||
|
std::map<PCN *, edge> leafToEdge;
|
||||||
|
|
||||||
|
// iterate over adjacent entries of current node
|
||||||
|
for (adjEntry adj : n->adjEntries)
|
||||||
|
{
|
||||||
|
// check if opposite node has higher numbering (belong to later node)
|
||||||
|
// add to outEdges
|
||||||
|
if (numbering[adj->theEdge()->opposite(n)] > numbering[n]) {
|
||||||
|
outEdges.push_back(adj->theEdge());
|
||||||
|
// add to consecutiveLeaves otherwise (declared earlier)
|
||||||
|
// leafRepresentation will be filled later on
|
||||||
|
} else {
|
||||||
|
consecutiveLeaves.push_back(leafRepresentation[adj->theEdge()->index()]);
|
||||||
|
// use leafToEdge to map leafRep object to edge object
|
||||||
|
// then store the edge in a collection
|
||||||
|
// <- insert code here ->
|
||||||
|
leafToEdge[leafRepresentation[adj->theEdge()->index()]] = adj->theEdge();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PCN *mergedLeaf;
|
||||||
|
// If first node, new P-node is created
|
||||||
|
if (n == order[0]) {
|
||||||
|
mergedLeaf = T.newNode(PCNT::PNode);
|
||||||
|
// consecutive leaves are merged
|
||||||
|
} else {
|
||||||
|
// T.makeConsecutive
|
||||||
|
// the function returns a boolean for success
|
||||||
|
// I think it checks if its possible to make consecutive
|
||||||
|
|
||||||
|
// IMPORTANT HERE
|
||||||
|
// here we can identify edges that result in non-planarity
|
||||||
|
if (!T.makeConsecutive(consecutiveLeaves)){
|
||||||
|
|
||||||
|
// keep trying different combinations until is passes
|
||||||
|
std::vector<PCN *> goodLeaves;
|
||||||
|
for (PCN* leaf: consecutiveLeaves) {
|
||||||
|
goodLeaves.push_back(leaf);
|
||||||
|
if (T.makeConsecutive(goodLeaves)) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
goodLeaves.pop_back();
|
||||||
|
delEdges.pushBack(leafToEdge[leaf]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
consecutiveLeaves.clear();
|
||||||
|
consecutiveLeaves.insert(consecutiveLeaves.end(),
|
||||||
|
goodLeaves.begin(),
|
||||||
|
goodLeaves.end());
|
||||||
|
|
||||||
|
|
||||||
|
// for rejected leaves,
|
||||||
|
// return false;
|
||||||
|
}
|
||||||
|
// remove all consecutive leaves except the first
|
||||||
|
// returns a single leaf
|
||||||
|
// second argument is "assumeConsecutive", which makeConsecutive checks
|
||||||
|
mergedLeaf = T.mergeLeaves(consecutiveLeaves, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
OGDF_ASSERT(!outEdges.empty());
|
||||||
|
|
||||||
|
// if there is more than 1 outEdge
|
||||||
|
if (outEdges.size() > 1) {
|
||||||
|
// clear and re-use consecutiveLeaves variable
|
||||||
|
consecutiveLeaves.clear();
|
||||||
|
// make a reference variabled
|
||||||
|
std::vector<PCN *> &addedLeaves = consecutiveLeaves;
|
||||||
|
|
||||||
|
// if mergedLeaf if a P-node
|
||||||
|
// PCTree_construction::insertLeaves
|
||||||
|
if (mergedLeaf->getNodeType() == PCNT::PNode) {
|
||||||
|
T.insertLeaves(outEdges.size(), mergedLeaf, &addedLeaves);
|
||||||
|
// otherwise mergedLeaf is a Leaf node
|
||||||
|
// PCTree_construction::replaceLeaf
|
||||||
|
} else {
|
||||||
|
OGDF_ASSERT(mergedLeaf->getNodeType() == PCNT::Leaf);
|
||||||
|
T.replaceLeaf(outEdges.size(), mergedLeaf, &addedLeaves);
|
||||||
|
}
|
||||||
|
|
||||||
|
// leaf representations are updated accordingly
|
||||||
|
for (int i = 0; i < outEdges.size(); i++) {
|
||||||
|
leafRepresentation[outEdges[i]->index()] = addedLeaves[i];
|
||||||
|
}
|
||||||
|
// if there is only 1 edge
|
||||||
|
// first outEdge is updated to mergedLeaf node
|
||||||
|
} else {
|
||||||
|
leafRepresentation[outEdges.front()->index()] = mergedLeaf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
|
||||||
|
string inputFile = argv[1];
|
||||||
|
string selection = argv[2];
|
||||||
|
string planarity = argv[3];
|
||||||
|
Graph G;
|
||||||
|
|
||||||
|
if (!GraphIO::read(G, inputFile, GraphIO::readGML)) {
|
||||||
|
std::cerr << "Could not read input.gml" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int b;
|
||||||
|
std::istringstream(planarity) >> b;
|
||||||
|
|
||||||
|
if (b) {
|
||||||
|
// create map from integer to node
|
||||||
|
// find edge and change its attribute
|
||||||
|
// implicit assumption that nodes retain order as given by input
|
||||||
|
std::unordered_map<int, ogdf::node> nodeMap;
|
||||||
|
// Add nodes to the graph and map them to integers
|
||||||
|
int index = 0;
|
||||||
|
for (ogdf::node v : G.nodes) {
|
||||||
|
nodeMap[index] = v;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// manually add our own random edges
|
||||||
|
int numEdgesToAdd = b; // Number of edges to add
|
||||||
|
int count = 0;
|
||||||
|
std::srand(150); // Seed the random number generator
|
||||||
|
int numNodes = G.numberOfNodes();
|
||||||
|
|
||||||
|
while (count < numEdgesToAdd) {
|
||||||
|
int sourceIndex = std::rand() % numNodes; // Random source node index
|
||||||
|
int targetIndex = std::rand() % numNodes; // Random target node index
|
||||||
|
|
||||||
|
if (sourceIndex == targetIndex) continue;
|
||||||
|
ogdf::edge targetEdge = G.searchEdge(nodeMap[sourceIndex], nodeMap[targetIndex], false);
|
||||||
|
if (targetEdge == nullptr) {
|
||||||
|
G.newEdge(nodeMap[sourceIndex], nodeMap[targetIndex]);
|
||||||
|
std::cout << sourceIndex << ", " << targetIndex << std::endl;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeArray<int> numbering(G);
|
||||||
|
// int num = computeSTNumbering(G, numbering, 0);
|
||||||
|
int num = computeSTNumbering(G, numbering, nullptr, nullptr, true);
|
||||||
|
OGDF_ASSERT(num == G.numberOfNodes());
|
||||||
|
|
||||||
|
// print after input
|
||||||
|
// graphPrinter(G);
|
||||||
|
std::cout << "G Planarity: " << ogdf::isPlanar(G) << std::endl;
|
||||||
|
std::cout << "Original number of nodes: " << G.numberOfNodes() << std::endl;
|
||||||
|
std::cout << "Original number of edges: " << G.numberOfEdges() << std::endl;
|
||||||
|
|
||||||
|
// separator for planarization
|
||||||
|
// <-------------->
|
||||||
|
|
||||||
|
// PQ implementation to make planar subgraph
|
||||||
|
std::cout << "start planarization" << std::endl;
|
||||||
|
List<edge> *delEdges = new List<edge>; // empty list
|
||||||
|
// changed to PC
|
||||||
|
if (selection == "pc") {
|
||||||
|
planarizePC<pc_tree::PCTree, pc_tree::PCNode, pc_tree::PCNodeType>(G, numbering, *delEdges);
|
||||||
|
} else if (selection == "pq") {
|
||||||
|
planarizePQ(G, numbering, *delEdges);
|
||||||
|
// } else if (selection == "bm") {
|
||||||
|
// SubgraphPlanarizer *crossMin = new SubgraphPlanarizer;
|
||||||
|
// crossMin->call(G)
|
||||||
|
} else if (selection == "fast") {
|
||||||
|
// PlanarSubgraphModule<int> *ps = new PlanarSubgraphFast<int>;
|
||||||
|
// ogdf::MaximalPlanarSubgraphSimple<int> mps(*(new PlanarSubgraphBoyerMyrvold));
|
||||||
|
ogdf::MaximalPlanarSubgraphSimple<int> mps(*(new PlanarSubgraphFast<int>));
|
||||||
|
mps.call(G, *delEdges);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
std::cout << "running maximum" << std::endl;
|
||||||
|
ogdf::MaximumPlanarSubgraph<int> mps;
|
||||||
|
mps.call(G, *delEdges);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Edges removed:" << delEdges->size() << std::endl;
|
||||||
|
|
||||||
|
for (edge e: *delEdges) {
|
||||||
|
// print removed edges
|
||||||
|
std::cout << e->adjSource() << std::endl;
|
||||||
|
G.delEdge(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GraphIO::write(G, "output.gml", GraphIO::writeGML);
|
||||||
|
|
||||||
|
|
||||||
|
// edgeListPrinter(*delEdges);
|
||||||
|
// std::cout << std::endl;
|
||||||
|
// std::cout << "subG planarity: " << ogdf::isPlanar(subgraph) << std::endl;
|
||||||
|
std::cout << "G planarity: " << ogdf::isPlanar(G) << std::endl;
|
||||||
|
std::cout << "Original number of nodes: " << G.numberOfNodes() << std::endl;
|
||||||
|
std::cout << "Subgraph number of edges: " << G.numberOfEdges() << std::endl;
|
||||||
|
// graphPrinter(G);
|
||||||
|
// std::cout << isPlanarPC<pc_tree::hsu::PCTree, pc_tree::hsu::PCNode, pc_tree::hsu::PCTree::PCNodeType>(G, numbering) << std::endl;
|
||||||
|
// bool result = isPlanarPC<pc_tree::PCTree, pc_tree::PCNode, pc_tree::PCNodeType>(subG, numbering);
|
||||||
|
// std::cout << result << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue