Using C++ Boost Graph Library (BGL) to Find Isomorphic Graphs
I want to get the graphs which are isomorphic (respecting the type - A/B). Of course, all graphs which have not the same number of connections, are sorted out in the beginning.
# So the matching structures are the ones in the green box:
nodes: {A,B,B,B}; bonds: {{0,1},{1,2},{1,3}}
nodes: {B,B,B,A}; bonds: {{3,2},{2,0},{3,1}}
nodes: {B,B,B,A}; bonds: {{0,1},{1,2},{1,3}}
# The structures in the red box are not expected to be the same:
nodes: {B,A,B,B}; bonds: {{0,1},{1,2},{1,3}}
nodes: {B,B,B,B}; bonds: {{0,1},{1,2},{1,3}}
nodes: {A,B,B}; bonds: {{0,1},{1,2}}
// (C) Copyright Jeremy Siek 2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#include <iostream>
#include <boost/graph/isomorphism.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
/*
Sample output:
isomorphic? 1
f: 9 10 11 0 1 3 2 4 6 8 7 5
*/
int
main()
{
using namespace boost;
const int n = 12;
typedef adjacency_list<vecS, listS, undirectedS,
property<vertex_index_t, int> > graph_t;
graph_t g1(n), g2(n);
std::vector<graph_traits<graph_t>::vertex_descriptor> v1(n), v2(n);
property_map<graph_t, vertex_index_t>::type
v1_index_map = get(vertex_index, g1),
v2_index_map = get(vertex_index, g2);
graph_traits<graph_t>::vertex_iterator i, end;
int id = 0;
for (tie(i, end) = vertices(g1); i != end; ++i, ++id) {
put(v1_index_map, *i, id);
v1[id] = *i;
}
id = 0;
for (tie(i, end) = vertices(g2); i != end; ++i, ++id) {
put(v2_index_map, *i, id);
v2[id] = *i;
}
add_edge(v1[0], v1[1], g1); add_edge(v1[1], v1[2], g1);
add_edge(v1[0], v1[2], g1);
add_edge(v1[3], v1[4], g1); add_edge(v1[4], v1[5], g1);
add_edge(v1[5], v1[6], g1); add_edge(v1[6], v1[3], g1);
add_edge(v1[7], v1[8], g1); add_edge(v1[8], v1[9], g1);
add_edge(v1[9], v1[10], g1);
add_edge(v1[10], v1[11], g1); add_edge(v1[11], v1[7], g1);
add_edge(v2[9], v2[10], g2); add_edge(v2[10], v2[11], g2);
add_edge(v2[11], v2[9], g2);
add_edge(v2[0], v2[1], g2); add_edge(v2[1], v2[3], g2);
add_edge(v2[3], v2[2], g2); add_edge(v2[2], v2[0], g2);
add_edge(v2[4], v2[5], g2); add_edge(v2[5], v2[7], g2);
add_edge(v2[7], v2[8], g2);
add_edge(v2[8], v2[6], g2); add_edge(v2[6], v2[4], g2);
std::vector<graph_traits<graph_t>::vertex_descriptor> f(n);
bool ret = isomorphism
(g1, g2, isomorphism_map
(make_iterator_property_map(f.begin(), v1_index_map, f[0])));
std::cout << "isomorphic? " << ret << std::endl;
std::cout << "f: ";
for (std::size_t v = 0; v != f.size(); ++v)
std::cout << get(get(vertex_index, g2), f[v]) << " ";
std::cout << std::endl;
return 0;
}
This is my attempt to get a minimal example of Boost working. I would be grateful if anybody could show me how to achieve this with Boost, if thats the proper library?

So, you posted the example from the Boost libraries. Some version before 2019.
Obviously, that's not going to represent your graphs. First modernize:
Live
Next, simplify, because you didn't tell us reasons to not have the intrinsic vertex index afforded by using
vecS:Live On Coliru
Adding Your Data
Since you need the type (A/B), let's add it to vertex properties:
Let's also create the bond graphs:
Now you can state the problem in code:
Let's implement our solution:
Really,
toGraphis a 1:1 helper to convert the input to adjacency_list:comparejust wraps up the call toisomorphismlike before:Now, solving it can be done by comparing all pairs of graphs in the problem:
In fact I'll also add debug output to verify the graphs:
Of course, we didn't make the problem dynamically sized for no reason, so let's generalize using an algorithm:
DEMO TIME
Live On Coliru
Prints
Or, with debug disabled just printing:
-> green problem solves true -> red problem solves false
LOOSE ENDS?
I love to note that this final program solves the entire two problems with extensive debug output, in 10 lines of code less than the example you started from.
Note, you mention in your question:
Now it isn't clear what you mean by that. You seem to expect the green box to match, though it seems obvious that the third graph would not match "respecting the type - A/B"? If you needed that, you'd have to include the corresponding vertex invariant
BONUS: Node Type Invariant
It took some squinting to realize that the "respecting the type" doesn't actually conflict with the expected result. So here goes: an invariant that just looks at the Node types:
However, to stop there could be a big mistake (especially if your graphs can get bigger). That's because the default invariant matches node degrees, which can be a huge optimization. Combining the heuristic with the type-requirement:
It's not pretty, but it works! Note how I improved the isomorphism mapping debug output so I could even understand the mappings :)
Live On Coliru
Prints