我在 MyGraph 属性顶点名称和边权重方面遇到问题

I have Problems with MyGraph Properties Vertices names , and Edges weight

在 MyGraphBuilder 中 Class 我在执行图 属性 作业时遇到了一些问题:

  1.  G:\QT\Projects\My Project\boost\graph\detail\adjacency_list.hpp:2700: error: forming reference to void
     typedef value_type& reference;
    
  2.   G:\QT\Projects\MY Project\boost\graph\dijkstra_shortest_paths.hpp:588: error: no matching function for call to 'choose_const_pmap(const type&, const boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertProperty, EdgeProperty>&, boost::edge_weight_t)'
    choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
    

另外,当我使用打印函数只打印节点和边的计数时,它只计算了节点,但是边的计数显示为“0”,你能告诉我这是什么问题吗?

头文件:

#ifndef MYGRAPHBUILDER_H
#define MYGRAPHBUILDER_H

// Generic Libraries
//===============================================
#include <iostream>
#include <vector>
#include <map>

// Boost Libraries
//===============================================
#include <boost/config.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/graph_utility.hpp>
// MyColleague Libraries
//===============================================
#include <modelDataStructure.h>
#include <modelDataHandler.h>
#include <modeldata.h>
#include <model.h>
// Osmium Libraries
//===============================================
#include <osmium/osm.hpp>
#include <osmium/index/map/flex_mem.hpp>
#include <osmium/visitor.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/node_ref.hpp>
//===============================================
using namespace std;
using namespace boost;
//===============================================
typedef osmium::unsigned_object_id_type idType ;
typedef map<idType, wayData> WayMap;//Define map of Ways ans Their ID
//==================================================
struct VertProperty
{
  idType id;
  osmium::Location loc;
};

struct EdgeProperty
{
  double length;
};

typedef adjacency_list < vecS, vecS, directedS,VertProperty,EdgeProperty > graph_t;
typedef graph_traits < graph_t >::vertex_descriptor Vertex; // Vertex declaration
typedef graph_traits < graph_t >::edge_descriptor Edge; // Edge as link between two Nodes specified by ID
//==================================================

class MyGraphBuilder
{
private:               // This Line is Useless just for clarity
  graph_t MyGraph;
  /////////////////////////////////////////////////////////

public:
  MyGraphBuilder(); // default Constructor
  MyGraphBuilder(Model); // Parameters Constructor
  ~MyGraphBuilder(); // Destructor
  double Distance(idType,idType); // function to calculate the distance between 2 Verices
  //===============================================
  //Accessors
  // function to get the Graph
  graph_t getGraph();
  //===============================================
  // Mutators
  void setGraph(graph_t);
   //===============================================
  void printGraph() const;
  //friend class MyAlgorithm;
};//end of the Class
/////////////////////////////////////
#endif // MYGRAPHBUILDER_H


CPP 文件

// Generic Libraries
//===============================================
#include <math.h>
// Belal Libraries
//===============================================
#include <mygraphbuilder.h>
// Boost Libraries
//===============================================
using namespace std;
using namespace boost;
/////////////////////////////////////////////////
MyGraphBuilder::MyGraphBuilder() // default Constructor
{
  Model OurModel;
  WayMap MyWayMap = OurModel.getWayMap();
  WayMap::iterator it;
  // it->first  ;// (key = WayID)
  // it->second ;// (Value WayData.nodRefList[idType])
  for ( it = MyWayMap.begin(); it != MyWayMap.end(); it++ ) // Loop the Whole Way Map
    {
      unsigned int NodesOfWayIndex = 0; //define Index
      idType VertixID; // define Variable to Store Vertix Index
      vector<Vertex> WayNodes(it->second.nodeRefList.size());//define a vector of nodes with size of Way
      for(auto j = it->second.nodeRefList.begin(); j != it->second.nodeRefList.end(); ++j){// Loop The Whole Nodes of Each way
          VertixID = it->second.nodeRefList.at(NodesOfWayIndex);
          //VertixID added as Bundeled property name to the vertex
          Vertex v = *vertices(MyGraph).first;
          Edge e = *edges(MyGraph).first;
          //=======================================================
          MyGraph[v].id = VertixID;
          MyGraph[v].loc = OurModel.getNodeLoaction(VertixID);
          //=======================================================
          WayNodes[NodesOfWayIndex] = VertixID;
          if(NodesOfWayIndex != 0) {
              MyGraph[e].length = Distance(WayNodes[NodesOfWayIndex - 1], WayNodes[NodesOfWayIndex]);
            }
        }
      NodesOfWayIndex++;
    }
  cout<<"\n\n Graph Was Built ...\n\n";
}
//===========================================================================
MyGraphBuilder::MyGraphBuilder(Model OurModel){  // Parameters Constructor
   WayMap MyWayMap = OurModel.getWayMap();
   WayMap::iterator it;
   // it->first  ;// (key = WayID)
   // it->second ;// (Value WayData.nodRefList[idType])
   for ( it = MyWayMap.begin(); it != MyWayMap.end(); it++ ) // Loop the Whole Way Map
     {
       unsigned int NodesOfWayIndex = 0; //define Index
       idType VertixID; // define Variable to Store Vertix Index
       vector<Vertex> WayNodes(it->second.nodeRefList.size());//define a vector of nodes with size of Way
       for(auto j = it->second.nodeRefList.begin(); j != it->second.nodeRefList.end(); ++j){// Loop The Whole Nodes of Each way
           VertixID = it->second.nodeRefList.at(NodesOfWayIndex);
           //VertixID added as Bundeled property name to the vertex
           Vertex v = *vertices(MyGraph).first;
           Edge e = *edges(MyGraph).first;
           //=======================================================
           MyGraph[v].id = VertixID;
           MyGraph[v].loc = OurModel.getNodeLoaction(VertixID);
           //=======================================================
           WayNodes[NodesOfWayIndex] = VertixID;
           if(NodesOfWayIndex != 0) {
               MyGraph[e].length = Distance(WayNodes[NodesOfWayIndex - 1], WayNodes[NodesOfWayIndex]);
             }
         }
       NodesOfWayIndex++;
     }
   cout<<"\n\n Graph Was Built ...\n\n";
 }

MyGraphBuilder::~MyGraphBuilder (){ // default Destructor

}

double MyGraphBuilder::Distance(idType Nod1_ID, idType Nod2_ID){ // Function to calculate Euclidean Distance between Vertices
  modelData*m_Data = new modelData;
  osmium::Location L1,L2; // define any 2 locations on earth
  L1 = m_Data->getNodeLoaction(Nod1_ID) ; // get first location
  L2 = m_Data->getNodeLoaction(Nod2_ID) ; // get second location
  double dist = 0; // distance
  double x1 = L1.lat(); // first location latitude
  double x2 = L2.lat(); // second location latitude
  double y1 = L1.lon(); // first location longitude
  double y2 = L2.lon(); // second location longitude
  dist = sqrt(pow((x1-x2),2)+pow((y1-y2),2));
  return dist;
}
// Accessors
graph_t MyGraphBuilder::getGraph(){
  return MyGraph;
}
// Mutators
void MyGraphBuilder::setGraph(graph_t YourGraph){
  MyGraphBuilder::MyGraph = YourGraph;
}
//=========================================
void MyGraphBuilder::printGraph()const{
  unsigned long long NodesCount = num_vertices(MyGraph);
  cout<<"Number of Vertices is :\t"<<NodesCount<<"\n";
  unsigned long long EdgesCount = num_edges(MyGraphBuilder::MyGraph);
  cout<<"Number of Edges is :\t"<<EdgesCount<<"\n";
  //for (auto v : make_iterator_range(vertices(MyGraph))) {
  //    cout << "Nodes " << v << " name " << MyGraph[v].name << "\n";
  //        for (auto oe : make_iterator_range(out_edges(v, MyGraph))) {
  //           cout << "Edge " << oe << " weight " << MyGraph[oe].weight << "\n";
  //        }
  //    }
}
    cout << "Nodes " << v << " name " << MyGraph[v].name << "\n";

此语法要求 boost::vertex_bundle_t 属性,但存在 none。

来自documentation:

Class templates adjacency_list and adjacency_matrix support the introduction of named properties via internal properties. However, this method is cumbersome in many uses, where it would be more intuitive to just specify a structure or class that contains internal properties for edges or vertices. Bundled properties allow one to use adjacency_list and adjacency_matrix in this manner, providing a simple way to introduce and access any number of internal properties for vertices and edges.

比较,其中顶点属性类型是class。这被称为 "bundle property",它们通常更易于使用。

如果您使用的是旧式内部属性:

property<vertex_name_t, idType>

您需要使用 属性-地图访问它们。您可以将它们与 getput 访问器方法一起使用:

boost::put(boost::vertex_name, MyGraph, 0, "one");

或者先拿一张属性地图:

auto name_pmap = boost::get(boost::vertex_name, MyGraph);
name_pmap[0] = "one";

这是与上一个答案相同的示例,但使用内部属性而不是包:

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
#include <iostream>
#include <random>

using idType = std::string; // mock osmium stuff?

using graph_t = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
      boost::property<boost::vertex_name_t, idType>, 
      boost::property<boost::edge_weight_t, double> >;

using boost::make_iterator_range;

class MyGraphBuilder {
    graph_t MyGraph;

  public:
    void generate();
    void printGraph() const;
};

#include <boost/graph/random.hpp>
void MyGraphBuilder::generate() {
    std::mt19937 prng { 42 }; // fixed random seed
    generate_random_graph(MyGraph, 5, 5, prng);

    boost::put(boost::vertex_name, MyGraph, 0, "one");

    // or grab a propertymap first:
    auto name_pmap = boost::get(boost::vertex_name, MyGraph);
    name_pmap[0] = "one";
    name_pmap[1] = "two";
    name_pmap[2] = "three";
    name_pmap[3] = "four";
    name_pmap[4] = "five";

    auto weight_pmap = boost::get(boost::edge_weight, MyGraph);
    for (auto e : make_iterator_range(edges(MyGraph))) {
        weight_pmap[e] = std::uniform_real_distribution<>(1.0, 10.0)(prng);
    }
}

void MyGraphBuilder::printGraph() const {
    std::cout << "Number of Vertices is:" << num_vertices(MyGraph) << "\n";
    std::cout << "Number of Edges is:" << num_edges(MyGraph) << "\n";

    print_graph(MyGraph, get(boost::vertex_name, MyGraph), std::cout);

    // to print with edge weights:
    for (auto v : make_iterator_range(vertices(MyGraph))) {
        for (auto oe : make_iterator_range(out_edges(v, MyGraph))) {
            std::cout << "Edge " << oe << " weight " << boost::get(boost::edge_weight, MyGraph, oe) << "\n";
        }
    }
}

int main() {
    MyGraphBuilder builder;

    builder.generate();
    builder.printGraph();
}

正在打印:

Number of Vertices is:5
Number of Edges is:5
one --> 
two --> four 
three --> one one 
four --> three 
five --> one 
Edge (1,3) weight 1.52275
Edge (2,0) weight 8.79559
Edge (2,0) weight 6.41004
Edge (3,2) weight 7.37265
Edge (4,0) weight 1.18526