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

allow more Param types #39

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

allow more Param types #39

wants to merge 3 commits into from

Conversation

rafaqz
Copy link
Owner

@rafaqz rafaqz commented Nov 25, 2021

@briochemc this PR addes select keywords everywhere so that we can filter by other wrapper types - e.g. AbstractParam. (and ignore for the case there are types in your object that don't reconstruct, but that's a minor detail)

@bgroenks96 you might want to have a look at this and give some feedback. We will need to changing the grouping as well to not always use Param.

But, from the new tests, this is the kind of this it adds with select:

struct FreeParam{T,P<:NamedTuple} <: AbstractParam{T}
    parent::P
end
FreeParam(nt::NT) where {NT<:NamedTuple} = begin
    ModelParameters._checkhasval(nt)
    FreeParam{typeof(nt.val),NT}(nt)
end
FreeParam(val; kwargs...) = FreeParam((; val=val, kwargs...))
FreeParam(; kwargs...) = FreeParam((; kwargs...))

sf = S2(
    FreeParam(99),
    FreeParam(7),
    Param(100.0; bounds=(50.0, 150.0))
)
params(sf; select=FreeParam) == (FreeParam(99), FreeParam(7))
m = Model(sf)
m[:val, select=Param] == (100.0,)
getindex(m, :val; select=FreeParam) == (99, 7)
m[:bounds, select=FreeParam] = ((1, 100), (1, 10)) 
m[:bounds] == ((1, 100), (1, 10), (50.0, 150.0))

Probably we want a @param MyParam macro to define all those constructors automatically

@codecov-commenter
Copy link

codecov-commenter commented Nov 28, 2021

Codecov Report

Merging #39 (285168e) into master (f2890ca) will increase coverage by 1.12%.
The diff coverage is 80.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #39      +/-   ##
==========================================
+ Coverage   79.88%   81.00%   +1.12%     
==========================================
  Files           4        4              
  Lines         174      179       +5     
==========================================
+ Hits          139      145       +6     
+ Misses         35       34       -1     
Impacted Files Coverage Δ
src/ModelParameters.jl 100.00% <ø> (ø)
src/tables.jl 77.77% <33.33%> (ø)
src/model.jl 78.40% <78.00%> (+0.62%) ⬆️
src/param.jl 88.63% <100.00%> (+1.79%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f2890ca...285168e. Read the comment docs.

@bgroenks96
Copy link
Collaborator

Could I get some context on this? Why is this necessary?

It seems to me that filtering is already possible by table operations on Model, and so-called "fixed" parameters can simply be left unchanged on reconstruction. Making the Param type polymorphic seems like an unnecessary complication of the type semantics, and appears to me to conflict a bit with the original design, i.e. allowing user-customization by defining arbitrary additional fields on the Param instances.

@rafaqz
Copy link
Owner Author

rafaqz commented Nov 29, 2021

The original design always had AbstractParam ?

But I get your point, there are 2 ways of achieving this - table/vector manipulation outside of the object, or modification of the param type.

This way is going to be better for type stability where that's required, and is pretty easy to specify by the user. But its also less flexible.

@bgroenks96
Copy link
Collaborator

I know the original design had AbstractParam, but I didn't think it really did anything? It seemed everything more or less assumed Param to be the type, either implicitly or explicitly.

I'm not sure this is better for type stability. The main type stability issue in using update is with the parameters being supplied as a Vector, or some indeterminate length collection, which makes it tricky (or sometimes impossible?) to make reconstruction fully type stable.

So, for example, if one works only with Param tuples, then manipulation via map/filter should also be entirely type stable.

In other words, I don't think this is the main problem hindering type stability... or am I missing something?

end
setparent!(m, newparent)
end
end
# TODO do this with lenses
@inline function _setindex(obj, xs::Tuple, nm::Symbol)
@inline function _setindex(obj, xs::Tuple, nm::Symbol; select=SELECT, ignore=IGNORE)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should select and ignore maybe have type bounds, Type{T} where {T<:AbstractParam}?

@@ -246,3 +246,28 @@ end
@test isa(tuplegroups.A.i, Tuple)
@test isa(tuplegroups.B.j, Tuple)
end

struct FreeParam{T,P<:NamedTuple} <: AbstractParam{T}
Copy link
Collaborator

Choose a reason for hiding this comment

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

If we're going to do this, then the macro to abstract away this boilerplate (and reduce chance of user error) should be included in this PR, I think.

FreeParam(val; kwargs...) = FreeParam((; val=val, kwargs...))
FreeParam(; kwargs...) = FreeParam((; kwargs...))

@testset "spefify param type" begin
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since you seem to agree that the FreeParam/FixedParam is not a good use-case for this feature, I would like to see an example use-case where this feature actually is actually necessary in contrast to using table manipulations, i.e. something where simply adding an extra field to Param wouldn't cut it or would be prohibitively difficult. I can't really think of one off the top of my head, but maybe you can.

@bgroenks96
Copy link
Collaborator

I have changed my mind about this, but I think the changes here will conflict a lot with #44, so it might be better for me to simply copy these changes into that PR by hand rather than try to resolve the merge conflicts.

@rafaqz
Copy link
Owner Author

rafaqz commented Feb 4, 2022

Nice to see you finally came around ;)

Probably making a separate PR afterwards is better, or do you need this for your PR?

@bgroenks96
Copy link
Collaborator

We can do it in another PR.

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.

3 participants