提升图表 bellman_ford_shortest_paths 与 labeled_graph

Boost Graph bellman_ford_shortest_paths with labeled_graph

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

谢谢

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

然而,还有更多。

首先,您几乎 "within your right" 想要使用 Node::id 作为顶点索引,并且可能有很多充分的理由使用 vector 以外的其他东西作为 顶点容器选择器¹.

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

The PredecessorMap type must be a Read/Write Property Map which key and vertex types the same as the vertex descriptor type of the graph.

iterator_property_map documents

This property map is an adaptor that converts any random access iterator into a Lvalue Property Map. The OffsetMap type is responsible for converting key objects to integers that can be used as offsets with the random access iterator.

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

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

UPDATE See "BONUS" below

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

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

奖金

我找到了缺失的 link:前身映射定义了错误的值类型:

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

显然会起作用:Live On Coliru


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