다항식에서 행렬을 대체 할 때의 문제

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으로 바꾸고 손으로 표현식을 입력해야합니까? 이 예에서 다항식에는 3 개의 항만 있지만 실제로는 수십 개의 항 (다변량 다항식)이 있습니다.

답변

1 wsdookadr Jan 12 2021 at 12:40

그래서 나는 질문이 주로 Matrix 다항식 의 개념을 중심으로 돌고 있다고 생각합니다 .

(여기서 P는 다항식이고 A는 행렬입니다)

자유항은 숫자이고 나머지는 행렬 인 나머지는 더할 수 없다는 말이라고 생각합니다. 사실상이 두 유형 사이에 더하기 연산이 정의되어 있지 않습니다.

TypeError : <class'sympy.matrices.immutable.ImmutableDenseMatrix '> 및 <class'sympy.core.numbers.One '>을 추가 할 수 없습니다.

그러나 이것은 특정 행렬에 대한 행렬 다항식을 평가하는 함수를 정의하여 피할 수 있습니다. 여기의 차이는 우리가 사용하고 있다는 점이다 행렬 지수 우리가 제대로 행렬 다항식의 무료 기간 계산, 그래서 는 IS 행렬 필요한 모양을 :a_0 * II=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)

산출:

이 예에서 다항식에는 3 개의 항만 있지만 실제로는 수십 개의 항 (다변량 다항식)이 있습니다.

eval_poly_matrix위 의 함수 는 계수가 0이 아닌 단항식을 추출 하는 .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. 행렬 곱셈 이 비교 환적 이기 때문에 Matrix 다항식 x*y이 다르다는 사실을 처리하십시오 . 분명히 sympy의 폴리 함수는 비 교환 변수를 지원하지 않지만 기호를 정의 할 수 있으며 앞으로 나아갈 방법이있는 것 같습니다.y*x commutative=False

위의 4 번째 지점에 대해 SymPy의 Matrix 표현식 에 대한 지원 이 있으며 여기에서 도움이 될 수 있습니다.

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를 따르십시오 .