-
Notifications
You must be signed in to change notification settings - Fork 35
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
[WIP] Distinguish "Hard Chaos" from "Partially Predictable Chaos" #83
Conversation
A few of the issues I can think of for now. Of course there's docs/tests/etc to do, but I think these things will need resolving first. I may add to this in the future. NamingThe function name ( Determination of perturbation range,
|
A few answers to your questions: Determination of perturbation range,
Two possible options:
Maximal Lyapunov exponent // Lyapunov prediction time Let's assume we are in the vicinity of a chaotic attractor, viz Note that it depends on the distances Secondly, note that in [Wernecke et al, 2017] we do not propose So here comes the tricky question: what is a sufficiently large Possible approaches:
Hope that brings you further. Cheers, hendrik |
src/chaos_distinction.jl
Outdated
|
||
# Perform regression to check cross-distance scaling | ||
ν = slope(log.(δs), log.(ds)) | ||
C = mean(Cs) |
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.
Here you average over the whole time evolution of the cross-correlation.
One is usually more interested in the long-term cross-correlation, i.e. neglecting the initial correlation, which is close to unity for any attractor.
My suggestion: neglect the initial time interval [0, 2 Tλ]
when averaging the cross-correlation.
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 think the cross-correlation should be calculated here at a single time point T=Tmax
(called Tλ
in this version, but I'll change the names now I understand Tλ
a bit better). This averaging operation C = mean(Cs)
should actually average over C(Tmax) for the different values of δ
.
There is no 'good' reason to perform this averaging, as I think C(Tmax) should be independent of δ
, but I did it anyway because:
- Calculating
C
is essentially free for eachδ
- It should help filter out any weird statistical variations in the values of
C
for eachδ
Please let me know if I have misunderstood this point.
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 are right, the cross-correlation C
should be independent of the initial distance δ
in the long-term limit, its computation comes at low cost and can be used to cross-check.
About the averaging:
Although a single measurement at time t=Tmax
should suffice to determine the residual cross-correlation, the correlation curve is typically fluctuating more or less strongly over time - especially when being computed from only a single pair of (chaotic) trajectories.
Thus, either
- one can perform an ensemble average (as done in the paper, note the definition of
C
) OR - one averages over time, e.g. the last 10% of the correlation curve.
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.
Ok, thanks. In this case the ensemble average should be computed (or more precisely the ensemble average D₁₂, then transformed to C₁₂ using equation 5 [using notation from the paper]).
src/chaos_distinction.jl
Outdated
C = mean(Cs) | ||
|
||
# Determine chaotic nature of the system | ||
if ν > ν_thresh_upp |
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.
Here you could additionally check whether C > C_thresh_upp
.
If so, the additional criterion is consistent with the scaling exponent.
If not, you have a sanity check and find that something did not work as intended.
Thanks for your help @hwernecke. A few thoughts on the direction:
|
I've also have not abandoned this, I was just very busy doing my Postdoc applications. I will review and reply in detail in the coming week as well. Just to say a quick note: finding plateaus on the fly is something we already do in ChaosTools for the methods we have that estimate embedding dimension (unrelated with this PR). The relevant code comes from this file: https://github.com/JuliaDynamics/DelayEmbeddings.jl/blob/master/test/R_dimension.jl which defines the function: """
saturation_point(x, y; threshold = 0.01, dxi::Int = 1, tol = 0.2)
Decompose the curve `y(x)` into linear regions using `linear_regions(x, y; dxi, tol)`
and then attempt to find a saturation point where the the first slope
of the linear regions become `< threshold`.
Return the `x` value of the saturation point.
"""
function saturation_point(Ds, E1s; threshold = 0.01, kwargs...)
lrs, slops = ChaosTools.linear_regions(Ds, E1s; kwargs...)
i = findfirst(x -> x < threshold, slops)
return i == 0 ? Ds[end] : Ds[lrs[i]]
end we could do something similar here. I will support this and give more details once I do my "proper" review. @efosong you don't have to apologize if this takes long. We all do this on our free time :) (edit: but it is of course always a great move to give a quick update that this isn't forgotten!) |
Alright, I've studied both the paper and this PR in detail; time for me to contribute a bit as well. But first things first: @hwernecke thanks very much for taking some time to help us with this implementation and @efosong once again thanks for working on this! Looking forward to grant you the bounty! I'll now make comments as appropriate. Technical things
Algorithm arguments
(edit: So, I do not recommend checking for the plateaua that was discussed above. This is possible though and if @efosong wants to do it then go ahead, but I am not so sure it is worth it) TestingThe code looks good, and will become better but one needs to test it rigorously. Can you please write tests that use @hwernecke Can you maybe suggest other system, preferably discrete, that you have tested this on while developing the method? The neural model discussed in the paper is probably too much for our scope here. Questions@hwernecke I can see from the paper that your definition of a "correlation function" is not the one traditionally found in the literature, where one trajectory is delayed with respect to the other, e.g. : https://en.wikipedia.org/wiki/Cross-correlation#Cross-correlation_of_deterministic_signals Is it really a different function ? |
Thanks @Datseris. I've made a couple of the simpler changes you suggested:
Still need to:
|
Very good, I'll review again when there are some basics tests! |
Possible candidates for testing the implementation are
The latter is a nice system to test the robustness of the implementation, as there are two distinct time-scales involved. |
The definition we used is more commonly called Pearson correlation, see https://en.wikipedia.org/wiki/Correlation_and_dependence#Definition The definition of cross-correlation you referenced above is not normalized around zero. |
Thanks @hwernecke , these are some extremely useful comments! |
issues with some of the variables names was originally missed due to scoping in the REPL
The function now has an interface and works when imported via the package. I'll write some tests. I'm not sure if there's a "good" way to test this other than simply trying some 'known' conditions and testing it gets them right? Not very rigorous but at least a sanity check. I think discrete systems will need a bit more work on the function itself but shouldn't be too bad, so I'll give that a go at some point. |
the symbol
I think this is totally fine.
Shouldn't be that much tweaking necessary. I can see in the source that everything that you do on |
The symbol
I'll at least need to change how sampling works to sample from a geometric distribution rather than exponential (so the step is always an integer). I've had a look and other than that I think it might work. |
handles both ContinuousDynamicalSystems and DiscreteDynamicalSystems
Latest commit adds 'support' for discrete-time dynamical systems. I've manually tested the Lorenz system for continuous-time, and the Hénon map for discrete-time. lmap = Systems.logistic(r=3.6)
p_integ = parallel_integrator(lmap, [0.4, 0.5])
step!(p_integ) # --> Error Worth an issue on DynamicalSystemsBase.jl @Datseris? If you'd like to try this out on the Lorenz out for yourself, you might need to pass a relatively large |
The stack trace for the error mentioned in the previous comment:
|
I have also tried to implement this about a year ago, but I got distracted by other things and I couldn't find the old code. I remember that when I tried to reproduce the plots from Figure 3, I needed parallelization since the number of initial conditions was quite high. |
@efosong the logistic map is special because its state is not a vector but just a number. I'll have a look once the PR is ready for review. I need a proper test file in the |
Yes making the code more modular is a valid suggestion, but this can wait after this is implemented, merged and tagged. |
oh sorry. I messed up and merged this into master when I wanted to actually merge the master into this branch.... shit. I continue this in #86 |
Closes #68
Todo: