-
Notifications
You must be signed in to change notification settings - Fork 17
Generalize TransferOperator #434
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
base: main
Are you sure you want to change the base?
Conversation
|
is there any paper in the literature that has generalized the transfer operator like this? Among other outcome spaces? if not, perhaps you can consider making this a paper. |
At least I am not aware of any such paper. Would be a cool contribution for sure! |
|
@rusandris Thanks for the PR! I am super busy at the moment, so I'm not able to review this in detail yet. I'll try to get to it within the next couple of weeks.
I'll have to do a thorough review dig deeper to understand this issue. I'll ping you when I've tested this out a bit, @rusandris. |
Just to be clear: i have no capacity to be involved in such a paper, but it is worth discussing with your supervisor Andras. |
I looked inside julia> probabilities(TransferOperator(),op,x;N=5,tolerance=1e-12)
distribution = [0.28892942757860407 0.7110705724213959]
distribution = [0.7110705724213959 0.28892942757860407]
distance = 0.7778172853930047
distribution = [0.28892942757860407 0.7110705724213959]
distance = 0.7778172853930047
distribution = [0.7110705724213959 0.28892942757860407]
distance = 0.7778172853930047
distribution = [0.28892942757860407 0.7110705724213959]
distance = 0.7778172853930047
distribution = [0.7110705724213959 0.28892942757860407]
distance = 0.7778172853930047
Probabilities{Float64,1} over 2 outcomes
Outcome(1) 0.7110705724213959
Outcome(2) 0.28892942757860407reveals of course that it works as it should. Since the transition matrix looks like this to.transfermatrix
2×2 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
⋅ 1.0
1.0 ⋅ the iterative method keeps flipping the initial random values inside the distribution. This wouldn't converge, unless the initial distribution is already given as probabilities(RelativeAmount(),op,x)
Probabilities{Float64,1} over 2 outcomes
Outcome(1) 0.5
Outcome(2) 0.5 |
|
I've seeen some new commits here, but it's been more than a year since i've looked at this and have forgotten many things, let me know if there is something in particular you'd like help with, or to discuss, and I'll bring myself back up to speed! |
|
Thanks, great to hear! I'm still working on it, but in short logistic_rule(x, p, n) = SVector{1}(p[1] * x[1] * (1.0 - x[1]))
p = [r]
ds = DeterministicIteratedMap(logistic_rule, [0.4], p)
x, t = trajectory(ds, 10^3; Ttr=10^4)
b = ValueBinning(FixedRectangularBinning(range(0,1;length=11)))
probabilities(TransferOperator(),b,x)through The eigenvector method can be better for example when the time series is periodic: ds = DeterministicIteratedMap(logistic_rule, [0.4], [3.84])
x, t = trajectory(ds, 10^3; Ttr=10^4)
probabilities(TransferOperator(),b,x;method=:iterate)
Probabilities{Float64,1} over 3 outcomes
2 0.09340928604503983
5 0.23372777459244914
10 0.6728629393625111
probabilities(TransferOperator(),b,x;method=:eigen)
Probabilities{Float64,1} over 3 outcomes
2 0.33333333333333337
5 0.3333333333333334
10 0.33333333333333326Let me know how this looks for you. |
|
@rusandris, great stuff! 🤘Super nice that the eigenvector approach works well for periodic time series. This is a major improvement which may have advantages in e.g. reducing false negatives in settings where e.g. extensive pseudoperiodic surrogate testing is done for some statistic. For that reason I vote for keeping the dependency. One comment though: following the convention from the test of the packaged: any keywords that controls the probabilities estimation should be part of the discretization type ('TransferOperator'), not as a keyword to the 'probabilities' function. |
My thinking was the following (and I'm sure there are some workarounds/better ways to do this): the seemed too verbose and difficult. These types are supposed to be internal and are only used once which is what you mean, right? |
|
@rusandris Thanks again for your great work! I'll do a thorough review of this in the coming days. In order to not give conflicting feedback here, I want to familiarize myself properly with the changes before I respond in detail. But in short: Breaking changesI see that there is a breaking change (converting Internal dispatch
Something like that! For consistency with the rest of the code base, I think the following would work: probabilities(probest::TransferOperatorApproximation(::ApproximationMethod), o::OutcomeSpace, x)where probabilities(::TransferOperatorApproximationIterative,outcome_space,x)
probabilities(::TransferOperatorApproximationEigen,outcome_space,x)I just need to see how it relates to the manual extraction of the transfer matrix in your suggested code. Why we don't want extra keywords in the functionWe want the base functions like If we were to break with this convention for the transfer operator, then there would be hundreds of possible ways to discretize and estimate probabilities from data using one unified syntax, EXCEPT for the transfer operator approximation, which has an extra keyword for We set reasonable, well-documented default behaviours, but leave the user the option to be as granular as they want. |
First draft PR. I tried to follow the design ideas mentioned here #424 .
TransferOperatorbecomes aProbabilitiesEstimator.First results:
which returns a
TransferOperatorApproximation <: ProbabilitiesEstimator.OP example:
Most important field is the
transfermatrixprobabilitiesfunction does work formally in that it gives an output:but for some reason, for this particular example, the iterative method used in
invariant_measuredoes not converge.the correct probabs of course would be
[0.5,0.5]as the eigenvector corresponding to eigenvalue 1 is[1,1]. This might be a separate issue though.Let me know what you think.