Тем не менее, вы, вероятно, хотите подкласс
ел бы иметь возможность выполнять матричные операции с использованием класса Python в качестве элементов - в данном случае простогоГалуа поле реализация. Он реализует необходимые__add__
, __mul__
, __sub__
и т.п.
Сначала я подумал, что это возможно смассивы numpy, с помощьюdtype
параметр, но изdtype
документация, Кажется, чтоdtype
не может быть произвольным классом Python. Например, у меня есть классGalois
который выполняет операции по модулю 2:
>>> from galois import Galois
>>> Galois(1) + Galois(0)
Galois(1)
>>> Galois(1) + Galois(1)
Galois(0)
Я могу попытаться использовать это в numpy:
>>> import numpy as np
>>> a = np.identity(4, Galois)
>>> a
array([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]], dtype=object)
Но если я выполняю операции над матрицами, элементы не следуют методам моего класса:
>>> b = np.identity(4, Galois)
>>> a+b
array([[2, 0, 0, 0],
[0, 2, 0, 0],
[0, 0, 2, 0],
[0, 0, 0, 2]], dtype=object)
Есть ли способ сделать это с NumPy?
Есть ли какая-либо другая матричная библиотека Python, которая может выполнять матричные операции (включая инверсию) над произвольным числовым классом?
ОбновитьСпасибо за ответы до сих пор. Но я все еще не в состоянии действительно использовать это, как я надеялся. Сложение и умножение кажутся хорошими, но не инверсия матрицы. Например, давайте попробуем получитьAES обратная матрица аффинного преобразования S-блока изматрица аффинного преобразования прямого S-блока.
class Galois(object):
MODULO = 2
def __init__(self, val):
self.val = int(val) % self.MODULO
def __add__(self, val):
return self.__class__((self.val + int(val)) % self.MODULO)
def __sub__(self, val):
return self.__class__((self.val - int(val)) % self.MODULO)
def __mul__(self, val):
return self.__class__((self.val * int(val)) % self.MODULO)
def __int__(self):
return self.val
def __repr__(self):
return "%s(%d)" % (self.__class__.__name__, self.val)
def __float__(self):
return float(self.val)
if __name__ == "__main__":
import numpy as np
Gv = np.vectorize(Galois)
a = Gv(np.identity(8)) + Gv(np.eye(8,8,-1)) + Gv(np.eye(8,8,-2)) + Gv(np.eye(8,8,-3)) + Gv(np.eye(8,8,-4)) + Gv(np.eye(8,8,4)) + Gv(np.eye(8,8,5)) + Gv(np.eye(8,8,6)) + Gv(np.eye(8,8,7))
print np.matrix(a)
print np.matrix(a).I
Результат:
[[Galois(1) Galois(0) Galois(0) Galois(0) Galois(1) Galois(1) Galois(1)
Galois(1)]
[Galois(1) Galois(1) Galois(0) Galois(0) Galois(0) Galois(1) Galois(1)
Galois(1)]
[Galois(1) Galois(1) Galois(1) Galois(0) Galois(0) Galois(0) Galois(1)
Galois(1)]
[Galois(1) Galois(1) Galois(1) Galois(1) Galois(0) Galois(0) Galois(0)
Galois(1)]
[Galois(1) Galois(1) Galois(1) Galois(1) Galois(1) Galois(0) Galois(0)
Galois(0)]
[Galois(0) Galois(1) Galois(1) Galois(1) Galois(1) Galois(1) Galois(0)
Galois(0)]
[Galois(0) Galois(0) Galois(1) Galois(1) Galois(1) Galois(1) Galois(1)
Galois(0)]
[Galois(0) Galois(0) Galois(0) Galois(1) Galois(1) Galois(1) Galois(1)
Galois(1)]]
[[ 0.4 0.4 -0.6 0.4 0.4 -0.6 0.4 -0.6]
[-0.6 0.4 0.4 -0.6 0.4 0.4 -0.6 0.4]
[ 0.4 -0.6 0.4 0.4 -0.6 0.4 0.4 -0.6]
[-0.6 0.4 -0.6 0.4 0.4 -0.6 0.4 0.4]
[ 0.4 -0.6 0.4 -0.6 0.4 0.4 -0.6 0.4]
[ 0.4 0.4 -0.6 0.4 -0.6 0.4 0.4 -0.6]
[-0.6 0.4 0.4 -0.6 0.4 -0.6 0.4 0.4]
[ 0.4 -0.6 0.4 0.4 -0.6 0.4 -0.6 0.4]]
Не тот результат, на который я надеялся. Похоже, что для инверсии матрицы numpy просто преобразует матрицу в число с плавающей точкой, а затем инверсию с помощью простых действительных чисел.