繁体   English   中英

Boost VF2 子图同构对于无向图不正确?

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM