Je voudrais prendre l'inverse modulaire d'une matrice comme [[1,2], [3,4]] mod 7 en Python. J'ai regardé numpy (qui fait l'inversion de matrice mais pas l'inversion de matrice modulaire) et j'ai vu quelques paquets de théorie de nombre en ligne, mais rien qui semble faire cette procédure relativement commune (au moins, il me semble relativement commun). Par ailleurs, l'inverse de la matrice ci-dessus est [[5, 5], [5, 3]] (mod 7). J'aimerais que Python le fasse pour moi.Le moyen le plus simple d'effectuer une inversion de matrice modulaire avec Python?
Répondre
Ce petit morceau de code semble faire: link
Notez le commentaire ci-dessous pour un peu d'amélioration. Semble faire l'algèbre linéaire correcte autant que je peux voir. Je n'ai jamais trouvé d'option dans les paquets réguliers, donc prendre un extrait de code du web (il y en a beaucoup plus disponible) est l'approche la plus simple.
Malheureusement, numpy ne dispose pas d'implémentations arithmétiques modulaires. Vous pouvez toujours coder l'algorithme proposé en utilisant la réduction de ligne ou les déterminants comme démontré here. Un inverse modulaire semble être très utile pour la cryptographie.
Droit, la cryptographie est correcte.J'implémente une variante du code de colline qui nécessite cette opération de matrice.Je préfère ne pas écrire ma propre fonction inverse modulaire, mais je le ferai si Je ne peux pas en trouver un en ligne – John
Parfois, il n'y a pas de repas gratuit :) – whatnick
Le lien semble avoir bitrotted, avez-vous un nouveau? –
Ok ... pour ceux qui s'en soucient, j'ai résolu mon propre problème. Cela m'a pris du temps, mais je pense que cela fonctionne. Il est sans doute pas le plus élégant, et devrait inclure un peu plus la gestion des erreurs, mais cela fonctionne:
import numpy
import math
from numpy import matrix
from numpy import linalg
def modMatInv(A,p): # Finds the inverse of matrix A mod p
n=len(A)
A=matrix(A)
adj=numpy.zeros(shape=(n,n))
for i in range(0,n):
for j in range(0,n):
adj[i][j]=((-1)**(i+j)*int(round(linalg.det(minor(A,j,i)))))%p
return (modInv(int(round(linalg.det(A))),p)*adj)%p
def modInv(a,p): # Finds the inverse of a mod p, if it exists
for i in range(1,p):
if (i*a)%p==1:
return i
raise ValueError(str(a)+" has no inverse mod "+str(p))
def minor(A,i,j): # Return matrix A with the ith row and jth column deleted
A=numpy.array(A)
minor=numpy.zeros(shape=(len(A)-1,len(A)-1))
p=0
for s in range(0,len(minor)):
if p==i:
p=p+1
q=0
for t in range(0,len(minor)):
if q==j:
q=q+1
minor[s][t]=A[p][q]
q=q+1
p=p+1
return minor
Ce n'est pas encore parfait. Je viens de réaliser que int (linalg.det (A)) ne vous donne pas toujours le bon déterminant. Hmm ... pas un grand fan de l'algorithme déterminant de numpy. Pour les matrices que je traite (en ce moment, juste de petites matrices 3x3), le déterminant devrait juste être un entier! Pourquoi l'algorithme det de numpy se trompe-t-il? – John
J'utilise maintenant int (round (linalg.det (A))). Brut. Mais je pense que ça fonctionne. – John
Merci pour le partage, sauvegardé afin que je puisse l'utiliser dans un stade ultérieur :). – bastijn
Une astuce hackish qui fonctionne lorsque des erreurs d'arrondi ne sont pas un problème:
- trouver l'inverse régulière (peuvent avoir des entrées non-entier), et le déterminant (un entier), tous deux mis en oeuvre dans numpy
- multiplier l'inverse par le déterminant, et autour de nombres entiers (hacky)
- multiplier maintenant tout en inverse multiplicatif du déterminant (modulo votre modulu s, le code ci-dessous)
- n'entrywise mod par votre module
Une manière moins hackish est de mettre effectivement en œuvre l'élimination gaussienne. Voici mon code utilisant l'élimination gaussienne, que j'ai écrit pour mes propres fins (les erreurs d'arrondi étaient un problème pour moi). q est le module, qui n'est pas nécessairement premier.
def generalizedEuclidianAlgorithm(a, b):
if b > a:
return generalizedEuclidianAlgorithm(b,a);
elif b == 0:
return (1, 0);
else:
(x, y) = generalizedEuclidianAlgorithm(b, a % b);
return (y, x - (a/b) * y)
def inversemodp(a, p):
a = a % p
if (a == 0):
print "a is 0 mod p"
return None
if a > 1 and p % a == 0:
return None
(x,y) = generalizedEuclidianAlgorithm(p, a % p);
inv = y % p
assert (inv * a) % p == 1
return inv
def identitymatrix(n):
return [[long(x == y) for x in range(0, n)] for y in range(0, n)]
def inversematrix(matrix, q):
n = len(matrix)
A = np.matrix([[ matrix[j, i] for i in range(0,n)] for j in range(0, n)], dtype = long)
Ainv = np.matrix(identitymatrix(n), dtype = long)
for i in range(0, n):
factor = inversemodp(A[i,i], q)
if factor is None:
raise ValueError("TODO: deal with this case")
A[i] = A[i] * factor % q
Ainv[i] = Ainv[i] * factor % q
for j in range(0, n):
if (i != j):
factor = A[j, i]
A[j] = (A[j] - factor * A[i]) % q
Ainv[j] = (Ainv[j] - factor * Ainv[i]) % q
return Ainv
EDIT: comme le soulignent les commentateurs, cet algorithme échoue dans certains cas. C'est un peu trivial à corriger, et je n'ai pas le temps de nos jours. À l'époque, cela fonctionnait pour des matrices aléatoires dans mon cas (les modules étaient des produits de grands nombres premiers). Fondamentalement, la première entrée non nulle pourrait ne pas être relativement primaire au module. Le cas principal est facile puisque vous pouvez rechercher une ligne différente et échanger. Dans le cas de non-prime, je pense qu'il pourrait être que toutes entrées principales ne sont pas premiers entre eux, donc vous devez les combiner
Merci pour le code. Il y a longtemps que je n'ai plus besoin de la solution (j'ai pris la classe l'automne dernier), mais j'apprécie vos efforts, tout comme la communauté, j'en suis sûr. J'aime beaucoup vos suggestions - un bon raisonnement mathématique, surtout sur votre première suggestion. Pour votre solution d'élimination gaussienne, le code que vous avez fourni est à peu près le même que celui que j'ai donné, mais vous pourriez faire valoir que c'est plus élégant (bien que nous ayons tous les deux des problèmes d'arrondi). De toute façon, excellent travail !! Merci d'avoir pris le temps de répondre à la question. – John
Mon code ne cause aucun problème d'arrondi. La première suggestion "hackish" fait, cependant. Pas de problème cependant! – WuTheFWasThat
Merci pour ce module utile !!! – SAbbasizadeh
Il peut être calculé en utilisant Sage (www.sagemath.org) comme
Matrice (IntegerModRing (7), [[1, 2], [3,4]]).inverse()
Bien que Sage est énorme à installer et vous devez utiliser la version de python qui vient avec ce qui est une douleur.
- 1. Quel est le moyen le plus simple de convertir une matrice de caractères en une matrice WCHAR?
- 2. Le moyen le plus simple de développer une interface graphique simple en Python
- 3. Inversion de matrice dans OpenCL
- 4. le moyen le plus simple et le plus rapide de construire une interface graphique wxPython
- 5. Le moyen le plus simple d'incrémenter une date en PHP?
- 6. Le moyen le plus simple de faire pivoter un rectangle
- 7. Le moyen le plus simple de concaténer NSString et int
- 8. Le moyen le plus simple de trier les nœuds DOM?
- 9. Le moyen le plus simple de vérifier les numéros
- 10. Le moyen le plus simple de développer des modules DNN?
- 11. Le moyen le plus simple de sauvegarder Tomcat avec une instance HTTP Apache
- 12. Multiplication et inversion de la matrice iPhone
- 13. Le moyen le plus simple d'authentifier l'utilisateur dans l'application iPhone?
- 14. Le moyen le plus simple de télécharger automatiquement les modules requis en Python?
- 15. Le moyen le plus simple d'exécuter une simple application GLES/EGL/OpenVG sur un PC?
- 16. Le moyen le plus simple de gérer des dépôts git centralisés sur une machine Linux?
- 17. Quel est le moyen le plus simple de faire une recherche parmi une liste de dictionnaires en Python?
- 18. Le moyen le plus simple d'enregistrer l'adresse IP du visiteur
- 19. Le moyen le plus simple pour totaliser les colonnes?
- 20. Inversion de chaîne en Python
- 21. Le moyen le plus rapide/le plus simple de rafraîchir datagridview?
- 22. Le moyen le plus simple pour télécharger des images
- 23. Le moyen le plus simple de copier une vue de données vers une datatable en C#?
- 24. Quel est le moyen le plus simple et le plus rapide pour mesurer les performances HD en utilisant Python?
- 25. moyen le plus simple de ne trier qu'une seule colonne
- 26. Le moyen le plus simple de convertir une URL en lien hypertexte dans une chaîne C#?
- 27. Le moyen le plus simple de remplacer une chaîne à l'aide d'un dictionnaire de remplacements?
- 28. Le moyen le plus simple de créer une application de bureau simulée interactive dans Silverlight?
- 29. Le moyen le plus simple de valider une entrée sur un fichier de mots?
- 30. Le moyen le plus simple de créer un message de confirmation avec jQuery/JavaScript?
Avez-vous regardé Sage? – Alejandro
Si vous finissez par écrire votre propre petit morceau de code. S'il vous plaît envisager de partager ici car je pense que beaucoup d'entre nous pourraient être intéressés :). – bastijn
L'inversion de matrice modulaire est intégrée dans 'sympy' (peut-être nouvelle depuis que cette question a été posée) et la réduction de ligne modulaire est assez facile aussi. Voir http://stackoverflow.com/a/37015283/2747370 –