使用labeled_graph 提升图bellman_ford_shortest_paths

Posted

技术标签:

【中文标题】使用labeled_graph 提升图bellman_ford_shortest_paths【英文标题】:Boost Graph bellman_ford_shortest_paths with labeled_graph 【发布时间】:2019-01-05 03:56:44 【问题描述】:

我正在尝试使用 Boost 库运行 Bellman-Ford 算法。我有一个带标签的图表,但我得到了一个例外invalid conversion from ‘void*’ to ‘int。任何帮助将不胜感激。这是我的代码:

// g++ -std=c++17 -Wall test.c++ -l boost_system && ./a.out 

#include <iostream>                  // for cout
#include <utility>                   // for pair
#include <algorithm>                 // for for_each
#include <vector>                    // For dist[] and pred[]
#include <limits>                    // To reliably indicate infinity
#include <map>
#include <list>

#include <boost/config.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/graph/directed_graph.hpp>
#include <boost/graph/labeled_graph.hpp>
#include <boost/graph/bellman_ford_shortest_paths.hpp>

using namespace boost;
using namespace std;

class Node

  public:
    int id;
    int group;
;

struct EdgeProperties 
  double weight;

  EdgeProperties()
  EdgeProperties(double w) weight = w; 
;

typedef labeled_graph<adjacency_list<hash_setS, hash_setS, directedS, Node, EdgeProperties>, int> Graph;

int main()

    cout << "Calling main()" << endl;

    Graph g;

    // populate the graph
    
        add_vertex( 0, g );
        g[0].id  = 0;
        g[0].group = 10;
        add_vertex( 1, g );
        g[1].id  = 1;
        g[1].group = 20;
        add_edge_by_label( 0, 1, EdgeProperties(110), g);
        add_edge_by_label( 1, 0, EdgeProperties(222), g);
        print_graph(g, get(&Node::id, g));
        cout << "There are " << num_vertices(g) << " nodes and " << num_edges(g) << " edges in the graph" << endl;
    

    // number of verticies in the graph
    auto n = num_vertices(g);

    // weight map
    auto ewp = weight_map(get(&EdgeProperties::weight, g.graph()));

    const int source = 0;
    const int target = 1;

    // Distance Map (with n elements of value infinity; source's value is 0)
    auto inf = numeric_limits<double>::max();
    vector<double> dist(n, inf);
    dist[source] = 0.0;

    // Predecessor Map (with n elements)
    vector<int> pred(n);

    bellman_ford_shortest_paths(
        g.graph(), 
        n, 
        ewp
            .distance_map(make_iterator_property_map(dist.begin(), get(&Node::id, g)))
            .predecessor_map(make_iterator_property_map(pred.begin(), get(&Node::id, g)))
    );

    return 0;

我在https://www.boost.org/doc/libs/1_53_0/libs/graph/example/bellman-example.cpp 上看到了这个例子,但这个例子没有使用带标签的图表。

这是我的代码的实时预览:

https://wandbox.org/permlink/WsQA8A0IyRvGWTIj

谢谢

【问题讨论】:

【参考方案1】:

问题的根源在您接受的现有答案中已被提及。

但是,还有更多。

首先,您几乎“在您的权利范围内”想要使用 Node::id 作为顶点索引,并且可能有很多很好的理由使用 vector 以外的其他东西作为 顶点容器选择器¹。

其次,那些东西应该……可能已经奏效了。 bellman_ford documents:

PredecessorMap 类型必须是一个读/写属性映射,其键和顶点类型与图的顶点描述符类型相同。

还有iterator_property_map documents:

此属性映射是一个适配器,可将任何随机访问迭代器转换为左值属性映射。 OffsetMap 类型负责将关键对象转换为整数,可用作随机访问迭代器的偏移量。

现在LValuePropertyMap可能实际上是只读的,但在这种情况下显然不应该。

当使用带有附加 id-map 参数的 make_iterator_property_map 时,它实际上应该像算法要求的键和值类型 vertex_descriptor 的任何关联属性映射一样表现。

更新请参阅下面的“奖励”

稍后我可能会更详细地了解为什么这不起作用,但现在让我们在不修改图形模型的情况下解决这个问题:

Live On Coliru

auto gg = g.graph();
auto id = get(&Node::id, gg);
std::map<Graph::vertex_descriptor, Graph::vertex_descriptor> assoc_pred;

bellman_ford_shortest_paths(gg, n,
    weight_map(get(&EdgeProperties::weight, gg))
    .distance_map(make_iterator_property_map(dist.begin(), id))
    .predecessor_map(make_assoc_property_map(assoc_pred))
    );

按预期工作:

Calling main()
1 --> 0 
0 --> 1 
There are 2 nodes and 2 edges in the graph

奖金

我找到了缺失的链接:前任映射定义了错误的值类型:

vector<Graph::vertex_descriptor> pred(n);

显然会起作用:Live On Coliru


¹这与顶点描述符略有不同,但在某种意义上是相关的,即顶点容器的选择通常会预测顶点描述符的实际类型

【讨论】:

再看一下其他方法编译失败的原因。 是的。毕竟这很简单。容易忽视,所以不用担心:)

以上是关于使用labeled_graph 提升图bellman_ford_shortest_paths的主要内容,如果未能解决你的问题,请参考以下文章

使用列入黑名单的边提升过滤图

提升状态图并行执行正交状态

通过与输入相同的提升图创建无向图

H5C3--background中cover,背景样式,提升响应区域+精灵图的使用

lift提升图

MATLAB 中分类预测生成提升图的置信度