Skip to content

Add factorial smc#240

Merged
SamDuffield merged 12 commits into
mainfrom
factorial-smc
Jun 2, 2026
Merged

Add factorial smc#240
SamDuffield merged 12 commits into
mainfrom
factorial-smc

Conversation

@SamDuffield
Copy link
Copy Markdown
Contributor

Adds SMC factorializer code.

Adaptive resampling doesn't play nice with factorial so we assume resampling is always applied (i.e. no weights carried through). This could probably be documented better.

@SamDuffield
Copy link
Copy Markdown
Contributor Author

Ah actually cuthbert SMC applies resampling at the start of the filter_combine. This might be problematic, will think about it more

@AdrienCorenflos
Copy link
Copy Markdown
Contributor

AdrienCorenflos commented May 21, 2026 via email

@SamDuffield
Copy link
Copy Markdown
Contributor Author

I'm not willing to change that one lol. Monte Carlo outputs should come weighted rather than resampled to reduce variance.

agreed! Will try find a solution at the factorial level

@SamDuffield SamDuffield marked this pull request as ready for review May 26, 2026 15:29
@SamDuffield
Copy link
Copy Markdown
Contributor Author

Fixed by adding a resampling step within join when non-constant weights are detected. For this implementation it's recommended to set the particle filter's resampling method to do nothing so I added no_resampling to the cuthbertlib atom to facilitate that.

Comment thread cuthbert/factorial/smc.py Outdated
Comment thread tests/cuthbert/factorial/test_smc.py Outdated
@SamDuffield SamDuffield requested a review from Sahel13 June 1, 2026 17:28
@SamDuffield
Copy link
Copy Markdown
Contributor Author

In order to allow a factorial initialisation with shape (F, N, ...) rather than (N, F, ...) I added an optional particle_axis to the particle filter's init_prepare. Wanted to check if you guys think this is ok? @Sahel13 @AdrienCorenflos

@Sahel13
Copy link
Copy Markdown
Collaborator

Sahel13 commented Jun 2, 2026

In order to allow a factorial initialisation with shape (F, N, ...) rather than (N, F, ...) I added an optional particle_axis to the particle filter's init_prepare. Wanted to check if you guys think this is ok? @Sahel13 @AdrienCorenflos

I am trying to find another way to do it right now XD I don't like this change, that argument is difficult to explain for standard smc. We could add a wrapper for init_prepare specific for factorial SMC, so that all code specific for factorial models stay in that one file. I'll make a pr once i'm done.

@SamDuffield
Copy link
Copy Markdown
Contributor Author

I am trying to find another way to do it right now XD I don't like this change, that argument is difficult to explain for standard smc. We could add a wrapper for init_prepare specific for factorial SMC, so that all code specific for factorial models stay in that one file. I'll make a pr once i'm done.

Oooh thanks!! One option I thought about is changing the factorial initialisation to be vmap(init_prepare)(model_inputs). But I think we definitely want to avoid this as it means that the initial model_inputs has to have a factorial axis whilst subsequent model_inputs will not as they only act locally (on a few factors).

@SamDuffield
Copy link
Copy Markdown
Contributor Author

I'm wondering if this code can be made to cover the EnKF without too much trouble either, maybe in a later PR though

* Some slight modifications to factorialize_init_state

* Update cuthbert/factorial/types.py

Co-authored-by: Sahel Iqbal <sahel13miqbal@proton.me>

---------

Co-authored-by: Sahel Iqbal <sahel13miqbal@proton.me>
@SamDuffield
Copy link
Copy Markdown
Contributor Author

alright @Sahel13 we good to merge this one? (I'm happy my end)

@Sahel13
Copy link
Copy Markdown
Collaborator

Sahel13 commented Jun 2, 2026

Just one final thing, when init_prepare returns an (F, N) shaped output instead of (F, N, 1), we get a shape error when running the filter. Do we want to support this, or are we fine with always requiring an explicit state dimension axis (i'm fine with this)?

@SamDuffield
Copy link
Copy Markdown
Contributor Author

Oh good point! We should match cuthbert.smc there (can’t remember if an explicit state dimension is required there or not).

I’d lean no requiring it though since for SMC we can support ArrayTrees not just Arrays for the particles

@Sahel13
Copy link
Copy Markdown
Collaborator

Sahel13 commented Jun 2, 2026

I’d lean no requiring it though since for SMC we can support ArrayTrees not just Arrays for the particles

Yeah standard SMC didn't have this limitation, so I have fixed it.

I've also modified the pyproject.toml, turns out ruff didn't catch that error with the unused import because we were using select instead of extend-select to modify the linting rules, which meant only the rules we specified in select were being enforced.

@Sahel13
Copy link
Copy Markdown
Collaborator

Sahel13 commented Jun 2, 2026

Actually I'll make a separate PR for that to keep git history clean.

@SamDuffield SamDuffield merged commit 7771ebb into main Jun 2, 2026
2 checks passed
@SamDuffield SamDuffield deleted the factorial-smc branch June 2, 2026 19:38
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