Ответ 1
Хакинг-трюк, который работает при ошибках округления, не является проблемой:
- найти регулярные обратные (могут иметь нецелые записи) и детерминант (целое число), оба реализованы в numpy
- умножить инверсию на определитель и округлить до целых (hacky)
- теперь умножаем все на детерминантный мультипликативный обратный (по модулю ваш модуль, код ниже)
- введите mod mod по модулю
Менее опасным способом является реализация гауссовой элиминации. Здесь мой код с использованием исключения Гаусса, который я написал для моих целей (ошибки округления были для меня проблемой). q - модуль, который не обязательно является простым.
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: как отмечают комментаторы, в некоторых случаях этот алгоритм терпит неудачу. Это немного нетривиально для исправления, и сейчас у меня нет времени. Тогда он работал для случайных матриц в моем случае (модули были продуктами больших простых чисел). В принципе, первая ненулевая запись может быть не взаимно простой с модулем. Простой случай легко, так как вы можете искать другую строку и своп. В случае, не относящемся к делу, я думаю, что все ведущие записи не являются относительно простыми, поэтому вы должны их комбинировать