-
Notifications
You must be signed in to change notification settings - Fork 40
feat: implement delete!! for VarNamedTuple (#1239) #1381
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,7 +24,7 @@ using DynamicPPL.VarNamedTuples: | |
| NoTemplate, | ||
| templated_setindex_no_overwrite!! | ||
| using AbstractPPL: AbstractPPL, VarName, concretize, prefix, @opticof | ||
| using BangBang: setindex!!, empty!! | ||
| using BangBang: setindex!!, empty!!, delete!! | ||
| using DimensionalData: DimensionalData as DD | ||
| using InvertedIndices: InvertedIndices as II | ||
| using OffsetArrays: OffsetArrays as OA | ||
|
|
@@ -2094,7 +2094,27 @@ Base.size(st::SizedThing) = st.size | |
| end | ||
| @test densify!!(vnt) == VarNamedTuple(; x=CA.ComponentArray(; a=1.0, b=2.0)) | ||
| end | ||
| @testset "delete!!" begin | ||
| vnt = VarNamedTuple() | ||
| vnt = setindex!!(vnt, 1.0, @varname(a)) | ||
| vnt = setindex!!(vnt, 2.0, @varname(b)) | ||
| vnt = setindex!!(vnt, 3.0, @varname(c)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These tests are a good starting point, but they are still too simple and only investigate the happy path where things are easy to make work. Notice how thorough the tests for get/set are above. Deletion is less important than those operations, so maybe the tests for deletion don't have to live up to that standard, but it needs to be much closer to them. |
||
|
|
||
| # Delete a single variable | ||
| vnt2 = delete!!(vnt, @varname(a)) | ||
| @test !haskey(vnt2, @varname(a)) | ||
| @test haskey(vnt2, @varname(b)) | ||
| @test haskey(vnt2, @varname(c)) | ||
|
|
||
| # Delete another variable | ||
| vnt3 = delete!!(vnt2, @varname(b)) | ||
| @test !haskey(vnt3, @varname(b)) | ||
| @test haskey(vnt3, @varname(c)) | ||
|
|
||
| # Original is unchanged | ||
| @test haskey(vnt, @varname(a)) | ||
| @test length(keys(vnt)) == 3 | ||
| end | ||
| @testset "skeleton" begin | ||
| function test_skeleton(orig_vnt, expected_skeleton) | ||
| @test (@inferred skeleton(orig_vnt)) == expected_skeleton | ||
|
|
||
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 for the PR!
While this implementation is correct in most cases, there are some cases where it will fail.
The
subsumescheck is a bit conservative and will fail to detect some things, which are described in http://turinglang.org/AbstractPPL.jl/stable/varname/#AbstractPPL.subsumes.Secondly, it doesn't allow you to delete part of a variable. Consider this:
Right now, this implementation of
delete!!will do nothing, because we have thatand
x[1]doesn't subsumex. I think it would be very reasonable to expect the call todelete!!to return something like this, where the vector has been converted into aPartialArray:Apart from this, it is also pretty inefficient, because it has to traverse the entire VarNamedTuple to figure out which keys should remain, and then rebuild a complete VarNamedTuple that doesn't contain it. (Look at the implementation of
subset: it's a loop over the keys which callstemplated_setindex!!.)This means that if you have a VNT that has 26 keys, and you remove one of them, you have to call
templated_setindex!!25 times. And this is probably unnecessary. VNT has a tree-like structure, which should allow you to identify exactly which branches can be pruned when you calldelete!!, and not have to touch any of the remaining ones. For example, look at the waysetindex!!is implemented. It uses the VarName to recurse into the correct part that needs to be changed, and doesn't touch anything else. The implementation here should be more surgical like that.It's not going to be easy to write correctly, and I can only apologise, but it's unlikely that I can review it.