带标签_Graph的Boost Graph bellman_ford_shortest_path

Boost Graph bellman_ford_shortest_paths with labeled_graph

本文关键字:Graph ford shortest path bellman 标签 Boost      更新时间:2023-10-16

我正在尝试使用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

谢谢

问题的来源已在您接受的现有答案中触及

然而,这还有更多。

首先,您非常"有权"使用Node::id作为顶点索引,并且使用vector以外的其他内容作为顶点容器选择器1可能有很多充分的理由。

其次,这些东西应该。。。可能已经奏效了。bellman_ford文档:

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

iterator_property_map文档:

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

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

当将make_iterator_property_map与额外的id映射参数一起使用时,它实际上应该表现得像任何关联属性映射一样——键和值类型vertex_descriptor都是算法所要求的。

更新请参阅下方的"奖金">

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

在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);

显然有效:在Coliru上直播


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