How makes all low values in the symbolic calculation become zero?

一个人想着一个人 提交于 2020-04-07 07:08:20

问题


How can I make all low values in a SymPy expression zero? For example, my result is:

1.0*a1*cos(q1) - 6.12e-17*(a2*sin(q2) + a3*sin(q2 + q3) + a4*sin(q2 + q3 + q4))*sin(q1) + 1.0*(a2*cos(q2) + a3*cos(q2 + q3) + a4*cos(q2 + q3 + q4))*cos(q1)

and I want to change second term (starting with 6.12e-17) to zero.


回答1:


A direct way to do this is to replace such numbers with 0. A naive eq.subs(small, 0) will fail because small that you enter is not likely to be exactly the same as the number. But eq.atoms(Float) will give you the set of such numbers:

>>> eq.xreplace(dict([(n,0) for n in eq.atoms(Float) if abs(n) < 1e-12]))
1.0*a1*cos(q1) + (1.0*a2*cos(q2) + 1.0*a3*cos(q2 + q3) + 1.0*a4*cos(q2 + q3 + q4))*cos(q1)



回答2:


Probably there are much more efficient ways(I am not familiar with that library) but I tried to do with regex. If e- exist in a part of the equation it replaces it to 0(you can remove directly if you want). But to be able to do this, I had to remove to spaces between +- operators inside the parentheses, so I could make a list by splitting from the other +- operators.

import re
result='''1.0*a1*cos(q1) - 6.12e-17*(a2*sin(q2) + a3*sin(q2+q3) 
+ a4*sin(q2+q3+q4))sin(q1) + 1.0(a2*cos(q2) 
+ a3*cos(q2+q3) + a4*cos(q2+q3+q4))*cos(q1)'''
too_small='e-'

mylist=re.split(r"\s+", result)

for i in range(len(mylist)):
    if too_small in mylist[i]:
        mylist[i]='0'

new_result=''.join(mylist)
print(new_result)

And this is the output:

1.0*a1*cos(q1)-0+a3*sin(q2+q3)+a4*sin(q2+q3+q4))sin(q1)+1.0(a2*cos(q2)+a3*cos(q2+q3)+a4*cos(q2+q3+q4))*cos(q1)

As I said, there are probably much better ways than this.




回答3:


What about more details? I guess you want replace part of a symbolic calculation string, Regular expression in Python could be helpful, you can code like this:

In [1]: import re

In [2]: s = '1.0*a1*cos(q1) - 6.12e-17*(a2*sin(q2) + a3*sin(q2 + q3) + ' \
   ...:     'a4*sin(q2 + q3 + q4))sin(q1) + 1.0(a2*cos(q2) + ' \
   ...:     'a3*cos(q2 + q3) + a4*cos(q2 + q3 + q4))*cos(q1)'

In [3]: s = re.sub(r'[+-/*/]\s\S*e-[1-9]\d+\S*\s', '', s)

In [4]: s
Out[4]: '1.0*a1*cos(q1) + a3*sin(q2 + q3) + a4*sin(q2 + q3 + q4))sin(q1) + 1.0(a2*cos(q2) + a3*cos(q2 + q3) + a4*cos(q2 + q3 + q4))*cos(q1)'

First argument of re.sub() function decide what you want to reduce, e-[1-9]\d+ represent a number lower than e-10 which you can modify, I hope it helps.




回答4:


SymPy’s nsimplify function with the rational=True argument converts floats within an expression to rational numbers (within a given tolerance). Something like 6.12e-17 will be converted to 0 if below the threshold. So, in your case:

from sympy import sin, cos, symbols, nsimplify

a1, a2, a3, a4 = symbols("a1, a2, a3, a4")
q1, q2, q3, q4 = symbols("q1, q2, q3, q4")

expr = (
      1.0*a1*cos(q1)
    - 6.12e-17*(a2*sin(q2) + a3*sin(q2 + q3) + a4*sin(q2 + q3 + q4))*sin(q1)
    + 1.0*(a2*cos(q2) + a3*cos(q2 + q3) + a4*cos(q2 + q3 + q4))*cos(q1)
    )

nsimplify(expr,tolerance=1e-10,rational=True)
# a1*cos(q1) + (a2*cos(q2) + a3*cos(q2 + q3) + a4*cos(q2 + q3 + q4))*cos(q1)


来源:https://stackoverflow.com/questions/57916749/how-makes-all-low-values-in-the-symbolic-calculation-become-zero

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!