/* This is a program written in D (dlang.org) to obtain the strongly connected components (SCC's) of a directed graph using Tarjan's algorithm (https://doi.org/10.1137/0201010). An SCC is a subset of the nodes of a directed graph (digraph) together with all the edges both ends of which are in the subset, such that every pair of nodes in the SCC is connected in both directions, directly or indirectly via the directed edges. This can includes single nodes regardless of whether or not they are connected to themselves. The input graph is input in the following format: For each input node, all the nodes it leads to are given on one line. Every node is represented by a character string, and "leads to" is represented by ">" and the list of nodes lead to is preceded by integer giving the number of them, and they are separated and termined by &. Extra spaces between the strings are ignored. For example 1 > 0 1,4 > 0 2 > 0 3 > 1 12 & 12 > 2 3 & 13,57 & 13,57 > 4 1,4 & 79 & 3 & 116 & 13,57,61 > 4 3 & 12 & 39 & 3 & The program creates and output text file containing the contents of each SCC. To run the program first compile it then run it with the data input file name e.g. dmd Tarjan.d ./Tarjan */ import std.stdio; import std.algorithm; import std.string; import std.file; import std.conv; class vertex { string name; int index; int lowlink; bool onStack; vertex [] descendents; void write(){ writeln("(name = ",name, ", index = ",index," lowlink = ",lowlink," onStack = ",onStack,", # descendents = ",descendents.length,")");} this(string name,int index,int lowlink,bool onStack,vertex [] descendents){ this.name = name; this.index = index; this.lowlink = lowlink; this.onStack = onStack; this.descendents = descendents;} } int index; vertex w; vertex[] S;//the stack vertex[] SCC;//accumulates each SCC as it is found, then it is emptied to the output. vertex[] G;//the graph File of;//output file //************************************ function strongConnect ******************************** // index is zero if it has not been set. Values >0 have been set void strongConnect(vertex v){ v.index = index; v.lowlink = index; index++; S ~= v;//push in v v.onStack = true; foreach(w;v.descendents){ if(w.index == -1){writeln("calling strongConnect for ",w.name); strongConnect(w); writeln("strongConnect for ",w.name," ended"); v.lowlink = min(v.lowlink,w.lowlink);} else if(w.onStack){ v.lowlink = min(v.lowlink,w.index);}} if(v.lowlink == v.index){ SCC = remove!("true")(SCC);//empties SCC if not already empty do{ writeln("S.length-1 = ",S.length-1); w= S[(S.length)-1]; SCC ~= w; --S.length;//s.pop() w.onStack = false; writeln("w = ");w.write();writeln(" v = ");v.write();}while(w.name!= v.name); of.write("SCC = ");foreach(v1;SCC){of.write(v1.name);of.write(" ");}of.writeln("");} } //************************************* function G_write_full *************************** void G_write_full(){ foreach(v;G){ v.write(); foreach(x;v.descendents){ write(" ");x.write();}}} //************************************* G_write_short *********************************** void G_write_short(){ foreach(v;G){v.write();}} //************************************* function main *********************************** void main(string[] args){ writeln("This is program Tarjan that implements Tarjan's algorithm for finding the"); writeln("maximal strongly connected components of the graph G"); if(args.length!=2){ writeln("Usage: "); return;} //create the input and output file names, and File objects, and reading in the data sp. string inputfilename = args[1]; File infile = File(inputfilename,"r"); if(!exists(inputfilename)){writeln("I cannnot find file ",inputfilename);return;} char[] outputfilename = can_write(inputfilename,"_out.txt"); of.open(outputfilename.idup,"w"); string[][] sp;//Each line corresponds to a set of strings, of which element 0 is the LHS of the string pairs and the remaining string[] buf;//the vertex names (with repetition) //elements are the RHS's corresponding to the LHS. //read in string pairs for the edges and populate vp. string s1,s2; int n; string line; for(;;){ infile.readf(" %s >",s1);buf ~= s1;//the LHS writeln("s1 = ",s1); if(infile.eof())break; infile.readf(" %s",n); for(int i=0;i",extension); write("Enter the extra characters: "); readln(chars);chars=chomp(chars); filename=base_name ~ chars ~ extension;}} write1=(!fn) || overwrite;} while (!write1); writeln("Output will be to the file ",filename); return filename;}