[英]Boost VF2 subgraph isomorphism incorrect for undirected graphs?
我正在尝试使用 Boost 的vf2_subgraph_iso
,但我不知道如何正确地将它用于小型无向图。
下面我展示了一个示例,其中具有 4 个顶点的图不是具有 4 个顶点的全连接图的子图(这对我来说似乎很奇怪)。 谁能帮我理解我在这里做错了什么?
我在Why is Boost VF2 subgraph isomorphismgiving an wrong answer上看到了帖子,这可能是同一个问题。
#include <boost/graph/vf2_sub_graph_iso.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <iostream>
#include <boost/graph/vf2_sub_graph_iso.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <iostream>
using namespace boost;
int main()
{
typedef adjacency_list<vecS, vecS, undirectedS, no_property> Graph;
// 0---1
// | |
// 2---3
Graph smallGraph;
{
vertex(0, smallGraph);
vertex(1, smallGraph);
vertex(2, smallGraph);
vertex(3, smallGraph);
add_edge(0, 1, smallGraph);
add_edge(0, 2, smallGraph);
add_edge(2, 3, smallGraph);
add_edge(1, 3, smallGraph);
}
Graph largeGraph;
{
vertex(0, largeGraph);
vertex(1, largeGraph);
vertex(2, largeGraph);
vertex(3, largeGraph);
add_edge(0, 1, largeGraph);
add_edge(0, 2, largeGraph);
add_edge(2, 3, largeGraph);
add_edge(1, 3, largeGraph);
add_edge(0, 3, largeGraph);
add_edge(1, 2, largeGraph);
}
vf2_print_callback<Graph, Graph> callback(smallGraph, largeGraph);
auto val = vf2_subgraph_iso(smallGraph, largeGraph, callback);
if (val)
std::cout << "Found subgraph." << std::endl;
else
std::cout << "Did not find subgraph." << std::endl;
return 0;
}
从vf2_subgraph_iso 文档中,“两个图 G1=(V1, E1) 和 G2=(V2, E2) 之间的同构是一个图的顶点到另一个图的顶点的双射映射 M,它保留了图的边缘结构. 当且仅当 M 是 G1 和 G2 的子图之间的同构时,M 被称为图子图同构。
在我上面的示例中,G2 = largeGraph,G1 = smallGraph,并且存在 G2 的子图,使得顶点映射(0-0、1-1、2-2、3-3)在子图和 G1 之间是双射的。
子图同构在这里定义为:
两个图 G1=(V1, E1) 和 G2=(V2, E2) 之间的同构是一个图的顶点到另一个图的顶点的双射映射 M,它保留了图的边缘结构
你期望持有什么映射? 我想您可能一直期望 {0 -> 0, 1 -> 1, 2 -> 2, 3 -> 3} 是双射顶点映射?
但是,情况并非如此,因为子图在参与映射的顶点之间缺少边。 例如3 -- 0
不在小图中,使其在结构上有所不同。
TL;DR当边是严格子集时,子图同构不是。 相反,它专注于映射顶点集。
这是一个反例,它在保留预期映射的同时生成一些随机边。 请注意,如果给定足够多的随机边,您可能会遇到意外的同态,因为子图在结构上是如此简单:
#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
或者,取决于运气,只是预期的:活着
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.