2017-02-01 7 views
1

私はnumpyを使ってPythonリスト/マトリックスの '力'を得ようとしています。私の唯一の現在の作業ソリューションはnp.dotを使用して、反復の関数()である:Numpy 2D Array - Power Of - 答えを返さない?

def matr_power(matrix, power): 
    matrix_a = list(matrix) 
    matrix_b = list(matrix) 
    for i in range(0, power-1): 
     matrix_a = np.dot(matrix_a, matrix_b) 
    return matrix_a 

このは私のニーズにを動作しますが、私はそれはおそらく最も効率的な方法ではありません注意してくださいね。

リストをnumpy配列に変換してパワー操作を実行してからリストに戻って、必要な形式で使用できるようにしました。変換は起きているように見えますが、力の計算はしません。

while (foo != bar): 
    matr_x = np.asarray(matr_a) 
    matr_y = matr_x ** n 
    matr_out = matr_y.tolist() 
    n += 1 
    # Other code here to output certain results 

問題は、マトリックスは予想通りのアレイに変換される、であるが、電源動作を行う場合(**matr_yには計算がこれまで行われなかったかのようにmatr_xと同様になってしまいます。私はnp.power(matr_y, n)とStack Overflowに関する関連する質問にある他の解決策を試してみました。

私はnumpyのドキュメントを使用しようとしましたが、誤解していますか、または、これが期待どおりに動作するはずです。

計算がmatr_x ** iは決して計算されない(または他の場合はmatr_yに保存されない)ことを除いて、PyCharmのデバッグコンソールをすべてチェックするとすべての行列/リスト/配列が変換されます。


回答

**オペレータとnumpyの行列を使用することは可能だが、最善の解決策は、(numpyの行列が廃止されたように)numpyののlinalgのmatrix_power法と組み合わせnumpyの配列を使用することです。

matr_x = np.array(mat_a) 
matr_y = np.linalg.matrix_power(matr_x, path_length) 
work_matr = matr_y.tolist() 

要素単位であること**の機能は、私は(唯一の0と1)を隣接行列を使用していなかった以前に発見された可能性があることを今も明らかです。

+1

:だから合計で、あなたはコードで34

よりもはるかに良いだけで7回の乗算が必要です。 –

+0

本当にありがとうございますが、power(matr_y、i)も期待通りに動作していないようです。これも要素的なのでしょうか? np.dot()で唯一のオプションを繰り返していますか? – Matchoo

+0

はい、 'power'は、そのdocstringの最初の行で説明されているように、要素単位です。 :) –

答えて

1

dotに複数のコールなしでnumpyのを使用して、マトリックスのパワーを計算する(少なくとも)2つのオプションがあります:

  • 使用numpy.linalg.matrix_powerが。
  • numpy matrixクラスを使用します。これは、**をマトリックス代数として定義しています。例えば

In [38]: a 
Out[38]: 
array([[0, 1, 0], 
     [1, 0, 1], 
     [0, 1, 0]]) 

In [39]: np.linalg.matrix_power(a, 2) 
Out[39]: 
array([[1, 0, 1], 
     [0, 2, 0], 
     [1, 0, 1]]) 

In [40]: np.linalg.matrix_power(a, 3) 
Out[40]: 
array([[0, 2, 0], 
     [2, 0, 2], 
     [0, 2, 0]]) 

In [41]: m = np.matrix(a) 

In [42]: m ** 2 
Out[42]: 
matrix([[1, 0, 1], 
     [0, 2, 0], 
     [1, 0, 1]]) 

In [43]: m ** 3 
Out[43]: 
matrix([[0, 2, 0], 
     [2, 0, 2], 
     [0, 2, 0]]) 
+1

Matthew、あなたはどちらを使うべきかわからない場合。ここでは、[公式の位置](http://stackoverflow.com/a/20964252/7207392)の一種です。 –

+1

@Matthewウォーレンが提供している2つの完璧な解決策の間にあなたが引き裂かれた場合に備えて、私はそれをリンクしていました。個人的に私は、 'matrix'クラスがそれが引き起こす混乱を相殺するのに十分ではないという点に同意する傾向があります。だから私は 'linalg.matrix_power'と一緒に行くだろう。効率的な整数乗算ルーチンを自分でプログラムしなければならない場合は、オペランド(M、M^2、M^4、M^8 ...)を繰り返し二乗して乗算を大量に保存し、指数の2進表現が設定される。 –

+0

@PaulPanzer本当に面白いと聞こえますが、どういう仕組みか少し混乱しています。あなたは簡潔な説明を展開したりリンクしたりすることができますか? – Matchoo

1

ウォーレンの答えは完全に良いです。

私はOPによって特別な要求があったとき、手で効率的な整数電力演算子を構築する方法を簡単に説明します。

私はこのアルゴリズムが何であるか知りませんが、このように動作します: X^35を計算したいとします。あなたがそれを純粋にするなら、それはあなたに34の乗算を要するでしょう。しかし、それよりはるかに良いことができます。 X^35 = X^32×X^2×Xと書いてください。あなたがここで行ったことは、35というバイナリ表現(100011)に従って製品を分割することです。さて、X^32の計算は実際には安いです。そこに到達するには、Xを四回繰り返し(5回)しなければならないからです。 numpyの配列、 `` **行為は*要素単位*の場合

def my_power(x, n): 
    out = None 
    p = x 
    while True: 
     if n % 2 == 1: 
      if out is None: 
       out = p 
      else: 
       out = out @ p # this requires a fairly up-to-date python 
           # if yours is too old use np.dot instead 
      if n == 1: 
       return out 
     n //= 2 
     p = p @ p