I was recently working on a project where I needed to read graphs in the graph6 format (used, e.g., by nauty and plantri) and calculate some things on them.
I wanted it to be fast, so I chose C++ and the Boost Graph Library for this task.
Either I don’t know how to search properly on the Internet, or there really isn’t a ready-made function to convert graph6 data into a Boost graph. Anyway, I present my implementation — for myself, so I don’t have to look for it if I ever want to use it, and for everyone else who doesn’t want to waste an hour of their time.
graph6 -> Boost
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
| #include <boost/graph/adjacency_list.hpp>
#include <boost/range/iterator_range.hpp>
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>
Graph;
typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
std::pair<int, std::vector<int>> data_to_n(const std::vector<int>& data) {
if (data[0] <= 62) {
return {data[0], std::vector(data.begin() + 1, data.end())};
}
if (data[1] <= 62) {
int value = (data[1] << 12) + (data[2] << 6) + data[3];
return {value, std::vector(data.begin() + 4, data.end())};
}
int value = (data[2] << 30) + (data[3] << 24) + (data[4] << 18) +
(data[5] << 12) + (data[6] << 6) + data[7];
return {value, std::vector(data.begin() + 8, data.end())};
}
Graph from_graph6_bytes(const std::string& bytes_in) {
std::vector<int> data;
for (const char c : bytes_in) {
int val = static_cast<int>(c) - 63;
if (val < 0 || val > 63) {
throw std::invalid_argument(
"Each input character must be in range(63, 127)");
}
data.push_back(val);
}
auto [n, remaining_data] = data_to_n(data);
if (remaining_data.size() != (n * (n - 1) / 2 + 5) / 6) {
throw std::runtime_error("Incorrect data length in graph6");
}
Graph G(n);
int bit_index = 0;
for (int j = 1; j < n; ++j) {
for (int i = 0; i < j; ++i) {
const int byte_index = bit_index / 6;
const int bit_position = 5 - (bit_index % 6);
if ((remaining_data[byte_index] >> bit_position) & 1) {
boost::add_edge(i, j, G);
}
++bit_index;
}
}
return G;
}
|