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

Missing import of PseudoSteppingSchemes.adaptive_step_parameters? #300

Closed
navidcy opened this issue Nov 9, 2022 · 11 comments
Closed

Missing import of PseudoSteppingSchemes.adaptive_step_parameters? #300

navidcy opened this issue Nov 9, 2022 · 11 comments
Labels
❓ question Further information is requested

Comments

@navidcy
Copy link
Collaborator

navidcy commented Nov 9, 2022

Isn't this method

successful_Xⁿ⁺¹, Δt = adaptive_step_parameters(pseudo_stepping,
successful_Xⁿ,
successful_Gⁿ,
eki;
Δt,
covariance_inflation,
momentum_parameter)

from the PseudoSteppingSchemes module

function adaptive_step_parameters(pseudo_scheme, Xₙ, Gₙ, eki; Δt=1.0,

and thus we need to import it?

cc @glwagner, @adelinehillier

@navidcy navidcy added the ❓ question Further information is requested label Nov 9, 2022
@glwagner
Copy link
Member

glwagner commented Nov 9, 2022

It looks like PseudoSteppingSchemes is importing it from EnsembleKalmanInversions

@navidcy
Copy link
Collaborator Author

navidcy commented Nov 9, 2022

But how is EnsembleKalmanInversions using the method PseudoSteppingSchemes defines without importing it?

@glwagner
Copy link
Member

glwagner commented Nov 9, 2022

It's defined by EnsembleKalmanInversions. The module that defines a function does not need to import it.

@navidcy
Copy link
Collaborator Author

navidcy commented Nov 9, 2022

But not that method. Or I missed it….

@glwagner
Copy link
Member

glwagner commented Nov 9, 2022

EnsembleKalmanInversions is included first in the source:

include("EnsembleKalmanInversions.jl")
include("PseudoSteppingSchemes.jl")

So, it defines the function adaptive_step_parameters. The first occurrence is here:

adaptive_step_parameters(::Nothing, Xⁿ, Gⁿ, y, Γy, process; Δt) = step_parameters(Xⁿ, Gⁿ, y, Γy, process; Δt), Δt

Next, PseudoSteppingSchemes imports this method:

import ..EnsembleKalmanInversions: adaptive_step_parameters, eki_objective

and extends it here:

function adaptive_step_parameters(pseudo_scheme, Xₙ, Gₙ, eki; Δt=1.0,

@navidcy
Copy link
Collaborator Author

navidcy commented Nov 9, 2022

But in line I'm referring at the first comment on this issue, EnsembleKalmanInversions seems to use the method that is extended by PseudoSteppingSchemes. Is this possible? How is this done since, as you point out, EnsembleKalmanInversions is included first in the source? That's my question.

@glwagner
Copy link
Member

glwagner commented Nov 9, 2022

The method to be used is resolved at the time the function is called (it doesn't have to do with the order in which the methods are defined). So by the time the user calls adaptive_step_parameters (or rather, calls the function that calls it), it's been extended appropriately.

The title of this issue says that EnsembleKalmanInversions should import adaptive_step_parameters from PseudoSteppingSchemes. But this is not possible because EnsembleKalmanInversions is loaded first and therefore PseudoSteppingSchemes does not exist when EnsembleKalmanInversions code is loaded.

@glwagner
Copy link
Member

glwagner commented Nov 9, 2022

This is an example:

julia> import ParameterEstimocean.Utils: tupleit

julia> tupleit(1)
(1,)

julia> tupleit(a::Number) = println("This isn't a tuple at all")
tupleit (generic function with 2 methods)

julia> tupleit(1)
This isn't a tuple at all

@glwagner
Copy link
Member

glwagner commented Nov 9, 2022

Or maybe this is a clearer example, where one function is used by another:

julia> g(x, y) = x + y
g (generic function with 1 method)

julia> f(x, y) = 2 * g(x, y)
f (generic function with 1 method)

julia> f(1, 2)
6

julia> g(x::Float64, y::Float64) = x - y
g (generic function with 2 methods)

julia> f(1, 2)
6

julia> f(1.0, 2.0)
-2.0

@navidcy
Copy link
Collaborator Author

navidcy commented Nov 9, 2022

So by the time the user calls adaptive_step_parameters (or rather, calls the function that calls it), it's been extended appropriately.

OK, all clear now. Thanks!!

@navidcy navidcy closed this as completed Nov 9, 2022
@glwagner
Copy link
Member

glwagner commented Nov 9, 2022

We can even use functions with no methods at all, provided the name is defined:

julia> function g end
g (generic function with 0 methods)

julia> f(x, y) = 2 * g(x, y)
f (generic function with 1 method)

julia> f(1, 2)
ERROR: MethodError: no method matching g(::Int64, ::Int64)
Stacktrace:
 [1] f(x::Int64, y::Int64)
   @ Main ./REPL[2]:1
 [2] top-level scope
   @ REPL[3]:1

julia> g(x, y) = x + y
g (generic function with 1 method)

julia> f(1, 2)
6

This is a useful technique for building up frameworks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
❓ question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants