Grupos
Na álgebra abstrata, um grupo é uma tupla , onde é um conjunto e é uma função modo que o seguinte vale:
Para todos os em , .
Existe um elemento em L de tal modo que para todos os x em L , X * E = x .
Para cada em G , existe um elemento y em G tal que x ∗ y = e .
A fim de um grupo é definido como o número de elementos de L .
Para cada número inteiro estritamente positivo , existe pelo menos um grupo da ordem n . Por exemplo, ( C n , + n ) é um tal grupo, onde C n = { 0 , . . . , n - 1 } e x + n y = ( x + y ) .
Grupos isomórficos
Seja e defina ∗ por x ∗ y = ( x × y ) . Em seguida, 1 * 1 = 1 = 2 * 2 e 1 * 2 = 2 = 2 * 1 .
Da mesma forma, e 0 + 2 1 = 1 = 1 + 2 0 .
Embora os elementos e as operações de grupos e ( C 2 , + 2 ) ter nomes diferentes, os grupos partilham a mesma estrutura.
Dois grupos e ( G 2 , * 2 ) são referidos como sendo isomorfos se existe um bijeç~ao φ : G 1 → L 2 de tal modo que φ ( x * 1 y ) = φ ( x ) * 2 ϕ ( y ) para todos os x , y em G 1 .
Nem todos os grupos da mesma ordem são isomórficos. Por exemplo, o grupo Klein é um grupo de ordem 4 que não é isomórfico para .
Tarefa
Escreva um programa ou função que aceite um número inteiro não negativo n como entrada e imprima ou retorne o número de grupos não isomórficos da ordem n .
Casos de teste
Input Output
0 0
1 1
2 1
3 1
4 2
5 1
6 2
7 1
8 5
9 2
10 2
11 1
12 5
13 1
14 2
15 1
16 14
17 1
18 5
19 1
20 5
(extraído do OEIS A000001 )
Regras adicionais
Não há limites para o tempo de execução ou uso da memória.
Built-ins que trivializam essa tarefa, como o Mathematica
FiniteGroupCount
, não são permitidos.Aplicam-se as regras padrão de código de golfe .
fonte
monkeys_on_typewriters
cobre tudo que não é coberto pelos built-in documentados.Respostas:
CJam,
189187 bytesSerá difícil explicar isso ... A complexidade do tempo é garantida
O(scary)
.Se você é corajoso o suficiente, tente online . No meu laptop de baixa qualidade, consigo até 6 com o interpretador Java ou 5 no interpretador online.
Explicação
Eu não tenho um grande conhecimento em matemática (acabei de terminar o ensino médio, começando o CS na universidade na próxima semana). Portanto, tenha paciência comigo se eu cometer erros, declarar o óbvio ou fazer coisas de maneiras terrivelmente ineficientes.
Minha abordagem é uma força bruta, embora eu tenha tentado torná-la um pouco mais inteligente. Os principais passos são:
Antes de analisar como cada etapa é executada, vamos obter um código trivial:
O algoritmo a seguir não funciona corretamente com n <4 , os casos de 0 a 3 são tratados com uma dupla negação.
A partir de agora, os elementos de um grupo serão escritos como {1, a, b, c, ...} , onde 1 é o elemento de identidade. Na implementação do CJam, os elementos correspondentes são {0, 1, 2, 3, ...} , em que 0 é o elemento de identidade.
Vamos começar da etapa 1. Escrever todos os operadores possíveis para um grupo de pedidos n é equivalente a gerar todas as tabelas n × n Cayley válidas . A primeira linha e coluna são triviais: ambas são {1, a, b, c, ...} (da esquerda para a direita, de cima para baixo).
Saber que uma tabela Cayley também é um quadrado latino reduzido (devido à propriedade de cancelamento) permite gerar as tabelas possíveis linha por linha. A partir da segunda linha (índice 1), geramos todas as permutações exclusivas para essa linha, mantendo a primeira coluna fixa ao valor do índice.
Nem todas essas permutações são válidas, é claro: cada linha e coluna deve conter todos os elementos exatamente uma vez. Um bloco de filtro é usado para esse fim (um valor verdadeiro mantém a permutação, um falso remove-o):
Observe que estou filtrando dentro do loop de geração: isso torna o código um pouco mais longo (comparado à geração e filtragem distintas), mas melhora muito o desempenho. O número de permutações de um conjunto de tamanho n é n!, portanto, a solução mais curta exigiria muita memória e tempo.
Uma lista de tabelas Cayley válidas é um ótimo passo para enumerar os operadores, mas, sendo uma estrutura 2D, ela não pode verificar a associatividade, que é uma propriedade 3D. Portanto, o próximo passo é filtrar as funções não associativas.
Ufa! Muito trabalho, mas agora enumeramos todos os grupos de ordem n (ou melhor, as operações nele - mas o conjunto é fixo, por isso é a mesma coisa). Próximo passo: encontre isomorfismos. Um isomorfismo é uma bijeção entre dois desses grupos, de modo que φ (x ∗ y) = φ (x) ∗ φ (y) . Gerar essas bijections no CJam é trivial:
Ne!
fará isso. Como podemos verificá-los? Minha solução começa com duas cópias da tabela Cayley para xy . Em uma cópia, φ é aplicado a todos os elementos, sem tocar na ordem das linhas ou colunas. Isso gera a tabela para φ (x ∗ y) . Por outro, os elementos são deixados como estão, mas as linhas e colunas são mapeadas através de φ . Ou seja, a linha / colunax se torna a linha / coluna φ (x) . Isso gera a tabela para φ (x) ∗ y (y) . Agora que temos as duas tabelas, basta compará-las: se são iguais, encontramos um isomorfismo.Obviamente, também precisamos gerar os pares de grupos para testar o isomorfismo. Precisamos de todas as 2 combinações dos grupos. Parece que o CJam não tem operador para combinações. Podemos gerá-los pegando cada grupo e combinando-o apenas com os elementos a seguir na lista. Curiosidade: o número de 2 combinações é n × (n - 1) / 2 , que também é a soma dos primeiros n - 1 números naturais. Esses números são chamados de números triangulares: tente o algoritmo no papel, uma linha por elemento fixo, e você verá o porquê.
O código acima corrige o primeiro elemento do par, L [X] , e o combina com outros grupos (vamos chamar cada um desses Y ). Passa o par para um bloco de teste de isomorfismo que mostrarei em um momento. O bloco dá uma lista de valores de Y para o qual L [X] é isomorfa a Y . Então L [X] é anexado a esta lista. Antes de entender por que as listas são configuradas dessa maneira, vejamos o teste de isomorfismo:
Ótimo, agora temos uma lista de conjuntos como [{L [0], Y1, Y2, ...}, {L [1], Y1, ...}, ...] . A idéia aqui é que, por propriedade transitiva, se quaisquer dois conjuntos tiverem pelo menos um elemento em comum, todos os grupos nos dois conjuntos serão isomórficos. Eles podem ser agregados em um único conjunto. Como L [X] nunca aparecerá nas combinações geradas por L [X + ...] , após a agregação de cada conjunto de isomorfismos haverá um elemento único. Portanto, para obter o número de isomorfismos, basta contar quantos grupos aparecem exatamente uma vez em todos os conjuntos de grupos isomórficos. Para fazer isso, desembrulhei os conjuntos para que eles se pareçam com [L [0], Y1, Y2, ..., L [1], Y1, ...] , classifique a lista para criar agrupamentos do mesmo grupo e, finalmente, Codifique-RLE.
Isso é tudo, pessoal.
fonte
CJam, 73 bytes
A complexidade de tempo do código acima é pior que O (n! N ) .
A entrada n = 4 já é demais para o intérprete online .
Usando o interpretador Java , a entrada n = 5 pode ser possível se você tiver RAM e paciência suficientes.
Localizando grupos
Dado um grupo (G, ∗) de ordem n , podemos escolher uma bijeção arbitrária φ: G -> C n de modo que φ (e) = 0 .
φ irá tornar-se um isomorfismo de (L, *) e (C n , * ') se definirmos *' por x *' y = φ (φ -1 (x) * φ -1 (y)) .
Isso significa que basta estudar todos os operadores do grupo em C n, de modo que 0 seja o elemento neutro.
Representaremos um operador de grupo ∗ em C n por uma matriz retangular T de dimensões n × n, de modo que T [x] [y] = x ∗ y .
Para gerar essa matriz, podemos começar escolhendo uma permutação de C n para cada um de seus n linhas.
Dessa forma, 0 estará presente em todos os linhas (mas não necessariamente em todas as colunas ), o que significa que a terceira condição (existência de uma inversa) será atendida, qualquer que seja e .
Podemos corrigir e = 0 exigindo que a primeira coluna de T seja igual a C n . Em particular, a segunda condição (existência de um elemento neutro) será mantida.
Para verificar se T corresponde a um operador de grupo, basta verificar se a primeira condição (associatividade) é válida. Isso pode ser feito exaustivamente, verificando se T [T [x] [y]] [z] == T [x] [T [y] [z]] para todos x, y, z em C n .
Contando grupos não isomórficos
O método acima para encontrar grupos produzirá alguns grupos isomórficos. Em vez de identificar quais são isomórficos, geramos a família de todos os grupos isomórficos para cada um deles.
Isso pode ser feito iterando sobre todas as bijections φ: C n -> C n e determinando a matriz associada Tφ , definida por Tφ [x] [y] = φ -1 (T [φ (x)] [φ (y )]) .
Tudo o que resta a fazer é contar o número de famílias distintas.
O que o código faz
fonte
Python 2 ,
515507 bytesExperimente online!
Utilizando a equivalência entre o número de subgrupos não isomórficos de ordemn do Σn e o número de classes de equivalência isomórfica de grupos finitos de ordem n .
Link para a versão detalhada .
fonte
s
e aG
matéria são importantes? Caso contrário, você pode usardef f(k,*s):...f(~-k,j,*s)...
edef c(k,*G):...c(~-k,s,*G)....
.