Search code examples
c++boostgraph-algorithmgraphvizboost-graph

Computing a dominator graph using Boost's Lengauer Tarjan algorithm and display it using graphviz


Let me first of all apologize in case I have violated the rules, as I am aware my question has already been asked in a modified way here: Lengauer Tarjan Algorithm in BGL (boost graph library). However, I am (still) unable to use the answer in order to display the result correctly.

To be more precise: I followed the answer linked and have sucessfully applied the Lengauer-Tarjan algorithm to my graph (which for convenience is part of the Boost documentation: http://www.boost.org/doc/libs/1_55_0/libs/graph/test/dominator_tree_test.cpp). Now, if understand the code correctly the relevant information about the dominator tree is stored in domTreePredMap which is of type PredMap:

const int numOfVertices = testSet[i].numOfVertices;
//See example for test_sets - it just the same routine
G g(
  testSet[i].edges.begin(), testSet[i].edges.end(),
  numOfVertices);

typedef graph_traits<G>::vertex_descriptor Vertex;
typedef property_map<G, vertex_index_t>::type IndexMap;
typedef
  iterator_property_map<vector<Vertex>::iterator, IndexMap>
  PredMap;

vector<Vertex> domTreePredVector, domTreePredVector2;
IndexMap indexMap(get(vertex_index, g));
graph_traits<G>::vertex_iterator uItr, uEnd;
int j = 0;
for (tie(uItr, uEnd) = vertices(g); uItr != uEnd; ++uItr, ++j)
{
  put(indexMap, *uItr, j);
}

// Lengauer-Tarjan dominator tree algorithm
domTreePredVector =
  vector<Vertex>(num_vertices(g), graph_traits<G>::null_vertex());
PredMap domTreePredMap =
  make_iterator_property_map(domTreePredVector.begin(), indexMap);

lengauer_tarjan_dominator_tree(g, vertex(0, g), domTreePredMap);`

For me one of the main advantages of Boost is the possibility to automatically generated graphical output using graphviz with write_graphviz(cout, g), where g is a graph from typedef G:

typedef adjacency_list<
    listS,
    listS,
    bidirectionalS,
    property<vertex_index_t, std::size_t>, no_property> G;

However, I am unable to translate the DomTreePredMap into something write_graphviz(cout, X) can understand. I appreciate any help outlining how a graph can be constructed from the domTreePredMap, which can be printed using graphviz.

Thank you all for reading all this and helping me out.


Solution

  • Sorry to bother you - I managed to find the answer myself in the boost documentary:

    Here is an minimal working example to illustrate my problem. Basically I want to compute the graph (one the left) and its dominator tree (on the right) as illustrated here: http://www.boost.org/doc/libs/1_40_0/libs/graph/doc/lengauer_tarjan_dominator.htm#fig:dominator-tree-example and print both graphs using graphviz.

    Following the example I have managed to compute and print the original graph and execute the Lengauer-Tarjan algorithms on it. The information on the dominator tree is stored in the DomPredMap and can be copied into an integer vector. At position i of the vector idom the id of the parent of node i is stored. If no parent node exists, max_int is stored. This information can be used to add the edges from idom[i] to i to the testSet from which the graph g2 can finally be constructed. Thank you for all your help and patience.

     #include <iostream>
     #include <boost/graph/graphviz.hpp>
     #include <boost/graph/adjacency_list.hpp>
     #include <boost/graph/dominator_tree.hpp>
     #include <algorithm>
     #include <fstream>
     #include <cstdlib>
     #include <string>
     #include <sstream>
     #include <vector> 
     using namespace std;
    
    
     struct DominatorCorrectnessTestSet
        {
          typedef pair<int, int> edge;
    
          int numOfVertices;
          vector<edge> edges;
          vector<int> correctIdoms;
        };
    
        using namespace boost;
    
        typedef adjacency_list<
            listS,
            listS,
            bidirectionalS,
            property<vertex_index_t, std::size_t>, no_property> G;
    
        int main(int, char*[])
        {
    
    
    
         typedef DominatorCorrectnessTestSet::edge edge;
    
          DominatorCorrectnessTestSet testSet[1];
    
    
    
          testSet[0].numOfVertices = 8, //Orignal problem see left hand side
          testSet[0].edges.push_back(edge(0, 1));
          testSet[0].edges.push_back(edge(1, 2));
          testSet[0].edges.push_back(edge(1, 3));
          testSet[0].edges.push_back(edge(2, 7));
          testSet[0].edges.push_back(edge(3, 4));
          testSet[0].edges.push_back(edge(4, 5));
          testSet[0].edges.push_back(edge(4, 6));
          testSet[0].edges.push_back(edge(5, 7));
          testSet[0].edges.push_back(edge(6, 4));
    
          testSet[1].numOfVertices = 8; //Used to create Dominator Tree
    
        const int numOfVertices = testSet[0].numOfVertices;
    
        G g(
          testSet[0].edges.begin(), testSet[0].edges.end(),
          numOfVertices);
    
        typedef graph_traits<G>::vertex_descriptor Vertex;
        typedef property_map<G, vertex_index_t>::type IndexMap;
        typedef
          iterator_property_map<vector<Vertex>::iterator, IndexMap>
          PredMap;
    
        vector<Vertex> domTreePredVector, domTreePredVector2;
        IndexMap indexMap(get(vertex_index, g));
        graph_traits<G>::vertex_iterator uItr, uEnd;
        int j = 0;
        for (tie(uItr, uEnd) = vertices(g); uItr != uEnd; ++uItr, ++j)
        {
          put(indexMap, *uItr, j);
        }
        write_graphviz(cout, g);
        // Lengauer-Tarjan dominator tree algorithm
        domTreePredVector =
          vector<Vertex>(num_vertices(g), graph_traits<G>::null_vertex());
        PredMap domTreePredMap =
          make_iterator_property_map(domTreePredVector.begin(), indexMap);
    
        lengauer_tarjan_dominator_tree(g, vertex(0, g), domTreePredMap);
    vector<int> idom(num_vertices(g));
             for (tie(uItr, uEnd) = vertices(g); uItr != uEnd; ++uItr)
             {
               if (get(domTreePredMap, *uItr) != graph_traits<G>::null_vertex())
                 idom[get(indexMap, *uItr)] =
                   get(indexMap, get(domTreePredMap, *uItr));
               else
                 idom[get(indexMap, *uItr)] = (numeric_limits<int>::max)();
             }
    
            for (int k =0; k <idom.size();k++){
    
                 if (k>0){
                 cout << idom[k] << " nach " << k << endl;
                 int t= idom[k];
                 testSet[1].edges.push_back(edge(t, k));
                 }
             }
    
           G g2(testSet[1].edges.begin(), testSet[1].edges.end(),8);
           int jj=0;
           for (tie(uItr, uEnd) = vertices(g2); uItr != uEnd; ++uItr, ++jj)
               {
                 put(indexMap, *uItr, jj);
               }
    
             write_graphviz(cout, g2);
             cout << endl;
    
    
    return 0;
    
    }
    

    enter image description here enter image description here