Atualmente, estou fazendo isso com a biblioteca do tatu , mas ela acaba sendo muito lenta. O problema é que eu preciso fazer isso por um trilhão de matrizes e acontece que calcular os dois determinantes é o gargalo do meu programa. Portanto, eu tenho duas perguntas
Existe algum truque que eu possa usar para calcular o determinante mais rapidamente, desde que eu saiba o tamanho deles? Talvez haja uma expansão confusa para matrizes 12 \ times12 que poderiam funcionar nesse caso?
Existe alguma outra maneira eficiente de testar a igualdade
Editar. Para responder aos comentários. Eu preciso calcular todos os gráficos não auto-complementares conectados da ordem , de modo que e tenham o mesmo número de árvores de abrangência. A motivação para isso pode ser encontrada nesta postagem do mathoverflow . Quanto à máquina, eu estou executando isso em uma máquina de 3,4 GHh de 8 núcleos em paralelo.
Editar. Consegui reduzir o tempo de execução esperado em 50% criando um programa C para calcular especificamente o determinante de uma matriz . Sugestões ainda são bem-vindas.
fonte
Respostas:
Como você já está usando C ++ e suas matrizes são definidas positivamente simétricas, eu realizaria um processo não dinâmico Q 12 I - Q - J 12 I - Q - J L D L TLDLT fatoração dinâmica de e também de . Aqui, estou assumindo que o também é definido positivamente, caso contrário, o exigirá um pivô para estabilidade numérica (também é possível que, embora não seja definido positivamente, o pivotamento não seja necessário, mas você deve experimentá-lo).Q 12I−Q−J 12I−Q−J LDLT
Isso é mais rápido que uma fatoração de LU e também mais rápido que Cholesky, porque raízes quadradas são evitadas. O determinante é simplesmente o produto dos elementos da matriz diagonal . O código para executar uma fatoração LDL é tão simples que você pode escrevê-lo em menos de 50 linhas de C. A página da Wikipedia descreve o algoritmo, e eu tenho um código de modelo simples para executar Cholesky aqui . Você pode simplificá-lo bastante e modificá-lo para evitar a raiz quadrada para implementar a fatoraçãoL D L TD LDLT
Como você também pode controlar o formato de armazenamento, é possível otimizar ainda mais a rotina para armazenar apenas metade da matriz e agrupá-la em uma matriz linear para maximizar a localidade da memória. Eu também escreveria rotinas simples de produtos personalizados e atualizações de classificação 1, já que os tamanhos dos problemas são tão pequenos que você deve deixar o compilador alinhar as rotinas para reduzir a sobrecarga de chamadas. Como é um loop de tamanho fixo, o compilador deve ser capaz de alinhar e desenrolar automaticamente as coisas quando apropriado.
Eu evitaria tentar fazer truques para aproveitar o fato de que Q12I−Q−J conter dentro da expressão. É provável que, para tamanhos de problemas tão pequenos, esses truques acabem sendo mais lentos do que simplesmente realizar dois cálculos determinantes separados. Obviamente, a única maneira de verificar essas alegações é tentar.Q
fonte
Sem algumas informações sobre a construção dessas matrizes simétricas reais definidas positivas, as sugestões a serem feitas são necessariamente limitadas.12×12
Fiz o download do pacote Armadillo do Sourceforge e dei uma olhada na documentação. Tente melhorar o desempenho da computação separada e , onde é a matriz de classificação um de todos, definindo por exemplo . A documentação observa que esse é o padrão para matrizes de tamanhodet(Q) det(12I−Q−J) J 4×4 , portanto, por omissão, presumo que a 12×12
det(Q,slow=false)
slow=true
opção seja um padrão para o caso .O queQ 12×12 o determinante será feito porque o cálculo é "jogado por cima de um muro" para o LAPACK (ou ATLAS) nesse ponto, sem indicação de que não é necessário girar; veja
slow=true
presumivelmente faz é uma rotação parcial ou total na obtenção de um formulário de escalão de linha, a partir do qual o determinante é facilmente encontrado. No entanto, você sabe com antecedência que a matriz é definitiva positiva, portanto, o giro é desnecessário para a estabilidade (pelo menos presumivelmente para a maior parte de seus cálculos. Não está claro se o pacote Armadillo lança uma exceção se os pivôs se tornarem indevidamente pequenos, mas isso deve ser um recurso de um pacote de álgebra linear numérica razoável.Edit : Encontrei o código do Tatu que implementa no arquivo de cabeçalho , usando modelos C ++ para funcionalidade substancial. A configuração não parece afetar como umdet
include\armadillo_bits\auxlib_meat.hpp
slow=false
det_lapack
e suas invocações nesse arquivo.O outro ponto seria seguir a recomendação de criar o pacote Armadillo vinculado a substituições de alta velocidade para BLAS e LAPACK, se você realmente estiver usando; veja a seção 5 do arquivo README.TXT do Armadillo para obter detalhes. [O uso de uma versão dedicada de 64 bits do BLAS ou LAPACK também é recomendado para obter velocidade nas máquinas atuais de 64 bits.]
A redução de linha na forma de escalão é essencialmente uma eliminação gaussiana e tem complexidade aritmética . Para ambas as matrizes, isso equivale ao dobro do trabalho, ou . Essas operações podem muito bem ser o "gargalo" em seu processamento, mas há pouca esperança de que, sem uma estrutura especial em23n3+O(n2) 43n3+O(n2) Q (ou algumas relações conhecidas entre os trilhões de casos de teste que permitem a amortização), o trabalho possa ser reduzido para .O(n2)
Para comparação, a expansão por co-fatores de uma matriz envolveoperações de multiplicação (e aproximadamente tantas adições / subtrações); portanto, para a comparação ( vs. ) favorece claramente a eliminação dos cofatores.n×n n! n=12 12!=479001600 23n3=1152
Outra abordagem que requer trabalho seria reduzir para a forma tridiagonal com transformações de Householder, que também coloca na forma tridiagonal. A computação e pode ser realizada posteriormente em operações. [O efeito da atualização do ranking um43n3+O(n2) Q 12I−Q det(Q) det(12I−Q−J) O(n) −J no segundo determinante pode ser expresso como um fator escalar dado pela resolução de um sistema tridiagonal.]
A implementação de uma computação independente pode valer a pena como uma verificação dos resultados de chamadas bem-sucedidas (ou com falha) à
det
função do Armadillo .Caso especial: Como sugerido por um Comentário de Jernej, suponha que onde como antes é a matriz (rank 1) de todos e seja um matriz diagonal não singular (positiva). De fato, para a aplicação proposta na teoria dos grafos, essas seriam matrizes inteiras. Em seguida, uma fórmula explícita paraQ=D−J J D=diag(d1,…,dn) det(Q) é:
Um esboço de sua prova oferece uma oportunidade para ilustrar uma aplicabilidade mais ampla, ou seja, sempre que tem um determinante conhecido e o sistemaD Dv=(1…1)T é rapidamente resolvido. Comece fatorando:
Agora está novamente no ranking 1, a saberD−1J (d−11…d−1n)T(1…1) . Observe que o segundo determinante é simplesmente:
onde é o polinómio característico de . Como uma matriz de classificação 1, deve ter (pelo menos) fatores de para explicar seu espaço nulo. O valor próprio "ausente" éf(x) D−1J f(x) n−1 x ∑d−1i , como pode ser visto no cálculo:
Segue-se que a característica polinomial , e é tal como mostrado acima para , .f(x)=xn−1(x−∑d−1i) f(1) det(I−D−1J) 1−∑d−1i
Observe também que se , então , uma matriz diagonal cujo determinante é simplesmente o produto de suas entradas diagonais.Q=D−J 12I−Q−J=12I−D+J−J=12I−D
fonte
Se você possui uma maneira estruturada de enumerar os gráficos dos quais deseja calcular os determinantes, talvez seja possível encontrar atualizações de baixa classificação que o transferem de um gráfico para outro.
Nesse caso, você poderia usar o lema determinante da matriz para calcular de forma barata o determinante do gráfico subsequente a ser enumerado usando seu conhecimento do determinante do gráfico atual.
Ou seja, para uma matriz e vetores : Isso pode ser generalizado se U e V forem matrizes e é :A u,v det(A+uvT)=(1+vTA−1u)det(A) n×m A n×n det(A+UVT)=det(Im+VTA−1U)det(A)
Para calcular com eficiência o inverso, você pode usar a fórmula de Sherman-Morrison para obter o inverso da matriz subsequente da matriz atual:(A+uvT)−1=A−1−A−1uvTA−11+vTA−1u
fonte