Kosaraju: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added Sidef)
Line 340: Line 340:
[7]
[7]
</pre>
</pre>

=={{header|Python}}==
<lang python>def kosaraju(g):
class nonlocal: pass

# 1. For each vertex u of the graph, mark u as unvisited. Let l be empty.
size = len(g)

vis = [False]*size # vertexes that have been visited
l = [0]*size
nonlocal.x = size
t = [[]]*size # transpose graph

def visit(u):
if not vis[u]:
vis[u] = True
for v in g[u]:
visit(v)
t[v] = t[v] + [u]
nonlocal.x = nonlocal.x - 1
l[nonlocal.x] = u

# 2. For each vertex u of the graph do visit(u)
for u in range(len(g)):
visit(u)
c = [0]*size

def assign(u, root):
if vis[u]:
vis[u] = False
c[u] = root
for v in t[u]:
assign(v, root)

# 3: For each element u of l in order, do assign(u, u)
for u in l:
assign(u, u)

return c

g = [[1], [2], [0], [1,2,4], [3,5], [2,6], [5], [4,6,7]]
print kosaraju(g)</lang>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>


=={{header|Racket}}==
=={{header|Racket}}==

Revision as of 16:49, 29 September 2018

Kosaraju is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
This page uses content from Wikipedia. The original article was at Graph. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)


Kosaraju's algorithm (also known as the Kosaraju–Sharir algorithm) is a linear time algorithm to find the strongly connected components of a directed graph. Aho, Hopcroft and Ullman credit it to an unpublished paper from 1978 by S. Rao Kosaraju. The same algorithm was independently discovered by Micha Sharir and published by him in 1981. It makes use of the fact that the transpose graph (the same graph with the direction of every edge reversed) has exactly the same strongly connected components as the original graph.

References

C#

<lang csharp>using System; using System.Collections.Generic;

class Node { public enum Colors { Black, White, Gray }

public Colors color { get; set; } public int N { get; }

public Node(int n) { N = n; color = Colors.White; } }

class Graph { public HashSet<Node> V { get; } public Dictionary<Node, HashSet<Node>> Adj { get; }

/// <summary> /// Kosaraju's strongly connected components algorithm /// </summary> public void Kosaraju() { var L = new HashSet<Node>();

Action<Node> Visit = null; Visit = (u) => { if (u.color == Node.Colors.White) { u.color = Node.Colors.Gray;

foreach (var v in Adj[u]) Visit(v);

L.Add(u); } };

Action<Node, Node> Assign = null; Assign = (u, root) => { if (u.color != Node.Colors.Black) { if (u == root) Console.Write("SCC: ");

Console.Write(u.N + " "); u.color = Node.Colors.Black;

foreach (var v in Adj[u]) Assign(v, root);

if (u == root) Console.WriteLine(); } };

foreach (var u in V) Visit(u);

foreach (var u in L) Assign(u, u); } }</lang>

D

Translation of: Kotlin

(mostly) with output like

Translation of: Go

<lang D>import std.container.array; import std.stdio;

/* the list index is the first vertex in the edge(s) */ auto g = [

   [1],
   [2],
   [0],
   [1, 2, 4],
   [3, 5],
   [2, 6],
   [5],
   [4, 6, 7],

];

int[] kosaraju(int[][] g) {

   // 1. For each vertex u of the graph, mark u as unvisited. Let l be empty.
   auto size = g.length; // all false by default
   Array!bool vis;
   vis.length = size;
   int[] l;              // all zero by default
   l.length = size;
   auto x = size;        // index for filling l in reverse order
   int[][] t;            // transpose graph
   t.length = size;
   // Recursive subroutine 'visit':
   void visit(int u) {
       if (!vis[u]) {
           vis[u] = true;
           foreach (v; g[u]) {
               visit(v);
               t[v] ~= u;  // construct transpose
           }
           l[--x] = u;
       }
    }
   // 2. For each vertex u of the graph do visit(u)
   foreach (u, _; g) {
       visit(u);
   }
   int[] c;  // used for component assignment
   c.length = size;
   // Recursive subroutine 'assign':
   void assign(int u, int root) {
       if (vis[u]) {  // repurpose vis to mean 'unassigned'
           vis[u] = false;
           c[u] = root;
           foreach(v; t[u]) {
               assign(v, root);
           }
       }
   }
   // 3: For each element u of l in order, do assign(u, u)
   foreach (u; l) {
       assign(u, u);
   }
   return c;

}

void main() {

   writeln(kosaraju(g));

}</lang>

Output:
[0, 0, 0, 3, 3, 5, 5, 7]

Go

<lang go>package main

import "fmt"

var g = [][]int{

   0: {1},
   1: {2},
   2: {0},
   3: {1, 2, 4},
   4: {3, 5},
   5: {2, 6},
   6: {5},
   7: {4, 6, 7},

}

func main() {

   fmt.Println(kosaraju(g))

}

func kosaraju(g [][]int) []int {

   // 1. For each vertex u of the graph, mark u as unvisited. Let L be empty.
   vis := make([]bool, len(g))
   L := make([]int, len(g))
   x := len(L)                // index for filling L in reverse order
   t := make([][]int, len(g)) // transpose graph
   // 2. recursive subroutine:
   var Visit func(int)
   Visit = func(u int) {
       if !vis[u] {
           vis[u] = true
           for _, v := range g[u] {
               Visit(v)
               t[v] = append(t[v], u) // construct transpose
           }
           x--
           L[x] = u
       }
   }
   // 2. For each vertex u of the graph do Visit(u)
   for u := range g {
       Visit(u)
   }
   c := make([]int, len(g)) // result, the component assignment
   // 3: recursive subroutine:
   var Assign func(int, int)
   Assign = func(u, root int) {
       if vis[u] { // repurpose vis to mean "unassigned"
           vis[u] = false
           c[u] = root
           for _, v := range t[u] {
               Assign(v, root)
           }
       }
   }
   // 3: For each element u of L in order, do Assign(u,u)
   for _, u := range L {
       Assign(u, u)
   }
   return c

}</lang>

Output:
[0 0 0 3 3 5 5 7]

Julia

Works with: Julia version 0.6
Translation of: Go

<lang julia>function korasaju(g::Vector{Vector{T}}) where T<:Integer

   # 1. For each vertex u of the graph, mark u as unvisited. Let L be empty.
   vis = falses(length(g))
   L   = Vector{T}(length(g))
   x   = length(L) + 1
   t   = collect(T[] for _ in eachindex(g))
   # Recursive
   function visit(u::T)
       if !vis[u]
           vis[u] = true
           for v in g[u]
               visit(v)
               push!(t[v], u)
           end
           x -= 1
           L[x] = u
       end
   end
   # 2. For each vertex u of the graph do visit(u)
   for u in eachindex(g)
       visit(u)
   end
   c = Vector{T}(length(g))
   # 3. Recursive subroutine:
   function assign(u::T, root::T)
       if vis[u]
           vis[u] = false
           c[u] = root
           for v in t[u]
               assign(v, root)
           end
       end
   end
   # 3. For each element u of L in order, do assign(u, u)
   for u in L
       assign(u, u)
   end
   return c

end

g = [[2], [3], [1], [2, 3, 5], [4, 6], [3, 7], [6], [5, 7, 8]] println(korasaju(g))</lang>

Output:
[1, 1, 1, 4, 4, 6, 6, 8]

Kotlin

Translation of: Go

<lang scala>// version 1.1.3

/* the list index is the first vertex in the edge(s) */ val g = listOf(

   intArrayOf(1),        // 0
   intArrayOf(2),        // 1
   intArrayOf(0),        // 2
   intArrayOf(1, 2, 4),  // 3
   intArrayOf(3, 5),     // 4
   intArrayOf(2, 6),     // 5
   intArrayOf(5),        // 6
   intArrayOf(4, 6, 7)   // 7

)

fun kosaraju(g: List<IntArray>): List<List<Int>> {

   // 1. For each vertex u of the graph, mark u as unvisited. Let l be empty.
   val size = g.size
   val vis = BooleanArray(size)                 // all false by default
   val l = IntArray(size)                       // all zero by default
   var x = size                                 // index for filling l in reverse order
   val t = List(size) { mutableListOf<Int>() }  // transpose graph
   
   // Recursive subroutine 'visit':
   fun visit(u: Int) {
       if (!vis[u]) {
           vis[u] = true
           for (v in g[u]) { 
               visit(v)
               t[v].add(u)  // construct transpose 
           }
           l[--x] = u
       }
    }
   // 2. For each vertex u of the graph do visit(u)
   for (u in g.indices) visit(u)
   val c = IntArray(size)  // used for component assignment 
   // Recursive subroutine 'assign':
   fun assign(u: Int, root: Int) {
       if (vis[u]) {  // repurpose vis to mean 'unassigned'
           vis[u] = false
           c[u] = root
           for (v in t[u]) assign(v, root)
       }
   }
   // 3: For each element u of l in order, do assign(u, u)
   for (u in l) assign(u, u)
   // Obtain list of SCC's from 'c' and return it   
   return c.withIndex()
           .groupBy { it.value }.values
           .map { ivl -> ivl.map { it.index } }

}

fun main(args: Array<String>) {

   println(kosaraju(g).joinToString("\n"))

}</lang>

Output:
[0, 1, 2]
[3, 4]
[5, 6]
[7]

Python

<lang python>def kosaraju(g):

   class nonlocal: pass
   # 1. For each vertex u of the graph, mark u as unvisited. Let l be empty.
   size = len(g)
   vis = [False]*size # vertexes that have been visited
   l = [0]*size
   nonlocal.x = size
   t = [[]]*size   # transpose graph
   def visit(u):
       if not vis[u]:
           vis[u] = True
           for v in g[u]:
               visit(v)
               t[v] = t[v] + [u]
           nonlocal.x = nonlocal.x - 1
           l[nonlocal.x] = u
   # 2. For each vertex u of the graph do visit(u)
   for u in range(len(g)):
       visit(u)
   c = [0]*size
   def assign(u, root):
       if vis[u]:
           vis[u] = False
           c[u] = root
           for v in t[u]:
               assign(v, root)
   # 3: For each element u of l in order, do assign(u, u)
   for u in l:
       assign(u, u)
   return c

g = [[1], [2], [0], [1,2,4], [3,5], [2,6], [5], [4,6,7]] print kosaraju(g)</lang>

Output:
[0, 0, 0, 3, 3, 5, 5, 7]

Racket

<lang racket>#lang racket

(require racket/dict)

G is a dictionary of vertex -> (list vertex)

(define (Kosuraju G)

 (letrec
     ((vertices (remove-duplicates (append (dict-keys G) (append* (dict-values G)))))
      (visited?-dict (make-hash)) ; or any mutable dict type
      (assigned-dict (make-hash)) ; or any mutable dict type
      (neighbours:in (λ (u) (for/list (([v outs] (in-dict G)) #:when (member u outs)) v)))  
      (visit! (λ (u L)
                (cond [(dict-ref visited?-dict u #f) L]
                      [else (dict-set! visited?-dict u #t)
                            (cons u (for/fold ((L L)) ((v (in-list (dict-ref G u)))) (visit! v L)))])))  
      (assign! (λ (u root)
                 (unless (dict-ref assigned-dict u #f)
                   (dict-set! assigned-dict u root)
                   (for ((v (in-list (neighbours:in u)))) (assign! v root)))))
      (L (for/fold ((l null)) ((u (in-dict-keys G))) (visit! u l))))
   
   (for ((u (in-list L))) (assign! u u))  
   (map (curry map car) (group-by cdr (dict->list assigned-dict) =))))

(module+ test

 (Kosuraju '((0 1)
             (2 0)
             (5 2 6)
             (6 5)
             (1 2)
             (3 1 2 4) ; equvalent to (3 . (1 2 4))
             (4 5 3)
             (7 4 7 6))))</lang>
Output:
'((7) (6 5) (4 3) (2 1 0))

Sidef

Translation of: Julia

<lang ruby>func korasaju(Array g) {

   # 1. For each vertex u of the graph, mark u as unvisited. Let L be empty.
   var vis = g.len.of(false)
   var L   = []
   var x   = g.end
   var t   = g.len.of { [] }
   # Recursive
   func visit(u) {
       if (!vis[u]) {
           vis[u] = true
           g[u].each {|v|
               visit(v)
               t[v] << u
           }
           L[x--] = u
       }
   }
   # 2. For each vertex u of the graph do visit(u)
   g.range.each {|u|
       visit(u)
   }
   var c = []
   # 3. Recursive subroutine:
   func assign(u, root) {
       if (vis[u]) {
           vis[u] = false
           c[u] = root
           t[u].each {|v|
               assign(v, root)
           }
       }
   }
   # 3. For each element u of L in order, do assign(u, u)
   L.each {|u|
       assign(u, u)
   }
   return c

}

var g = [[1], [2], [0], [1, 2, 4], [3, 5], [2, 6], [5], [4, 6, 7]] say korasaju(g)</lang>

Output:
[0, 0, 0, 3, 3, 5, 5, 7]

zkl

<lang zkl>const VISITED=0,ASSIGNED=1;

fcn visit(u,G,L){ // u is ((visited,assigned), (id,edges))

  u0:=u[0];
  if(u0[VISITED]) return();
  u0[VISITED]=True;
  foreach idx in (u[1][1,*]){ visit(G[idx],G,L) } // vist out-neighbours
  L.insert(0,u);	// prepend u to L

} fcn assign(u,root,G){ // u as above, root is a list of strong components

  u0:=u[0];
  if(u0[ASSIGNED]) return();
  root.append(u[1][0]);
  u0[ASSIGNED]=True;
  uid:=u[1][0];
  foreach v in (G){  // traverse graph to find in-neighbours, fugly
     n,ins := v[1][0],v[1][1,*];
     if(ins.holds(uid)) assign(G[n],root,G); // assign in-neighbour
  } 

} fcn kosaraju(graph){ // Use Tarjan's algorithm instead of this one

  // input: graph G = (V, Es)
  // output: set of strongly connected components (sets of vertices)
  // convert graph to ( (index,lowlink,onStack),(id,links)), ...)
  // sorted by id
  G:=List.createLong(graph.len(),0);
  foreach v in (graph){ G[v[0]]=T( List(False,False),v) }
  L:=List();
  foreach u in (G){ visit(u,G,L) }
  components:=List.createLong(graph.len(),List.copy,True);
  foreach u in (L){ assign(u,components[u[1][0]],G) }
  components=components.filter();
  println("List of strongly connected components:");
  foreach c in (components){ println(c.reverse().concat(",")) }
  return(components);

}</lang> <lang zkl> // graph from https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm

  // with vertices id zero based (vs 1 based in article)
  // ids start at zero and are consecutive (no holes), graph is unsorted

graph:= // ( (id, links/Edges), ...)

  T( T(0,1), T(2,0),     T(5,2,6), T(6,5),
     T(1,2), T(3,1,2,4), T(4,5,3), T(7,4,7,6) );

kosaraju(graph);</lang>

Output:
List of strongly connected components:
1,2,0
4,3
6,5
7