子图同构is defined here as:
两个图 G1=(V1, E1) 和 G2=(V2, E2) 之间的同构是一个图的顶点到另一个图的顶点的双射映射 M,它保留了图的边缘结构
您期望持有什么映射?我想您可能一直期望 {0 -> 0, 1 -> 1, 2 -> 2, 3 -> 3} 是那个双射顶点映射?
但是,情况并非如此,因为子图在参与映射的顶点之间缺少边。例如。 3 -- 0 不在小图中,使其在结构上有所不同。
TL;DR 当边是严格子集时,子图同构不是。相反,它专注于映射顶点集。
反例
这是一个反例,它在保留预期映射的同时生成一些随机边。请注意,在给定足够多的随机边时,您可能会遇到意外的同态,因为子图在结构上是如此简单:
Live On Wandbox
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/vf2_sub_graph_iso.hpp>
#include <iostream>
#include <random>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/algorithm/cxx11/all_of.hpp>
using boost::make_iterator_range;
using boost::adaptors::transformed;
using boost::algorithm::all_of;
int main()
{
using Graph =
boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>;
using V = Graph::vertex_descriptor;
// 0---1
// | |
// 2---3
Graph small(4);
add_edge(0, 1, small);
add_edge(0, 2, small);
add_edge(2, 3, small);
add_edge(1, 3, small);
Graph large(500);
add_edge(100, 200, large);
add_edge(100, 300, large);
add_edge(300, 400, large);
add_edge(200, 400, large);
// helper to recognizes (sets of) vertices from the intended subset
auto all_in_subset = [set = std::set{100, 200, 300, 400}](auto... vs) {
return ((0 != set.count(vs)) && ...);
};
// add some random edges for
auto randvertex = std::bind(
std::uniform_int_distribution<V>(0, boost::num_vertices(large) - 1),
std::mt19937{std::random_device{}()});
for (int n = 0; n < 400; ++n) {
V src = randvertex();
V tgt = randvertex();
// only add edges outside of the subset - preserving structure
if (!all_in_subset(src, tgt))
add_edge(src, tgt, large);
}
auto callback = [&](auto bijection, auto) {
auto vs = make_iterator_range(vertices(small));
auto mapped =
vs | transformed([&](auto v) { return get(bijection, v); });
if (boost::algorithm::all_of(mapped, all_in_subset)) {
std::cout << "In subset: ";
} else {
std::cout << "Random match: ";
}
for (auto v : vs) {
std::cout << '(' << v << " -> " << get(bijection, v) << ") ";
}
std::cout << std::endl;
return true;
};
bool found = boost::vf2_subgraph_iso(small, large, callback);
std::cout << "Found subgraph:" << std::boolalpha << found << std::endl;
}
打印例如
In subset: (0 -> 100) (1 -> 200) (2 -> 300) (3 -> 400)
In subset: (0 -> 100) (1 -> 300) (2 -> 200) (3 -> 400)
Random match: (0 -> 122) (1 -> 268) (2 -> 454) (3 -> 128)
Random match: (0 -> 122) (1 -> 454) (2 -> 268) (3 -> 128)
Random match: (0 -> 128) (1 -> 268) (2 -> 454) (3 -> 122)
Random match: (0 -> 128) (1 -> 454) (2 -> 268) (3 -> 122)
In subset: (0 -> 200) (1 -> 100) (2 -> 400) (3 -> 300)
In subset: (0 -> 200) (1 -> 400) (2 -> 100) (3 -> 300)
Random match: (0 -> 220) (1 -> 234) (2 -> 367) (3 -> 340)
Random match: (0 -> 220) (1 -> 367) (2 -> 234) (3 -> 340)
Random match: (0 -> 234) (1 -> 220) (2 -> 340) (3 -> 367)
Random match: (0 -> 234) (1 -> 340) (2 -> 220) (3 -> 367)
Random match: (0 -> 268) (1 -> 122) (2 -> 128) (3 -> 454)
Random match: (0 -> 268) (1 -> 128) (2 -> 122) (3 -> 454)
In subset: (0 -> 300) (1 -> 100) (2 -> 400) (3 -> 200)
In subset: (0 -> 300) (1 -> 400) (2 -> 100) (3 -> 200)
Random match: (0 -> 340) (1 -> 234) (2 -> 367) (3 -> 220)
Random match: (0 -> 340) (1 -> 367) (2 -> 234) (3 -> 220)
Random match: (0 -> 367) (1 -> 220) (2 -> 340) (3 -> 234)
Random match: (0 -> 367) (1 -> 340) (2 -> 220) (3 -> 234)
In subset: (0 -> 400) (1 -> 200) (2 -> 300) (3 -> 100)
In subset: (0 -> 400) (1 -> 300) (2 -> 200) (3 -> 100)
Random match: (0 -> 454) (1 -> 122) (2 -> 128) (3 -> 268)
Random match: (0 -> 454) (1 -> 128) (2 -> 122) (3 -> 268)
Found subgraph:true
或者,取决于运气,只是预期的:Live
In subset: (0 -> 100) (1 -> 200) (2 -> 300) (3 -> 400)
In subset: (0 -> 100) (1 -> 300) (2 -> 200) (3 -> 400)
In subset: (0 -> 200) (1 -> 100) (2 -> 400) (3 -> 300)
In subset: (0 -> 200) (1 -> 400) (2 -> 100) (3 -> 300)
In subset: (0 -> 300) (1 -> 100) (2 -> 400) (3 -> 200)
In subset: (0 -> 300) (1 -> 400) (2 -> 100) (3 -> 200)
In subset: (0 -> 400) (1 -> 200) (2 -> 300) (3 -> 100)
In subset: (0 -> 400) (1 -> 300) (2 -> 200) (3 -> 100)
Found subgraph:true