Search code examples
c++boostboost-graph

How do you add edges to boost::adjacency_matrix with property bundles?


I was trying to add edges in a boost::adjacency_matrix graph w/ bundled vertex and edge properties.

The code was as follows:

// VD and ED are just trivial structs
using Graph = boost::adjacency_matrix<boost::directedS, VD, ED>;
using Vertex = boost::graph_traits<Graph>::vertex_descriptor;
using Edge = boost::graph_traits<Graph>::edge_descriptor;

const unsigned kNodesCount = 4;
Graph g { kNodesCount };

// create two nodes
auto one = boost::add_vertex(g);
auto two = boost::add_vertex(g);

// add edge between nodes (vertices)
boost::add_edge(one, two, g);

I got a SIGABRT due to a failed assertion within the boost::add_edge overload for boost::adjacency_matrix. It turns out it's UNDER CONSTRUCTION (as are a few other functions for adjacency matrices).

   template <typename D, typename VP, typename EP, typename GP, typename A>
  inline typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor
  add_vertex(adjacency_matrix<D,VP,EP,GP,A>& g) {
    // UNDER CONSTRUCTION
    BOOST_ASSERT(false);
    return *vertices(g).first;
  }

  template <typename D, typename VP, typename EP, typename GP, typename A,
            typename VP2>
  inline typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor
  add_vertex(const VP2& /*vp*/, adjacency_matrix<D,VP,EP,GP,A>& g) {
    // UNDER CONSTRUCTION
    BOOST_ASSERT(false);
    return *vertices(g).first;
  }

  template <typename D, typename VP, typename EP, typename GP, typename A>
  inline void
  remove_vertex(typename adjacency_matrix<D,VP,EP,GP,A>::vertex_descriptor /*u*/,
                adjacency_matrix<D,VP,EP,GP,A>& /*g*/)
  {
    // UNDER CONSTRUCTION
    BOOST_ASSERT(false);
  }

So, my question is: how do we get around this? All the examples I find online utilize boost::adjacency_list. Is there a way of achieving the same thing currently?


Solution

  • You don't. It's just not necessary to add vertices since you already initialized it with all the kNodesCount you require. Instead, get the vertex descriptor for the existing vertices:

    Live On Coliru

    #include <boost/graph/adjacency_matrix.hpp>
    #include <boost/graph/graph_utility.hpp>
    struct VD { };
    struct ED { };
    
    // VD and ED are just trivial structs
    using Graph  = boost::adjacency_matrix<boost::directedS, VD, ED>;
    using Vertex = Graph::vertex_descriptor;
    using Edge   = Graph::edge_descriptor;
    
    int main() {
        const unsigned kNodesCount = 4;
        Graph g { kNodesCount };
    
        // create two nodes
        Vertex one = vertex(0, g);
        Vertex two = vertex(1, g);
    
        // add edge between nodes (vertices)
        add_edge(one, two, g);
        print_graph(g);
    }
    

    Prints

    0 --> 1 
    1 --> 
    2 --> 
    3 --> 
    

    In fact, due to the trivial nature of vertex descriptors in the adjacency_matrix<> model, you can hardcode the vertex descriptors like:

    Live On Coliru

    add_edge(0, 1, g);
    

    Can you add vertices to a matrix at all?

    No, not dynamically. The operations supported are listed under