Skip to content

Replace PrefixContext with model.prefix #1011

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

Draft
wants to merge 20 commits into
base: py/remove-samplingcontext
Choose a base branch
from

Conversation

penelopeysm
Copy link
Member

@penelopeysm penelopeysm commented Aug 5, 2025

Part of #1010. Maybe don't look at this until all the InitContext stuff is merged.

Most of this PR is boring stuff: moving code around, making sure things are prefixed when they should be, making sure things aren't prefixed when they shouldn't be.

There is one slightly awkward catch: we have to thread model.prefix through to tilde_assume!!. The reason for this is quite subtle and has to do with submodels. Consider the following:

@model function f()
    x ~ Normal() # (2)
end
@model function g()
    return a ~ to_submodel(f()) # (1)
end

pg = prefix(g(), @varname(hello))

In this case, we want the sampled variable to be called hello.a.x. If we use automatic prefixing as is shown here, this is easy to do: inside tilde_assume!! of the top-level model (1), a will already have been prefixed with hello, so the left argument to tilde_assume!! will be hello.a. We can thus simply set this as the appropriate 'prefix' for the inner model.

The problem arises if we don't automatically prefix:

@model function f()
    x ~ Normal() # (2)
end
@model function g()
    return a ~ to_submodel(f(), false) # (1)
end

pg = prefix(g(), @varname(hello))

If we run this, everything is the same as before: when we get to (1), tilde_assume!! knows that the prefixed left-hand side is hello.a. However, because we don't want to prefix the submodel, the inner variable should only be called hello.x, and not hello.a.x.

This means that we have to store the prefix hello separately so that we can apply it to the submodel without the a as well.

Note that in the absence of submodels, this would be entirely unnecessary.

It's quite possible that similar thing will happen with conditioning and fixed values: for 'normal' (i.e. non-submodel) models there's no need to pass it through, but specifically for submodels it is needed. Previously all this information would have been accessed via the context argument to tilde_assume!! so in a sense we are just making this more explicit.

@penelopeysm penelopeysm changed the base branch from main to py/remove-samplingcontext August 5, 2025 16:28
Copy link
Contributor

github-actions bot commented Aug 5, 2025

Benchmark Report for Commit 93ceec4

Computer Information

Julia Version 1.11.6
Commit 9615af0f269 (2025-07-09 12:58 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 4 × AMD EPYC 7763 64-Core Processor
  WORD_SIZE: 64
  LLVM: libLLVM-16.0.6 (ORCJIT, znver3)
Threads: 1 default, 0 interactive, 1 GC (on 4 virtual cores)

Benchmark Results

|                 Model | Dimension |  AD Backend |      VarInfo Type | Linked | Eval Time / Ref Time | AD Time / Eval Time |
|-----------------------|-----------|-------------|-------------------|--------|----------------------|---------------------|
| Simple assume observe |         1 | forwarddiff |             typed |  false |                 13.6 |                 1.3 |
|           Smorgasbord |       201 | forwarddiff |             typed |  false |                757.0 |                35.4 |
|           Smorgasbord |       201 | forwarddiff | simple_namedtuple |   true |                484.4 |                47.5 |
|           Smorgasbord |       201 | forwarddiff |           untyped |   true |               1070.9 |                32.5 |
|           Smorgasbord |       201 | forwarddiff |       simple_dict |   true |               7656.7 |                25.5 |
|           Smorgasbord |       201 | reversediff |             typed |   true |               1145.4 |                37.0 |
|           Smorgasbord |       201 |    mooncake |             typed |   true |               1052.0 |                13.3 |
|    Loop univariate 1k |      1000 |    mooncake |             typed |   true |               6926.6 |                51.1 |
|       Multivariate 1k |      1000 |    mooncake |             typed |   true |               1011.2 |                 8.6 |
|   Loop univariate 10k |     10000 |    mooncake |             typed |   true |              81644.5 |                46.4 |
|      Multivariate 10k |     10000 |    mooncake |             typed |   true |               8209.4 |                10.2 |
|               Dynamic |        10 |    mooncake |             typed |   true |                143.2 |                30.1 |
|              Submodel |         1 |    mooncake |             typed |   true |                 17.2 |                27.4 |
|                   LDA |        12 | reversediff |             typed |   true |               1084.5 |                 2.0 |

Copy link

codecov bot commented Aug 5, 2025

Codecov Report

❌ Patch coverage is 90.38462% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.15%. Comparing base (331279c) to head (c670ef0).

Files with missing lines Patch % Lines
src/prefix.jl 85.18% 4 Missing ⚠️
src/compiler.jl 88.88% 1 Missing ⚠️
Additional details and impacted files
@@                      Coverage Diff                      @@
##           py/remove-samplingcontext    #1011      +/-   ##
=============================================================
- Coverage                      81.46%   81.15%   -0.32%     
=============================================================
  Files                             39       40       +1     
  Lines                           3825     3778      -47     
=============================================================
- Hits                            3116     3066      -50     
- Misses                           709      712       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

github-actions bot commented Aug 5, 2025

DynamicPPL.jl documentation for PR #1011 is available at:
https://TuringLang.github.io/DynamicPPL.jl/previews/PR1011/

@penelopeysm penelopeysm force-pushed the py/no-prefix-context branch 2 times, most recently from 180816d to 93ceec4 Compare August 6, 2025 00:08
@penelopeysm penelopeysm mentioned this pull request Aug 8, 2025
8 tasks
@penelopeysm penelopeysm force-pushed the py/remove-samplingcontext branch from 5278370 to 331279c Compare August 8, 2025 10:23
@penelopeysm penelopeysm force-pushed the py/no-prefix-context branch from 93ceec4 to c670ef0 Compare August 8, 2025 10:25
@penelopeysm penelopeysm force-pushed the py/remove-samplingcontext branch 3 times, most recently from 0bd4e02 to 8e3dcac Compare August 10, 2025 23:26
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.

1 participant