仅将 std::vector 属性的元素传递给 BGL 算法

发布于 2024-09-30 04:09:13 字数 656 浏览 3 评论 0原文

我有一个图,其中多个边权重存储为

namespace boost {
    enum edge_weightvector_t {
        edge_weightvector = 1337
    };
    BOOST_INSTALL_PROPERTY(edge, weightvector);
}

typedef boost::adjacency_list<
    boost::vecS,
    boost::vecS,
    boost::undirectedS,
    boost::no_property,
    boost::property<boost::edge_weightvector_t, std::vector<int> >
> graph_t;

权重全部推到向量上。

现在我想调用 prim_minimum_spanning_tree()< /code>函数在图上,向量中的第一个元素用作权重。

如何执行正确的函数调用?

I have a graph with multiple edge weightings stored as

namespace boost {
    enum edge_weightvector_t {
        edge_weightvector = 1337
    };
    BOOST_INSTALL_PROPERTY(edge, weightvector);
}

typedef boost::adjacency_list<
    boost::vecS,
    boost::vecS,
    boost::undirectedS,
    boost::no_property,
    boost::property<boost::edge_weightvector_t, std::vector<int> >
> graph_t;

The weightings are all pushed onto the vector.

Now I want to call the prim_minimum_spanning_tree() function on the graph, with the first elements in the vector used as weightings.

How can I perform a correct function call?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

最舍不得你 2024-10-07 04:09:13

我现在已经做到了,首先将所需的权重复制到附加属性,然后运行算法并随后复制回来。它很丑陋,但对我来说却很有效。

I've did it now by first copying the desired weightings to an additional property, then running the algorithm and copying back afterwards. It is ugly, but it does the trick in my case.

浮萍、无处依 2024-10-07 04:09:13

我最近尝试做同样的事情(使用向量属性),但未能仅使用其中一个值运行算法。但是,我发现使用 外部属性 是这是一种不会导致不必要的复制操作并将属性映射显式传递给算法的好方法。

如果您使用随机访问容器,则可以使用 boost::iterator_property_map 来包装该容器并使其成为 property_map。它不需要边缘描述符,而是需要基于 0 的边缘索引来实现边缘和属性值之间的有效映射。这是要点,进一步完成后,您会找到完整的示例:

// ... 
EdgeIndexMap edgeIds = get(edge_index, g);
// ...
typedef std::vector<int> Weights;
typedef std::vector<Weights> WeightsVector;
typedef iterator_property_map <Weights::iterator, EdgeIndexMap> WeightMap;
// ...
Weights weights; // = ...
WeightMap wm(weights.begin(), edgeIds);
// ...
some_bgl_algorithm(g, wm);

这里是一个完整的示例:

  using namespace boost;

  void sampleExteriorProperties()
  {
     typedef adjacency_list<vecS, vecS, undirectedS,
                            no_property,
                            //property<edge_index_t, int, property<edge_weight_t, int> >
                            property<edge_index_t, std::size_t>
                            > Graph;
     typedef graph_traits<Graph>::edge_descriptor Edge;
     typedef graph_traits<Graph>::edge_iterator EdgeIterator;
     typedef property_map<Graph, edge_index_t>::type EdgeIndexMap;
     //typedef property_map<Graph, edge_weight_t>::type WeightMap;

     const int NVERTICES = 5;
     const int NEDGES = 8;

     Graph g(NVERTICES);

     // Add edges WITH indexes.
     int edgeIndex = 0;
     add_edge(0, 1, edgeIndex++, g);
     add_edge(0, 2, edgeIndex++, g);
     add_edge(0, 3, edgeIndex++, g);
     add_edge(1, 2, edgeIndex++, g);
     add_edge(1, 4, edgeIndex++, g);
     add_edge(2, 3, edgeIndex++, g);
     add_edge(2, 4, edgeIndex++, g);
     add_edge(3, 4, edgeIndex++, g);

     // Weights: there must be a weight for every edge.
     // Weights will be later on accessed by edge index.
     assert(num_edges(g) == NEDGES);
     typedef std::vector<int> Weights;
     typedef std::vector<Weights> WeightsVector;
     WeightsVector weightVector({ { 2, 3, 5, 7, 9, 11, 13, 17 },
                                  { 8, 7, 6, 5, 4, 3, 2, 1 }
                                });

     EdgeIndexMap edgeIds = get(edge_index, g);

     for (Weights &weights : weightVector)
     {
        // Use the iterator_property_map to read the properties from a
        // random access container. Remember: Edge ids are used to access
        // the correct value from the container!
        typedef iterator_property_map <Weights::iterator, EdgeIndexMap> WeightMap;
        WeightMap wm(weights.begin(), edgeIds);

        EdgeIterator eIt, eItEnd;
        tie(eIt, eItEnd) = edges(g);
        while (eIt!=eItEnd)
        {
           std::cout << *eIt << ": " << wm[*eIt] << " ";
           ++eIt;
        }
        std::cout << std::endl;

        // Explicitly pass the exterior map to the algorithm.
        std::vector<Edge> mstEdges;
        kruskal_minimum_spanning_tree(g, std::back_inserter(mstEdges),
                                      weight_map(wm));

        std::for_each(mstEdges.begin(), mstEdges.end(),
                      [](const Edge &val){std::cout << val << " ";});
        std::cout << std::endl;
     }

  }

I recently tried to do the same (to use a vector property) and failed to run algorithms only with one of the values. However, I found that using exterior properties is a good approach that won't lead to unnecessary copy actions and to pass the property map explicitly to the algorithm.

If you use random access containers you can use boost::iterator_property_map that will wrap that container and make it a property_map. Instead of edge descriptors it requires 0-based edge indices for the efficient mapping between edges and property values. Here is the punchline, further done you find the complete example:

// ... 
EdgeIndexMap edgeIds = get(edge_index, g);
// ...
typedef std::vector<int> Weights;
typedef std::vector<Weights> WeightsVector;
typedef iterator_property_map <Weights::iterator, EdgeIndexMap> WeightMap;
// ...
Weights weights; // = ...
WeightMap wm(weights.begin(), edgeIds);
// ...
some_bgl_algorithm(g, wm);

And here a complete example:

  using namespace boost;

  void sampleExteriorProperties()
  {
     typedef adjacency_list<vecS, vecS, undirectedS,
                            no_property,
                            //property<edge_index_t, int, property<edge_weight_t, int> >
                            property<edge_index_t, std::size_t>
                            > Graph;
     typedef graph_traits<Graph>::edge_descriptor Edge;
     typedef graph_traits<Graph>::edge_iterator EdgeIterator;
     typedef property_map<Graph, edge_index_t>::type EdgeIndexMap;
     //typedef property_map<Graph, edge_weight_t>::type WeightMap;

     const int NVERTICES = 5;
     const int NEDGES = 8;

     Graph g(NVERTICES);

     // Add edges WITH indexes.
     int edgeIndex = 0;
     add_edge(0, 1, edgeIndex++, g);
     add_edge(0, 2, edgeIndex++, g);
     add_edge(0, 3, edgeIndex++, g);
     add_edge(1, 2, edgeIndex++, g);
     add_edge(1, 4, edgeIndex++, g);
     add_edge(2, 3, edgeIndex++, g);
     add_edge(2, 4, edgeIndex++, g);
     add_edge(3, 4, edgeIndex++, g);

     // Weights: there must be a weight for every edge.
     // Weights will be later on accessed by edge index.
     assert(num_edges(g) == NEDGES);
     typedef std::vector<int> Weights;
     typedef std::vector<Weights> WeightsVector;
     WeightsVector weightVector({ { 2, 3, 5, 7, 9, 11, 13, 17 },
                                  { 8, 7, 6, 5, 4, 3, 2, 1 }
                                });

     EdgeIndexMap edgeIds = get(edge_index, g);

     for (Weights &weights : weightVector)
     {
        // Use the iterator_property_map to read the properties from a
        // random access container. Remember: Edge ids are used to access
        // the correct value from the container!
        typedef iterator_property_map <Weights::iterator, EdgeIndexMap> WeightMap;
        WeightMap wm(weights.begin(), edgeIds);

        EdgeIterator eIt, eItEnd;
        tie(eIt, eItEnd) = edges(g);
        while (eIt!=eItEnd)
        {
           std::cout << *eIt << ": " << wm[*eIt] << " ";
           ++eIt;
        }
        std::cout << std::endl;

        // Explicitly pass the exterior map to the algorithm.
        std::vector<Edge> mstEdges;
        kruskal_minimum_spanning_tree(g, std::back_inserter(mstEdges),
                                      weight_map(wm));

        std::for_each(mstEdges.begin(), mstEdges.end(),
                      [](const Edge &val){std::cout << val << " ";});
        std::cout << std::endl;
     }

  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文