在执行线性操作之前是否存在使用某种形式的域检查的(可能有效的)线性代数包?
numpy
在线性操作之前已执行某种域检查:如果维度不匹配,则会引发ValueError
。我想更准确地识别我的域名(例如,通过使用指定空间基础的标记),并在域名不匹配时获得相同的行为。
假设我有两个3维的空间
向量空间A
代表水果:尺寸1 =香蕉,2 =苹果,3 =梨。 A
的向量是一个食谱
向量空间B
代表衣服:尺寸1 =鞋子,2 =裤子,3 =衬衫。 B
的向量是衣柜。
以下是我想要的(而不是numpy
)
import numpy as np
a = np.array([1,2,3], domain='fruits')
b = np.array([3,2,1], domain='clothes')
a + b # I want it to raise a ValueError: can't sum clothes and fruits
答案 0 :(得分:1)
您可以按subclassing numpy arrays滚动自己的矢量空间。我设法提出了一个简单的子类,基本上是numpy.ndarray
加上一个名字。通过限制相同类型名称的数组的加法和减法,我们基本上可以做你想要实现的。这假设你真的想要一个向量空间:在这种情况下,我们只需要在向量元素之间定义加法,而不是乘法(虽然这也很容易以相同的方式实现)。
这是我的班级:
import numpy as np
class named_ndarray(np.ndarray):
def __new__(cls, name, inparray):
obj = np.asarray(inparray).view(cls)
obj._name = name
return obj
def __array_finalize__(self, obj):
if obj is None: return
self._name = getattr(obj, '_name', None)
def __add__(self,other):
if np.isscalar(other) or (type(other)==type(self) and other._name==self._name):
return named_ndarray(self._name,np.asarray(self) + np.asarray(other))
else:
raise TypeError('Named type "{}" can only be added to the same type! (Other is "{}")'.format(self._name,other._name))
def __radd__(self,other):
return __add__(self,other)
def __sub__(self,other):
if np.isscalar(other) or (type(other)==type(self) and other._name==self._name):
return named_ndarray(self._name,np.asarray(self) - np.asarray(other))
else:
raise TypeError('Only same type can be subtracted from named type "{}"! (Other is "{}")'.format(self._name,other._name))
def __rsub__(self,other):
if np.isscalar(other) or (type(other)==type(self) and other._name==self._name):
return named_ndarray(self._name,np.asarray(self) - np.asarray(other))
else:
raise TypeError('Named type "{}" can only be subtracted from the same type! (Other is "{}")'.format(self._name,other._name))
前两种方法是ndarray
等同于__init__()
。可以通过指定名称并从现有数组或列表初始化来使用此类:
fruitvec1 = named_ndarray('fruits',[1,3,5])
fruitvec2 = named_ndarray('fruits',[2,4,6])
clothesvec = named_ndarray('clothes',[1,1,1])
通过覆盖__add__
,__radd__
,__sub__
和__rsub__
方法,我们可以确保只有相同类型的命名数组和标量(整数,浮点数等)。 )可以添加。通过单独进行乘法/除法,这些将对标量的预期工作(并且这样的两个对象不应相互相乘)。如果您想要超越线性空间,则应该类似地定义__mul__
,__rmul__
,__truediv__
,__rtruediv__
(后者假定为Python 3或from __future__ import division
)
以下是这些对象的行为:
>>> fruitvec1*3
named_ndarray([ 3, 9, 15])
>>> 3/fruitvec1
named_ndarray([ 3. , 1. , 0.6])
>>> fruitvec1 - 2*fruitvec2
named_ndarray([-3, -5, -7])
>>> fruitvec1 + clothesvec/4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "foo.py", line 17, in __add__
raise TypeError('Named type "{}" can only be added to the same type! (Other is "{}")'.format(self._name,other._name))
TypeError: Named type "fruits" can only be added to the same type! (Other is "clothes")