Open In App

Equivalence Relation on a Set

Last Updated : 14 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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

  1. Reflexive Relation: (a, a) ∈ R ∀ a ∈ A, i.e. aRa for all a ∈ A.
  2. Symmetric Relation: ∀ a, b ∈ A, (a, b) ∈ R ↔ (b, a) ∈ R.
  3. 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

  1. Empty relation on a non-empty set is never equivalence.
  2. 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


Output

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)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads