Search code examples
c++boostgraphboost-graph

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


in MyGraphBuilder Class I'm facing some Problems During My Implementation of the Graph property assignment:

  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),
    

Also When I used The Print Function to just Print The Count of Nodes and Edges, it Counted Nodes Only, but the Count of Edges Showed '0' can you tell me what is the problem please ?

Header File:

#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 File

// 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";
  //        }
  //    }
}

Solution

  •     cout << "Nodes " << v << " name " << MyGraph[v].name << "\n";
    

    This syntax asks for the boost::vertex_bundle_t property, but none exists.

    From the 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.

    Compare with How can I solve this error in Printing Nodes and Edges Boost Graph Library?, where the vertex property type is a class. This is known as a "bundle property" and they're generally more user-friendly to use.

    If you are using the older style of internal properties:

    property<vertex_name_t, idType>
    

    You need to access them using property-maps. You can use them with the get or put accessor methods:

    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";
    

    Here's the same example from the previous answer but using internal properties instead of bundles:

    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();
    }
    

    Printing:

    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