[英]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.