如何使用 BGL 计算边缘介数

问题描述

根据 this 帖子,我能够编译此代码

Graph_type newGraph(edge_arrayNoDuplicates,edge_arrayNoDuplicates + numEdges,transmission_delay,numVertices);

boost::shared_array_property_map<double,boost::property_map<Graph_type,vertex_index_t>::const_type>
            edge_centrality_map(num_vertices(newGraph),get(boost::vertex_index,newGraph));
    brandes_betweenness_centrality(newGraph,edge_centrality_map);

我想获得边缘中心图而不是中心图,我认为我正确地实现了它,但我不确定。 我希望从中得到的是能够使用调用 brandes_betweenness_centrality(newGraph,edge_centrality_map) 的返回值并找到具有最高边缘介数的边缘,然后删除该边缘。我不知道如何访问从调用brandes 算法返回的值。它甚至返回值吗?如果没有,我如何访问边缘介数?

解决方法

好的,我只是posted the simplified graph reading code

在您当前的问题中,我看到了新的 edge_arrayNoDuplicates 变量名称,这表明您在某种程度上删除了重复的边。

作为专业提示,我建议您无需任何手动工作即可获得相同的效果,方法是为边缘容器选择器选择 setS 而不是 vecS

using Graph_type =
    boost::adjacency_list<boost::setS,boost::vecS,boost::bidirectionalS,boost::no_property,boost::property<boost::edge_weight_t,float>>;

那是两个字母改变了,完成了。实际上,为了提高性能,您可能仍希望保留 vecS,但您可能应该查看分析器告诉您的信息。如果它足够快,我不会打扰。


那么中介算法的代码有一些问题。

boost::shared_array_property_map<
    double,boost::property_map<Graph_type,boost::vertex_index_t>::const_type>
    edge_centrality_map(num_vertices(g),get(boost::vertex_index,g));

首先,让我们现代一点,避免类型信息的重复:

auto edge_centrality_map = boost::make_shared_array_property_map(
    num_vertices(g),1.,g));

接下来,这有一个问题,它使用顶点索引,你最多需要一个边缘索引。但让我们先进一步看看:

brandes_betweenness_centrality(g,edge_centrality_map);

您将 edge_centrality_map 作为单个地图参数传递。检查 the docs 告诉我唯一的 2 参数重载是

template<typename Graph,typename CentralityMap>
void
brandes_betweenness_centrality(const Graph& g,CentralityMap centrality_map);

因此,无论您如何命名变量,它都不会是 EdgeCentralityMap,而是 (Vertex)CentralityMap。哎呀。这可能就是您在那里使用 vertex_index 以使其完全编译的原因。

我建议使用常规映射而不是共享数组属性映射:

std::map<Graph_type::edge_descriptor,double> edge_centralities;

这样您就不必使用 edge_index(您还没有)使用间接寻址。您可以直接将其调整为属性映射:

auto ecm = boost::make_assoc_property_map(edge_centralities);

然后您可以在算法中使用它。为了避免必须提供某种中心性映射,我们可以使用命名参数重载:

brandes_betweenness_centrality(g,boost::edge_centrality_map(ecm));

输出结果:

for (auto edge : boost::make_iterator_range(edges(g))) {
    auto s = invmap.at(source(edge,g));
    auto t = invmap.at(target(edge,g));
    std::cout << "Betweenness for " << s << "-" << t << " "
              << edge_centralities.at(edge) << "\n";
}

现场演示

Live On Coliru(数据来源:put_data_here.txt

示例使用更大的图形并显示具有最高中心性的前 10 条边:

int main() {
    Mappings mappings;
    Graph_type g = readInGraph("put_data_here.txt",mappings);

    using ECMap = std::map<Graph_type::edge_descriptor,double>;
    using ECEntry = ECMap::value_type;
    ECMap ecm;
    brandes_betweenness_centrality(
        g,boost::edge_centrality_map(boost::make_assoc_property_map(ecm)));

    std::vector<std::reference_wrapper<ECEntry>> ranking(ecm.begin(),ecm.end());

    {
        // top-n
        auto n = std::min(10ul,ranking.size());
        auto first = ranking.begin(),middle = first + n,last = ranking.end();
        std::partial_sort(
                first,middle,last,[](ECEntry const& a,ECEntry const& b) { return a.second > b.second; });

        ranking.erase(middle,last);
    }

    auto& edgenames = mappings.right;

    for (ECEntry const& entry : ranking) {
        auto [edge,centrality] = entry;
        auto s = edgenames.at(source(edge,g));
        auto t = edgenames.at(target(edge,g));
        std::cout << s << "-" << t << " centrality " << centrality << "\n";
    }
}

印刷品

J-Q centrality 35.1
J-H centrality 20.5905
N-H centrality 18.0905
C-P centrality 16.1
H-B centrality 14.5571
P-S centrality 13.6024
J-C centrality 13.3833
H-E centrality 12.8905
Q-R centrality 12.6
L-G centrality 12.5333