如何在SymPy中将非常小的数字简化为0?

问题描述 投票:1回答:3

我正在使用python 2.7.10中的sympy 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.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简化纯数字项?

python sympy
3个回答
1
投票

如果您使用的是Matrix(sympy.matrices.dense.MutableDenseMatrix),包括带有sybolic元素的矩阵,则可以使用以下函数完成转换:

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

例如:

from sympy import *

e = .0000001 # change according to your definition of small
x, y, z = symbols('x y z')
mlist = [[0.0, 1.0*cos(z)], [x*y, 1.05000000000000], [0,     6.12323399573677e-17]]
m = Matrix(mlist)
m
Out[4]: 
Matrix([
[0.0,           1.0*cos(z)],
[x*y,                 1.05],
[  0, 6.12323399573677e-17]])

round2zero(m,e)
m
Matrix([
[  0, 1.0*cos(z)],
[x*y,       1.05],
[  0,          0]])

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

0
投票

Sympy的nsimplify函数与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

© www.soinside.com 2019 - 2024. All rights reserved.