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

时间:2015-09-29 02:53:48

标签: python sympy

我正在使用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。是否可以使用if (width == 0 && height == 0 && !isFullyWrapContent) {简化纯数字项?

3 个答案:

答案 0 :(得分: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]])

答案 1 :(得分: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

答案 2 :(得分: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的。