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

add Base.copy(::ParticleFilterState) #509

Merged
merged 3 commits into from
Jul 3, 2023
Merged

Conversation

georgematheos
Copy link
Contributor

No description provided.

@ztangent
Copy link
Member

Looks great! It strikes me that we might also want to implement Base.(:==) (and also Base.hash since that's required for every type that implements ==), so that we can check that copies are accurate? And to add a test case somewhere.

@georgematheos
Copy link
Contributor Author

@ztangent For equality, what do you think between the following possible semantics?

For checking equality w.r.t. particle weights:

  1. Two PF states a and b are equal if a.log_weights .+ a.lml_estimate == b.log_weights .+ b.lml_estimate and all else is the same
  2. Two PF states a and b are equal if a.log_weights == b.log_weights && a.lml_estimate == b.lml_estimate and all else is the same

For dealing with new_traces:
A. Two PF states which are identical except their new_traces field are equal.
B. PF states must have equivalent new_traces fields to be equal.

The benefit of doing 1-A is that it would make it easier to do things like dictionary lookups based on equivalent PF states which might come from different paths through an inference algorithm. But it also seems like it could be confusing if, e.g., calling update_refs! on two equivalent PF states can yield non-equivalent states.

What do you think?

@georgematheos
Copy link
Contributor Author

Re A vs B -- since we expect in normal usage the new_traces vector to have undef values, errors can be thrown if we try to check the equality or two new_traces arrays containing undef values. So I think we should potentially use semantics A.

@ztangent
Copy link
Member

ztangent commented Jul 1, 2023

Thanks for raising these questions! I think 1-A sounds like a fine way to go -- or at least, I currently can't think of edge cases where you'd want a stricter equality check. Re 1, I'd maybe check that this is still correct when custom priority weights are used when resampling, as in the second branch of this code:

https://github.com/probcomp/GenParticleFilters.jl/blob/7eae3c1ff5036a48f6b02e88023a202f15c95e3c/src/resample.jl#L171-L184

Re A vs. B, I think not checking new_traces is fine given that it's not supposed to be exposed as part of the interface.

@georgematheos
Copy link
Contributor Author

@ztangent I've committed a change which implements 2-A. I'm heading out on vacation now, so I will only be able to respond sporadically for the coming month, but hopefully this is a viable change for now!

Re implementation 1 vs 2 -- I switched to implementation 2. (Also, I realize that my proposal for "1" gets the math slightly wrong, by the way. This isn't the reason for the switch, though.)

The reason I switched from 1 to 2 is I realized I do not understand what the semantics are supposed to be regarding how the values of log_ml_est and log_weights are set. I had thought that the log_ml_est was just a performance optimization of some sort, and that in principle the ParticleFilterState data structure could be implemented where the log ML estimate was just obtained as logsumexp(log_weights) - n_particles, without changing any semantics. But as I'm looking at the code now, I realize that there are a couple methods that do not seem to treat the separation between log_weights and the log_ml_est as a semantically irrelevant implementation detail. get_log_weights can return different things, depending how much of the log ML estimate is factored into the weight vector and how much into log_ml_est. Likewise, the code you linked above appears like it might care about the separation of log_weights and log_ml_est, though I would need to read more carefully to be sure.

You or @alex-lew may understand these semantics, and so know if there is a better implementation of equality for the ParticleFilterState. Or perhaps it is actually the case that the semantics should always that the separation of log_ml_est and log_weights is irrelevant, and there are a couple of interface methods that currently mistakenly return different things depending on this separation?

Anyway, if this is going to require longer discussion, perhaps we could commit this implementation of 2-A for now, and open an issue to discuss potentially changing equality semantics for particle filters.

@ztangent
Copy link
Member

ztangent commented Jul 3, 2023

Going with 2-A sounds good to me! Yes, on second thought, we probably shouldn't say two particle filters are equal if get_log_weights returns different things. I've made one additional commit to ensure that the implementation of hash is consistent with the semantics of ==. But apart from that, I think we can merge this -- thanks for making these changes! :)

@ztangent ztangent merged commit 3287746 into master Jul 3, 2023
5 checks passed
@ztangent ztangent deleted the 20230620pfstate-copy branch March 18, 2024 20:16
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.

None yet

2 participants