首页 > 解决方案 > Python-如何将矩阵与符号和 0 相乘

问题描述

我是 python 的新手,但是有没有办法将矩阵与 0 和符号相乘?例如,见下文:

import sympy as sym
import numpy as np
teams=np.matrix([[1,2],[3,4]])
teams=teams-1
n=4
x,a,b=sym.symbols('x a b')
X=np.empty((n,n), dtype=object)
Y=np.empty((n,n), dtype=object)
Z=np.empty((n,n), dtype=object)
for i in range(n):
    for j in range(n):
            if j==i:
                X[i,j]=x
            elif ([i,j] in teams.tolist()):
                Y[i,j]=a
            elif ([j,i] in teams.tolist()):
                Y[i,j]=a
            else:
                Z[i,j]=b
for i in range(n):
    for j in range(n):
        if X[i,j]==None:
            X[i,j]=0
        if Y[i,j]==None:
            Y[i,j]=0
        if Z[i,j]==None:
            Z[i,j]=0

print(np.matmul(X,Y))

TypeError                                 Traceback (most recent call last)
<ipython-input-189-00b753462a2d> in <module>
      2 print(Y)
      3 print(Z)
----> 4 print(np.matmul(X,Y))

TypeError: ufunc 'matmul' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

我知道它为什么会搞砸,我试图将一个符号乘以一个数字,但我想知道是否有办法让它认识到一个符号乘以 0 只是零,如果被添加到另一个符号应该被忽略。

标签: pythonnumpysympy

解决方案


问题不在于symbolsdtype,而在于 object dtype。 matmul不(或不)使用对象 dtype 数组。快速版本使用BLAS库函数,这些函数仅适用于 C 数字类型 - 浮点数和整数。 np.dot确实有一个较慢的分支,它适用于非数字 dtypes。

在一个isympy会话中:

In [4]: X                                                                       
Out[4]: 
array([[x, 0, 0, 0],
       [0, x, 0, 0],
       [0, 0, x, 0],
       [0, 0, 0, x]], dtype=object)

In [5]: Y                                                                       
Out[5]: 
array([[0, a, 0, 0],
       [a, 0, 0, 0],
       [0, 0, 0, a],
       [0, 0, a, 0]], dtype=object)

In [6]: np.dot(X,Y)                                                             
Out[6]: 
array([[0, a*x, 0, 0],
       [a*x, 0, 0, 0],
       [0, 0, 0, a*x],
       [0, 0, a*x, 0]], dtype=object)

但是,matmul对我有用。我想知道这是不是因为我的 numpy 版本?

In [7]: np.matmul(X,Y)                                                          
Out[7]: 
array([[0, a*x, 0, 0],
       [a*x, 0, 0, 0],
       [0, 0, 0, a*x],
       [0, 0, a*x, 0]], dtype=object)

In [8]: np.__version__                                                          
Out[8]: '1.17.4'

作为一般规则混合sympy并不是numpy一个好主意。 numpy包含的数组symbols必须是对象 dtype。对象 dtype 上的数学取决于将操作委托给方法。结果是命中注定。乘法和加法可能有效(x+x),但np.sin不能,因为x.sin()失败。如果sympy.lambdify你想sympynumpy. 否则,请尝试使用 pure sympy

In [12]: X*X                                                                    
Out[12]: 
array([[x**2, 0, 0, 0],
       [0, x**2, 0, 0],
       [0, 0, x**2, 0],
       [0, 0, 0, x**2]], dtype=object)

In [13]: np.sin(X)                                                              
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
AttributeError: 'Symbol' object has no attribute 'sin'

===

来自 numpy 1.17.0 发行说明

Support of object arrays in matmul¶
It is now possible to use matmul (or the @ operator) with object arrays. For instance, it is now possible to do:

from fractions import Fraction
a = np.array([[Fraction(1, 2), Fraction(1, 3)], [Fraction(1, 3), Fraction(1, 2)]])
b = a @ a

推荐阅读