Byłoby lepiej użyć Sage lub innego odpowiedniego narzędzia do tego.
Poniżej tylko naiwny non-ekspert próba zrobienia czegoś, ale obrócony eliminacji Gaussa należy podać dokładny wynik do odwracalności:
import random
from scipy.linalg import toeplitz
import numpy as np
def is_invertible_F2(a):
"""
Determine invertibility by Gaussian elimination
"""
a = np.array(a, dtype=np.bool_)
n = a.shape[0]
for i in range(n):
pivots = np.where(a[i:,i])[0]
if len(pivots) == 0:
return False
# swap pivot
piv = i + pivots[0]
row = a[piv,i:].copy()
a[piv,i:] = a[i,i:]
a[i,i:] = row
# eliminate
a[i+1:,i:] -= a[i+1:,i,None]*row[None,:]
return True
n = 10
column = [random.choice([0,1]) for x in xrange(n)]
row = [column[0]]+[random.choice([0,1]) for x in xrange(n-1)]
matrix = toeplitz(column, row)
print(is_invertible_F2(matrix))
print(int(np.round(np.linalg.det(matrix))) % 2)
Zauważ, że np.bool_
jest analogiczna do F_2 tylko w ograniczonym znaczeniu - - operacja binarna +
w F_2 jest -
dla bool, a unary op -
jest +
. Mnożenie jest jednak takie samo.
>>> x = np.array([0, 1], dtype=np.bool_)
>>> x[:,None] - x[None,:]
array([[False, True],
[ True, False]], dtype=bool)
>>> x[:,None] * x[None,:]
array([[False, False],
[False, True]], dtype=bool)
Powyższa gausjańska eliminacja wykorzystuje tylko te operacje, więc działa.
Można to zrobić z Sage dość łatwo ([Przykład] (http://aleph.sagemath.org/?z=eJzzDVawVfBNLCnKrAguSExO1XB30zDS1FEwBiJNXq7yjMycVIWQotJUK14uBSDwBSkP1itKzEvJz41PzUnNTc0r0dCESGamKfjqZRbHZ-aVpRaVZCblpGpoQvWBQFJRamI2gsvLVVCUmVeioO5rpQ5j-yIEgYYgieuBzSxOBVkFU6GFpkZBC1UdABH6PRM=&lang=sage)). Będę zainteresowany, aby sprawdzić, czy istnieje całkiem sprytne rozwiązanie na stosie nauki (numpy/scipy/sympy/mpmath/pandas itp.). – DSM
Myślę, że jeśli uznasz macierz za F_2 jako macierz nad Z, używając tylko 0 i 1, to wyznacznik przez F_2 powinien być wyznacznikiem ponad Z modulo 2 (tzn. Sprawdzenie staje się jeśli wyznacznik ponad Z jest równy lub nieparzysty) . To może nie być optymalne algorytmicznie. –
@ArminRigo Niestety nie mogę uruchomić tego pomysłu. Ustaw n = 100 w powyższym kodzie i wydrukuj linalg.det (macierz), linalg.det (macierz)% 2. Zawsze otrzymuję 0 dla linalg.det (macierzy)% 2, co jest prawdopodobnie spowodowane problemami zmiennoprzecinkowymi. Czy istnieje dokładna funkcja wyznaczająca liczbę całkowitą? – marshall