2017-12-08 10 views
0

二次元マトリックスを構築するために一次元のvectorを使ったMatrix classを書きました。私の主な目標は、このクラスを使用して行列に行または列を追加し、通常の行列操作を行うことができることです。私の現在の問題は、どのようにを追加/減算/乗算要素は2つの行列の要素ですか? this answerのアイデアを適用して、この問題を解決するためにベクトルプロパティを使用したいと思います。しかし、これまで私は成功していませんでした。要素ごとに2つのベクトル演算に変換と正負を使用するにはどうすればよいですか?ベクトル上で操作を実装するためにcythonで "transform"と構造体を使用する

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 x、double y): ダブル演算子(double x、double y): return x + y'このエラーが発生しました: 'double(double x、double y): ^ - -------------------------------------------------- --------- matrix.pyx:16:43:C関数の定義がここで許可されていません。 ' – Dalek

+0

@DavidWまあ、[ここ]からの 'plus'の使用はどうですか?(http://en.cppreference。 com/w/cpp/utility/functional/plus)? C++ライブラリのヘッダーはどうすればよいですか?もう一度ありがとう:) – Dalek

答えて

1

あなたの問題の大きな部分は、C++変換関数のドキュメントを誤解し、関数の引数が1つしかない場合、 "UnaryOperation"バリアントを呼び出していることです。

代わりに "BinaryOperation"バージョンを呼び出す必要があります。コンテナ範囲には、イテレータの開始と終了が必要であることに注意してください(2番目の入力と出力は同じ長さとみなされます)。

は、ここでは、最小限の作業例です:私は気づいたあなたのコードの

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を不整合な状態に置くことができるからです。Pythonは割り当てられたストレージよりも大きいと考えています** – Dalek

+0

例えば、 'getVal'と' setVal'は 'self._columns'の結果を使ってどの要素を選ぶかを決定します。しかし、 'columns'プロパティはsetterを持っているので、ユーザは任意の値に' self._columns'を割り当てることができます。行と列を正しく追加する方法がある場合、変更できないはずのもののように思えます。 – DavidW

+0

もう一度有益な答えをありがとう。私は別の質問をすることができますが、これに関連することはますます少なくなりますか? – Dalek

関連する問題