Python 如何将Symphy中的非常小的数字简化为0?
我正在用Python2.7.10中的Symphy 0.7.6进行一些矩阵计算。比如说,Python 如何将Symphy中的非常小的数字简化为0?,python,sympy,Python,Sympy,我正在用Python2.7.10中的Symphy 0.7.6进行一些矩阵计算。比如说, M = [cos(q1), -6.12323399573677e-17*sin(q1), -1.0*sin(q1), 150*sin(q1)] [sin(q1), 6.12323399573677e-17*cos(q1), 1.0*cos(q1), 150*sin(q1)] [ 0, -1.0, 6.123233
M =
[cos(q1), -6.12323399573677e-17*sin(q1), -1.0*sin(q1), 150*sin(q1)]
[sin(q1), 6.12323399573677e-17*cos(q1), 1.0*cos(q1), 150*sin(q1)]
[ 0, -1.0, 6.12323399573677e-17, 445]
[ 0, 0, 0, 1]
然后我将simplify
应用于M
,结果是:
M =
[cos(q1), 0, -1.0*sin(q1), 150*sin(q1)]
[sin(q1), 0, 1.0*cos(q1), 150*sin(q1)]
[ 0, -1.0, 6.12323399573677e-17, 445]
[ 0, 0, 0, 1]
很明显,-6.12323399573677e-17*sin(q1)
被简化为0
,但6.12323399573677e-17
不是。是否可以使用simplify
简化纯数字项?如果使用矩阵(sympy.Matrix.dense.MutableDenseMatrix),包括带有合成元素的矩阵,则可以使用以下函数进行转换:
def round2zero(m, e):
for i in range(m.shape[0]):
for j in range(m.shape[1]):
if (isinstance(m[i,j], Float) and m[i,j] < e):
m[i,j] = 0
如果您使用的是矩阵(sympy.Matrix.dense.MutableDenseMatrix),包括带有合成元素的矩阵,则可以使用以下函数进行转换:
def round2zero(m, e):
for i in range(m.shape[0]):
for j in range(m.shape[1]):
if (isinstance(m[i,j], Float) and m[i,j] < e):
m[i,j] = 0
一些模糊可以帮助检测更多可设置为零的值:
import sympy
import random
def fuzz_simplify(matrix, min=-1.0, max=1.0, iterations=1000, tolerance=0.005):
m = sympy.Matrix(matrix)
free_sym = range(len(J.free_symbols))
f = sympy.lambdify(m.free_symbols,m)
sum = f(*[0 for i in free_sym])
for i in range(0, iterations):
rand_params = [random.uniform(min,max) for i in free_sym]
sum += f(*rand_params)
for i in range(0, J.shape[0]):
for j in range(0, J.shape[1]):
if sum[i,j] < tolerance:
m[i,j] *= 0
return m
导入sympy
随机输入
def fuzz_simplify(矩阵,最小值=-1.0,最大值=1.0,迭代次数=1000,公差=0.005):
m=共矩阵(矩阵)
自由符号=范围(len(J.自由符号))
f=符号lambdify(m.free_符号,m)
总和=f(*[0表示自由符号中的i])
对于范围内的i(0,迭代次数):
rand_params=[自由符号中i的随机均匀(最小值、最大值)]
总和+=f(*rand_参数)
对于范围(0,J.shape[0])中的i:
对于范围(0,j.shape[1])内的j:
如果总和[i,j]<公差:
m[i,j]*=0
返回m
一些模糊化可以帮助检测更多可以设置为零的值:
import sympy
import random
def fuzz_simplify(matrix, min=-1.0, max=1.0, iterations=1000, tolerance=0.005):
m = sympy.Matrix(matrix)
free_sym = range(len(J.free_symbols))
f = sympy.lambdify(m.free_symbols,m)
sum = f(*[0 for i in free_sym])
for i in range(0, iterations):
rand_params = [random.uniform(min,max) for i in free_sym]
sum += f(*rand_params)
for i in range(0, J.shape[0]):
for j in range(0, J.shape[1]):
if sum[i,j] < tolerance:
m[i,j] *= 0
return m
导入sympy
随机输入
def fuzz_simplify(矩阵,最小值=-1.0,最大值=1.0,迭代次数=1000,公差=0.005):
m=共矩阵(矩阵)
自由符号=范围(len(J.自由符号))
f=符号lambdify(m.free_符号,m)
总和=f(*[0表示自由符号中的i])
对于范围内的i(0,迭代次数):
rand_params=[自由符号中i的随机均匀(最小值、最大值)]
总和+=f(*rand_参数)
对于范围(0,J.shape[0])中的i:
对于范围(0,j.shape[1])内的j:
如果总和[i,j]<公差:
m[i,j]*=0
返回m
Symphy的n使用rational=True
参数将表达式中的浮点数转换为有理数(在给定公差范围内)。如果低于阈值,则类似于6.12323399573677e-17的内容将转换为0。因此,在你的情况下:
from sympy import Symbol, Matrix, sin, cos, nsimplify
q1 = Symbol("q1")
M = Matrix([
[cos(q1), -6.12323e-17*sin(q1), 1.0*sin(q1), 150*sin(q1)],
[sin(q1), 6.12323e-17*cos(q1), 1.0*cos(q1), 150*sin(q1)],
[ 0, -1.0, 6.123233e-17, 445],
[ 0, 0, 0, 1],
])
nsimplify(M,tolerance=1e-10,rational=True)
# Matrix([
# [cos(q1), 0, -sin(q1), 150*sin(q1)],
# [sin(q1), 0, cos(q1), 150*sin(q1)],
# [ 0, -1, 0, 445],
# [ 0, 0, 0, 1]])
请注意,这也是如何将-1.0
转换为1Sympy的n使用rational=True
参数将表达式中的浮点数转换为有理数(在给定公差内)的。如果低于阈值,则类似于6.12323399573677e-17的内容将转换为0。因此,在你的情况下:
from sympy import Symbol, Matrix, sin, cos, nsimplify
q1 = Symbol("q1")
M = Matrix([
[cos(q1), -6.12323e-17*sin(q1), 1.0*sin(q1), 150*sin(q1)],
[sin(q1), 6.12323e-17*cos(q1), 1.0*cos(q1), 150*sin(q1)],
[ 0, -1.0, 6.123233e-17, 445],
[ 0, 0, 0, 1],
])
nsimplify(M,tolerance=1e-10,rational=True)
# Matrix([
# [cos(q1), 0, -sin(q1), 150*sin(q1)],
# [sin(q1), 0, cos(q1), 150*sin(q1)],
# [ 0, -1, 0, 445],
# [ 0, 0, 0, 1]])
请注意,这也是如何将-1.0
转换为1
的。您有完整的scipy堆栈还是只有sympy?我有scipy 0.13.0b1请注意,在当前版本的sympy中,像-6.12323399573677e-17*sin(q1)
这样的表达式不再简化为0
(这是我希望它的行为方式)。你有完整的scipy堆栈还是只有sympy?我有scipy 0.13.0b1请注意,像-6.12323399573677e-17*sin(q1)
这样的表达式在当前版本的sympy中不再简化为0
(这是我希望它的行为)。非常感谢你的回复。然而,np.abs()不能应用于辛矩阵中的符号项。它返回TypeError:无法确定Abs的真值(cos(q1))<0.0001。我原以为这个问题会有简单的解决办法,但似乎没有。我必须仔细检查每一项,并检查它是否是数字。非常感谢您的回复。然而,np.abs()不能应用于辛矩阵中的符号项。它返回TypeError:无法确定Abs的真值(cos(q1))<0.0001。我原以为这个问题会有简单的解决办法,但似乎没有。我必须检查每一项,看它是否是数字。