Masalah saat mengganti matriks dalam polinomial

Jan 12 2021

Contoh: biarkan

M = Matrix([[1,2],[3,4]]) # and 
p = Poly(x**3 + x + 1)    # then
p.subs(x,M).expand()

memberikan kesalahan:

TypeError: tidak dapat menambahkan <class'sympy.matrices.immutable.ImmutableDenseMatrix '> dan <class' sympy.core.numbers.One '>

yang sangat masuk akal karena dua suku pertama menjadi matriks tetapi suku terakhir (suku konstanta) bukanlah matriks melainkan skalar. Untuk memperbaiki situasi ini, saya mengubah polinomial menjadi

p = Poly(x**3 + x + x**0)    # then

kesalahan yang sama terus berlanjut. Apakah saya wajib mengetik ekspresi dengan tangan, mengganti x dengan M? Dalam contoh ini polinomial hanya memiliki tiga suku tetapi pada kenyataannya saya menjumpai (polinomial multivariat dengan) lusinan suku.

Jawaban

1 wsdookadr Jan 12 2021 at 12:40

Jadi saya pikir pertanyaannya terutama berkisar pada konsep polinomial Matriks :

(di mana P adalah polinomial, dan A adalah matriks)

Saya pikir ini mengatakan bahwa suku bebas adalah angka, dan tidak dapat ditambahkan dengan sisanya yang merupakan matriks, secara efektif operasi penjumlahan tidak ditentukan antara kedua jenis tersebut.

TypeError: tidak dapat menambahkan <class'sympy.matrices.immutable.ImmutableDenseMatrix '> dan <class' sympy.core.numbers.One '>

Namun, hal ini dapat dielakkan dengan mendefinisikan fungsi yang mengevaluasi polinomial matriks untuk matriks tertentu. Perbedaannya di sini adalah bahwa kita sedang menggunakan matriks eksponensial , jadi kami benar menghitung jangka bebas dari polinomial matriks a_0 * Idi mana I=A^0adalah matriks identitas dari bentuk yang diperlukan:

from sympy import *
x = symbols('x')
M = Matrix([[1,2],[3,4]])
p = Poly(x**3 + x + 1)

def eval_poly_matrix(P,A):
    res = zeros(*A.shape)
    for t in enumerate(P.all_coeffs()[::-1]):
        i, a_i = t
        res += a_i * (A**i)
    return res

eval_poly_matrix(p,M)

Keluaran:

Dalam contoh ini polinomial hanya memiliki tiga suku tetapi pada kenyataannya saya menjumpai (polinomial multivariat dengan) lusinan suku.

Fungsi di eval_poly_matrixatas dapat diperluas untuk bekerja untuk polinomial multivariat dengan menggunakan .monoms()metode untuk mengekstrak monomial dengan koefisien bukan nol , seperti:

from sympy import *
x,y = symbols('x y')
M = Matrix([[1,2],[3,4]])
p = poly( x**3 * y + x * y**2 + y )

def eval_poly_matrix(P,*M):
    res = zeros(*M[0].shape)
    for m in P.monoms():
        term = eye(*M[0].shape)
        for j in enumerate(m):
            i,e = j
            term *= M[i]**e
        res += term
    return res

eval_poly_matrix(p,M,eye(M.rows))

Catatan: Beberapa pemeriksaan kewarasan, penanganan kasus edge, dan pengoptimalan dapat dilakukan:

  1. Jumlah variabel yang ada dalam polinomial berkaitan dengan jumlah matriks yang diteruskan sebagai parameter (yang pertama tidak boleh lebih besar dari yang terakhir, dan jika lebih rendah dari beberapa logika perlu ada untuk mengatasinya, saya hanya menangani kasusnya ketika keduanya sama)
  2. Semua matriks harus berbentuk bujursangkar sesuai definisi polinomial matriks
  3. Sebuah diskusi tentang versi multivarian dari fitur aturan Horner di komentar pertanyaan ini . Ini mungkin berguna untuk meminimalkan jumlah perkalian matriks.
  4. Tangani fakta bahwa dalam polinomial Matriks x*yberbeda dari y*xkarena perkalian matriks bersifat non-komutatif . Rupanya fungsi poli dalam sympy tidak mendukung variabel non-komutatif , tetapi Anda dapat mendefinisikan simbol dengan commutative=Falsedan sepertinya ada cara untuk maju ke sana

Tentang poin ke-4 di atas, ada dukungan untuk ekspresi Matrix di SymPy, dan itu dapat membantu di sini:

from sympy import *
from sympy.matrices import MatrixSymbol

A = Matrix([[1,2],[3,4]])
B = Matrix([[2,3],[3,4]])

X = MatrixSymbol('X',2,2)
Y = MatrixSymbol('Y',2,2)
I = eye(X.rows)

p = X**2 * Y + Y * X ** 2 + X ** 3 - I
display(p)

p = p.subs({X: A, Y: B}).doit()
display(p)

Keluaran:

Untuk perkembangan lebih lanjut tentang fitur ini ikuti # 18555