Open In App

How to iterate over boost graph to get incoming and outgoing edges of vertex?

Last Updated : 11 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

What is Boost Graph?

The Boost Graph (BG) are multi-graph concept, it is factored into much smaller pieces. The reason for this is that any one algorithm cannot fulfill the need for all graph operations. 

Furthermore, there are many graph data structures that provide a very effective implementation in the overall view for particular algorithms but are not that effective on all operations implementations. We provide the graph algorithm writer with a good selection from which to choose the concept that is closest to their algorithm by breaking down the graph interface into several smaller concepts.

Boost Graph Library

Boost Graph Library (BGL) is a library that provides Boost graph functions by including in a header.

The Boost Graph Library (BGL) algorithms consist of algorithms like:

  • Breadth First Search
  • Depth First Search
  • Uniform Cost Search

The basic implementation of boost graph algorithms is based on the above 3 algorithms, But now BG algorithms in the BGL include:

  • Dijkstra’s Shortest Paths
  • Bellman-Ford Shortest Paths
  • Johnson’s All-Pairs Shortest Paths
  • Kruskal’s Minimum Spanning Tree
  • Prim’s Minimum Spanning Tree
  • Connected Components
  • Strongly Connected Components
  • Dynamic Connected Components (using Disjoint Sets)
  • Topological Sort
  • Transpose
  • Reverse Cuthill Mckee Ordering
  • Smallest Last Vertex Ordering
  • Sequential Vertex Coloring 

Iterate over BG to get incoming and outgoing edges of vertex?

To iterate through the edges and vertices BGL for graphs provides functions like in_edges(), out_edges() which iterate through the incoming edges and the outgoing edges respectively. 

These functions return pairs denoting how many incoming edges are there on a vertex. Moreover, if you want to know about complexity so it depends on the inside data structure used for the graph. For adjacency lists, the edge function is O(out-degree of v).

Comparison between STL and BGL 

 

Refer to the below code with detailed explanations in the comments.

Note: To run the code download Boost graph library (BGL) in your computer as the iterator in STL is not sufficient to bound the various ways that graph algorithms may traverse. After that Import the below code to your local system.  

C++




// In this code we will see how iteration
// is done in BG.
// We will only focus on directional
// and bidirectional graphs
 
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <iostream>
using namespace std;
 
// Only out edges are stored at each vertex.
static void Directed();
 
// Adding (A, B) and (B, A) only creates one edge
static void Bidirectional();
 
int main(int, char*[])
{
    Directed();
    Bidirectional();
    return 0;
}
 
void Directed()
{
    cout << std::endl << "Directed()" << std::endl;
    typedef boost::adjacency_list<boost::vecS, boost::vecS,
                                  boost::directedS>
        Graph;
 
    // Create a graph object.
    Graph g;
 
    // Adding vertex to graph
    // vertex 1
    boost::graph_traits<Graph>::vertex_descriptor v0
        = add_vertex(g);
 
    // vertex 2
    boost::graph_traits<Graph>::vertex_descriptor v1
        = add_vertex(g);
 
    // vertex 3
    boost::graph_traits<Graph>::vertex_descriptor v2
        = add_vertex(g);
 
    // Directed graphs can only store out_edges.
    // That is, a call to add_edge(A, B) will
    // only produce an edge that is
    // accessible from A, not from B.
 
    // In edges
    add_edge(v0, v1, g);
    add_edge(v2, v1, g);
 
    // Out edges
    add_edge(v1, v2, g);
    add_edge(v1, v0, g);
 
    // We can't obtain incoming edges as
    // with a directed graph only out_edges
    // are stored on the vertices.
 
    // Getting a list of outgoing edges from vertex
    typedef boost::graph_traits<Graph>::out_edge_iterator
        out_edge_iterator;
    std::pair<out_edge_iterator, out_edge_iterator> outEdges
        = out_edges(1, g);
 
    std::cout << std::endl << "Out edges: " << std::endl;
    for (out_edge_iterator iter = outEdges.first;
         iter != outEdges.second; ++iter) {
        cout << *iter << " ";
    }
 
    cout << std::endl;
}
 
// Bidirectional graph
void Bidirectional()
{
    std::cout << std::endl
              << "Bidirectional()" << std::endl;
    typedef boost::adjacency_list<boost::vecS, boost::vecS,
                                  boost::bidirectionalS>
        Graph;
 
    // Create a graph object
    Graph g;
 
    boost::graph_traits<Graph>::vertex_descriptor v0
        = add_vertex(g);
    boost::graph_traits<Graph>::vertex_descriptor v1
        = add_vertex(g);
    boost::graph_traits<Graph>::vertex_descriptor v2
        = add_vertex(g);
 
    // Add in edges
    add_edge(v0, v1, g);
    add_edge(v2, v1, g);
 
    // Add out edges
    add_edge(v1, v2, g);
    add_edge(v1, v0, g);
 
    // List of incoming edges to vertex 1.
    // We can see the in edges we'd expect ( (0, 1) and (2,
    // 1)
    // ). Iterating over incoming edge of vertex
 
    // Just like iterator in stl(c++) graphs have associated
    // types defined in header as graph_traits.hpp so we are
    // accessing the type of iterator used for traversing
    // through in_edge
    typedef boost::graph_traits<Graph>::in_edge_iterator
        in_edge_iterator;
 
    std::pair<in_edge_iterator, in_edge_iterator> inEdges
        = in_edges(1, g);
 
    cout << "In edges: " << endl;
 
    for (in_edge_iterator iter = inEdges.first;
         iter != inEdges.second; ++iter) {
        cout << *iter << " ";
    }
 
    // List of outgoing edges from vertex 1.
    // We can see the out edges we'd expect ( (1, 2) and (1,
    // 0) ). Similarly, here we are accessing the type of
    // iterator used for traversing through out_edge
    typedef boost::graph_traits<Graph>::out_edge_iterator
        out_edge_iterator;
 
    std::pair<out_edge_iterator, out_edge_iterator> outEdges
        = out_edges(1, g);
 
    // Iterating over outgoing edge of vertex
    std::cout << std::endl << "Out edges: " << std::endl;
    for (out_edge_iterator iter = outEdges.first;
         iter != outEdges.second; ++iter) {
        std::cout << *iter << " ";
    }
}


Python




import boost.graph as bg
import sys
 
# Only out edges are stored at each vertex.
 
 
def Directed():
    print("\nDirected()\n")
    # Create a graph object.
    g = bg.AdjacencyList(bg.VecS, bg.VecS, bg.DirectedS)
 
    # Adding vertex to graph
    # vertex 1
    v0 = bg.add_vertex(g)
 
    # vertex 2
    v1 = bg.add_vertex(g)
 
    # vertex 3
    v2 = bg.add_vertex(g)
 
    # Directed graphs can only store out_edges.
    # That is, a call to add_edge(A, B) will
    # only produce an edge that is
    # accessible from A, not from B.
 
    # In edges
    bg.add_edge(v0, v1, g)
    bg.add_edge(v2, v1, g)
 
    # Out edges
    bg.add_edge(v1, v2, g)
    bg.add_edge(v1, v0, g)
 
    # We can't obtain incoming edges as
    # with a directed graph only out_edges
    # are stored on the vertices.
 
    # Getting a list of outgoing edges from vertex
    outEdges = bg.out_edges(1, g)
    print("\nOut edges: \n")
    for iter in range(outEdges[0], outEdges[1]):
        print(iter)
 
    print("\n")
 
# Bidirectional graph
 
 
def Bidirectional():
    print("\nBidirectional()\n")
    # Create a graph object
    g = bg.AdjacencyList(bg.VecS, bg.VecS, bg.BidirectionalS)
 
    v0 = bg.add_vertex(g)
    v1 = bg.add_vertex(g)
    v2 = bg.add_vertex(g)
 
    # Add in edges
    bg.add_edge(v0, v1, g)
    bg.add_edge(v2, v1, g)
 
    # Add out edges
    bg.add_edge(v1, v2, g)
    bg.add_edge(v1, v0, g)
 
    # List of incoming edges to vertex 1.
    # We can see the in edges we'd expect ( (0, 1) and (2, 1)
    # ). Iterating over incoming edge of vertex
 
    # Just like iterator in stl(c++) graphs have associated
    # types defined in header as graph_traits.hpp so we are
    # accessing the type of iterator used for traversing
    # through in_edge
    inEdges = bg.in_edges(1, g)
 
    print("In edges: ")
    for iter in range(inEdges[0], inEdges[1]):
        print(iter)
 
    # List of outgoing edges from vertex 1.
    # We can see the out edges we'd expect ( (1, 2) and (1,
    # 0) ). Similarly, here we are accessing the type of
    # iterator used for traversing through out_edge
 
    outEdges = bg.out_edges(1, g)
 
    # Iterating over outgoing edge of vertex
    print("\nOut edges: ")
    for iter in range(outEdges[0], outEdges[1]):
        print(iter)
 
 
if __name__ == "__main__":
    Directed()
    Bidirectional()
    sys.exit(0)


Java




import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jgrapht.Graph;
import org.jgrapht.Graphs;
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm.SingleSourcePaths;
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;
 
public class GraphTraversal {
    public static void main(String[] args)
    {
        directedGraph();
        bidirectionalGraph();
    }
 
    public static void directedGraph()
    {
        System.out.println("Directed Graph");
 
        Graph<Integer, DefaultEdge> g
            = new DefaultDirectedGraph<>(DefaultEdge.class);
 
        // Adding vertices to the graph
        Integer v1 = 1, v2 = 2, v3 = 3;
        g.addVertex(v1);
        g.addVertex(v2);
        g.addVertex(v3);
 
        // Adding edges to the graph
        g.addEdge(v1, v2);
        g.addEdge(v3, v2);
        g.addEdge(v2, v3);
        g.addEdge(v2, v1);
 
        // Iterating over outgoing edges from vertex 2
        List<DefaultEdge> outEdges
            = new ArrayList<>(g.outgoingEdgesOf(v2));
        System.out.println("Out edges: ");
        Iterator<DefaultEdge> iter = outEdges.iterator();
        while (iter.hasNext()) {
            DefaultEdge edge = iter.next();
            System.out.print("(" + g.getEdgeSource(edge)
                             + ", " + g.getEdgeTarget(edge)
                             + ") ");
        }
        System.out.println();
    }
 
    public static void bidirectionalGraph()
    {
        System.out.println("Bidirectional Graph");
 
        Graph<Integer, DefaultEdge> g
            = new DefaultDirectedGraph<>(DefaultEdge.class);
 
        // Adding vertices to the graph
        Integer v1 = 1, v2 = 2, v3 = 3;
        g.addVertex(v1);
        g.addVertex(v2);
        g.addVertex(v3);
 
        // Adding edges to the graph
        g.addEdge(v1, v2);
        g.addEdge(v3, v2);
        g.addEdge(v2, v3);
        g.addEdge(v2, v1);
 
        // Iterating over incoming edges to vertex 2
        List<DefaultEdge> inEdges
            = new ArrayList<>(g.incomingEdgesOf(v2));
        System.out.println("In edges: ");
        Iterator<DefaultEdge> iter = inEdges.iterator();
        while (iter.hasNext()) {
            DefaultEdge edge = iter.next();
            System.out.print("(" + g.getEdgeSource(edge)
                             + ", " + g.getEdgeTarget(edge)
                             + ") ");
        }
        System.out.println();
 
        // Iterating over outgoing edges from vertex 2
        List<DefaultEdge> outEdges
            = new ArrayList<>(g.outgoingEdgesOf(v2));
        System.out.println("Out edges: ");
        iter = outEdges.iterator();
        while (iter.hasNext()) {
            DefaultEdge edge = iter.next();
            System.out.print("(" + g.getEdgeSource(edge)
                             + ", " + g.getEdgeTarget(edge)
                             + ") ");
        }
        System.out.println();
    }
}
 
// This code is contributed by Akash Jha


C#




using System;
using System.Collections.Generic;
using QuickGraph;
 
public class GraphTraversal {
    public static void Main(string[] args)
    {
        DirectedGraph();
        BidirectionalGraph();
    }
 
    public static void DirectedGraph()
    {
        Console.WriteLine("Directed Graph");
 
        var g = new BidirectionalGraph<int, Edge<int> >();
 
        // Adding vertices to the graph
        var v1 = 1;
        var v2 = 2;
        var v3 = 3;
        g.AddVertex(v1);
        g.AddVertex(v2);
        g.AddVertex(v3);
 
        // Adding edges to the graph
        g.AddEdge(new Edge<int>(v1, v2));
        g.AddEdge(new Edge<int>(v3, v2));
        g.AddEdge(new Edge<int>(v2, v3));
        g.AddEdge(new Edge<int>(v2, v1));
 
        // Iterating over outgoing edges from vertex 2
        var outEdges = new List<Edge<int> >(g.OutEdges(v2));
        Console.WriteLine("Out edges: ");
        foreach(var edge in outEdges)
        {
            Console.Write("(" + edge.Source + ", "
                          + edge.Target + ") ");
        }
        Console.WriteLine();
    }
 
    public static void BidirectionalGraph()
    {
        Console.WriteLine("Bidirectional Graph");
 
        var g = new BidirectionalGraph<int, Edge<int> >();
 
        // Adding vertices to the graph
        var v1 = 1;
        var v2 = 2;
        var v3 = 3;
        g.AddVertex(v1);
        g.AddVertex(v2);
        g.AddVertex(v3);
 
        // Adding edges to the graph
        g.AddEdge(new Edge<int>(v1, v2));
        g.AddEdge(new Edge<int>(v3, v2));
        g.AddEdge(new Edge<int>(v2, v3));
        g.AddEdge(new Edge<int>(v2, v1));
 
        // Iterating over incoming edges to vertex 2
        var inEdges = new List<Edge<int> >(g.InEdges(v2));
        Console.WriteLine("In edges: ");
        foreach(var edge in inEdges)
        {
            Console.Write("(" + edge.Source + ", "
                          + edge.Target + ") ");
        }
        Console.WriteLine();
 
        // Iterating over outgoing edges from vertex 2
        var outEdges = new List<Edge<int> >(g.OutEdges(v2));
        Console.WriteLine("Out edges: ");
        foreach(var edge in outEdges)
        {
            Console.Write("(" + edge.Source + ", "
                          + edge.Target + ") ");
        }
        Console.WriteLine();
    }
}


Javascript




const { Graph, alg } = require("graphlib");
 
function directedGraph() {
  console.log("Directed Graph");
 
  const g = new Graph({ directed: true });
 
  // Adding vertices to the graph
  const v1 = 1,
    v2 = 2,
    v3 = 3;
  g.setNode(v1);
  g.setNode(v2);
  g.setNode(v3);
 
  // Adding edges to the graph
  g.setEdge(v1, v2);
  g.setEdge(v3, v2);
  g.setEdge(v2, v3);
  g.setEdge(v2, v1);
 
  // Iterating over outgoing edges from vertex 2
  const outEdges = g.outEdges(v2);
  console.log("Out edges: ");
  for (const edge of outEdges) {
    console.log(`(${edge.v}, ${edge.w})`);
  }
  console.log();
}
 
function bidirectionalGraph() {
  console.log("Bidirectional Graph");
 
  const g = new Graph({ directed: true });
 
  // Adding vertices to the graph
  const v1 = 1,
    v2 = 2,
    v3 = 3;
  g.setNode(v1);
  g.setNode(v2);
  g.setNode(v3);
 
  // Adding edges to the graph
  g.setEdge(v1, v2);
  g.setEdge(v3, v2);
  g.setEdge(v2, v3);
  g.setEdge(v2, v1);
 
  // Iterating over incoming edges to vertex 2
  const inEdges = g.inEdges(v2);
  console.log("In edges: ");
  for (const edge of inEdges) {
    console.log(`(${edge.v}, ${edge.w})`);
  }
  console.log();
 
  // Iterating over outgoing edges from vertex 2
  const outEdges = g.outEdges(v2);
  console.log("Out edges: ");
  for (const edge of outEdges) {
    console.log(`(${edge.v}, ${edge.w})`);
  }
  console.log();
}
 
directedGraph();
bidirectionalGraph();




Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads