26. Clases de equivalencia y particiones

Una relación de equivalencia divide un conjunto en grupos llamados clases de equivalencia. Esos grupos forman una partición: cubren todo el conjunto y no se superponen.

26.1 Introducción

Las relaciones de equivalencia permiten agrupar elementos que son equivalentes según un criterio. Cada grupo obtenido se llama clase de equivalencia.

Cuando todas las clases se consideran juntas, forman una partición del conjunto original. Esta idea aparece en clasificación, normalización, agrupamiento de datos, roles, categorías y clases modulares.

26.2 Qué es una clase de equivalencia

Dada una relación de equivalencia R sobre un conjunto A, la clase de equivalencia de un elemento a es el conjunto de todos los elementos de A que están relacionados con a.

[a] = {x ∈ A | x R a}

La notación [a] se lee "clase de equivalencia de a".

26.3 Ejemplo con restos módulo 3

Consideremos la relación sobre números enteros: dos números están relacionados si tienen el mismo resto al dividir por 3.

a R b si a % 3 = b % 3

Esta relación produce tres clases principales: números con resto 0, resto 1 y resto 2.

26.4 Clases módulo 3

[0] = {..., -6, -3, 0, 3, 6, ...} [1] = {..., -5, -2, 1, 4, 7, ...} [2] = {..., -4, -1, 2, 5, 8, ...}

Cada número entero pertenece exactamente a una de estas tres clases.

26.5 Representantes de una clase

Un mismo grupo puede nombrarse usando cualquiera de sus elementos como representante.

[1] = [4] = [7]

Esto ocurre porque 1, 4 y 7 tienen el mismo resto al dividir por 3. Todos representan la misma clase de equivalencia.

26.6 Clases iguales o disjuntas

En una relación de equivalencia, dos clases de equivalencia son iguales o no tienen elementos en común.

Si [a] ∩ [b] ≠ ∅, entonces [a] = [b]

No puede haber clases parcialmente superpuestas. Esta propiedad permite formar particiones limpias.

26.7 Qué es una partición

Una partición de un conjunto es una colección de subconjuntos no vacíos que cumplen dos condiciones: cubren todo el conjunto y no se superponen entre sí.

A = A₁ ∪ A₂ ∪ ... ∪ Aₙ Aᵢ ∩ Aⱼ = ∅ si i ≠ j

Cada elemento del conjunto original debe pertenecer a una y solo una parte.

26.8 Ejemplo de partición

A = {1, 2, 3, 4, 5, 6} P = {{1, 3, 5}, {2, 4, 6}}

La colección P es una partición de A porque separa los números en impares y pares, sin dejar elementos fuera y sin repetir elementos entre grupos.

26.9 Lo que no es una partición

Colección Problema
{{1, 2}, {2, 3}, {4}} Los grupos se superponen porque el 2 aparece en dos partes
{{1, 2}, {3}} No cubre todo A si A = {1, 2, 3, 4}
{{1, 2}, ∅, {3, 4}} Una partición no debe contener subconjuntos vacíos

26.10 Relación entre equivalencias y particiones

Toda relación de equivalencia produce una partición del conjunto. Las clases de equivalencia son las partes de esa partición.

Relación de equivalencia → clases de equivalencia → partición

También ocurre al revés: toda partición puede definir una relación de equivalencia, donde dos elementos están relacionados si pertenecen al mismo bloque.

26.11 Ejemplo con roles de usuario

Si relacionamos usuarios por tener el mismo rol, obtenemos clases de equivalencia por rol.

Administradores = {Ana, Carla} Editores = {Luis, Marta} Lectores = {Diego}

Estos grupos forman una partición si cada usuario tiene exactamente un rol principal.

26.12 Ejemplo con categorías de productos

Los productos también pueden agruparse por categoría.

Periféricos = {teclado, mouse} Pantallas = {monitor} Almacenamiento = {disco, pendrive}

Cada categoría funciona como una clase de equivalencia si cada producto pertenece a una sola categoría.

26.13 Agrupar clases en JavaScript

Podemos construir clases de equivalencia agrupando elementos por una clave.

const usuarios = [
  { nombre: "Ana", rol: "admin" },
  { nombre: "Carla", rol: "admin" },
  { nombre: "Luis", rol: "editor" },
  { nombre: "Marta", rol: "editor" },
  { nombre: "Diego", rol: "lector" }
];

function agruparPorClave(elementos, obtenerClave) {
  return elementos.reduce((grupos, elemento) => {
    const clave = obtenerClave(elemento);
    if (!grupos[clave]) {
      grupos[clave] = [];
    }
    grupos[clave].push(elemento);
    return grupos;
  }, {});
}

const clasesPorRol = agruparPorClave(usuarios, usuario => usuario.rol);

console.log(clasesPorRol);

Cada propiedad del objeto resultante representa una clase de equivalencia.

26.14 Agrupar números por resto

También podemos agrupar números por el resto que dejan al dividir por 3.

function agruparPorClave(elementos, obtenerClave) {
  return elementos.reduce((grupos, elemento) => {
    const clave = obtenerClave(elemento);
    if (!grupos[clave]) {
      grupos[clave] = [];
    }
    grupos[clave].push(elemento);
    return grupos;
  }, {});
}

const numeros = [0, 1, 2, 3, 4, 5, 6, 7, 8];

const clasesModulo3 = agruparPorClave(numeros, numero => numero % 3);

console.log(clasesModulo3);

El resultado tiene tres grupos: resto 0, resto 1 y resto 2.

26.15 Verificar si una colección es partición

Para verificar una partición finita, podemos comprobar que no haya grupos vacíos, que no haya elementos repetidos entre grupos y que todos los elementos del universo estén cubiertos.

function esParticion(universo, grupos) {
  if (grupos.some(grupo => grupo.length === 0)) {
    return false;
  }

  const elementosAgrupados = grupos.flat();
  const sinRepetidos = new Set(elementosAgrupados);
  const universoSet = new Set(universo);

  return sinRepetidos.size === elementosAgrupados.length
    && sinRepetidos.size === universoSet.size
    && [...sinRepetidos].every(elemento => universoSet.has(elemento));
}

console.log(esParticion(
  [1, 2, 3, 4, 5, 6],
  [[1, 3, 5], [2, 4, 6]]
));

La función devuelve verdadero porque los grupos cubren el universo sin superponerse.

26.16 Aplicaciones prácticas

Área Clases de equivalencia Partición
Usuarios Usuarios con el mismo rol Roles del sistema
Productos Productos de la misma categoría Categorías del catálogo
Archivos Archivos con la misma extensión Tipos de archivo
Números Mismo resto módulo n Clases modulares
Datos Registros con la misma clave normalizada Grupos de datos equivalentes

26.17 Errores frecuentes

  • Crear grupos que se superponen y llamarlos partición.
  • Olvidar cubrir todos los elementos del conjunto original.
  • Incluir grupos vacíos dentro de una partición.
  • Creer que cada representante define una clase distinta aunque pertenezcan al mismo grupo.
  • Confundir clase de equivalencia con elemento individual.

26.18 Qué debes recordar de este tema

  • La clase de equivalencia de a contiene todos los elementos equivalentes a a.
  • Las clases de equivalencia son iguales o disjuntas.
  • Una partición cubre todo el conjunto sin superposiciones y sin partes vacías.
  • Toda relación de equivalencia produce una partición.
  • Toda partición puede definir una relación de equivalencia.
  • En JavaScript, agrupar por clave permite construir clases de equivalencia.

26.19 Conclusión

Las clases de equivalencia y las particiones muestran cómo una relación de equivalencia organiza un conjunto en grupos bien definidos. Esta idea es central para clasificar, agrupar y normalizar datos.

En el próximo tema estudiaremos relaciones de orden.