A relation is a subset of the cartesian product of a set with another set. A relation contains ordered pairs of elements of the set it is defined on. To learn more about relations refer to the article on “Relation and their types“.
What is a Transitive Relation?
A relation R on a set A is called transitive relation if and only if
∀ a, b, c ∈ A, if (a, b) ∈ R and (b, c) ∈ R then (a, c) ∈ R,
where R is a subset of (A x A), i.e. the cartesian product of set A with itself.
This means if an ordered pair of elements “a” to “b” (aRb) and “b” to “c” (bRc) is present in relation R, then an ordered pair of elements “a” to “c” (aRC) should also be present in the relation R. If any such aRc is not present for any aRb & bRc in R then R is not a transitive relation.
Example:
Consider set A = {a, b, c}
R = {(a, b), (b, c), (a, c)} is transitive relation but
R = {(a, b), (b, c)} is not transitive relation
Properties of Transitive Relation
- Empty relation on any set is always transitive.
- Universal relation on any set is always transitive.
How to verify a Transitive Relation?
To verify transitive relation:
- Firstly, find the tuples of form aRb & bRc in the relation.
- For every such pair check if aRc is also present in R.
- If any of the tuples does not exist then the relation is not transitive else it is transitive.
Follow the below illustration for a better understanding
Illustration:
Consider set R = {(1, 2), (1, 3), (2, 3), (3, 4)}
For the pairs (1, 2) and (2, 3):
=> The relation (1, 3) exists
=> This satisfies the condition.
For the pairs (1, 3) and (3, 4):
=> The relation (1, 4) does not exist
=> This does not satisfy the condition.
So the relation is not transitive.
Below is the code implementation of the idea:
C++
#include <bits/stdc++.h>
using namespace std;
class Relation {
public :
bool checkTransitive(set<pair< int , int > > R)
{
if (R.size() == 0) {
return true ;
}
map< int , set< int > > tup;
for ( auto i = R.begin(); i != R.end(); i++) {
if (tup.find(i->first) == tup.end()) {
set< int > temp;
temp.insert(i->second);
tup.insert(
pair< int , set< int > >(i->first, temp));
}
else {
tup.at(i->first).insert(i->second);
}
}
for ( auto a = tup.begin(); a != tup.end(); a++) {
set< int > all_b_in_aRb = tup.at(a->first);
for ( int b : all_b_in_aRb) {
if (tup.find(b) != tup.end()
&& a->first != b) {
set< int > all_c_in_bRc = tup.at(b);
for ( int c : all_c_in_bRc) {
if (all_b_in_aRb.find(c)
== all_b_in_aRb.end()) {
return false ;
}
}
}
}
}
return true ;
}
};
int main()
{
set<pair< int , int > > R;
R.insert(make_pair(1, 1));
R.insert(make_pair(1, 2));
R.insert(make_pair(2, 1));
R.insert(make_pair(2, 2));
R.insert(make_pair(1, 3));
R.insert(make_pair(2, 3));
R.insert(make_pair(3, 4));
R.insert(make_pair(1, 4));
Relation obj;
if (obj.checkTransitive(R)) {
cout << "Transitive Relation" << endl;
}
else {
cout << "Not a Transitive Relation" << endl;
}
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class pair {
int first, second;
pair( int first, int second)
{
this .first = first;
this .second = second;
}
}
class GFG {
static class Relation {
boolean checkTransitive(Set<pair> R)
{
if (R.size() == 0 ) {
return true ;
}
HashMap<Integer, Set<Integer> > tup
= new HashMap<>();
for (pair i : R) {
if (!tup.containsKey(i.first)) {
Set<Integer> temp = new HashSet<>();
temp.add(i.second);
tup.put(i.first, temp);
}
else {
Set<Integer> temp = new HashSet<>();
temp = tup.get(i.first);
temp.add(i.second);
tup.put(i.first, temp);
}
}
for (Integer a : tup.keySet()) {
Set<Integer> all_b_in_aRb = tup.get(a);
for ( int b : all_b_in_aRb) {
if (tup.containsKey(b) && a != b) {
Set<Integer> all_c_in_bRc
= tup.get(b);
for (Integer c : all_c_in_bRc) {
if (all_b_in_aRb.contains(c)) {
return false ;
}
}
}
}
}
return true ;
}
}
public static void main(String[] args)
{
Set<pair> R = new HashSet<>();
R.add( new pair( 1 , 1 ));
R.add( new pair( 1 , 2 ));
R.add( new pair( 2 , 1 ));
R.add( new pair( 2 , 2 ));
R.add( new pair( 1 , 3 ));
R.add( new pair( 2 , 3 ));
R.add( new pair( 3 , 4 ));
R.add( new pair( 1 , 4 ));
Relation obj = new Relation();
if (obj.checkTransitive(R)) {
System.out.println( "Transitive Relation" );
}
else {
System.out.println( "Not a Transitive Relation" );
}
}
}
|
Python3
class Relation:
def checkTransitive( self , R):
if len (R) = = 0 :
return True
tup = dict ()
for i in R:
if tup.get(i[ 0 ]) is None :
tup[i[ 0 ]] = {i[ 1 ]}
else :
tup[i[ 0 ]].add(i[ 1 ])
for a in tup.keys():
all_b_in_aRb = tup.get(a)
if all_b_in_aRb is not None :
for b in all_b_in_aRb:
all_c_in_bRc = tup.get(b)
if a ! = b and all_c_in_bRc is not None :
if not all_c_in_bRc.issubset(all_b_in_aRb):
return False
return True
if __name__ = = '__main__' :
R = {( 1 , 1 ), ( 1 , 2 ), ( 2 , 1 ), ( 2 , 2 ), ( 1 , 3 ), ( 2 , 3 ), ( 3 , 4 ), ( 1 , 4 )}
obj = Relation()
if obj.checkTransitive(R):
print ( "Transitive Relation" )
else :
print ( "Not a Transitive Relation" )
|
C#
using System;
using System.Collections.Generic;
class pair {
public int first, second;
public pair( int first, int second)
{
this .first = first;
this .second = second;
}
}
public class GFG {
class Relation {
public bool checkTransitive(HashSet<pair> R)
{
if (R.Count == 0) {
return true ;
}
Dictionary< int , HashSet< int > > tup
= new Dictionary< int , HashSet< int > >();
foreach (pair i in R)
{
if (!tup.ContainsKey(i.first)) {
HashSet< int > temp = new HashSet< int >();
temp.Add(i.second);
tup[i.first] = temp;
}
else {
HashSet< int > temp = new HashSet< int >();
temp = tup[i.first];
temp.Add(i.second);
tup[i.first] = temp;
}
}
foreach ( var a in tup)
{
HashSet< int > all_b_in_aRb = tup[a.Key];
foreach ( int b in all_b_in_aRb)
{
if (tup.ContainsKey(b) && a.Key != b) {
HashSet< int > all_c_in_bRc = tup[b];
foreach ( int c in all_c_in_bRc)
{
if (all_b_in_aRb.Contains(c)) {
return false ;
}
}
}
}
}
return true ;
}
}
static public void Main()
{
HashSet<pair> R = new HashSet<pair>();
R.Add( new pair(1, 1));
R.Add( new pair(1, 2));
R.Add( new pair(2, 1));
R.Add( new pair(2, 2));
R.Add( new pair(1, 3));
R.Add( new pair(2, 3));
R.Add( new pair(3, 4));
R.Add( new pair(1, 4));
Relation obj = new Relation();
if (obj.checkTransitive(R)) {
Console.WriteLine( "Transitive Relation" );
}
else {
Console.WriteLine( "Not a Transitive Relation" );
}
}
}
|
Javascript
class Relation {
constructor() {}
checkTransitive(R) {
if (R.size === 0) {
return true ;
}
const tup = new Map();
for (const i of R) {
if (!tup.has(i[0])) {
const temp = new Set();
temp.add(i[1]);
tup.set(i[0], temp);
} else {
tup.get(i[0]).add(i[1]);
}
}
for (const a of tup) {
const all_b_in_aRb = tup.get(a[0]);
for (const b of all_b_in_aRb) {
if (tup.has(b) && a[0] !== b) {
const all_c_in_bRc = tup.get(b);
for (const c of all_c_in_bRc) {
if (!all_b_in_aRb.has(c)) {
return false ;
}
}
}
}
}
return true ;
}
}
function main() {
const R = new Set();
R.add([1, 1]);
R.add([1, 2]);
R.add([2, 1]);
R.add([2, 2]);
R.add([1, 3]);
R.add([2, 3]);
R.add([3, 4]);
R.add([1, 4]);
const obj = new Relation();
if (obj.checkTransitive(R)) {
console.log( "Transitive Relation" );
} else {
console.log( "Not a Transitive Relation" );
}
}
main();
|
Output
Not a Transitive Relation
Time Complexity: O(N * K * log N) where N is the number of tuples in relation and K is the maximum number of tuples (a, b) for which a are same
Auxiliary Space: O(N)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
02 Jan, 2023
Like Article
Save Article