Simplification of expression with symbols only or with mixed values and symbols

38 views
Skip to first unread message

Mikhael Myara

unread,
Jul 26, 2020, 4:56:45 PM7/26/20
to sympy
Something weird, I would like to understand why.

After some computations I reach a quite complex expression :

Capture d’écran 2020-07-26 à 22.49.18.png



From that I run the following code :

import sympy as sp

H=-(-CB*Ve*s*(-CA*s - 1/RA)**2/(RB*(CB*s + 1/RB)*(CA*s - (-CA*s - 1/RA)**2/(CA*s - CB**2*s**2/(CB*s + 1/RB) + CB*s + 1/RA) + 2/RA)*(CA*s - CB**2*s**2/(CB*s + 1/RB) + CB*s + 1/RA)) - CB*Ve*s/(RB*(CB*s + 1/RB)))/(Ve*(CA*s - CB**2*s**2/(CB*s + 1/RB) + CB*s + 1/RA))

H1=H.subs({RB:1e3,CA:1e-6})
display(H1)
H1.simplify()
display(H1)

H2 = H.simplify()
display(H2)
H3=H2.subs({RB:1e3,CA:1e-6})
H3.simplify()
display(H3)


And I obtain what follows. I am surprized that inserting values instead of some symbols disables sympy simplification. In some more complex cases, the computation times required for simplification are huge and lead to non simplified expressions.


Any idea why ?


  Best regards,

    Mike

Capture d’écran 2020-07-26 à 22.54.31.png



Oscar Benjamin

unread,
Jul 30, 2020, 7:43:18 PM7/30/20
to sympy
Have you tried using exact Rational values instead of floats? For example 1e-6 could be Rational(1, 10**6) or S(1)/10**6. It is best to avoid using floats if possible.

Also simplify is not an in-place method so you need to use:
   H3 = H3.simplify()
rather than
   H3.simplify()

-- 
Oscar

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/5622efd3-9718-4d8b-b5cb-373235ab7d42o%40googlegroups.com.

Mikhael Myara

unread,
Jul 31, 2020, 12:12:45 AM7/31/20
to sympy
Thanks for your answer.
However : this was a simplified example in a larger context. The values can be arbitrary (for example generated by numerical random number generator) and so the use of rationnal is not practical ...
I knew about the fact that simplify is not a in-place method, the last line of my previous code was a mistake (however it did not change the result displayed for this time). Sorry about that.
Thanks again,
   Mike
To unsubscribe from this group and stop receiving emails from it, send an email to sy...@googlegroups.com.

Oscar Benjamin

unread,
Jul 31, 2020, 10:52:23 AM7/31/20
to sympy
On Sun, 26 Jul 2020 at 21:56, Mikhael Myara
<mikhae...@umontpellier.fr> wrote:
>
> And I obtain what follows. I am surprized that inserting values instead of some symbols disables sympy simplification. In some more complex cases, the computation times required for simplification are huge and lead to non simplified expressions.

I think that inserting Float rather than Symbol or Rational can lead
to significant problems for some polynomial type simplifications such
as cancellation of factors. The long computation times might be the
result of converting Float to Rational somewhere which can sometimes
lead to very polynomials with high order or large coefficients. It's
hard to investigate that without self-contained code demonstrating the
problem though.

Do you have a reason to think that expression can be simplified much?
The main thing I notice is that it has repeating subexpressions so
something like cse might be useful:
https://docs.sympy.org/latest/modules/rewriting.html#common-subexpression-detection-and-collection

Oscar

Mikhael Myara

unread,
Jul 31, 2020, 10:59:00 AM7/31/20
to sympy
Perhaps my example was not clear enough. I start with a fully symbolic expression. Then, I try two things :
- ask a simplify on the fully symbolic expression, that works well,
- replace  some symbols in the initial expression and then simplify.

The first step shows that a simplified expression exists, and replacing by values  may not change this fact (it can lead to an even more simplified expresssion isn'nt it ?).

I do not understand why Sympy cannot simplify at all the initial expression when symbols are replaced by values, whereas we know that a simplified expresssion exists as Sympy itself found it from the fully symbolic version.

David Bailey

unread,
Jul 31, 2020, 12:21:22 PM7/31/20
to sy...@googlegroups.com
On 31/07/2020 15:59, Mikhael Myara wrote:
Perhaps my example was not clear enough. I start with a fully symbolic expression. Then, I try two things :
- ask a simplify on the fully symbolic expression, that works well,
- replace  some symbols in the initial expression and then simplify.

The first step shows that a simplified expression exists, and replacing by values  may not change this fact (it can lead to an even more simplified expresssion isn'nt it ?).

I do not understand why Sympy cannot simplify at all the initial expression when symbols are replaced by values, whereas we know that a simplified expresssion exists as Sympy itself found it from the fully symbolic version.

My guess would be that due to rounding errors, when the floating point numbers get combined - added or subtracted etc. those rounding errors make what would be exact matches become inexact. For example A-B+B might be slightly different from A. Put another way, floating point numbers don't (quite) obey the laws of arithmetic!

I would definitely advise that you work with symbols and integers until you are ready to substitute floating point numbers.

I can't quite see why you would want to substitute and then simplify.

David

Mikhael Myara

unread,
Jul 31, 2020, 12:26:46 PM7/31/20
to sympy
Thanks for your answer.

I don’t do it « for sport » ;-) My example is a reduced example coming from a practical situation I encountered. Here it is :
I developed a small software that solves the voltages and currents of an electronic circuit described by means of a standard format (« netlist »). This file is parsed, equations are solved. In this netlist file, the values of the components are given. I imagined that I could mix symbolic and numerical values in the description of the circuit (for example we want to study de variations of a single component, not of all), and it seems to be a bad idea because mixed expressions seem to be really difficult to handle for Sympy. So I will have to make 100% symbolic treatment and then only replace the values of the components. It was to explore the possibilities for my students : this kind of question will help me giving to them good orientations during classroom work.

Thanks again,
   Mike

Oscar Benjamin

unread,
Jul 31, 2020, 2:46:08 PM7/31/20
to sympy
On Fri, 31 Jul 2020 at 17:26, Mikhael Myara
<mikhae...@umontpellier.fr> wrote:
>
> Thanks for your answer.
>
> I don’t do it « for sport » ;-) My example is a reduced example coming from a practical situation I encountered.

I understand that you have reduced this but it is a lot better if the
reduction is self-contained so that others can literally copy-paste
the code to test what is happening with an expression that
demonstrates the issue. I could probably tell you exactly what the
problem is in a given example if you provided minimal code for that
example.

> Here it is :
> I developed a small software that solves the voltages and currents of an electronic circuit described by means of a standard format (« netlist »). This file is parsed, equations are solved. In this netlist file, the values of the components are given.

How exactly are they given in the file (e.g. to how many digits)?

If the file has something like 0.12 then you can read that in directly
as Rational('0.12') rather than converting the string to a float. Then
you will have an object that represents the value from the file
exactly with no rounding error. Alternatively you can use nsimplify to
convert the floats to an approximate rational representation (direct
string to Rational is better though).

> I imagined that I could mix symbolic and numerical values in the description of the circuit (for example we want to study de variations of a single component, not of all), and it seems to be a bad idea because mixed expressions seem to be really difficult to handle for Sympy.

Generally speaking simplification will work better with numbers rather
than symbols. However this is only true if you give numbers in exact
form. When you pass a float to sympy it will be treated as an
inherently imprecise object. As a result many simplifications will be
refused and also any arithmetic will be computed in floating point.
The kind of simplification needed here is most likely factorisation
and cancellation of polynomials which is poorly conditioned in
floating point.

> So I will have to make 100% symbolic treatment and then only replace the values of the components. It was to explore the possibilities for my ? students : this kind of question will help me giving to them good orientations during classroom work.

If the class work involves using sympy then good orientation would be
to avoid the use of floats in symbolic computation.

--
Oscar

Aaron Meurer

unread,
Jul 31, 2020, 3:51:58 PM7/31/20
to sympy
If you compare H.factor() and H1.factor(), you will see that there are
factors in the numerator and denominator that should cancel out. The
issue is that SymPy has issues doing polynomial division with floating
point coefficients. Due to their inexact nature, SymPy has to guess if
a polynomial expression should cancel or not when they are present,
and the logic for doing this isn't as good as it should be. With
rational coefficients, this problem doesn't exist because the
arithmetic is all exact.

To be clear, I do think SymPy should be able to do a better job here,
but this isn't an easy problem to solve.

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAHVvXxSYoquYGqOCdavwGnafPEb%3DnqWU-L8fK%3DYkYKSs8UR%3DrA%40mail.gmail.com.

Mikhael Myara

unread,
Jul 31, 2020, 4:06:11 PM7/31/20
to sympy


Le vendredi 31 juillet 2020 20:46:08 UTC+2, Oscar a écrit :
On Fri, 31 Jul 2020 at 17:26, Mikhael Myara
<mikhae...@umontpellier.fr> wrote:
>
> Thanks for your answer.
>
> I don’t do it « for sport » ;-) My example is a reduced example coming from a practical situation I encountered.

I understand that you have reduced this but it is a lot better if the
reduction is self-contained so that others can literally copy-paste
the code to test what is happening with an expression that
demonstrates the issue. I could probably tell you exactly what the
problem is in a given example if you provided minimal code for that
example.

That's what I did in my first post + screen copies :
import sympy as sp

H=-(-CB*Ve*s*(-CA*- 1/RA)**2/(RB*(CB*+ 1/RB)*(CA*- (-CA*- 1/RA)**2/(CA*- CB**2*s**2/(CB*+ 1/RB) + CB*+ 1/RA) + 2/RA)*(CA*- CB**2*s**2/(CB*+ 1/RB) + CB*+ 1/RA)) - CB*Ve*s/(RB*(CB*+ 1/RB)))/(Ve*(CA*- CB**2*s**2/(CB*+ 1/RB) + CB*+ 1/RA))

H1=H.subs({RB:1e3,CA:1e-6})
display(H1)
H1.simplify()
display(H1)

H2 = H.simplify()
display(H2)
H3=H2.subs({RB:1e3,CA:1e-6})
H3=H3.simplify()
display(H3)



 
> Here it is :
> I developed a small software that solves the voltages and currents of an electronic circuit described by means of a standard format (« netlist »). This file is parsed, equations are solved. In this netlist file, the values of the components are given.

How exactly are they given in the file (e.g. to how many digits)?

If the file has something like 0.12 then you can read that in directly
as Rational('0.12') rather than converting the string to a float. Then
you will have an object that represents the value from the file
exactly with no rounding error. Alternatively you can use nsimplify to
convert the floats to an approximate rational representation (direct
string to Rational is better though).


Values can change a lot, from 1é-10 to 1e10 typically. In most cases 2 to 3 significant numbers, but can be much more.

 

> I imagined that I could mix symbolic and numerical values in the description of the circuit (for example we want to study de variations of a single component, not of all), and it seems to be a bad idea because mixed expressions seem to be really difficult to handle for Sympy.

Generally speaking simplification will work better with numbers rather
than symbols. However this is only true if you give numbers in exact
form. When you pass a float to sympy it will be treated as an
inherently imprecise object. As a result many simplifications will be
refused and also any arithmetic will be computed in floating point.
The kind of simplification needed here is most likely factorisation
and cancellation of polynomials which is poorly conditioned in
floating point.


ok.
 

> So I will have to make 100% symbolic treatment and then only replace the values of the components. It was to explore the possibilities for my ? students : this kind of question will help me giving to them good orientations during classroom work.

If the class work involves using sympy then good orientation would be
to avoid the use of floats in symbolic computation.

Indeed.
 

--
Oscar

Mikhael Myara

unread,
Jul 31, 2020, 4:07:53 PM7/31/20
to sympy
That's what I guess too. I used the symbolic math toolbox of Matlab in a recent past and I did not notice this behavior. But perhaps I do not remember very well, I am not sure.

Thanks for your answer Aaron.
> To unsubscribe from this group and stop receiving emails from it, send an email to sy...@googlegroups.com.

Oscar Benjamin

unread,
Jul 31, 2020, 5:06:01 PM7/31/20
to sympy
On Fri, 31 Jul 2020 at 21:06, Mikhael Myara
<mikhae...@umontpellier.fr> wrote:
>
> Le vendredi 31 juillet 2020 20:46:08 UTC+2, Oscar a écrit :
>>
>> On Fri, 31 Jul 2020 at 17:26, Mikhael Myara
>> <mikhae...@umontpellier.fr> wrote:
>> >
>> > Thanks for your answer.
>> >
>> > I don’t do it « for sport » ;-) My example is a reduced example coming from a practical situation I encountered.
>>
>> I understand that you have reduced this but it is a lot better if the
>> reduction is self-contained so that others can literally copy-paste
>> the code to test what is happening with an expression that
>> demonstrates the issue. I could probably tell you exactly what the
>> problem is in a given example if you provided minimal code for that
>> example.
>>
> That's what I did in my first post + screen copies :
>>
>> import sympy as sp
>>
>> H=-(-CB*Ve*s*(-CA*s - 1/RA)**2/(RB*(CB*s + 1/RB)*(CA*s - (-CA*s - 1/RA)**2/(CA*s - CB**2*s**2/(CB*s + 1/RB) + CB*s + 1/RA) + 2/RA)*(CA*s - CB**2*s**2/(CB*s + 1/RB) + CB*s + 1/RA)) - CB*Ve*s/(RB*(CB*s + 1/RB)))/(Ve*(CA*s - CB**2*s**2/(CB*s + 1/RB) + CB*s + 1/RA))

Have you tried copy-pasting that? I get this:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'CB' is not defined

Of course I'm being pedantic because I can guess that all of those are
supposed to be symbols but it takes some time for me to figure out
what symbols they are and write the small piece of code that defines
them (presumably that's what Aaron did). More importantly there are
multiple ways to define a symbol (real, positive, ...) and some
simplifications depend on that so even if I do fill in the missing
code then I won't know if I'm seeing the same behaviour as you.

>> > I developed a small software that solves the voltages and currents of an electronic circuit described by means of a standard format (« netlist »). This file is parsed, equations are solved. In this netlist file, the values of the components are given.
>>
>> How exactly are they given in the file (e.g. to how many digits)?
>>
>> If the file has something like 0.12 then you can read that in directly
>> as Rational('0.12') rather than converting the string to a float. Then
>> you will have an object that represents the value from the file
>> exactly with no rounding error. Alternatively you can use nsimplify to
>> convert the floats to an approximate rational representation (direct
>> string to Rational is better though).
>
> Values can change a lot, from 1é-10 to 1e10 typically. In most cases 2 to 3 significant numbers, but can be much more.

It sounds like these would be fine to parse directly as Rational when
reading the file:

>>> from sympy import *
>>> Rational('1e-10')
1/10000000000
>>> Rational('0.112345e-10')
22469/2000000000000000

If you want to display the result with decimal dot notation then you
can convert the Rationals in any expression to Float at the end for
printing using the nfloat function:

>>> nfloat(_)
1.12345000000000e-11


--
Oscar

Mikhael Myara

unread,
Aug 1, 2020, 2:44:30 AM8/1/20
to sympy
ok I forgot variables declaration ...
Reply all
Reply to author
Forward
0 new messages