0

I am trying to implement Kosaraju's Strongly connected components algorithm using recursive approach in C++. While the program runs fine on small graphs but terminates in-between execution while running node-ranking step of the algorithm on large graphs having 875714 nodes.

The function that causes the problem is : Graph::fillOrder(int v, bool visited[], stack &Stack)

File link : File link: https://drive.google.com/file/d/1aL19d6FCTT9vW70jBGyH-r7MpOOQ7gyz/view?usp=sharing

I went through the net to search for a possible solution to it but couldn't find one. While there are few non-recursive approaches suggesting that recursive approaches hit stack overflow problem, I want to know if that's the case is there any way to solve it ?

#include<iostream>
#include<list>
#include<stack>
#include<fstream>

using namespace std;

class Graph{
    int V;
    list<int> *adj;

    void fillOrder(int v, bool visited[], stack<int> &stack);
    void DFSUtil(int v, bool visited[], int &count);

public:
    Graph(int V);
    void addEdge(int v, int w);
    void printSCCs();
    Graph getTranspose();
};

Graph::Graph(int V){
    this->V = V;
    adj = new list<int>[V];
}

void Graph::DFSUtil(int v, bool visited[], int &count){
    visited[v] = true;
    count++;
    list<int>::iterator it;
    for(it = adj[v].begin(); it!=adj[v].end(); it++){
        if(!visited[*it])
            DFSUtil(*it, visited, count);
    }
}

Graph Graph::getTranspose(){
    Graph g(V);
    for(int v=0; v<V; v++){
        list<int>::iterator it;
        for(it=adj[v].begin(); it!=adj[v].end(); it++){
            g.adj[*it].push_back(v);
        }
    }
    return g;
}

//add edge to graph
void Graph::addEdge(int v, int w){
    adj[v].push_back(w);
}

//node ranking function
void Graph::fillOrder(int v, bool visited[], stack<int> &Stack){
    visited[v] = true;

    list<int> :: iterator it;
    for(it=adj[v].begin(); it!=adj[v].end(); it++){
        if(!visited[*it])
            fillOrder(*it, visited, Stack);
    }

    Stack.push(v);
}

//print SCCs
void Graph::printSCCs(){
    stack<int> Stack;

    //keeping track of nodes visited
    bool *visited = new bool[V];
    for(int i=0; i<V; i++){
        visited[i]=false;
    }

    //node ranking
    for(int i=0; i<V; i++){
        cout<<i<<" ";
        if(visited[i]==false){
            fillOrder(i, visited, Stack);
        }
    }

    //computing transpose of the graph
    Graph gr = getTranspose();

    //reseting visited values for every node to false
    for(int i=0; i<V; i++){
        visited[i]=false;
    }
    int max_count=0;
    while(Stack.empty()==false){
        int v = Stack.top();
        Stack.pop();

        if(visited[v]==false){
            int count=0;
            gr.DFSUtil(v, visited, count);
            if(count>max_count){
                max_count = count;
                cout<<"\nMax count: "<<max_count;
            }
        }
    }
}

int main() 
{       
    Graph g(875714);

    ifstream file;
    file.open("SCC.txt");
    int s, e;
    while(file>>s>>e){
        //eleminating self loops
        if(s==e)
            continue;
        else
            g.addEdge((s-1), (e-1)); //for files containing nodes from 1
    }
    cout << "Following are strongly connected components in "
            "given graph \n"; 
    g.printSCCs();

    return 0; 
} 

Expected result: print size of each strongly connected component in the graph

Actual result: Termination while execution without completing the entire program

No error message before termination

Shubham Yadav
  • 561
  • 7
  • 16
  • 1
    Q: Are you getting an error message, and/or stack traceback? Q: Does the error say "Stack overflow" (or similar)? Q: "While there are few non-recursive approaches suggesting that recursive approaches hit stack overflow problem, I want to know if that's the case is there any way to solve it"? A: Have you considered trying one of those few non-recursive approaches? Or checking for a compiler switch to increase stack size? -1 for not including exact error message, or specifying compiler/compiler version. – paulsm4 Jul 03 '19 at 22:15
  • 1
    PS: If you're using GCC, you can use something like `gcc -Wl,--stack,4194304 -o program program.c`. Look here: https://stackoverflow.com/questions/2275550/ – paulsm4 Jul 03 '19 at 22:19
  • 1
    While you can rewrite `DFSUtil` to reduce the stack pressure a bit (at the very least `visited` and `count` can be combined into one parameter by using a struct), or provide compiler or linker options to increase the stack size, eventually you'll find situations where you run out of stack space. Rewriting to use looping, instead of recursion, should be way more scalable. – 1201ProgramAlarm Jul 03 '19 at 22:39
  • Probably not an issue, but also worth validating in addEdge that values are in range 0..(V-1) – racraman Jul 03 '19 at 22:44
  • @paulsm4. Answer to your question: There are no messages before termination, it just terminates in-between the execution. I'm unaware of the exact problem being caused in the program, and therefore put a question here to get some suggestions about what's going wrong. Have also included a screenshot of the output screen. As said, while searching for possible solutions I came across some non-recursive approaches, but I wanted to know what's going on wrong in this program so didn't try those approaches. Please do consider removing the -1. – Shubham Yadav Jul 04 '19 at 05:51
  • @1201ProgramAlarm so you too suggest that for such programs, non-recursive approaches are better ? – Shubham Yadav Jul 04 '19 at 05:54
  • 2
    If the recursion depth is too large, you'll need to change to non-recursive approaches. Space available for the stack is usually much less than heap space, so avoiding recursion can allow for a much larger problem space. I try to avoid it whenever possible. – 1201ProgramAlarm Jul 04 '19 at 14:56
  • Your programme stops after which time? I tried to execute it on my PC, it has been running for 35mn now, not finished – Damien Jul 04 '19 at 16:10
  • @Damien in my PC it hardly runs for 10secs and terminates – Shubham Yadav Jul 04 '19 at 17:31
  • The programme finally terminated here after a rather long time. Large amount of data was printed. Cannot know if the result is correct of course. I did not modify your code – Damien Jul 04 '19 at 17:36
  • @Damien how did it even run on your machine ? is there an option to increase the stack size while compiling ? – Shubham Yadav Jul 04 '19 at 17:37
  • I did not use any specific option, except -03 and -std=c++17. I use gcc 6.3.0. In a comment above, paulsm4 mentioned some options that you may try but that I did not use – Damien Jul 04 '19 at 17:43
  • @Damien yeah it ran after changing the stack size to 16MiB, the large data that was printed was actually for debugging which I created for small graph. Thanks for taking out the time to run it for so long. I have changed the code so it doesn't print that again. Any suggestions to improve the running time ? – Shubham Yadav Jul 04 '19 at 17:58
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/196010/discussion-between-damien-and-shubham-yadav). – Damien Jul 04 '19 at 18:05

0 Answers0