Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle sympy integers #1202

Merged
merged 5 commits into from
Aug 6, 2020
Merged

Handle sympy integers #1202

merged 5 commits into from
Aug 6, 2020

Conversation

mstimberg
Copy link
Member

As noted in #812 , we always converted integers to float whenever we use sympy (most importantly for differential equations). Back in the days we could not fix it because it led to problems with floor division. This has been fixed in sympy quite a while ago, in sympy 1.1 (we already require sympy >=1.2), so this is no longer an issue. With this PR, we take care to represent integers as integers in sympy, which fixes #1199 .

Note that there are still places where we convert integers to floats that are unrelated to sympy. For an expression x + 1, where x is a floating point variable (and therefore the whole expression is floating point), we try to rearrange things during the optimization step (e.g. to replace x + 0 by x), which leads to the expression being converted to x + 1.0. Changing this would be quite some work, but I don't think it is necessary.

@mstimberg mstimberg requested a review from thesamovar July 6, 2020 09:22
Copy link
Member

@thesamovar thesamovar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks fine, but I'm a bit confused about some of the changes to the tests. Maybe you can comment on that before we merge this?

__k_4_v = -dt*(__k_3_v + v)/tau
_v = 0.166666666666667*__k_1_v + 0.333333333333333*__k_2_v + 0.333333333333333*__k_3_v + 0.166666666666667*__k_4_v + v
_v = __k_1_v/6 + __k_2_v/3 + __k_3_v/3 + __k_4_v/6 + v
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This I'm not sure about. If we know that x is a float, then we can safely convert x/2 to 0.5*x and this will be faster. Probably the compiler does it already if -funsafe-math-optimizations is on, but would be interesting to know if there are cases where the new version would cause it to run slower. What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not really about optimized code here: when we define the RK4 state updater, we write things like k_3 = dt*f(x+k_2/2,t+dt/2) – before, sympy converted this to floating point numbers and to multiplications along the way. I don't think this is for sympy to do where we are still at the level of mathematics. Optimizing the generated code is a different question, I don't think we currently turn divisions into multiplications but we could (even though I doubt it makes a measurable difference). We can run our benchmark suite after merging, but I'm not really worried about this. I'm more worried that results change slightly due to the numerical difference, this might be worth investigating further.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I agree that sympy shouldn't be doing that for us because it doesn't know that it might be relevant that it's an integer.

@@ -33,7 +33,7 @@ def get_conditionally_linear_system(eqs, variables=None):
--------
>>> from brian2 import Equations
>>> eqs = Equations("""
... dv/dt = (-v + w**2) / tau : 1
... dv/dt = (-v + w**2.0) / tau : 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this have performance implications?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that it is just a change in the doctest, I'm quite sure it does not ;)
But in general it is the same issue as above: before w**2 and w**2.0 where both converted to w**2.0 when we handed them to sympy – now they are given to sympy as either an integer or a float.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK!

('x = 1.0/x', 'x = 1.0/x'),
('x = 1.0', 'x = 1.0'),
('x = 2.0*(x + 1.0)', 'x = 2.0*(x + 1.0)'),
('x = clip(x + y, 0.0, inf)', 'x = clip(x + y, 0.0, inf)'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, I'm confused: why were these integers before and now floats?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, this is confusing... The explication is: we are using sympy behind the scenes in this test to compare the optimized expressions. This is to avoid that x + 1 is considered as different from 1 + x, for example.

Here we are testing the codegen optimization and during this process we do sometimes replace integers by floats as a side-effect (e.g. x + 1 will turn into x + 1.0 if x is a float). This is fine and nothing to worry about, but it made the test fail due to sympy making a difference between the two expressions now. When we are testing that x = 1/x does not change during optimization, we are not caring about whether the 1 continues to be an integer – instead of making the test comparison more complicated, I simply turned all values into floats...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh I see. OK, in that case I'm all good! Happy to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

IndexError for integers in generated equations code
2 participants