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++ 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 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. |
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# 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 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)