【问题标题】:how to use a compressed_sparse_row_graph and dijkstra with the BOOST graph library如何将compressed_sparse_row_graph 和dijkstra 与BOOST 图形库一起使用
【发布时间】:2014-09-05 19:30:04
【问题描述】:

背景:我是一个 hack,无论如何都不是一个好的程序员,FORTRAN 实际上是我的语言,需要一些关于这个 boost 代码的帮助。当我实现这个时,我在向量的第 779 行得到一个“向量下标超出范围”错误。这是我的代码,任何帮助将不胜感激!

程序从文件中读取边,构建图,然后我想计算一个顶点到所有其他顶点的距离。

这个问题看起来应该很容易解决,但我很苦恼,谢谢!

-杰夫

#include "stdafx.h"
#include <stdexcept>
#include <boost/graph/adjacency_list.hpp> 
#include <iostream> 
#include <utility>               
#include <algorithm>             
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/compressed_sparse_row_graph.hpp>
#include <boost/graph/dijkstra_shortest_paths_no_color_map.hpp> 

#include <fstream>
#include <string>
#include <stdio.h>
#include <time.h>     
#include <iostream>

using namespace std;
using namespace boost;



int main()
{


long int num_nodes;
long int num_edges;
char *gfile ; //graph data file
char  buffer[128] ;
istringstream instream ;
gfile="grid.out";
ifstream infile( gfile, ios::in );
infile.getline(buffer, 128);
instream.clear() ;
instream.str(buffer) ;
instream >> num_nodes >> num_edges;

float wt;  // Allocate n ints and save ptr in a.
int num_arcs = num_edges;
int n1,n2;

  cout << "READING graph into C++ program from file grid.out";  cout << endl;cout << endl;  cout << endl;
  cout << "Found ";cout << num_nodes; cout << " nodes, and "; cout << num_edges; cout << " edges";cout  << endl;

     typedef std::pair < int, int > Edge;
     struct Edge_Cost
     {
         double weight;
     };

     struct vertex_data {
         boost::graph_traits<
             boost::compressed_sparse_row_graph< boost::directedS > >::vertex_descriptor p;
         double d;
     };

     typedef boost::compressed_sparse_row_graph<
         boost::directedS,
         vertex_data,
         Edge_Cost
     > graph_t;

     typedef boost::graph_traits < graph_t >::vertex_descriptor
         vertex_descriptor;
     graph_t* Graph;

     std::vector<vertex_descriptor> p;//path
     std::vector<double> d;    //distance

         int numb_edges                  = num_edges;
         Edge* edge_list                 = new Edge [numb_edges];
         Edge* ptr_edge_list             = edge_list;
         Edge_Cost* edge_weight_list     = new Edge_Cost[numb_edges];
         Edge_Cost* ptr_edge_weight_list = edge_weight_list;

    for (int i=0; i<num_edges; ++i)
    {
        //get a line from the file, vertex n1 is linked to vertex n2 by weight wt, but first vertex in file is 1 not 0, so -1


                //here is an example of the file:
                //grid.out:  first line is nvertex, nedges
//10  10
//1 2 0.296033428
//2 3 0.038954928
//3 4 0.080953663
//4 5 0.917876269
//5 6 0.026168687
//6 7 0.037261078
//7 8 0.409351058
//8 9 0.398426038
//9 10 0.942112529
//10 11 0.006422981

        infile.getline(buffer, 128);
        instream.clear() ;
            instream.str(buffer) ;
        instream >> n1 >> n2 >> wt;
        *ptr_edge_list++        = Edge(n1-1,n2-1);
        (ptr_edge_weight_list++)->weight =wt;
    }

Graph = new graph_t(boost::edges_are_unsorted,edge_list,ptr_edge_list,edge_weight_list,num_nodes);

    vertex_descriptor s = vertex(1,*Graph);

        //get one set of distances
    boost::dijkstra_shortest_paths_no_color_map
         (*Graph,s,
         boost::predecessor_map(&p[0]).
         distance_map(&d[0]).
         weight_map(boost::get(&Edge_Cost::weight, *Graph))
         );



return 0;
} 

【问题讨论】:

  • "'向量下标超出范围' ..." 学习如何调试代码的良好起点。启动调试器,并逐行执行! (“我是个黑客,不是一个好的程序员”不,你不是,黑客首先应该知道如何编写好的程序,但要探索克服这个问题的技术)
  • 谢谢,我确实知道该怎么做(是的,我只是半个黑客),仍然没有帮助,似乎图表构建正确,节点数,边等。

标签: c++ boost


【解决方案1】:

Graph 类型必须是 Vertex List Graph 和 Incidence Graph 的模型。 docs

看看http://www.boost.org/doc/libs/1_56_0/libs/graph/doc/compressed_sparse_row.html#models 的表现如何:

compressed_sparse_row_graph 类模板模型(即, 实现了许多 BGL 图概念的要求, 允许它与大多数 BGL 算法一起使用。特别是, 它对以下特定的图形概念进行建模:

  • 图表
  • 发病率图
  • 邻接图
  • VertexListGraph
  • EdgeListGraph
  • 属性图

这应该是可能的。让我稍后尝试回发

啊。这个问题有点误导。错误是您没有在距离和前任地图中保留足够的空间。

前驱图记录最小生成树中的边。算法完成后,V 中所有 u 的边 (p[u],u) 都在最小生成树中。如果 p[u] = u 那么 u 要么是源顶点,要么是源顶点不可到达的顶点。 PredecessorMap 类型必须是图形的读/写属性映射whose key and value types are the same as the vertex descriptor 类型。

换句话说,使用足够高的容量来处理最高的顶点描述符(示例中的 11 个)

从源顶点start_vertex到graph图中每个顶点的最短路径权重记录在这个property map中。最短路径权重是沿最短路径的边权重之和。 DistanceMap 类型必须是 Read/Write Property Map 的模型。图的顶点描述符类型需要可用作距离图的键类型

这里也一样。

清理

这是代码Live On Coliru的清理

  • 避免new(以及缺少的delete[]
  • 通过使用 std::getline 避免 getline 的不安全缓冲区
  • cout 语句组合在一行中
  • 适当调整前驱图/距离图的大小
  • 删除虚假评论 (// Allocate n ints and save ptr in a.?)
#include <algorithm>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/compressed_sparse_row_graph.hpp>
#include <boost/graph/dijkstra_shortest_paths_no_color_map.hpp>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>
#include <utility>

using namespace boost;

int main()
{
    std::ifstream infile("input.txt", std::ios::in);

    long int num_nodes;
    long int num_edges;
    {
        std::string line;
        std::getline(infile, line);
        std::istringstream instream(line);
        instream >> num_nodes >> num_edges;
    }

    std::cout << "READING graph into C++ program from file" << std::endl;
    std::cout << "Found " << num_nodes << " nodes, and " << num_edges << " edges" << std::endl;

    typedef std::pair < int, int > Edge;
    struct Edge_Cost
    {
        double weight;
    };

    struct vertex_data
    {
        boost::graph_traits<
        boost::compressed_sparse_row_graph< boost::directedS > >::vertex_descriptor p;
        double d;
    };

    typedef boost::compressed_sparse_row_graph<
    boost::directedS,
          vertex_data,
          Edge_Cost
          > graph_t;

    typedef boost::graph_traits < graph_t >::vertex_descriptor
    vertex_descriptor;

    std::vector<Edge> edge_list;
    std::vector<Edge_Cost> edge_weight_list;

    for(int i=0; i<num_edges; ++i)
    {
        float wt;
        int n1,n2;

        //get a line from the file, vertex n1 is linked to vertex n2 by weight
        //wt, but first vertex in file is 1 not 0, so -1

        std::string line;
        std::getline(infile, line);
        std::istringstream instream(line);
        instream >> n1 >> n2 >> wt;

        edge_list.emplace_back(n1-1, n2-1);
        edge_weight_list.push_back(Edge_Cost{wt});

        std::cout << "Read: " << n1 << " " << n2 << " " << wt << "\n";
    }

    graph_t Graph(boost::edges_are_unsorted,edge_list.begin(),edge_list.end(),&edge_weight_list[0],edge_list.size());

    vertex_descriptor s = vertex(1,Graph);
    std::vector<vertex_descriptor> p(11);//path
    std::vector<double> d(11);    //distance

    //get one set of distances
    boost::dijkstra_shortest_paths_no_color_map
        (Graph,s,
         boost::predecessor_map(&p[0]).
         distance_map(&d[0]).
         weight_map(boost::get(&Edge_Cost::weight, Graph))
        );
}

【讨论】:

  • 我已经稍微清理了代码,看到它Live On Coliru(特别缺少:输入错误处理)
  • 哇,非常感谢。这个问题具有误导性,因为我不知道问题是什么,你是对的,解决了它。我现在看到了愚蠢的错误。谢谢你的时间!非常感谢!
  • 它正在工作,但我不能使用你的代码,我有一个旧版本的 VS 并且 emplace_back 和 push_back 函数不能正常工作,没什么大不了的,我的代码似乎工作,谢谢你又来了!
  • @Jeff,你为什么不修复这些地方呢?您的代码被破坏和泄漏(不,它没有泄漏裸体)。见c++03 version Live On Coliru
  • 是的,我会的!就像我说的我是个黑客,我什至不知道我的代码在哪里泄漏!我真的应该付钱给别人为我做这件事(你收多少钱?......开玩笑......我正在学习)。老实说,这是我的第一个 C++ 程序(任何 C 语言中的第一个程序)。我一定会比较你所做的和我所做的学习!而且我正在安装vs2012,它应该可以很好地处理这些矢量操作,所以我也可以学习这些;)非常感谢您的帮助,您不知道...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多