SymPy 矩阵参数不可比较
SymPy Matrix argument not comparable
我正在使用 SymPy 执行一些操作并偶然发现了这个:
如果我声明以下矩阵并尝试获取它的 2 范数(最大单值):
from sympy import Matrix
Matrix([[4, 1, 0, 0], [1, 4, 1, 0], [0, 1, 4, 1], [0, 0, 1, 4]]) # declare matrix
print(x.norm(2)) # print it's 2-norm
我得到了预期的结果:
sqrt(9*sqrt(5)/2 + 43/2)
但是,当我声明一个看似等价的矩阵并尝试将其设为 2 范数时,出现错误:
from sympy import Matrix
x = Matrix([[7, -13, -3, -1, 0], [-2, 4, 2, 0, 0], [5, -9, -2, 0, 1]]) # declare matrix
print(x.norm(2)) # print it's 2-norm
错误:
Traceback (most recent call last):
File "main.py", line 29, in <module>
print(x.norm(2))
File "venv/lib/python3.9/site-packages/sympy/matrices/matrices.py", line 1984, in norm
return Max(*self.singular_values())
File "venv/lib/python3.9/site-packages/sympy/functions/elementary/miscellaneous.py", line 391, in __new__
args = frozenset(cls._new_args_filter(args))
File "venv/lib/python3.9/site-packages/sympy/functions/elementary/miscellaneous.py", line 564, in _new_args_filter
raise ValueError("The argument '%s' is not comparable." % arg)
ValueError: The argument 'sqrt(121 + 43127/(3*(1723619 + 2*sqrt(199009527)*I/9)**(1/3)) + (1723619 + 2*sqrt(199009527)*I/9)**(1/3))' is not comparable.
看了源码才知道is not comparable
的意思是一个对象可以计算为实数或者已经是实数了。我不知道如何将该矩阵计算为实数(它是一个矩阵)。
任何人都可以解释为什么我在一个矩阵中出现此错误而在另一个矩阵中却没有?
谢谢!
正如您从回溯中看到的那样,它尝试计算奇异值的最大值:
Max(*self.singular_values())
在你的情况下,你可以通过执行 x.singular_values()
来可视化奇异值(输出很长,所以我不打算在这里粘贴它。
但是,其中一些奇异值是复数,因此无法进行比较。函数 Max
需要实数!例如,您可以执行:
Max(5 + I, 3)
# ValueError: The argument '5 + I' is not comparable.
编辑:
正如奥斯卡在评论中指出的那样,虚部真的很小。因此,我们可以将奇异值转换为数值数据类型,如果虚部低于阈值则丢弃虚部并继续公式:
x = Matrix([[7, -13, -3, -1, 0], [-2, 4, 2, 0, 0], [5, -9, -2, 0, 1]]) # declare matrix
sv = [complex(t) for t in x.singular_values()]
# discard imaginary components if they are lower than a threshold
threshold = 1e-08
sv = [t.real if t.imag < threshold else t for t in sv]
max(sv)
# out: 18.99465957621187
我正在使用 SymPy 执行一些操作并偶然发现了这个:
如果我声明以下矩阵并尝试获取它的 2 范数(最大单值):
from sympy import Matrix
Matrix([[4, 1, 0, 0], [1, 4, 1, 0], [0, 1, 4, 1], [0, 0, 1, 4]]) # declare matrix
print(x.norm(2)) # print it's 2-norm
我得到了预期的结果:
sqrt(9*sqrt(5)/2 + 43/2)
但是,当我声明一个看似等价的矩阵并尝试将其设为 2 范数时,出现错误:
from sympy import Matrix
x = Matrix([[7, -13, -3, -1, 0], [-2, 4, 2, 0, 0], [5, -9, -2, 0, 1]]) # declare matrix
print(x.norm(2)) # print it's 2-norm
错误:
Traceback (most recent call last):
File "main.py", line 29, in <module>
print(x.norm(2))
File "venv/lib/python3.9/site-packages/sympy/matrices/matrices.py", line 1984, in norm
return Max(*self.singular_values())
File "venv/lib/python3.9/site-packages/sympy/functions/elementary/miscellaneous.py", line 391, in __new__
args = frozenset(cls._new_args_filter(args))
File "venv/lib/python3.9/site-packages/sympy/functions/elementary/miscellaneous.py", line 564, in _new_args_filter
raise ValueError("The argument '%s' is not comparable." % arg)
ValueError: The argument 'sqrt(121 + 43127/(3*(1723619 + 2*sqrt(199009527)*I/9)**(1/3)) + (1723619 + 2*sqrt(199009527)*I/9)**(1/3))' is not comparable.
看了源码才知道is not comparable
的意思是一个对象可以计算为实数或者已经是实数了。我不知道如何将该矩阵计算为实数(它是一个矩阵)。
任何人都可以解释为什么我在一个矩阵中出现此错误而在另一个矩阵中却没有?
谢谢!
正如您从回溯中看到的那样,它尝试计算奇异值的最大值:
Max(*self.singular_values())
在你的情况下,你可以通过执行 x.singular_values()
来可视化奇异值(输出很长,所以我不打算在这里粘贴它。
但是,其中一些奇异值是复数,因此无法进行比较。函数 Max
需要实数!例如,您可以执行:
Max(5 + I, 3)
# ValueError: The argument '5 + I' is not comparable.
编辑:
正如奥斯卡在评论中指出的那样,虚部真的很小。因此,我们可以将奇异值转换为数值数据类型,如果虚部低于阈值则丢弃虚部并继续公式:
x = Matrix([[7, -13, -3, -1, 0], [-2, 4, 2, 0, 0], [5, -9, -2, 0, 1]]) # declare matrix
sv = [complex(t) for t in x.singular_values()]
# discard imaginary components if they are lower than a threshold
threshold = 1e-08
sv = [t.real if t.imag < threshold else t for t in sv]
max(sv)
# out: 18.99465957621187