如何在BOOST图库中使用compressed_sparse_row_graph和dijkstra

时间:2014-09-05 19:30:04

标签: c++ boost

背景:我是一个黑客,无论如何不是一个好的程序员,FORTRAN实际上是我的语言,需要一些帮助这个增强代码。当我实现它时,我在向量的第779行得到了'向量下标超出范围'错误。这是我的代码,非常感谢任何帮助!

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

问题似乎应该很容易解决,但我很挣扎,谢谢!

-Jeff

#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;
} 

1 个答案:

答案 0 :(得分: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算法一起使用。特别是,   它模拟了以下特定图形概念:

     
      
  • 图形
  •   
  • IncidenceGraph的
  •   
  • AdjacencyGraph
  •   
  • 点列表图VertexListGraph
  •   
  • 边列表图EdgeListGraph
  •   
  • 属性图PropertyGraph
  •   

这应该是可能的。 Lemme尝试并在一瞬间回发

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

  

前趋映射记录最小生成树中的边。完成算法后,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到图形图中每个顶点的最短路径权重记录在此属性映射中。最短路径权重是沿最短路径的边缘权重之和。 DistanceMap类型必须是读/写属性映射的模型。图的顶点描述符类型需要可用作距离图的密钥类型

在此,同样适用。

清理

这是 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))
        );
}