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

Generate Taylor series #1298

Merged
merged 17 commits into from
Nov 5, 2024
Merged

Generate Taylor series #1298

merged 17 commits into from
Nov 5, 2024

Conversation

hersle
Copy link
Contributor

@hersle hersle commented Oct 7, 2024

Is something like this suited for Symbolics.jl?

@hersle hersle marked this pull request as draft October 7, 2024 18:55
@codecov-commenter
Copy link

codecov-commenter commented Oct 7, 2024

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 78.04%. Comparing base (3e31a75) to head (7b0546f).
Report is 29 commits behind head on master.

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@             Coverage Diff             @@
##           master    #1298       +/-   ##
===========================================
+ Coverage    6.69%   78.04%   +71.35%     
===========================================
  Files          47       50        +3     
  Lines        4618     4856      +238     
===========================================
+ Hits          309     3790     +3481     
+ Misses       4309     1066     -3243     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@hersle
Copy link
Contributor Author

hersle commented Oct 7, 2024

One problem is that the coefficients come out as floats (I want them to be rationals) because of substitute(..., x => 0). A minimal example:

julia> @variables x
1-element Vector{Num}:
 x

julia> y = expand_derivatives(Differential(x)(sin(x)) / 2)
(1//2)*cos(x)

julia> substitute(y, x => 0)
0.5

Using fold does not help:

julia> substitute(y, x => 0, fold=false)
(1//2)*cos(0)

julia> substitute(y, x => 0, fold=true)
0.5

The issue is that e.g. cos(0) evaluates to the float 1.0, so (1//2) * 1.0 is converted to 0.5 (see #1299). Is there an easy way to fix this?

src/taylor.jl Outdated Show resolved Hide resolved
@ChrisRackauckas
Copy link
Member

This does seem like a good thing for Symbolics.

@shashi do you know how to make substitute not convert to float?

@hersle
Copy link
Contributor Author

hersle commented Oct 8, 2024

One (far from perfect) solution is to rationalize() float coefficients into rational numbers. This seems to work well for the tests, except for e.g. the first irrational term in the series for acos(x) = π/2 + ..., which becomes 122925461//78256779.

@hersle
Copy link
Contributor Author

hersle commented Oct 8, 2024

There is also TaylorSeries.jl, which could perhaps compose with Symbolics.jl.

@hersle hersle force-pushed the taylor branch 4 times, most recently from 0728407 to cfa315b Compare October 10, 2024 11:50
@hersle
Copy link
Contributor Author

hersle commented Oct 10, 2024

I have made quite a hefty rewrite of the perturbation example. My goal has been to significantly shorten it and better display the features of Symbolics.jl, and particularly the power of the new Taylor series functions.

I hope I have not lost the spirit of the old tutorial. Please let me know if you want me to restore some of it.

@hersle hersle marked this pull request as ready for review October 10, 2024 11:50
@hersle
Copy link
Contributor Author

hersle commented Oct 10, 2024

I would appreciate it if someone looks at this :) Suggestions are welcome! Particularly regarding how you think the public Taylor series interface should work, i.e. the current series, taylor and taylor_coeff functions.

cc @karlwessel and #1292 and SciML/ModelingToolkit.jl#3098

@karlwessel
Copy link
Contributor

I love to take a more closer look at this, but not before mid of next week.

@karlwessel
Copy link
Contributor

There is also TaylorSeries.jl, which could perhaps compose with Symbolics.jl.

This is what makes evaluating the usefulness of this PR complicated for me.
The package TaylorSeries and Symbolics + this PR seem to overlap pretty heavily:

  • both implement some notion of a variable,
  • both implement derivatives for basic julia functions,
  • both allow to define Taylor series using this functionality.

What does TaylorSeries provide that wouldn't be easily doable using this PR?

  • probably a lot of ease of use functions like evaluating Taylor series
  • multivariate Taylor series
  • integration of Taylor series

What does Symbolics + this PR provide that wouldn't be easily doable with TaylorSeries?

  • expansion of user defined functions around different variables
  • the whole Symbolics ecosystem

In a perfect World:

  1. should TaylorSeries use Symbolics to implement all of its stuff
  2. should TaylorSeries just work with Symbolics?
  3. should this PR use Symbolics to implement its functionality?

In our world: Is it ok for them to just live happily side by side? If yes: is this really worth adding to Symbolics, or would it be enough to add a tutorial that shows how to expand a function as a Taylor series?

src/taylor.jl Outdated Show resolved Hide resolved
Copy link
Contributor

@karlwessel karlwessel left a comment

Choose a reason for hiding this comment

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

I am mixed about the changes. A lot of the explanations in the text have become much clearer, especially on describing perturbation theory and its advantages (for CAS and in general).
It also does a good job to show of the new implemented features for working with Taylor series.

However, since the previous version had to implement all of the taylor specific features by hand it was easier for me to understand the procedure and adapt it for my own problem. Now if one of the new library methods fails for my own specific problem I wouldn't really know what to do. That of course wouldn't be a problem if the new methods just work for everything.

docs/src/tutorials/perturbation.md Outdated Show resolved Hide resolved
docs/src/tutorials/perturbation.md Show resolved Hide resolved
@karlwessel
Copy link
Contributor

I would suggest to split this PR into multiple steps/stages.

In the first step introduce and implement easy to understand simple versions of the Taylor series methods in the perturbation example, specific to the perturbation example.

In the next step see how those methods can be used or adapted to work for the example on perturbation theory for ODEs in ModelingToolkit.

And last, if those methods have proven to work in the examples and maybe have been used to solve other perturbation problems (multivariate equations, PDEs, field equations) we can use that experience to decide how and where to add those methods to the Symbolics library or its ecosystem.

@hersle
Copy link
Contributor Author

hersle commented Nov 4, 2024

Thanks for the feedback, I agree with many of your points. Maybe splitting the changes according to your 3 incremental stages would be the best approach.

What does Symbolics + this PR provide that wouldn't be easily doable with TaylorSeries?

Ideally, I agree it would be fantastic to compose with TaylorSeries.jl. That should work for series with numerical coefficients (e.g. exp(x) = 1.0 + 1.0*x + ...), but maybe not as well for series with symbolic coefficients, as the tutorial examples? This is the most important concern for Symbolics, in my opinion.

since the previous version had to implement all of the taylor specific features by hand it was easier for me to understand the procedure and adapt it for my own problem.

I can relate to this. But I think if Symbolics is to be a viable CAS, it is more important to have the expected convenience functions so every user does not have to reimplement them. It is also on the wanted feature list (#59).

I must leave this as-is for now. It works and is "complete", but can surely be improved. If I get time, maybe I will get back at it. Anyone is welcome to take over, of course.

@ChrisRackauckas
Copy link
Member

The additional functionality is definitely a yes: yes people can build this functionality from pure Julia but of course that's the case because the library is all Julia. That's no reason to not improve the user experience. That doesn't mean we can't have tutorials of people doing this stuff by hand, but most people shouldn't need to.

Let's get this rebased and tests passing. I think the only thing left is to potentially write out a few more steps in the perturbation tutorial.

@hersle
Copy link
Contributor Author

hersle commented Nov 4, 2024

Alright I will try to do it in the near future.

@hersle
Copy link
Contributor Author

hersle commented Nov 4, 2024

I rebased and incorporated some of @karlwessel's suggestions. Hopefully this reaches a balance point.

I'm not 100% convinced the current series(), taylor(), taylor_coeff(), ... interface is optimal, but hopefully it is a decent starting point. I don't feel strongly about it, as long as it is simple, consistent and convenient, so anyone is welcome to change it.

@ChrisRackauckas ChrisRackauckas merged commit 1305b7e into JuliaSymbolics:master Nov 5, 2024
10 of 12 checks passed
@karlwessel
Copy link
Contributor

Thanks for finalizing this! I wasn't aware this was on the wanted features list.

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.

4 participants