2017-12-08 42 views
0

2 차원 행렬을 구축하기 위해 vector을 사용하는 Matrix class을 작성하려고했습니다. 내 주요 목표는이 클래스를 사용하여 행렬을 행렬에 추가 할 수 있고, 또한 정상적인 행렬 연산을 수행 할 수 있다는 것입니다. 내 현재 문제는 어떻게 추가/뺄셈/두 행렬의 요소로 요소를 곱하면됩니까? this answer 아이디어를 적용하여이 문제를 해결하기 위해 벡터 속성을 사용하고 싶습니다. 그러나 지금까지 나는 성공하지 못했습니다. 어떻게 요소 와이즈 두 벡터 작업에 transform과 plus/minus를 사용할 수 있습니까 ??"transform"및 구조체를 cython에서 벡터에 대한 연산을 구현하는 데 사용

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()) 

이 문제를 해결하기위한 답을 얻게되면 감사하겠습니다.

+0

빠른 포인터 :'plus'는'operator []'보다는'operator()'를 가져야한다고 생각합니다. 템플릿 함수를 만들기보다는'double'을 정의하는 것이 더 쉽습니다. – DavidW

+0

@DaivdW 어떻게해야합니까? double 연산자() (double x, double y) : 더블 연산자 (double x, double y) : return x + y'이 오류가 발생했습니다 : double 연산자 (double x, double y) : ^ - -------------------------------------------------- --------- matrix.py : 16 : 43 : C 함수 정의가 허용되지 않습니다. ' – Dalek

+0

@DavidW 글쎄, [여기]에서'plus '를 사용하는 것은 어떨까요? (http : //en.cppreference. co.kr/w/cpp/utility/functional/plus)? C++ 라이브러리에서 헤더를 가져 오는 방법은 무엇입니까? 다시 한번 감사드립니다 :) – Dalek

답변

1

큰 문제는 C++ 변환 함수에 대한 설명서를 잘못 이해하고 "UnaryOperation"변형 (함수가 단 하나의 인수 만 사용하는 경우)을 호출한다는 것입니다.

대신 "BinaryOperation"버전을 호출해야합니다. 컨테이너 범위의 경우 begin 및 end 반복자가 필요합니다 (두 번째 입력과 출력은 동일한 길이로 가정 됨).

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은 할당 된 저장소보다 크기가 큰 것으로 생각합니다.

+0

고마워요! 답변을 많이 주셔서 감사합니다! ** 당신이 행과 열 속성에 할당을 허용한다는 것을 무엇을 의미하는지 자세히 설명 해주시겠습니까? 아이디어는 Matrix를 일관성없는 상태로 놓을 수 있기 때문에 파이썬은 할당 된 저장소보다 크기가 크다고 생각합니다 ** – Dalek

+0

예를 들어,'getVal'과'setVal'은'self._columns'의 결과를 사용하여 선택할 요소를 결정합니다. 그러나'columns' 속성은 setter를 가지므로 사용자는 임의의 값에'self._columns'를 할당 할 수 있습니다. 행과 열을 올바르게 추가하는 방법이있을 때 변경할 수 없어야하는 것처럼 보입니다. – DavidW

+0

유용한 답변을 다시 한번 고맙습니다. 이 질문과 관련하여 다른 질문을해도 될까요? – Dalek