-
-
Notifications
You must be signed in to change notification settings - Fork 65
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
Predictor Corrector method #53
Conversation
Added PCEuler as a type. alg_order and alg_compatible has been set. Has not set any other property - this may need to change.
The code has been refactored from basic_method_caches to the new file cache_types.jl. Code passed the default tests.
It is a singleton object since there are no static constants for this algorithm. Plan is to first focus on getting the ConstantCache version working, before creating the more optimized Cache version.
Now it's fields contains the bbprime functions. The optional arguments of theta and eta are set to 0.5 by default.
Code current runs for not in place problems. It has been checked to agree with EM. Careful testing of the deviation from the analytics is the next step - to check for higher order bugs.
Both is in place and not in place versions have been implemented. Test code is in test/predcorr_test.jl. This current version of script includes all the plotting and the timing. The next commit which will remove these plotting and timing features for brievity and runspeed. In terms of speed, here are some output from the test script. EM in place : 1.665ms (21771 allocations: 2.01 MiB) RKMil in place : 1.881ms (23776 allocations: 2.10 MiB) PC not in place: 2.626ms (40673 allocations: 3.44 MiB) PC in place : 1.942ms (24271 allocations: 2.16 MiB) The convergence test shows that both the PC has order 1 scaling in practice. In fact, the overall offset point is also lower for PC. At dt=1/2^10 RKMil : 6.02e-3 PC : 1.44e-3
The testing code has now been incoorporated into test/runtest.jl . Due to some conflicts in the use of f and g, the test script for predictor correcter now uses f_nondiag, g_nondiag. Pkg.test on StochasticDiffEq passed. A pull request will be submitted with this commit.
src/algorithms.jl
Outdated
struct PCEuler{T<:Real} <: StochasticDiffEqAlgorithm | ||
theta::T | ||
eta::T | ||
bbprime::Function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parameterize this for stability purposes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on this a little more? Would you like the PCEuler to be parametrized by the type of the function bbprime?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Julia, every function is a different type and Function
is just an abstract type. This allows specialization on functions and then allows things like inlining. If you ::Function
in a type, then it just knows it's a <:Function
and cannot optimize directly on it. So yup, just make that ::F
and a free-roaming F
parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, will make the change.
src/algorithms.jl
Outdated
Reference: Stochastics and Dynamics, Vol. 8, No. 3 (2008) 561–581 | ||
Note that the original paper has a typo in the definition of bbprime... | ||
""" | ||
# TODO: Check if this can be implemented with @pure. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't need @pure
. It'll infer without it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks - I will remove the comment.
src/perform_step/predcorr.jl
Outdated
end | ||
|
||
f_n = f(uprev,p,t) | ||
ubar = @muladd uprev + dt*f_n + gdW_n |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@muladd
on the function makes everything inside @muladd
, so these aren't needed (there are probably some other functions in this library that need cleaning for that)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome - I did note that adding this did not change the speed. Will remove them.
src/perform_step/predcorr.jl
Outdated
gdW_np1 = g(ubar,p,tnp1).*dW | ||
end | ||
|
||
u .= @muladd uprev + (theta*dt)*fbar_np1 + ((1-theta)*dt)*fbar_n + eta*gdW_np1 + (1-eta)*gdW_n |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't want to .=
for numbers and static arrays. It'll work but be slower.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I will copy what you did for EM then.
test/predcorr_tests.jl
Outdated
@@ -0,0 +1,89 @@ | |||
using StochasticDiffEq, DiffEqProblemLibrary, DiffEqDevTools, Base.Test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just rename this file as nondiagonal_tests.jl
: I assume other algorithms will get added to it later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
Looks great! Just a few minor changes and I'll merge. I'm happily surprised it does that much better on this problem: that's a very big improvement! I wonder if it's order 1 on commutative noise problems or something like that: that could make sense. |
src/algorithms.jl
Outdated
Note that the original paper has a typo in the definition of bbprime... | ||
""" | ||
# TODO: Check if this can be implemented with @pure. | ||
PCEuler(bbprime::Function; theta::T=1/2, eta::T=1/2) where {T<:Real} = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't ::Function
in a type signature. It has a non-intuitive anti-specialization behavior, but also not all functions <:Function
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, I have been doing that for a while now (in code I write), thanks for the tip! Will change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In personal codes it's fine. In package codes:
struct MyF end
(::MyF)(t) = 2t
f = MyF()
f(t)
works but f
is not <:Function
. You run into these weird cases the more usage things get. But if you don't do silly things yourself, you're safe 👍 (except for the non-specialization thing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah that reminds me that I saw you did something like that to define the analytic solution to f. Ok will remove the ::Function in the type signature.
Codecov Report
@@ Coverage Diff @@
## master #53 +/- ##
=========================================
Coverage ? 76.98%
=========================================
Files ? 32
Lines ? 3389
Branches ? 0
=========================================
Hits ? 2609
Misses ? 780
Partials ? 0
Continue to review full report at Codecov.
|
Just noticed |
Good stuff, thanks. After seeing that from RKMil, I wonder how much of that is from the RK handling of the derivative handling. Would you mind doing a PR to do |
This needs to get added to the docs page http://docs.juliadiffeq.org/latest/solvers/sde_solve.html . It should probably be recommended when http://docs.juliadiffeq.org/latest/features/performance_overloads.html but that should wait on the change to |
Hi Chris - I would like to do the ggprime implementation of Milstein. The issue is that the one in the textbook does not have implicit noise and neither do any papers explicitly construct this. I am a physicist so I cant really do the proofs for these methods. Perhaps, you want to have a stab at the proof? Once I have the formula, I can do a PR for the method. |
What do you mean by implicit noise? This shouldn't have any implicit terms. |
Ah I see. Sure that should be easy to code up. But currently I am kind of rushing to prepare for the APS march meeting. Perhaps we could discuss this further when we meet in person next month? I am thinking of working on the Wiktorsson approximations and creating a better interface for that stuff through NoiseProcess. Once that is done, perhaps we can multiple dispatch on the type of problem (commutative, diagonal, etc...). This way we do not need to define RKMIlCommute, RKMil etc. What do you think? |
Yeah, share your idea when you can. As always, there's no rush. Could you open an issue to discuss this? I'm very curious about your idea here. I want to do something for this, and we should have a more constrained version of jumps that allow for these kinds of schemes from Platen. |
BTW, schemes are usually drift-implicit because the inverse of the normal has infinite moments making it hard to prove convergence. There's things like truncated schemes though to get around this. |
Sure I will open an issue on the NoiseProcess stuff. Thanks for explaining why the diffusion-implicit is hard. Interesting for the predictor-corrector, I numerically found that eta=0.5 is critical for getting that order 1 scaling. Perhaps its an interesting research direction to investigate whether the same higher order scaling can be done if we have an eta (implicit diffusion) for the milstein case? Like say we get order 1.5 for doing order 1 level work? |
That's super convergence. A lot of it is just finding the right conditions to make convergence "better", like how on additive noise the Euler-Maruyama scheme is Order 1.0. It would be very interesting to find out super convergence criterias for high order SDE schemes. I would assume that many of the common categories (additive, multiplicative) have some super convergence stuff going on. |
The predictor corrector method for SDEs have been implemented and tested.
Both the in place and not in place versions have been implemented.
The testing code used the problem from the commutative_tests.jl .
The speed of the code has not been benchmarked rigorously. For a single setting of dt=0.002, the following speeds were achieved.
The convergence tests shows that both the PC has better accuracy than EM and surprisingly also RKMilCommute. Although the PC is proven to be order 0.5, it showed order 1 scaling for this particular problem (see figure below). At dt=1/2^10, the l2 errors are respectively
RKMil : 6.02e-3
PCEuler : 1.44e-3