Проверить, обратима ли матрица над конечным полем

Я хотел бы проверить, является ли случайная матрица определенного типа обратимой над конечным полем, в частности F_2. Я могу проверить, обратима ли матрица над вещественными числами, используя следующий простой код.

import random
from scipy.linalg import toeplitz
import numpy as np
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)
if (np.linalg.matrix_rank(matrix) < n):
    print "Not invertible!"

Есть ли способ добиться того же, но через F_2?


person marshall    schedule 27.04.2013    source источник
comment
You could do it with Sage easily enough (example) . Мне будет интересно посмотреть, есть ли хорошее решение в стеке науки (numpy/scipy/sympy/mpmath/pandas и т. д.).   -  person DSM    schedule 27.04.2013
comment
Я думаю, что если вы рассматриваете матрицу над F_2 как матрицу над Z, используя только 0 и 1, то определитель над F_2 должен быть определителем над Z по модулю 2 (т.е. проверка становится, если определитель над Z четный или нечетный). Это не может быть алгоритмически оптимальным.   -  person Armin Rigo    schedule 27.04.2013
comment
@ArminRigo К сожалению, я не могу заставить эту идею работать. Установите n = 100 в приведенном выше коде и напечатайте linalg.det(matrix), linalg.det(matrix)%2. Я всегда получаю 0 для linalg.det(matrix)%2, что предположительно связано с проблемами с плавающей запятой. Существует ли точный целочисленный определитель?   -  person marshall    schedule 28.04.2013
comment
@marshall: det в Numpy/Scipy работает только с плавающей запятой.   -  person pv.    schedule 28.04.2013
comment
@marshall: я заметил, что вы добавили тег sympy. Он сделает полный целочисленный определитель, но будет ужасно медленным.   -  person DSM    schedule 28.04.2013
comment
@DSM Да, я действительно не хочу использовать для этого sympy. В конце концов, мне интересно, в какой части научного стека должно быть это?   -  person marshall    schedule 28.04.2013


Ответы (2)


Для этого лучше использовать Sage или другой подходящий инструмент.

Нижеследующее является просто бесхитростной попыткой неспециалиста что-то сделать, но метод исключения Гаусса с поворотом должен дать точный результат для обратимости:

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)

Обратите внимание, что np.bool_ аналогичен F_2 только в ограниченном смысле --- бинарная операция + в F_2 является - для логического значения, а унарная операция - является +. Хотя умножение то же самое.

>>> 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)

Приведенное выше исключение Гаусса использует только эти операции, поэтому оно работает.

person pv.    schedule 27.04.2013
comment
Спасибо. Я не возражаю против импорта внешних библиотек для этой конкретной задачи, если это правильно. Я никогда не использовал шалфей и понятия не имею, например, насколько хорошо он взаимодействует с матрицами scipy. - person marshall; 28.04.2013
comment
+ и - одно и то же в F_2. - person asmeurer; 28.04.2013
comment
@asmeuer: да, но не для логических значений. - person pv.; 29.04.2013

К сожалению, SymPy пока не может обрабатывать конечные поля в матрицах, хотя поддержка планируется.

Однако, как отметили некоторые комментаторы, вы можете просто проверить определитель над целыми числами. Если это 1 (mod 2), матрица обратима. Чтобы на самом деле найти инверсию, вы можете просто взять нормальную инверсию над целыми числами, умножить на определитель (чтобы у вас не было дробей) и изменить каждый элемент на 2. Я не могу представить, что это было бы слишком эффективно, и вы, вероятно, могли бы использовать любую библиотеку матриц, даже числовую (с округлением до ближайшего целого числа). SymPy также может выполнять каждый из этих шагов.

Я должен указать, что в общих циклических конечных полях часть «умножения на определитель» необходимо будет отменить, умножив на обратный мод p (это не нужно по модулю 2, потому что единственная возможность - 1).

person asmeurer    schedule 28.04.2013
comment
Спасибо, это интересно. Я полагаю, что хорошим дополнением было бы то, что scipy мог вычислить определитель над целыми числами. - person marshall; 29.04.2013