[英]Using “transform” and a struct in cython to implement operations on vectors
我一直在尝试编写一个使用一维vector
的Matrix class
,以建立一个二维矩阵。 我的主要目标是能够使用此类在我的矩阵中添加行或列,并且能够执行常规的矩阵运算。 我当前的问题是如何将两个矩阵的元素相加/相减/相乘 ? 我想使用矢量属性来通过应用此答案的思想来解决此问题。 但是到目前为止,我还没有成功。 如何对元素逐个两个矢量操作使用transform和plus / minus?
from libcpp.vector cimport vector
import cython
import numpy as np
import ctypes
cimport numpy as np
cimport cython
cdef extern from "<algorithm>" namespace "std" nogil:
OutputIter copy[InputIter,OutputIter](InputIter,InputIter,OutputIter)
#http://en.cppreference.com/w/cpp/algorithm/transform
OutputIter transform[InputIter, OutputIter, UnaryOperation]( InputIter,InputIter,OutputIter, UnaryOperation )
cdef struct plus:
T operator[] (T& x, T& y):
return x+y
cdef class Matrix:
cdef vector[double] matrix
cdef int _rows
cdef int _columns
def __cinit__(self, int rows=0, int columns=0, bint Identity=False):
self._rows=rows
self._columns=columns
self.matrix.resize(rows*columns)
if Identity:
self._IdentityMatrix()
property rows:
def __get__(self):
return self._rows
def __set__(self, int x):
self._rows = x
property columns:
def __get__(self):
return self._columns
def __set__(self, int y):
self._columns = y
cpdef double getVal(self, int r, int c):
return self.matrix[r*self._columns+c]
cpdef void setVal(self, int r, int c, double v):
self.matrix[r*self._columns+c] = v
cpdef void AddRow(self, vector[double] row):
cdef int i
if (row.size()!=self._columns):
raise Exception('The size of appended row is wrong!')
else:
self._rows+=1
for i from 0 <= i <self._columns:
self.matrix.push_back(row[i])
cpdef void AddColumn(self, vector[double] col):
cdef int i
if (col.size()!=self._rows):
raise Exception('The size of appended column is wrong!')
else:
for i from 0 <= i <self._rows:
self.matrix.insert(self.matrix.begin()+i+(i+1)*self._columns, col[i])
self._columns+=1
cpdef Matrix transpose(self):
cdef int i,j
cdef Matrix m = Matrix(self._columns,self._rows)
for i from 0 <= i <self._columns:
for j from 0 <= j <self._rows:
m.setVal(i,j,self.getVal(j,i))
return m
cdef void _IdentityMatrix(self):
cdef int i
if (self._rows!=self._columns):
raise Exception('In order to generate identity matrix, the number of rows and columns must be equal')
else:
for i from 0 <= i <self._columns:
self.setVal(i,i,1.0)
cpdef void add(self, Matrix m):
if ((self._rows!=m._rows) or (self._columns!=m._columns)):
raise Exception('In order to add two matrices, they must have equal number of rows and columns')
else:
transform(self.begin( ), m.begin( ), self.begin( ),plus())
如果能得到解决这个问题的答案,我将不胜感激。
问题的很大一部分是您误解了C ++转换函数的文档,并且正在调用它的“ UnaryOperation”变体(该函数仅接受一个参数)。
相反,您需要调用“ BinaryOperation”版本。 请注意,对于容器范围,需要一个开始和结束迭代器(假定第二个输入和输出的长度相等)。
这是一个最小的工作示例:
from libcpp.vector cimport vector
cdef extern from "<algorithm>" namespace "std":
#http://en.cppreference.com/w/cpp/algorithm/transform
OutputIter transform[InputIter1, InputIter2, OutputIter, BinaryOperation]( InputIter1,InputIter1,InputIter2,OutputIter, BinaryOperation)
cdef extern from "<functional>" namespace "std":
cdef cppclass plus[T]:
plus()
def example():
cdef vector[double] v1=[1,2,3]
cdef vector[double] v2=[2,3,4]
transform(v1.begin(),v1.end(),
v2.begin(),
v1.begin(),
plus[double]())
print(v1)
我注意到的代码的一小部分细节是您允许分配rows
和columns
属性。 这是一个坏主意,因为它让您将Matrix置于不一致的状态,Python认为该状态比分配的存储更大。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.