Equivalence Relation on a Set
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.
What is an Equivalence Relation?
A relation R on a set A is called an equivalence relation if it is
- Reflexive Relation: (a, a) ∈ R ∀ a ∈ A, i.e. aRa for all a ∈ A.
- Symmetric Relation: ∀ a, b ∈ A, (a, b) ∈ R ↔ (b, a) ∈ R.
- Transitive Relation: ∀ 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.
Example: Consider set A = {a, b}
R = {(a, a), (a, b), (b, a)} is not equivalence as for (b, b) tuple is not present but
R = {(a, a), (a, b), (b, a), (b, b)} is an equivalence relation.
Properties of Equivalence Relation
- Empty relation on a non-empty set is never equivalence.
- Universal relation over any set is always equivalence.
How to verify an Equivalence Relation?
The process of identifying/verifying if any given relation is equivalency:
- Check if the relation is Reflexive.
- Check if the relation is Symmetric.
- Check if the relation is Transitive.
Follow the below illustration for a better understanding
Example: Consider set R = {(1, 1), (1, 3), (2, 2), (3, 3), (3, 1), (3, 2), (3, 4), (4, 4), (4, 3)}
Pairs (1, 1), (2, 2), (3, 3), (4, 4) exist:
⇒ This satisfies the reflexive condition.
The symmetric condition is also satisfied.
For the pairs (1, 3) and (3, 4):
⇒ The relation (1, 4) does not exist
⇒ This does not satisfy the transitive condition.
So the relation is not transitive.
Hence it is not equivalence.
Note: (1, 4) and (4, 1) will be inserted in R to make it an equivalence relation.
C++
// C++ Program for checking // Equivalence relation #include <bits/stdc++.h> using namespace std; class Relation { public : bool checkEquivalence(set< int > A, set<pair< int , int > > R) { bool transitive = checkTransitive(R); bool symmetric = checkSymmetric(R); bool reflexive = checkReflexive(A, R); return (transitive && symmetric && reflexive); } bool checkTransitive(set<pair< int , int > > R) { // Empty relation is always transitive if (R.size() == 0) { return true ; } // Create a unordered_map to store tuple as key value // pair map< int , set< int > > tup; // Creating unordered_map of relation where (a) is key // and (b) is value 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 of all b's related with a set< int > all_b_in_aRb = tup.at(a->first); // Taking all c's from each b one by one for ( int b : all_b_in_aRb) { if (tup.find(b) != tup.end() && a->first != b) { // Set of all c's related with b set< int > all_c_in_bRc = tup.at(b); // All c's related with each b must be // subset of all b's related with a for ( int c : all_c_in_bRc) { if (all_b_in_aRb.find(c) == all_b_in_aRb.end()) { return false ; } } } } } // For all aRb and bRc there exist aRc in relation R return true ; } bool checkSymmetric(set<pair< int , int > > R) { // Empty relation is always symmetric if (R.size() == 0) { return true ; } for ( auto i = R.begin(); i != R.end(); i++) { // Making a mirror tuple auto temp = make_pair(i->second, i->first); if (R.find(temp) == R.end()) { // If bRa tuple does not exists in relation // R return false ; } } // bRa tuples exists for all aRb in relation R return true ; } bool checkReflexive(set< int > A, set<pair< int , int > > R) { // Empty relation on a non-empty relation set is never reflexive. if (A.size() > 0 && R.size() == 0) { return false ; } // Relation defined on an empty set is always reflexive. else if (A.size() == 0) { return true ; } for ( auto i = A.begin(); i != A.end(); i++) { // Making a tuple of same element auto temp = make_pair(*i, *i); if (R.find(temp) == R.end()) { // If aRa tuple not exists in relation R return false ; } } // All aRa tuples exists in relation R return true ; } }; int main() { // Creating a set A set< int > A{ 1, 2, 3, 4 }; set<pair< int , int > > R; // Inserting tuples in relation R R.insert(make_pair(1, 1)); R.insert(make_pair(1, 3)); R.insert(make_pair(2, 2)); R.insert(make_pair(3, 3)); R.insert(make_pair(3, 1)); R.insert(make_pair(3, 4)); R.insert(make_pair(4, 4)); R.insert(make_pair(4, 3)); Relation obj; // R is not equivalence as for (1, 3) and (3, 4) tuples -> (1, 4) tuple is not present if (obj.checkEquivalence(A, R)) { cout << "Equivalence Relation" << endl; } else { cout << "Not a Equivalence Relation" << endl; } return 0; } |
Java
// Java Program for checking Equivalence relation 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 checkEquivalence(Set<Integer> A, Set<pair> R) { boolean transitive = checkTransitive(R); boolean symmetric = checkSymmetric(R); boolean reflexive = checkReflexive(A, R); return (transitive && symmetric && reflexive); } boolean checkTransitive(Set<pair> R) { // Property 1 if (R.size() == 0 ) { return true ; } // Create a hashmap to store tuple as key value // pair HashMap<Integer, Set<Integer> > tup = new HashMap<>(); // Creating hashmap of relation where (a) is key // and (b) is value 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 of all b's related with a Set<Integer> all_b_in_aRb = tup.get(a); // Taking all c's from each b one by one for ( int b : all_b_in_aRb) { if (tup.containsKey(b) && a != b) { // Set of all c's related with b Set<Integer> all_c_in_bRc = tup.get(b); // All c's related with each b must // be subset of all b's related with // a for (Integer c : all_c_in_bRc) { if (all_b_in_aRb.contains(c)) { return false ; } } } } } // For all aRb and bRc there exist aRc in // relation R return true ; } boolean checkSymmetric(Set<pair> R) { // Property 1 if (R.size() == 0 ) { return true ; } for (var i : R) { // Making a mirror pair // Eg : (1, 2) => mirror pair = (2, 1) pair temp = new pair(i.second, i.first); if (!R.contains(temp)) { // If bRa tuple does not exists in // relation R return false ; } } // bRa tuples exists for all aRb in relation R return true ; } boolean checkReflexive(Set<Integer> A, Set<pair> R) { // Property 1 if (A.size() > 0 && R.size() == 0 ) { return false ; } // Property 2 else if (A.size() == 0 ) { return true ; } for (var i : A) { if (!R.contains( new pair(i, i))) { // If aRa tuple not exists in relation R return false ; } } // All aRa tuples exists in relation R return true ; } } public static void main(String[] args) { // Creating a set A Set<Integer> A = new HashSet<>(); A.add( 1 ); A.add( 2 ); A.add( 3 ); A.add( 4 ); // Creating relation R Set<pair> R = new HashSet<>(); // Inserting tuples in relation R R.add( new pair( 1 , 1 )); R.add( new pair( 1 , 3 )); R.add( new pair( 2 , 2 )); R.add( new pair( 3 , 3 )); R.add( new pair( 3 , 1 )); R.add( new pair( 3 , 4 )); R.add( new pair( 4 , 4 )); R.add( new pair( 4 , 3 )); Relation obj = new Relation(); // R is not equivalence as for (1, 3) and (3, 4) // tuples -> (1, 4) tuple is not present if (obj.checkEquivalence(A, R)) { System.out.println( "Equivalence Relation" ); } else { System.out.println( "Not a Equivalence Relation" ); } } } // This code is contributed by lokeshmvs21. |
Python3
class Relation: def checkEquivalence( self , A, R): transitive = self .checkTransitive(R) symmetric = self .checkSymmetric(R) reflexive = self .checkReflexive(A, R) return transitive and symmetric and reflexive def checkTransitive( self , R): # Empty relation is always transitive if len (R) = = 0 : return True # Create a dictionary to # store tuple as key value pair tup = dict () # Creating dictionary of relation # where (a) is key and (b) is value 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(): # Set of all b's related with a all_b_in_aRb = tup.get(a) if all_b_in_aRb is not None : # Taking all c's from each b one by one for b in all_b_in_aRb: # Set of all c's related with b 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): # All c's related with each b must be # subset of all b's related with a return False # For all aRb and bRc there exist aRc in relation R return True def checkSymmetric( self , R): # Empty relation is always symmetric if len (R) = = 0 : return True for i in R: if (i[ 1 ], i[ 0 ]) not in R: # If bRa tuple does not exists in relation R return False # bRa tuples exists for all aRb in relation R return True def checkReflexive( self , A, R): # Empty relation on a non-empty # relation set is never reflexive. if len (A) > 0 and len (R) = = 0 : return False # Relation defined on an empty # set is always reflexive. elif len (A) = = 0 : return True for i in A: if (i, i) not in R: # If aRa tuple not exists in relation R return False # All aRa tuples exists in relation R return True # Driver code if __name__ = = '__main__' : # Creating a set A A = { 1 , 2 , 3 , 4 } # Creating relation R R = {( 1 , 1 ), ( 1 , 3 ), ( 2 , 2 ), ( 3 , 3 ), ( 3 , 1 ), ( 3 , 4 ), ( 4 , 4 ), ( 4 , 3 )} obj = Relation() # R is not equivalence as for (1, 3) and # (3, 4) tuples -> (1, 4) tuple is not present if obj.checkEquivalence(A, R): print ( "Equivalence Relation" ) else : print ( "Not a Equivalence Relation" ) |
C#
// C# Program for checking // Equivalence relation using System; using System.Collections.Generic; class Relation { public bool checkEquivalence(HashSet< int > A, HashSet<Tuple< int , int >> R) { bool transitive = checkTransitive(R); bool symmetric = checkSymmetric(R); bool reflexive = checkReflexive(A, R); return (transitive && symmetric && reflexive); } bool checkTransitive(HashSet<Tuple< int , int >> R) { // Empty relation is always transitive if (R.Count == 0) { return true ; } // Create a dictionary to store tuple as key value // pair Dictionary< int , HashSet< int >> tup = new Dictionary< int , HashSet< int >>(); // Creating dictionary of relation where (a) is key // and (b) is value foreach ( var i in R) { if (!tup.ContainsKey(i.Item1)) { HashSet< int > temp = new HashSet< int >(); temp.Add(i.Item2); tup.Add(i.Item1, temp); } else { tup[i.Item1].Add(i.Item2); } } foreach ( var a in tup) { // Set of all b's related with a HashSet< int > all_b_in_aRb = tup[a.Key]; // Taking all c's from each b one by one foreach ( int b in all_b_in_aRb) { if (tup.ContainsKey(b) && a.Key != b) { // Set of all c's related with b HashSet< int > all_c_in_bRc = tup[b]; // All c's related with each b must be // subset of all b's related with a foreach ( int c in all_c_in_bRc) { if (!all_b_in_aRb.Contains(c)) { return false ; } } } } } // For all aRb and bRc there exist aRc in relation R return true ; } bool checkSymmetric(HashSet<Tuple< int , int >> R) { // Empty relation is always symmetric if (R.Count == 0) { return true ; } foreach ( var i in R) { // Making a mirror tuple Tuple< int , int > temp = new Tuple< int , int >(i.Item2, i.Item1); if (!R.Contains(temp)) { // If bRa tuple does not exists in relation // R return false ; } } // bRa tuples exists for all aRb in relation R return true ; } bool checkReflexive(HashSet< int > A, HashSet<Tuple< int , int >> R) { // Empty relation on a non-empty relation set is never reflexive. if (A.Count > 0 && R.Count == 0) { return false ; } // Relation defined on an empty set is always reflexive. else if (A.Count == 0) { return true ; } foreach ( int i in A) { // Making a tuple of same element Tuple< int , int > temp = new Tuple< int , int >(i, i); if (!R.Contains(temp)) { // If aRa tuple not exists in relation R return false ; } } // All aRa tuples exists in relation R return true ; } } public class GFG { static public void Main () { // Creating a set A HashSet< int > A = new HashSet< int >(){ 1, 2, 3, 4 }; HashSet<Tuple< int , int >> R = new HashSet<Tuple< int , int >>(); // Inserting tuples in relation R R.Add( new Tuple< int , int >(1, 1)); R.Add( new Tuple< int , int >(1, 3)); R.Add( new Tuple< int , int >(2, 2)); R.Add( new Tuple< int , int >(3, 3)); R.Add( new Tuple< int , int >(3, 1)); R.Add( new Tuple< int , int >(3, 4)); R.Add( new Tuple< int , int >(4, 4)); R.Add( new Tuple< int , int >(4, 3)); Relation obj = new Relation(); // R is not equivalence as for (1, 3) and (3, 4) tuples -> (1, 4) tuple is not present if (obj.checkEquivalence(A, R)) { Console.WriteLine( "Equivalence Relation" ); } else { Console.WriteLine( "Not a Equivalence Relation" ); } } } // contributed by akashish__ |
Javascript
// Javascript program for checking Equivalence relation class Relation { checkEquivalence(A, R) { let transitive = this .checkTransitive(R); let symmetric = this .checkSymmetric(R); let reflexive = this .checkReflexive(A, R); return transitive && symmetric && reflexive; } checkTransitive(R) { // Empty relation is always transitive if (R.length === 0) { return true ; } // Create an object to store tuple as key-value pair let tup = {}; // Creating object of relation where (a) is key and (b) is value for (let i of R) { if (tup[i[0]] === undefined) { tup[i[0]] = new Set([i[1]]); } else { tup[i[0]].add(i[1]); } } for (let a in tup) { // Set of all b's related with a let allBInARb = tup[a]; if (allBInARb) { // Taking all c's from each b one by one for (let b of allBInARb) { // Set of all c's related with b let allCInBRc = tup[b]; if (a !== b && allCInBRc) { if (!Array.from(allCInBRc).every(c => allBInARb.has(c))) { // All c's related with each b must be subset of // all b's related with a return false ; } } } } } // For all aRb and bRc there exists aRc in relation R return true ; } checkSymmetric(R) { // Empty relation is always symmetric if (R.length === 0) { return true ; } for (let i of R) { if (!R.has((i[1], i[0]))) { // If bRa tuple does not exists in relation R return false ; } } // bRa tuples exists for all aRb in relation R return true ; } checkReflexive(A, R) { // Empty relation on a non-empty relation set is never reflexive. if (A.size > 0 && R.length === 0) { return false ; } // Relation defined on an empty set is always reflexive. else if (A.size === 0) { return true ; } for (let i of A) { if (!R.has([i, i])) { // If aRa tuple not exists in relation R return false ; } } // All aRa tuples exists in relation R return true ; } } // Creating set A let A = new Set([1, 2, 3, 4]); // Creating relation R let R = new Set([[1, 1], [1, 3], [2, 2], [3, 3], [3, 1], [3, 4], [4, 4], [4, 3]]); // Creating an object of the Relation class let obj = new Relation(); // Checking if R is an equivalence relation if (obj.checkEquivalence(A, R)) { console.log( "Equivalence Relation" ); } else { console.log( "Not a Equivalence Relation" ); } //This code is contributed by Edula Vinay Kumar Reddy |
Not a Equivalence 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 is the same.
Auxiliary Space: O(N)
Please Login to comment...