繁体   English   中英

在cython中使用“ transform”和结构对向量执行操作

[英]Using “transform” and a struct in cython to implement operations on vectors

我一直在尝试编写一个使用一维vectorMatrix 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)

我注意到的代码的一小部分细节是您允许分配rowscolumns属性。 这是一个坏主意,因为它让您将Matrix置于不一致的状态,Python认为该状态比分配的存储更大。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM