Introducción
Este capítulo continúa nuestro estudio de la teoría de grupos explorando los subgrupos y los generadores. El concepto de elemento primitivo se introducirá al final. Asumimos que ya estás familiarizado con la definición de un grupo. Si necesitas un repaso, echa un vistazo a este artículo.
Para desarrollar la intuición, comenzamos con los grupos aditivos, que son sencillos y ayudan a clarificar conceptos centrales como los subgrupos y los generadores.
Luego pasamos a los grupos multiplicativos de enteros módulo . Los enteros en sí mismos, bajo la multiplicación, no forman un grupo: solo el y el tienen inversos multiplicativos en , por lo que los axiomas de grupo fallan. Para solucionar esto, consideramos la multiplicación módulo , enfocándonos en los enteros menores que que son coprimos con este. Estos enteros coprimos sí tienen inversos multiplicativos módulo , y juntos forman un grupo bien definido. Esta construcción juega un papel central en la teoría de números y es fundamental para muchos sistemas criptográficos.
Coprimos: Dos números son coprimos si su Máximo Común Divisor (MCD) es 1.
Ejemplo 1: 8 y 15 son coprimos porque
Factores de 8: 1, 2, 4, 8
Factores de 15: 1, 3, 5, 15
Factor común: 1
El mcd es 1.Ejemplo 2: 12 y 18 NO son coprimos porque
Factores de 12: 1, 2, 3, 4, 6, 12
Factores de 18: 1, 2, 3, 6, 9, 18
Factor común: 1, 2, 3, 6
El mcd es 6.
Finalmente, examinamos los generadores: elementos que pueden producir un grupo o subgrupo entero a través de la multiplicación repetida. Comprender los generadores revela importantes estructuras de subgrupos, especialmente cuando es primo, y destaca su papel crítico en las aplicaciones criptográficas.
1. Grupos Aditivos
Los grupos aditivos usan la adición (a menudo módulo algún número) como operación, siendo el elemento identidad el y el inverso de un elemento el , lo que hace que su estructura sea relativamente sencilla. Sumerjámonos en ejemplos para ver cómo funcionan.
1.1 Ejemplo:
Para calentar, considera bajo la adición. Comienza con la clausura:
nos lleva fuera del conjunto. Para arreglar esto, usamos la adición módulo 6:
Ahora cada resultado permanece en . Aquí está la tabla de adición:
Cada resultado está en , por lo que se cumple la clausura. Comprueba las otras propiedades:
- Asociatividad: La agrupación no cambia el resultado:
- ,
- .
- Identidad: El funciona como el elemento identidad, ya que (ver la primera fila o columna de la tabla).
- Inversos: Cada elemento tiene un par que suma :
| Elemento | Inverso | Comprobación |
|---|---|---|
Por lo tanto, es un grupo con orden (el número de elementos en un conjunto) .
Ejercicio 1.1: Comprueba si es un grupo.
Pista: Intenta construir la tabla de adición como hicimos para .
Hacer esto a mano puede ser un poco tedioso, así que aquí tienes un script de Python que generará la tabla de adición completa para cualquier :
def print_addition_table(mod):
header = ["+ mod " + str(mod)] + list(range(mod))
print(" | ".join(str(h).rjust(4) for h in header))
print("-" * (6 * (mod + 1)))
for row in range(mod):
line = [str(row).rjust(4)]
for col in range(mod):
value = row + col
result = value % mod
if value >= mod:
line.append(f"{value} ≡ {result}".rjust(6))
else:
line.append(str(result).rjust(6))
print(" | ".join(line))
# Try it with Z_9
print_addition_table(9)
Seguimiento: Después de analizar , intenta generar la tabla para . ¿Puedes determinar si también es un grupo?
Por lo tanto, es un grupo de orden . Los grupos finitos como este son clave en la aritmética modular y la criptografía. A continuación, dirigimos nuestra atención a cómo ciertos elementos y subconjuntos dentro de un grupo pueden revelar una estructura más profunda—a través de subgrupos y generadores.
2. Subgrupos y Generadores
2.1 Entendiendo los Subgrupos
Al estudiar grupos, a menudo encontramos subconjuntos que retienen la estructura del grupo bajo la misma operación. Estos subconjuntos especiales, llamados subgrupos, se comportan como versiones en miniatura del grupo principal. Sin embargo, no cualquier subconjunto califica—exploremos esto con ejemplos para ver qué hace a un subgrupo.
Ejemplo 2.1.1: Subgrupos en
Considera , el grupo de todos los enteros bajo la adición, y dos subconjuntos familiares:
- El conjunto de los enteros pares:
- El conjunto de los enteros impares:
Comprobemos los enteros pares:
- Clausura: La suma de dos números pares es par (p. ej., ).
- Identidad: El es par y está incluido.
- Inversos: El inverso de cualquier número par también es par (p. ej., el inverso de es ).
- Asociatividad: Heredada de .
Los enteros pares satisfacen todas las propiedades de grupo—este es un subgrupo válido.
Ahora comprobemos los enteros impares:
- Clausura: , que es par—no es parte del conjunto. Por lo tanto, la clausura falla.
- Identidad: El no es impar, por lo que falta el elemento identidad.
- Inversos: Para el , el es impar—pero como la clausura y la identidad ya fallan, no es un subgrupo.
Los enteros impares bajo la adición no satisfacen los criterios de subgrupo—son solo un subconjunto, no un subgrupo.
Ejemplo 2.1.2: Subgrupos en
Ahora toma y prueba dos subconjuntos:
- Pares módulo 8:
- Primera mitad:
Para :
- Clausura: , (ambos en el conjunto).
- Identidad: El está presente.
- Inversos: , , (todos los pares funcionan).
- Asociatividad: Se cumple desde .
¡Este es un subgrupo!
Para :
- Clausura: (no en el conjunto).
- Identidad: El está presente.
- Inversos: Para el , ningún elemento en da (p. ej., ).
Este falla en ser un grupo, por lo que es solo un subconjunto, no un subgrupo.
Definición: Un subconjunto de un grupo es un subgrupo si es un grupo bajo la misma operación, lo que significa que satisface la clausura, contiene la identidad, tiene inversos para todos sus elementos y hereda la asociatividad de .
Ejercicio 2.1.1: Encuentra todos los subgrupos de .
2.2 Generadores en Grupos Aditivos
Ahora que hemos visto los subgrupos, exploremos cómo elementos individuales pueden generarlos—o incluso a todo el grupo. Revisaremos , el grupo aditivo bajo la adición módulo , y examinaremos qué pasa cuando sumamos repetidamente un elemento a sí mismo, como un “paseo” alrededor de los números módulo .
Ejemplo 2.2.1: Generadores en
Intento 1:
Esto da . Sumar repetidamente recorre el grupo entero.
Intento 2:
Esto da —solo la mitad del grupo.
Intento 3:
Esto da , ¡aún más pequeño!
Intento 5:
Esto da , cubriéndolo todo, igual que el .
Ejercicio 2.2.1: En , ¿qué elementos generan el entero? ¿Qué elementos generan subgrupos propios?
2.2.2 Subgrupos Generados por Elementos
Ahora considera cualquier grupo con una operación binaria (como la adición o la multiplicación), y sea un elemento de . Al aplicar repetidamente la operación de grupo a , podemos formar el conjunto de elementos que genera. Este conjunto se denota y se llama el subgrupo cíclico generado por .
Por ejemplo en grupos aditivos:
Para muchos elementos, es un subgrupo propio. Pero cuando , decimos que es un generador de , y que es un grupo cíclico.
Como se muestra en el Ejemplo 2.2.1, calculamos los subgrupos generados por elementos en bajo la adición módulo 6. Los subgrupos generados por cada elemento son los siguientes:
- (subgrupo propio)
- (subgrupo propio)
- (subgrupo propio)
- (subgrupo propio)
Los elementos y generan el grupo entero , convirtiéndolos en generadores, mientras que , , y generan subgrupos propios.
Ejemplo 2.2.3: Generadores en
Ahora prueba bajo la adición módulo 5:
Cada elemento distinto de cero es un generador.
Esto sucede porque para todo , y el es primo.
Conclusión: En , un elemento genera el grupo entero si y solo si . Para un primo, todos los elementos distintos de cero son generadores. Para un compuesto, solo algunos elementos califican.
2.3 Código: Explorando Generadores Aditivos en
def additive_closure(a, n):
"""Generates {0, a, 2a, 3a, ...} mod n until it repeats."""
result = []
current = 0
while current not in result:
result.append(current)
current = (current + a) % n
return sorted(result) # Sorted for readability
# Show generated sets in (Z_6 , +)
print("Z_6:")
for a in range(6):
print(f"Generated by {a}: {additive_closure(a, 6)}")
# Show generated sets in (Z_5, +)
print("\nZ_5:")
for a in range(5):
print(f"Generated by {a}: {additive_closure(a, 5)}")
Salida:
(Z_6, +):
Generated by 0: [0]
Generated by 1: [0, 1, 2, 3, 4, 5]
Generated by 2: [0, 2, 4]
Generated by 3: [0, 3]
Generated by 4: [0, 2, 4]
Generated by 5: [0, 1, 2, 3, 4, 5]
(Z_5, +):
Generated by 0: [0]
Generated by 1: [0, 1, 2, 3, 4]
Generated by 2: [0, 1, 2, 3, 4]
Generated by 3: [0, 1, 2, 3, 4]
Generated by 4: [0, 1, 2, 3, 4]
Habiendo explorado los grupos aditivos, ahora pasamos a sus contrapartes multiplicativas.
3. Grupos Multiplicativos
Los grupos multiplicativos operan bajo la multiplicación (a menudo módulo algún número), siendo el elemento identidad el , aunque encontrar inversos puede tener más matices, especialmente en entornos finitos. Para ilustrar esto, examinaremos un ejemplo concreto usando la multiplicación módulo .
3.1 Ejemplo:
Considera :
- Se cumple la clausura, p. ej., , está en el conjunto.
- Identidad: El elemento identidad es el , pero esto falla para el , que no tiene inverso;
- Inversos: Cada elemento distinto de cero tiene un inverso:
Dado que el no tiene inverso, no es un grupo. Pero si eliminamos el y consideramos solo los elementos distintos de cero — es decir, — obtenemos un grupo bajo la multiplicación. Este conjunto a menudo se denota como y es un grupo de orden 6.
Puedes usar este código para generar la tabla de multiplicación para cualquier módulo :
def print_multiplication_table(mod):
header = ["× mod " + str(mod)] + list(range(mod))
print(" | ".join(str(h).rjust(4) for h in header))
print("-" * (6 * (mod + 1)))
for row in range(mod):
line = [str(row).rjust(4)]
for col in range(mod):
value = row * col
result = value % mod
if value >= mod:
line.append(f"{value} ≡ {result}".rjust(6))
else:
line.append(str(result).rjust(6))
print(" | ".join(line))
print_multiplication_table(5)
3.2 Ejemplo: No Es un Grupo
Ahora probemos el conjunto bajo la multiplicación mod 6.
| 1 | |||||
| 2 | |||||
| 3 | |||||
| 4 | |||||
| 5 |
Ahora tenemos un problema más fundamental: algunas multiplicaciones dan como resultado 0, que no es parte del conjunto. Por lo tanto, este conjunto y operador binario no están cerrados, así que no es un grupo.
3.3 Ejemplo:
Como otro ejemplo, consideremos ahora la multiplicación en :
Solo los elementos —aquellos que son coprimos con 8—tienen inversos multiplicativos módulo 8:
Los elementos restantes, , comparten todos un factor común con 8 y, por lo tanto, no tienen inversos. Así, no es un grupo bajo la multiplicación.
3.4. ¿Qué es ?
El conjunto se define formalmente como:
Es decir, consiste en todos los elementos en que tienen un inverso multiplicativo módulo .
-
Cuando es primo, cada elemento distinto de cero es invertible, por lo que:
-
Cuando es compuesto, solo los elementos coprimos con son invertibles. Por ejemplo:
En ambos casos, forma un grupo bajo la multiplicación. Sin embargo, el conjunto completo no siempre forma un grupo—a menos que sea primo.
Anteriormente, usamos para demostrar por qué la ausencia de inversos (y la presencia de divisores de cero) rompe la estructura de grupo cuando es compuesto. Esta distinción es más que técnica: juega un papel central en la comprensión de la aritmética modular, los algoritmos criptográficos y la teoría de números.
En la siguiente sección, exploraremos cómo cambia la estructura de cuando es primo.
3.5 Por Qué Funcionan los Módulos Primos
Estos fallos motivan los módulos primos. En , donde es primo, cada elemento tiene un inverso. De hecho, esto está garantizado por un resultado clásico de la teoría de números.
Considera el patrón para módulo :
- Si no es primo, no es un grupo debido a los divisores de cero y los inversos faltantes (p. ej., ).
- Si es primo, es un grupo.
3.6 Código de Python para Calcular el Inverso
Uno de los métodos más simples y eficientes es usar la función integrada de Python pow(a, -1, p) para calcular inversos modulares. Entre bastidores, esto funciona debido a un famoso resultado de la teoría de números llamado pequeño teorema de Fermat, que garantiza que existe un inverso y nos dice:
cuando el módulo es un número primo y no es divisible por .
Aquí tienes un ejemplo:
def mod_inverse(a, p):
return pow(a, -1, p)
# Test for Z_7^*
def test_inverses(p):
print(f"Testing inverses modulo {p}:")
for a in range(1, p):
inv = mod_inverse(a, p)
print(f"Inverse of {a} mod {p} is {inv} (check: {a} * {inv} = {a * inv % p})")
if __name__ == "__main__":
p = 7
test_inverses(p)
Salida:
Testing inverses modulo 7:
Inverse of 1 mod 7 is 1 (check: 1 * 1 = 1)
Inverse of 2 mod 7 is 4 (check: 2 * 4 = 1)
Inverse of 3 mod 7 is 5 (check: 3 * 5 = 1)
Inverse of 4 mod 7 is 2 (check: 4 * 2 = 1)
Inverse of 5 mod 7 is 3 (check: 5 * 3 = 1)
Inverse of 6 mod 7 is 6 (check: 6 * 6 = 1)
3.7 Ejercicios
Ejercicios de Matemáticas:
-
Encuentra el inverso modular (si existe) para lo siguiente, usando la función
pow(a, -1, n)de Python o una calculadora. Para módulos primos, opcionalmente puedes usar el pequeño teorema de Fermat: -
¿Para qué valores de en existe el inverso modular?
Ejercicios de Programación:
-
Escribe una función
list_all_inverses(n)que devuelva un diccionario con todos los elementos en junto con sus inversos (si existen). -
Escribe un programa que tome la entrada del usuario
ayn, y compruebe si existe un inverso modular. Si es así, imprime el inverso. Pruébalo con diferentes valores y observa qué descubres. -
Reto: Elige algunos números primos pequeños
py escribe un programa que compruebe sipow(a, p - 1, p) == 1para todos losaen{1, 2, ..., p - 1}. ¿Se cumple esto para cadaa? ¿Qué pasa sipno es primo?
4. Generadores en Grupos Multiplicativos
Ahora dirigimos nuestra atención a los generadores en los grupos multiplicativos. Para desarrollar la intuición, comenzamos con ejemplos concretos en , explorando cómo elementos individuales pueden generar el grupo completo—o solo una parte de él—a través de la multiplicación repetida.
Ejemplo 4.1:
Intento 3:
. El elemento es un generador.
Intento 2:
, un subgrupo, no el grupo completo.
Prueba con Otros Elementos:
- :
- :
- :
Resumen:
| Elemento | Conjunto Generado | Tamaño | ¿Generador? |
|---|---|---|---|
| ❌ | |||
| ✅ | |||
| ❌ | |||
| ✅ | |||
| ❌ |
4.1 Elementos Primitivos
Como vemos, en el grupo aditivo , donde es primo, se garantiza que cada elemento distinto de cero es un generador. Es decir, sumar repetidamente cualquier elemento distinto de cero eventualmente recorrerá todos los elementos del grupo. Sin embargo, en los grupos multiplicativos , solo algunos elementos son generadores—estos se llaman elementos primitivos. Este contraste resalta una diferencia fundamental: los grupos aditivos sobre primos son siempre cíclicos con todos los elementos distintos de cero como generadores, mientras que los grupos multiplicativos sobre primos son cíclicos pero tienen solo un subconjunto de elementos que sirven como generadores.
Definición: Un elemento es un elemento primitivo si
Toma, por ejemplo, : y son elementos primitivos, mientras que , y no lo son.
Un resultado fundamental en la teoría de números garantiza que para cualquier primo , el grupo es cíclico, lo que significa que siempre contiene al menos un elemento primitivo. Esto contrasta con el grupo aditivo , donde cada elemento distinto de cero genera el grupo completo.
Ejemplo 4.1.1:
-
Elemento 2:
, por lo que es un elemento primitivo. -
Elemento 3:
, por lo que también es un elemento primitivo.
Ejemplo 4.1.2:
-
Elemento 2:
, por lo que es un elemento primitivo. -
Elemento 3:
, un subgrupo, no el grupo completo.
Ejemplo 4.1.3:
-
Elemento 3:
, orden (grupo completo). Por lo tanto, es un elemento primitivo de .
Nota Adicional: Aunque mencionamos anteriormente que es siempre un grupo, no siempre es cíclico cuando no es primo. En contraste, cuando es primo, es siempre cíclico. Esta distinción importa en la práctica—especialmente en criptografía—donde preferimos trabajar con grupos cíclicos, por lo que a menudo elegimos módulos primos para asegurar que tenga esta estructura cíclica.
4.2 Código de Python: Encontrando Elementos Primitivos Módulo un Primo
Para encontrar elementos primitivos en , calculamos el subgrupo generado por un elemento candidato y comprobamos si incluye todos los elementos de . El siguiente código verifica si un elemento dado es primitivo realizando esta comprobación. Puedes usarlo para explorar y probar más ejemplos de elementos primitivos:
def is_primitive_element(g, p):
"""Check if g is a primitive element modulo p."""
required = set(range(1, p))
generated = set()
val = 1
for _ in range(1, p):
val = (val * g) % p
generated.add(val)
return generated == required
def primitive_elements(p):
"""Find all primitive elements of prime p."""
elements = []
for g in range(2, p):
if is_primitive_element(g, p):
elements.append(g)
return elements
# Example usage:
prime = 11
print(f"Primitive elements modulo {prime}: {primitive_elements(prime)}")
Salida de Muestra:
Primitive elements modulo 11: [2, 6, 7, 8]
Para un enfoque más eficiente, la biblioteca galois puede calcular directamente los elementos primitivos en el grupo multiplicativo de un cuerpo finito, que para un primo corresponde a . Primero, instala la biblioteca con pip install galois, luego usa:
import galois
print(galois.GF(7).primitive_elements) # Output: [3, 5]
Este método está optimizado para primos grandes, haciéndolo ideal para aplicaciones prácticas, mientras que el código manual de arriba ayuda a comprender el concepto de los elementos primitivos.
Ejercicio
Apliquemos lo que hemos aprendido sobre los generadores y los elementos primitivos.
-
Usa el código de Python anterior para encontrar un generador de .
(Pista: Estás buscando un elemento cuyas potencias generen todos los elementos de .) -
Usa tu generador para listar todos los elementos de en la forma .
(Pista: Deberías obtener 12 potencias distintas.) -
Para cada uno de los siguientes valores de , escribe el subgrupo generado por .
(Pista: Este enfoque te ayuda a encontrar todos los subgrupos sin fuerza bruta. Por ejemplo, considera el caso a continuación)
Ejemplo:
Si (un generador de ), entonces:
- El subgrupo generado por es:
Ahora intenta esto para .
(Recuerda: calcula primero, luego enumera sus potencias sucesivas módulo 13 hasta que vuelvas al 1.)
- Usa tu trabajo anterior para listar todos los subgrupos distintos de .
(Pista: Algunas potencias de generan el mismo subgrupo.)
Conclusión:
Este capítulo se centró en comprender los grupos multiplicativos módulo un primo y sus estructuras de subgrupos. Vimos que estos grupos son cíclicos, lo que significa que pueden ser generados por un solo elemento — llamado elemento primitivo. También exploramos cómo las potencias de un elemento primitivo generan subgrupos cíclicos, y cómo diferentes potencias producen diferentes subgrupos.
Debido a que aún no hemos introducido herramientas formales como el Teorema de Lagrange, abordamos el descubrimiento de subgrupos de forma manual — especialmente en el ejercicio final, donde probamos algunos valores de para ver qué subgrupos generaban. En el siguiente capítulo, aprenderás los principios subyacentes que te permiten determinar los tamaños de los subgrupos y los generadores de manera sistemática.