Un truco hacker que trabaja cuando los errores de redondeo no son un problema:
- encontrar la inversa regulares (pueden tener entradas no enteros), y el determinante (un número entero), ambos implementado en numpy
- multiplicar la inversa por el determinante, y la ronda de números enteros (hacky)
- ahora multiplica todo por inverso multiplicativo del determinante (modulo tu modulu s, código de abajo)
- qué entrywise mod por su módulo de
Una manera menos hacker es para aplicar en la práctica la eliminación de Gauss. Aquí está mi código usando la eliminación de Gauss, que escribí para mis propios fines (los errores de redondeo fueron un problema para mí). q es el módulo, que no es necesariamente primo.
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
EDITAR: como comentan, en algunos casos este algoritmo falla. No es trivial repararlo, y no tengo tiempo hoy en día. En aquel entonces funcionaba para matrices aleatorias en mi caso (los módulos eran productos de primos grandes). Básicamente, la primera entrada distinta de cero podría no ser relativamente primo para el módulo. El caso principal es fácil ya que puede buscar una fila diferente y cambiar. En el caso no primo, creo que podría ser que todo entradas principales no son primos entre sí lo que hay que combinarlos
¿Has mirado a Sage? – Alejandro
Si termina escribiendo su propio pequeño código. Por favor, considere compartirlo aquí, ya que creo que muchos de nosotros podríamos estar interesados :). – bastijn
La inversión de matriz modular está integrada en 'sympy' (posiblemente nueva ya que se formuló esta pregunta) y la reducción modular de filas es bastante fácil también. Ver http://stackoverflow.com/a/37015283/2747370 –