я хотел бы иметь возможность выполнять матричные операции с использованием класса 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, которая может выполнять матричные операции (включая инверсию) с произвольным числовым классом?
Спасибо за ответы. Но я все еще не могу использовать его, как я надеялся. Сложение и умножение кажутся хорошими, но не обращение матрицы. Например, давайте попробуем получить матрицу аффинного преобразования S-блока AES из матрицы аффинного преобразования прямого 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 просто преобразует матрицу в числа с плавающей запятой, а затем выполняет инверсию с простыми действительными числами.