ปัญหาเมื่อแทนที่เมทริกซ์ในพหุนาม

Jan 12 2021

ตัวอย่าง: let

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

ให้ข้อผิดพลาด:

TypeError: ไม่สามารถเพิ่ม <class'sympy.matrices.immutable.ImmutableDenseMatrix '> และ <class' sympy.core.numbers.One '>

ซึ่งเป็นไปได้มากเนื่องจากสองเทอมแรกกลายเป็นเมทริกซ์ แต่เทอมสุดท้าย (เทอมคงที่) ไม่ใช่เมทริกซ์ แต่เป็นสเกลาร์ เพื่อแก้ไขสถานการณ์นี้ฉันเปลี่ยนพหุนามเป็น

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

ข้อผิดพลาดเดิมยังคงมีอยู่ ฉันจำเป็นต้องพิมพ์นิพจน์ด้วยมือโดยแทนที่ x ด้วย M หรือไม่ ในตัวอย่างนี้พหุนามมีเพียงสามคำ แต่ในความเป็นจริงฉันพบ (พหุนามหลายตัวแปรที่มี) หลายสิบคำ

คำตอบ

1 wsdookadr Jan 12 2021 at 12:40

ดังนั้นฉันคิดว่าคำถามส่วนใหญ่จะวนเวียนอยู่กับแนวคิดของพหุนามเมทริกซ์ :

(โดยที่ P เป็นพหุนามและ A คือเมทริกซ์)

ฉันคิดว่านี่เป็นการบอกว่าระยะอิสระเป็นตัวเลขและไม่สามารถบวกกับส่วนที่เหลือซึ่งเป็นเมทริกซ์ได้อย่างมีประสิทธิภาพการดำเนินการบวกไม่ได้กำหนดไว้ระหว่างสองประเภทนี้

TypeError: ไม่สามารถเพิ่ม <class'sympy.matrices.immutable.ImmutableDenseMatrix '> และ <class' sympy.core.numbers.One '>

อย่างไรก็ตามสิ่งนี้สามารถหลีกเลี่ยงได้โดยการกำหนดฟังก์ชันที่ประเมินพหุนามเมทริกซ์สำหรับเมทริกซ์เฉพาะ ความแตกต่างที่นี่คือที่ที่เรากำลังใช้เมทริกซ์ยกกำลังเพื่อให้เราได้อย่างถูกต้องคำนวณระยะฟรีของพหุนามเมทริกซ์a_0 * Iที่I=A^0เป็นเมทริกซ์เอกลักษณ์ของรูปร่างที่ต้องการ:

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)

เอาท์พุต:

ในตัวอย่างนี้พหุนามมีเพียงสามคำ แต่ในความเป็นจริงฉันพบ (พหุนามหลายตัวแปรที่มี) หลายสิบคำ

ฟังก์ชันeval_poly_matrixข้างต้นสามารถขยายเพื่อใช้กับพหุนามหลายตัวแปรโดยใช้.monoms()วิธีการแยกโมโนเมียลที่มีสัมประสิทธิ์ที่ไม่ใช่ศูนย์ดังนี้:

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

หมายเหตุ: การตรวจสอบความมีสติการจัดการกรณีขอบและการเพิ่มประสิทธิภาพสามารถทำได้:

  1. จำนวนตัวแปรที่มีอยู่ในพหุนามเกี่ยวข้องกับจำนวนเมทริกซ์ที่ส่งผ่านเป็นพารามิเตอร์ (อดีตไม่ควรมากกว่าตัวหลังและหากต่ำกว่าตรรกะบางอย่างที่จำเป็นต้องมีเพื่อจัดการกับสิ่งนั้นฉันจะจัดการเฉพาะกรณีนี้เท่านั้น เมื่อทั้งสองเท่ากัน)
  2. เมทริกซ์ทั้งหมดต้องเป็นกำลังสองตามนิยามของพหุนามเมทริกซ์
  3. การอภิปรายเกี่ยวกับคุณลักษณะกฎของ Hornerเวอร์ชันหลายตัวแปรในความคิดเห็นของคำถามนี้ สิ่งนี้อาจมีประโยชน์ในการลดจำนวนการคูณเมทริกซ์
  4. จัดการกับความจริงที่ว่าในพหุนามเมทริกซ์x*yจะแตกต่างจากy*xเพราะคูณเมทริกซ์ไม่สามารถสับเปลี่ยน เห็นได้ชัดว่าฟังก์ชัน poly ใน sympy ไม่รองรับ ตัวแปรที่ไม่สับเปลี่ยนแต่คุณสามารถกำหนดสัญลักษณ์ด้วยcommutative=Falseและดูเหมือนว่าจะมีทางไปข้างหน้า

เกี่ยวกับจุดที่ 4 ข้างต้นมีการรองรับนิพจน์ Matrixใน SymPy และสามารถช่วยได้ที่นี่:

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)

เอาท์พุต:

สำหรับการพัฒนาเพิ่มเติมเกี่ยวกับคุณลักษณะนี้โปรดติดตาม# 18555