9

I ran into the following problem:

I have a sympy matrix of sympy expressions, each cell looking something like the following example, call it ex1:

In: ex1

Out: -mu_0_0 + t*((0.8*mu_0_1 + 2.22044604925031e-16)*Max(0, alpha_0_1_4)**2 + (0.8*mu_1_1 + 2.22044604925031e-16)*Max(0, alpha_0_1_3)**2 + (0.8*mu_3_1 + 2.22044604925031e-16)*Max(0, alpha_0_1_2)**2 + (0.8*mu_6_1 + 2.22044604925031e-16)*Max(0, alpha_0_1_1)**2 + (0.4*mu_10_0 + 0.4*mu_10_1 - 0.4)*Max(0, alpha_0_1_0)**2) + (-t + 1)*(0.498558013279766*mu_0_1 + 0.0238962672572783*mu_10_0 + 0.0238962672572783*mu_10_1 + 0.18596764210715*mu_1_1 + 0.0201673973158616*mu_3_1 + 0.0475144127826656*mu_6_1 - 0.023896267257278) + Max(0, -alpha_0_0_0)**2  

The matrix is later to be lambdified. However, before that, I would like to get rid of the 2.22044604925031e-16 and like floats; these are artifcats from some other part of the code and should be 0.

I would like to clean the expressions in my matrix cells from these, but can't figure out how to.

ex1.round() crashes my python when applied to ex1, and it does not seem to work for simple expression such as

In: sympy.sympify(0.01*t).round(1)  
TypeError: can't convert expression to float

If I try it via N, as

In: sympy.N(eq, n=3)

I get:

RecursionError: maximum recursion depth exceeded

(I am not even sure this would work anyway, as I understand this would just reduce the floats to n significant digits?)

Is there any way to clean these expressions in the way I want?

Thanks in advance!

I will leave the expression structure, in case it is of any help:

sympy.srepr(ex1)  

"Add(Mul(Integer(-1), Symbol('mu_0_0')), Mul(Symbol('t'), Add(Mul(Add(Mul(Float('0.80000000000000004', prec=15), Symbol('mu_0_1')), Float('2.2204460492503131e-16', prec=15)), Pow(Max(Integer(0), Symbol('alpha_0_1_4')), Integer(2))), Mul(Add(Mul(Float('0.80000000000000004', prec=15), Symbol('mu_1_1')), Float('2.2204460492503131e-16', prec=15)), Pow(Max(Integer(0), Symbol('alpha_0_1_3')), Integer(2))), Mul(Add(Mul(Float('0.80000000000000004', prec=15), Symbol('mu_3_1')), Float('2.2204460492503131e-16', prec=15)), Pow(Max(Integer(0), Symbol('alpha_0_1_2')), Integer(2))), Mul(Add(Mul(Float('0.80000000000000004', prec=15), Symbol('mu_6_1')), Float('2.2204460492503131e-16', prec=15)), Pow(Max(Integer(0), Symbol('alpha_0_1_1')), Integer(2))), Mul(Add(Mul(Float('0.40000000000000002', prec=15), Symbol('mu_10_0')), Mul(Float('0.40000000000000002', prec=15), Symbol('mu_10_1')), Float('-0.3999999999999998', prec=15)), Pow(Max(Integer(0), Symbol('alpha_0_1_0')), Integer(2))))), Mul(Add(Mul(Integer(-1), Symbol('t')), Integer(1)), Add(Mul(Float('0.49855801327976634', prec=15), Symbol('mu_0_1')), Mul(Float('0.02389626725727826', prec=15), Symbol('mu_10_0')), Mul(Float('0.02389626725727826', prec=15), Symbol('mu_10_1')), Mul(Float('0.18596764210714989', prec=15), Symbol('mu_1_1')), Mul(Float('0.020167397315861646', prec=15), Symbol('mu_3_1')), Mul(Float('0.047514412782665633', prec=15), Symbol('mu_6_1')), Float('-0.023896267257278034', prec=15))), Pow(Max(Integer(0), Mul(Integer(-1), Symbol('alpha_0_0_0'))), Integer(2)))"
DavidP
  • 105
  • 3
  • 12

1 Answers1

17

One can traverse the expression tree with preorder_traversal, and replace floats by their rounded values. In the example below, the floats are rounded to 1 digit after the decimal dot.

from sympy import *
x, y = symbols('x y')
ex1 = 3.1415*(2.00003*x + 3e-12) + x*(y + 0.0003*x - 4e-13)**2 + 1.234567
ex2 = ex1
for a in preorder_traversal(ex1):
    if isinstance(a, Float):
        ex2 = ex2.subs(a, round(a, 1))
print(ex1)  # original
print(ex2)  # rounded

Output (with original expression for comparison):

x*(0.0003*x + y - 4.0e-13)**2 + 6.283094245*x + 1.23456700000942
x*y**2 + 6.3*x + 1.2
  • Works like a charm, and also allows me great flexibility in what I can check for/replace with -- thanks a bunch! – DavidP May 05 '17 at 15:53