簡體   English   中英

自定義 BGL 圖與拓撲排序一起工作需要什么?

[英]What is required for a custom BGL graph to work with topological sort?

我創建了一個自定義 BGL 圖 model,就像在這個答案中一樣: What is need to use BGL algorithms on existing data structure ( edges and vertices as vector<Object *>)? .

它采用了一個自定義數據結構,用於一些 Boost.Graph 算法。

鏈接的答案足以讓深度優先搜索工作( Coliru )但我在使用boost::topological_sort時遇到了問題:

std::list<V> rev_topo;
boost::topological_sort(g, back_inserter(rev_topo));

給予:科利魯

In file included from /usr/include/boost/iterator/iterator_categories.hpp:15,
                 from /usr/include/boost/unordered/detail/implementation.hpp:18,
                 from /usr/include/boost/unordered/detail/set.hpp:6,
                 from /usr/include/boost/unordered/unordered_set.hpp:20,
                 from /usr/include/boost/unordered_set.hpp:17,
                 from /usr/include/boost/graph/adjacency_list.hpp:21,
                 from /home/sehe/Projects/stackoverflow/test.cpp:3:
/usr/include/boost/mpl/eval_if.hpp: In instantiation of ‘struct boost::mpl::eval_if<boost::detail::has_vertex_property_type<Glue::MyGraph, mpl_::bool_<false> >, boost::detail::get_vertex_property_type<Glue::MyGraph>, boost::no_property>’:
/usr/include/boost/graph/graph_traits.hpp:276:12:   required from ‘struct boost::vertex_property_type<Glue::MyGraph>’
/usr/include/boost/graph/properties.hpp:201:12:   required from ‘struct boost::detail::vertex_property_map<Glue::MyGraph, boost::vertex_index_t>’
/usr/include/boost/graph/properties.hpp:212:10:   required from ‘struct boost::property_map<Glue::MyGraph, boost::vertex_index_t, void>’
/usr/include/boost/graph/named_function_params.hpp:415:69:   required from ‘struct boost::detail::override_const_property_t<int, boost::vertex_index_t, Glue::MyGraph, false>’
/usr/include/boost/graph/named_function_params.hpp:571:31:   required from ‘struct boost::detail::map_maker_helper<false, Glue::MyGraph, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >, boost::default_color_type, int>’
/usr/include/boost/graph/named_function_params.hpp:604:41:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/graph/depth_first_search.hpp:337:80:   required from ‘void boost::graph::detail::depth_first_search_impl<Graph>::operator()(const Graph&, const ArgPack&) const [with ArgPack = boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >; Graph = Glue::MyGraph]’
/usr/include/boost/graph/depth_first_search.hpp:342:5:   required from ‘typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const ArgPack&)>::type boost::graph::depth_first_search_with_named_params(const Param0&, const ArgPack&) [with Param0 = Glue::MyGraph; ArgPack = boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >; typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const ArgPack&)>::type = void]’
/usr/include/boost/graph/depth_first_search.hpp:345:3:   required from ‘typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const typename boost::detail::convert_bgl_params_to_boost_parameter<boost::bgl_named_params<T, Tag, Base> >::type&)>::type boost::depth_first_search(const Param0&, const boost::bgl_named_params<T, Tag, Base>&) [with Param0 = Glue::MyGraph; P = boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > >; T = boost::graph_visitor_t; R = boost::bgl_named_params<int, boost::buffer_param_t>; typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const typename boost::detail::convert_bgl_params_to_boost_parameter<boost::bgl_named_params<T, Tag, Base> >::type&)>::type = void]’
/usr/include/boost/graph/topological_sort.hpp:65:23:   required from ‘void boost::topological_sort(VertexListGraph&, OutputIterator, const boost::bgl_named_params<P, T, R>&) [with VertexListGraph = Glue::MyGraph; OutputIterator = std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> >; P = int; T = boost::buffer_param_t; R = boost::no_property]’
/usr/include/boost/graph/topological_sort.hpp:71:21:   required from ‘void boost::topological_sort(VertexListGraph&, OutputIterator) [with VertexListGraph = Glue::MyGraph; OutputIterator = std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> >]’
/home/sehe/Projects/stackoverflow/test.cpp:139:55:   required from here
/usr/include/boost/mpl/eval_if.hpp:38:31: error: no type named ‘type’ in ‘boost::mpl::eval_if<boost::detail::has_vertex_property_type<Glue::MyGraph, mpl_::bool_<false> >, boost::detail::get_vertex_property_type<Glue::MyGraph>, boost::no_property>::f_’ {aka ‘struct boost::no_property’}
   38 |     typedef typename f_::type type;
      |                               ^~~~
In file included from /usr/include/boost/graph/breadth_first_search.hpp:23,
                 from /home/sehe/Projects/stackoverflow/test.cpp:4:
/usr/include/boost/graph/named_function_params.hpp: In instantiation of ‘struct boost::detail::override_const_property_t<int, boost::vertex_index_t, Glue::MyGraph, false>’:
/usr/include/boost/graph/named_function_params.hpp:571:31:   required from ‘struct boost::detail::map_maker_helper<false, Glue::MyGraph, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >, boost::default_color_type, int>’
/usr/include/boost/graph/named_function_params.hpp:604:41:   required from ‘struct boost::detail::map_maker<Glue::MyGraph, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >, boost::graph::keywords::tag::color_map, boost::default_color_type>’
/usr/include/boost/graph/named_function_params.hpp:620:7:   required by substitution of ‘template<class Graph, class ArgPack> typename boost::detail::map_maker<Graph, ArgPack, boost::graph::keywords::tag::color_map, boost::default_color_type>::map_type boost::detail::make_property_map_from_arg_pack_gen<boost::graph::keywords::tag::color_map, boost::default_color_type>::operator()<Graph, ArgPack>(const Graph&, const ArgPack&) const [with Graph = Glue::MyGraph; ArgPack = boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >]’
/usr/include/boost/graph/depth_first_search.hpp:337:80:   required from ‘void boost::graph::detail::depth_first_search_impl<Graph>::operator()(const Graph&, const ArgPack&) const [with ArgPack = boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >; Graph = Glue::MyGraph]’
/usr/include/boost/graph/depth_first_search.hpp:342:5:   required from ‘typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const ArgPack&)>::type boost::graph::depth_first_search_with_named_params(const Param0&, const ArgPack&) [with Param0 = Glue::MyGraph; ArgPack = boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >; typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const ArgPack&)>::type = void]’
/usr/include/boost/graph/depth_first_search.hpp:345:3:   required from ‘typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const typename boost::detail::convert_bgl_params_to_boost_parameter<boost::bgl_named_params<T, Tag, Base> >::type&)>::type boost::depth_first_search(const Param0&, const boost::bgl_named_params<T, Tag, Base>&) [with Param0 = Glue::MyGraph; P = boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > >; T = boost::graph_visitor_t; R = boost::bgl_named_params<int, boost::buffer_param_t>; typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const typename boost::detail::convert_bgl_params_to_boost_parameter<boost::bgl_named_params<T, Tag, Base> >::type&)>::type = void]’
/usr/include/boost/graph/topological_sort.hpp:65:23:   required from ‘void boost::topological_sort(VertexListGraph&, OutputIterator, const boost::bgl_named_params<P, T, R>&) [with VertexListGraph = Glue::MyGraph; OutputIterator = std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> >; P = int; T = boost::buffer_param_t; R = boost::no_property]’
/usr/include/boost/graph/topological_sort.hpp:71:21:   required from ‘void boost::topological_sort(VertexListGraph&, OutputIterator) [with VertexListGraph = Glue::MyGraph; OutputIterator = std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> >]’
/home/sehe/Projects/stackoverflow/test.cpp:139:55:   required from here
/usr/include/boost/graph/named_function_params.hpp:415:69: error: no type named ‘const_type’ in ‘struct boost::property_map<Glue::MyGraph, boost::vertex_index_t, void>’
  415 |       typedef typename boost::property_map<Graph, Prop>::const_type result_type;
      |                                                                     ^~~~~~~~~~~
In file included from /home/sehe/Projects/stackoverflow/test.cpp:5:
/usr/include/boost/graph/depth_first_search.hpp: In instantiation of ‘void boost::graph::detail::depth_first_search_impl<Graph>::operator()(const Graph&, const ArgPack&) const [with ArgPack = boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >; Graph = Glue::MyGraph]’:
/usr/include/boost/graph/depth_first_search.hpp:342:5:   required from ‘typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const ArgPack&)>::type boost::graph::depth_first_search_with_named_params(const Param0&, const ArgPack&) [with Param0 = Glue::MyGraph; ArgPack = boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >; typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const ArgPack&)>::type = void]’
/usr/include/boost/graph/depth_first_search.hpp:345:3:   required from ‘typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const typename boost::detail::convert_bgl_params_to_boost_parameter<boost::bgl_named_params<T, Tag, Base> >::type&)>::type boost::depth_first_search(const Param0&, const boost::bgl_named_params<T, Tag, Base>&) [with Param0 = Glue::MyGraph; P = boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > >; T = boost::graph_visitor_t; R = boost::bgl_named_params<int, boost::buffer_param_t>; typename boost::result_of<boost::graph::detail::depth_first_search_impl<Param0>(Param0, const typename boost::detail::convert_bgl_params_to_boost_parameter<boost::bgl_named_params<T, Tag, Base> >::type&)>::type = void]’
/usr/include/boost/graph/topological_sort.hpp:65:23:   required from ‘void boost::topological_sort(VertexListGraph&, OutputIterator, const boost::bgl_named_params<P, T, R>&) [with VertexListGraph = Glue::MyGraph; OutputIterator = std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> >; P = int; T = boost::buffer_param_t; R = boost::no_property]’
/usr/include/boost/graph/topological_sort.hpp:71:21:   required from ‘void boost::topological_sort(VertexListGraph&, OutputIterator) [with VertexListGraph = Glue::MyGraph; OutputIterator = std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> >]’
/home/sehe/Projects/stackoverflow/test.cpp:139:55:   required from here
/usr/include/boost/graph/depth_first_search.hpp:337:80: error: no match for call to ‘(const boost::detail::make_property_map_from_arg_pack_gen<boost::graph::keywords::tag::color_map, boost::default_color_type>) (const Glue::MyGraph&, const boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::visitor, const boost::topo_sort_visitor<std::back_insert_iterator<std::__cxx11::list<YourLibrary::myVertex*> > > >, boost::parameter::aux::arg_list<boost::parameter::aux::tagged_argument<boost::graph::keywords::tag::buffer, const int>, boost::parameter::aux::empty_arg_list> >&)’
  337 |                                     boost::detail::make_color_map_from_arg_pack(g, arg_pack),
      |                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
In file included from /usr/include/boost/graph/breadth_first_search.hpp:23,
                 from /home/sehe/Projects/stackoverflow/test.cpp:4:
/usr/include/boost/graph/named_function_params.hpp:620:7: note: candidate: ‘template<class Graph, class ArgPack> typename boost::detail::map_maker<Graph, ArgPack, MapTag, ValueType>::map_type boost::detail::make_property_map_from_arg_pack_gen<MapTag, ValueType>::operator()(const Graph&, const ArgPack&) const [with Graph = Graph; ArgPack = ArgPack; MapTag = boost::graph::keywords::tag::color_map; ValueType = boost::default_color_type]’
  620 |       operator()(const Graph& g, const ArgPack& ap) const {
      |       ^~~~~~~~
/usr/include/boost/graph/named_function_params.hpp:620:7: note:   substitution of deduced template arguments resulted in errors seen above

為了使用boost::topological_sort ,“膠水”層必須滿足哪些額外要求? 在內部,拓撲排序使用depth_first_search ,但似乎它可能需要頂點索引 map。

正如您正確推測的那樣,錯誤小說告訴您沒有索引 map。 這是默認顏色 map 所必需的

UTIL/OUT : color_map(ColorMap color)算法使用它來跟蹤其在圖形中的進度。 The type ColorMap must be a model of Read/Write Property Map and its key type must be the graph's vertex descriptor type and the value type of the color map must model ColorValue .

默認值:從大小為num_vertices(g)default_color_typestd::vector創建的iterator_property_map並將i_map用於索引 map。

事實上,如果您自己滿足顏色 map 要求,甚至不需要索引 map: Live On Coliru

std::map<V, boost::default_color_type> vertex_colors;
boost::topological_sort(
        g,
        back_inserter(rev_topo),
        boost::color_map(boost::make_assoc_property_map(vertex_colors))
    );

更多思考:教授 BGL 頂點索引

現在,許多算法都需要索引映射,並且許多算法變得更加方便,就像上面一樣,當您的圖形 model確實具有頂點索引 map 時。

一個頂點索引應該 map 頂點描述符為整數[0, n) (其中n是頂點的總數)。 在示例圖 model 的情況下,普通索引將是頂點向量中的元素索引。

因此,您還可以將索引 map 表示為:

auto idmap = boost::make_function_property_map<V>([&](V v) {
    auto match = std::find(begin(vv), end(vv), v);
    assert(match != end(vv));
    return std::distance(begin(vv), match);
});

現在您可以根據其默認顏色 map 調用算法: Coliru

boost::topological_sort(
        g,
        back_inserter(rev_topo),
        boost::vertex_index_map(idmap)
    );

這不是一個很大的勝利,因為現在我們仍然需要可選的命名參數,甚至需要看起來比之前的vertex_colors map 更復雜的idmap裝置?

簡化/集成到 Model

我們可以通過教 BGL 如何從 Glue::MyGraph model 獲取我們的屬性映射來使其變得更好。

BGL 將使用

  • 類型特征boost::property_map<Graph, Tag>告訴 BGL 屬性映射的類型。

    在這里,對於頂點索引 map, Tag將是例如boost::vertex_index_t

  • 訪問器函數

    • get(tag, graph)

      返回該類型的屬性映射的副本

    • get(tag_type, graph, descriptor)

    對於可寫屬性映射,還有相應的put訪問器,但為了簡潔起見,我將保留它。 有關該庫功能的更多信息,請參閱Boost PropertyMap Library的文檔。

讓我們這樣做。 我們首先將idmap生成器移動到MyGraph model,因此我們不再需要了解實現細節:

    auto idmap() const {
        using V = YourLibrary::myVertex const*;
        return boost::make_function_property_map<V>([this](V v) {
            auto match = std::find(begin(_vertices), end(_vertices), v);
            assert(match != end(_vertices));
            return std::distance(begin(_vertices), match);
        });
    }

這意味着您可以簡單地調用g.idmap()來獲得相同的屬性 map。 但是,我們希望圖書館“神奇地”知道。 所以,首先我們專門研究這個特征:

namespace boost {
    template <> struct property_map<Glue::MyGraph, boost::vertex_index_t> {
        using const_type = decltype(std::declval<Glue::MyGraph>().idmap());
    };
}

很高興我們可以推斷出所有這些類型。 僅剩下一步:訪問器函數,它們也是啟用 ADL 的自定義點,因此我們將它們放入我們的 Glue 命名空間:

    auto get(boost::vertex_index_t, MyGraph const& g) {
        return g.idmap();
    }
    auto get(boost::vertex_index_t, MyGraph const& g, YourLibrary::myVertex const* v) {
        return g.idmap()[v];
    }
}  // namespace Glue

布丁的證明

現在,由於庫“只理解”我們的 model 的頂點索引,我們可以享受不需要任何額外幫助的算法:

std::list<V> order;
boost::topological_sort(g, back_inserter(order));

我們可以使用其他訪問器來獲得樂趣:

std::cout << "Topo order:\n";
order.reverse(); // output is reversed
for (auto v : order)
    std::cout << "Vertex index:" << get(boost::vertex_index, g, v)
              << " name:" << v->name << "\n";

在您自己的(非通用庫)代碼中,您可能會編寫

auto idmap = g.idmap(); // or
auto idmap = get(boost::vertex_index, g, v);

並使用idmap[v]來獲取值。

現場演示

住在科利魯

#include <algorithm>
#include <boost/container/flat_map.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/depth_first_search.hpp>
#include <boost/graph/topological_sort.hpp>
#include <boost/property_map/function_property_map.hpp>
#include <iostream>
#include <utility>

namespace YourLibrary {
    struct myVertex {
        myVertex(std::string n) : name(std::move(n)) {}
        std::string name;
    };

    struct myEdge {
        myVertex* _s = nullptr;
        myVertex* _t = nullptr;

        [[nodiscard]] myVertex* source() const { return _s; }
        [[nodiscard]] myVertex* target() const { return _t; }
    };

    using Vertices = std::vector<myVertex *>;
    using Edges = std::vector<myEdge *>;
}  // namespace YourLibrary

namespace Glue {

    struct MyGraph {
        struct EdgeOrder {
            template <typename A, typename B>
                bool operator()(A const* a, B const* b) const { return source(a) < source(b); }
            private:
            static auto source(YourLibrary::myVertex const* v) { return v; }
            static auto source(YourLibrary::myEdge const* e) { return e->source(); }
        };

        using Vertices = YourLibrary::Vertices;
        using Edges = YourLibrary::Edges;

        Vertices& _vertices;
        Edges& _edges;

        auto idmap() const {
            using V = YourLibrary::myVertex const*;
            return boost::make_function_property_map<V>([this](V v) {
                auto match = std::find(begin(_vertices), end(_vertices), v);
                assert(match != end(_vertices));
                return std::distance(begin(_vertices), match);
            });
        }

        MyGraph(Vertices& vv, Edges& ee) : _vertices(vv), _edges(ee)  { 
            assert(std::is_sorted(_edges.begin(), _edges.end(), EdgeOrder{}));
        }
    };
}  // namespace Glue

namespace boost {

    template <> struct graph_traits<Glue::MyGraph> {
        // Due to Graph concept
        using vertex_descriptor      = YourLibrary::myVertex*;
        using edge_descriptor        = YourLibrary::myEdge*;
        using directed_category      = directed_tag;
        using edge_parallel_category = allow_parallel_edge_tag;
        static vertex_descriptor null_vertex() { return nullptr; }

        // Due to Vertex List concept
        struct traversal_category : vertex_list_graph_tag, incidence_graph_tag { };
        using vertex_iterator        = Glue::MyGraph::Vertices::const_iterator;
        using vertices_size_type     = std::size_t;

        // Due to Incidence Graph concept
        using out_edge_iterator = Glue::MyGraph::Edges::const_iterator;
        using degree_size_type = std::size_t;
    };

}  // namespace boost

namespace Glue {
    // Due to Vertex List concept
    auto vertices(MyGraph const& g) {
        return std::make_pair(g._vertices.begin(), g._vertices.end());
    }

    std::size_t num_vertices(MyGraph const& g) {
        return g._vertices.size();
    }

    // Due to Incidence Graph concept
    auto source(YourLibrary::myEdge const* e, MyGraph const& /*g*/) {
        return e->source();
    }
    auto target(YourLibrary::myEdge const* e, MyGraph const& /*g*/) {
        return e->target();
    }

    auto out_edges(YourLibrary::myVertex const* v, MyGraph const& g) {
        return std::equal_range(g._edges.begin(), g._edges.end(), v, MyGraph::EdgeOrder{});;
    }
    std::size_t out_degree(YourLibrary::myVertex const* v, MyGraph const& g) {
        auto oee = std::equal_range(g._edges.begin(), g._edges.end(), v, MyGraph::EdgeOrder{});
        return std::distance(oee.first, oee.second);
    }

    auto get(boost::vertex_index_t, MyGraph const& g) {
        return g.idmap();
    }
    auto get(boost::vertex_index_t, MyGraph const& g, YourLibrary::myVertex const* v) {
        return g.idmap()[v];
    }
}  // namespace Glue

namespace boost {
    template <> struct property_map<Glue::MyGraph, boost::vertex_index_t> {
        using const_type = decltype(std::declval<Glue::MyGraph>().idmap());
    };
}

int main() {
    // I hate manual memory management, so let's own some objects
    auto a = std::make_unique<YourLibrary::myVertex>("a");
    auto b = std::make_unique<YourLibrary::myVertex>("b");
    auto c = std::make_unique<YourLibrary::myVertex>("c");
    auto ab = std::make_unique<YourLibrary::myEdge>(YourLibrary::myEdge{a.get(), b.get()});
    auto cb = std::make_unique<YourLibrary::myEdge>(YourLibrary::myEdge{c.get(), b.get()});

    // These were given in your question:
    YourLibrary::Vertices vv { a.get(), b.get(), c.get() };
    YourLibrary::Edges ee { ab.get(), cb.get() };

    // this is the glue required to fulfill the BGL concepts:
    using boost::make_iterator_range;

    Glue::MyGraph g(vv, ee);
    for (auto v : make_iterator_range(vertices(g)))
        for (auto e : make_iterator_range(out_edges(v, g)))
            std::cout << "out edge ("
                      << source(e, g)->name << " -> "
                      << target(e, g)->name << ")\n";

    // this is showing that you can now BFS on it
    using V = boost::graph_traits<Glue::MyGraph>::vertex_descriptor;
    V start_vertex = a.get();
    std::map<V, boost::default_color_type> color_data;

    boost::breadth_first_search(g, start_vertex,
        boost::visitor(boost::default_bfs_visitor {})
            .color_map(boost::make_assoc_property_map(color_data)));

    boost::depth_first_search(g, boost::default_dfs_visitor {},
        boost::make_assoc_property_map(color_data), start_vertex);

    // named params
    boost::depth_first_search(g,
        boost::visitor(boost::default_dfs_visitor {})
            .color_map(boost::make_assoc_property_map(color_data))
            .root_vertex(start_vertex));

    std::list<V> order;
    boost::topological_sort(g, back_inserter(order));

    std::cout << "Topo order:\n";
    order.reverse(); // output is reversed

    auto idmap = g.idmap();
    for (auto v : order)
        std::cout << "Vertex index:" << idmap[v] << " name:" << v->name << "\n";
}

印刷

out edge (a -> b)
out edge (c -> b)
Topo order:
Vertex index:2 name:c
Vertex index:0 name:a
Vertex index:1 name:b

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM