c++ - 将外部属性映射附加到图形

标签 c++ boost boost-graph

将边权重作为内部属性添加到图中很简单:

void InternalProperties()
{
    std::cout << "InternalProperties()" << std::endl;

    // Graph with internal edge weights
    using EdgeWeightProperty = boost::property<boost::edge_weight_t, double>; // <tag, type>

    using GraphWithInternalEdgeWeightsType =  boost::adjacency_list<boost::setS, // out edge container
                                                                    boost::vecS, // vertex container
                                                                    boost::undirectedS, // directed or undirected
                                                                    boost::no_property, // vertex properites
                                                                    EdgeWeightProperty> // edge properties
                                                                    ;

    // Create a graph object
    GraphWithInternalEdgeWeightsType g(3);

    // add two edges with edge weights
    EdgeWeightProperty e1 = 5;
    add_edge(0, 1, e1, g);

    EdgeWeightProperty e2 = 3;
    add_edge(1, 2, e2, g);

    boost::property_map<GraphWithInternalEdgeWeightsType, boost::edge_weight_t>::type edgeWeightMap = get(boost::edge_weight_t(), g);

    using edge_iter = boost::graph_traits<GraphWithInternalEdgeWeightsType>::edge_iterator;
    std::pair<edge_iter, edge_iter> edgePair;
    for(edgePair = edges(g); edgePair.first != edgePair.second; ++edgePair.first) {
      std::cout << edgeWeightMap[*edgePair.first] << " ";
    }
}

现在,如果我想做同样的事情并演示使用“外部属性”,我想到了这个,但实际上根本没有回到原始图表的链接:

void ExternalProperties()
{
    std::cout << std::endl << "ExternalProperties()" << std::endl;

    // Graph with external edge weights
    using GraphWithExternalEdgeWeightsType =  boost::adjacency_list<boost::setS, // out edge container
                                                                    boost::vecS, // vertex container
                                                                    boost::undirectedS> // directed or undirected
                                                                    ;

    // Create a graph object
    GraphWithExternalEdgeWeightsType g(3);

    // add edges (without edge weights)
    add_edge(0, 1, g);
    add_edge(1, 2, g);

    // create a map from edge_descriptors to weights and populate it
    std::map<GraphWithExternalEdgeWeightsType::edge_descriptor, double> edgeWeightMap;
    edgeWeightMap[boost::edge(0,1,g).first] = 5;
    edgeWeightMap[boost::edge(1,2,g).first] = 3;

    using edge_iter = boost::graph_traits<GraphWithExternalEdgeWeightsType>::edge_iterator;
    std::pair<edge_iter, edge_iter> edgePair;
    for(edgePair = edges(g); edgePair.first != edgePair.second; ++edgePair.first) {
      std::cout << edgeWeightMap[*edgePair.first] << " ";
    }
}

有什么方法可以让 get(boost::edge_weight_t(), g);(来自内部示例)返回这张 map ?喜欢在这个外部示例中说 g.setPropertyMap(boost::edge_weight_t, edgeWeightMap) 吗?

最佳答案

我不确定收获是什么,但也许这有助于激发灵感:

#include <boost/graph/adjacency_list.hpp>
#include <boost/property_map/property_map.hpp>
#include <map>
#include <iostream>

namespace MyLib {
    struct MyGraph : boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS> {
        using base_type = boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS>;
        using base_type::adjacency_list;

        std::map<edge_descriptor, double> m_weights;
    };

    auto get(boost::edge_weight_t, MyGraph& g)       { return boost::make_assoc_property_map(g.m_weights); }
    auto get(boost::edge_weight_t, MyGraph const& g) { return boost::make_assoc_property_map(g.m_weights); }
}

namespace boost {
    template <> struct graph_traits<MyLib::MyGraph> : graph_traits<adjacency_list<setS, vecS, undirectedS> > {};

    template <> struct property_map<MyLib::MyGraph, edge_weight_t, void> {
        using Traits = graph_traits<MyLib::MyGraph>;

        using Edge       = Traits::edge_descriptor;
        using type       = boost::associative_property_map<std::map<Edge, double> >;
        using const_type = boost::associative_property_map<std::map<Edge, double> > const;
    };
}

void ExternalProperties() {
    std::cout << "ExternalProperties()" << std::endl;

    // Graph with external edge weights
    // Create a graph object
    using Graph = MyLib::MyGraph;
    Graph g(3);

    // add edges (without edge weights)
    add_edge(0, 1, g);
    add_edge(1, 2, g);

    // create a map from edge_descriptors to weights and populate it
    auto edgeWeightMap = MyLib::get(boost::edge_weight, g);
    edgeWeightMap[boost::edge(0, 1, g).first] = 5;
    edgeWeightMap[boost::edge(1, 2, g).first] = 3;

    using edge_iter = boost::graph_traits<Graph>::edge_iterator;
    std::pair<edge_iter, edge_iter> edgePair;

    for (edgePair = edges(g); edgePair.first != edgePair.second; ++edgePair.first) {
        std::cout << edgeWeightMap[*edgePair.first] << " ";
    }
}

int main() {
    ExternalProperties();
}

我无法避免 boost::get 的歧义,您可以相信 ADL 会在没有命名空间限定的情况下选择“最佳”重载。

Live On Coliur

关于c++ - 将外部属性映射附加到图形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41579825/

相关文章:

c++ - 默认参数和变量列表

c++ - shared_ptr<void> t(new char[num]) 意味着内存泄漏?

boost - 查找 boost multi index 标签到索引和索引数量

c++ - 用boost spirit X3高效解析琐碎文件

c++ - 查询完整的有向图,判断上下游关系和距离

c++ - 如何从 Win32 C++ 应用程序输出到父控制台窗口?

c++ - 如何子类化和重新实现包含在命名空间中的类?

c++ - 当进程退出时收到通知

c++ - 在 C++ 中包含目录时指定完整路径

c++ - 使用黑名单边缘提升过滤图