Transitive closure is defined as:

Closure

Process

Let be the graph which we are calculating the transitive closure of.

  1. Initialise a square matrix, (using a 2-dimensional array) of size . Let be this matrix.
  2. Convert to an adjacency matrix of by a nested for loop.
    1. For every node in , loop through every node in and if an edge exists, set . Else, set it to 0.
  3. Use the transitive closure property:
    1. For every node :
      1. For every node
        1. For every node , check if . i.e. there is a path from to via
  4. Return . If is 1, then there exists a path from to .

Warshall’s Algorithm uses dynamic programming because it:

  • Splits problem into sub-problems: The problem of finding all paths between any two nodes and in a graph has a trivial and non-trivial section. It can be easily checked if exists, than a path of length 1 exists between and . The non-trivial section is seeing if there is a path with any intermediate nodes. If a path between and exists (with ), then a path exists from to via . Hence, we need to check whether and have paths. This is splitting into sub-problems.
  • Uses overlapping solutions to sub-problems: When checking for paths between and (our sub-problems), any paths that start with and make use of as an intermediate node will benefit from the solution to . Hence, the solution of sub-problems can overlap.

As a recurrence relation, this can be expressed as:

Pseudocode

Simple
Algorithm Transitive_Closure(G):
	T ← |V| x |V| array
	
	//Initialise the T matrix
	For i from 1 to |V| do:
		For j from 1 to |V| do:
			If i=j or edge i-j exists in G then:
				T[i][j] ← 1
			Else:
				T[i][j] ← 0
			End if
		End do
	End do

	For k from 1 to |V| do:
		From i from 1 to |V| do:
			From j from 1 to |V| do:
				If T[i][k] = 1 AND T[k][j] = 1 then:
					T[i][j] ← 1
				End if
			End do
		End do
	End do
	Return T
End Algorithm
Slightly Improved

Since the equality check does not depend on , it can be moved outside the j-loop, which does not change the time complexity, but does make it faster in real-time:

Algorithm Transitive_Closure(G):

	...
	
	For k from 1 to |V| do:
		From i from 1 to |V| do:
			If T[i][k] = 1 then:
				From j from 1 to |V| do:
					If T[k][j] = 1 then:
						T[i][j] ← 1
					End if
				End do
			End if
		End do
	End do
	Return T
End Algorithm

Time Complexity

The time complexity of Warshall’s Algorithm is relatively straightforward. It consists of three nested for loops, each running for times, giving a time complexity of:

This time complexity applies for all cases:

Case ScenarioInput DescriptionGrowth FunctionAsymptoticNotes
Worst
Time complexity is same for every case
Average
Best

Implementation

Transitive_Closure