Conversation
Shouldn't call Core.Compiler.return_type directly in many places.
Will be used a lot when bridging from Distributions to MeasureBase.
Currently unused and undocumented, can add it back later when needed.
Created by generative AI.
Assisted by generative AI.
Unused and untested. (cherry picked from commit 1d27188)
Not used currently. (cherry picked from commit 9844583)
A rebase can easily be written explicitly. (cherry picked from commit fb3c98c)
`mintegral` should be used instead to express posteriors. (cherry picked from commit 3c61180)
To be re-introduced in sub-module MeasureOperators. (cherry picked from commit 0cdca3d)
Working notes on the batched-first approach, its concepts, extension points and layout rules, the changes relative to master, device verification, known limitations and open decisions, to guide reviews and next steps while the branch evolves. To be removed before the merge. Created by generative AI.
Collaborator
Author
|
Note that that is very much in flux still, with a lot of AI-generated code (with carefuly guidance) and will still receive both significant changes and then manual review, polish, some renames, etc. CC @cscherrer |
Reactant only supports 64-bit Linux and macOS, so runtests.jl adds it on the fly where supported (as MGVI does) and includes the Reactant tests from test/test_reactant.jl instead of a separate test project. Created by generative AI.
Leading singleton dimensions of summed batches are dropped by reshaping, since dropdims on static matrices doesn't infer on Julia 1.13. The common variate rank of superposition components is folded pairwise and density measures evaluate array variates directly, which Julia 1.10 needs to infer these kernels. The allocation tests call the kernels directly, local closures allocate inside test sets on Julia 1.10. The docs include the MeasureOperators docstrings and all cross-references resolve. Created by generative AI.
The main univariate families (Normal, Uniform, Exponential, Logistic, Cauchy, Laplace, LogNormal, Weibull, Gamma, Beta, Poisson, Bernoulli) get branch-free density formulas, support masks and transports to the standard measure matching their shape, so batches evaluate on GPUs and under Reactant. MvNormal works on column batches through its Cholesky factor (kept lazy, Cholesky.L scalar-indexes on GPUs) and Dirichlet through stick-breaking Beta transports with cumulative sums and products along the variate dimension, both with Adapt rules. Incomplete gamma and beta functions go through hooks whose ForwardDiff and ChainRules derivatives come from the densities. Draws use the Distributions samplers on the CPU and the standard transports on other compute units. Batched densities of univariate wrappers broadcast their point kernels, only array-variate wrappers evaluate via logpdf. Beta and Dirichlet transports stay on the CPU (SpecialFunctions' incomplete beta functions don't compile for GPUs or Reactant), MvNormal and Dirichlet parameters stay constants under Reactant. Created by generative AI.
Pkg is a test dependency, the on-demand Reactant install needs it. The allocation tests measure inside a function, since @allocated at top level reports a boxed result on Julia 1.10. Created by generative AI.
All allocation checks go through allocations_of in test/testutils.jl, which warms up and measures inside a function, since @allocated at top level reports a boxed result on Julia 1.10. Created by generative AI.
FixedSizeArrays becomes a test dependency: fixed-size inputs to densities and transports give fixed-size outputs, since the kernels allocate via similar. Created by generative AI.
Variates of the right shape never throw. Densities are -Inf outside the support, including infinite values and non-integers for counting-based measures, transports are NaN outside the support of the source measure, and wrong shapes throw an ArgumentError from checked_arg. The standard measure transports, Half and the wrapped distribution families mask their results and use abs, clamp and min guards so that the formulas stay total on the CPU and identical on devices. Infinite values lie outside the support of wrapped univariate distributions. Documented in logdensityof, transport_to and checked_arg, with tests through the combinators on CPU and JLArrays. Created by generative AI.
Created by generative AI.
The marginalization map is built with the PropSelFunction constructor, whose type parameters changed in PropertyFunctions 0.3. Created by generative AI.
This was referenced Sep 19, 2026
The base measure of a superposition sums the base measures of all components unconditionally, so the Radon-Nikodym derivative of a component with respect to it must count every base measure with mass at the point, not only those of components whose support contains it. Otherwise densities came out too large where a component vanishes, e.g. by log(2) for a superposition of a normal and a uniform measure outside the unit interval. Created by generative AI.
AsMeasure, Dirac, product measures and transport functions compare by value, so they hash by value as well, which keeps equal measures with array-valued parameters usable as dictionary keys and cache witnesses. Created by generative AI.
The output size of a pushforward is learned from a test value whenever the origin's variates have a fixed layout, not only when the origin has a flat size. Pushforwards of tuple products (such as unshaped measures) thereby declare their variate rank, so their batched kernels and the transport broadcast hook no longer fall back to pointwise evaluation. Created by generative AI.
The check whether all marginals of a tuple product have fixed stream sizes is folded pairwise over the marginal types, so that it infers as a constant and the types of pushforwards of such products stay inferrable. Created by generative AI.
The fixed-stream-size check and the output size of pushforwards are type-level information, declared non-differentiable so that Zygote can differentiate through the construction of pushforwards of tuple products. Created by generative AI.
On the floating-point grid the endpoints of the unit interval stand for their nearest interior points: uniform inputs are clamped into the open interval (from the smallest normal float, since devices may flush subnormals, to the grid point below one) before quantiles, and tail probabilities of the direct log-space conversions between standard measures never underflow to zero. Inputs outside the unit interval stay NaN. This is the null-set convention BAT has used in practice, applied once in MeasureBase for the standard measures, Half, the wrapped families, Dirichlet and the generic logistic path; the bounds are non-differentiable helpers so that autodiff passes through them. Created by generative AI.
The private static helpers duplicated tools that StaticThings now provides: `_size_dims`, `_reshape_batch`, the leading-dimension family (`_sum_leading_dims`, `_drop_leading_dims`, `_merge_leading_dims`, `_all_leading_dims`), `_get_or_view`/`_split_after` for vectors, the type-level `_static_axes_size`, and the pairwise folds over tuple types of products and superpositions. They are gone in favour of `size_dims`, `maybestatic_reshape`, `sum_leading_dims`, `drop_leading_dims`, `merge_leading_dims`, `all_leading_dims`, `maybestatic_view`, `split_at`, `axes2size(::Type)`, `static_all` and `static_reduce`. Hand-rolled `map(dynamic, ...)` became `asnonstatic` and `_both` Static's `&`. `mspace_ndims` now follows from `maybestatic_length` and returns an `IntegerLike`. `Static.StaticInt` is not an `Integer`, so the dispatch that consumes it takes `IntegerLike` and `_unit_dof` compares static ranks instead of testing for a literal zero. Requires StaticThings 0.3, whose `maybestatic_reshape` no longer turns arbitrary arrays into static arrays. Created by generative AI.
The multiplicity of the with-rest protocol and the batch size of random variate generation were `Dims`, which turned every statically sized power into a dynamic one as soon as it was consumed from a stream. Both are `SizeLike` now and stay static: `_chunk_rows` multiplies with `size2length`, powers hand their `pwr_size` to their base unchanged, combined measures and tuple products split and reshape their rows with `_chunk_rows` and `maybestatic_reshape`, and `_fixed_stream_length` keeps static lengths. The static split of static vectors is therefore reachable through with-rest. Bulk draws of a fully static batch size return static arrays on the CPU, so `rand` of a statically sized power, product or bind allocates nothing. Other compute units keep allocating their own arrays. Standard measures check their variates directly: going through their base measures makes the inliner cut the recursion, and the resulting call boxes the variate of every scalar marginal of a tuple product. Created by generative AI.
A hierarchical model over a named tuple of scalar and static-array marginals (a bind of a named tuple product with a kernel whose marginals depend on the primary variate but whose sizes don't) checks that random variates, transports to and from a static standard power and densities are type stable and allocation free, plus static powers, nested static powers and batches of static variates. `test/transport.jl` imports `MeasureBase` itself, so that it runs on its own and not only as part of the suite. Created by generative AI.
Created by generative AI.
`mspace_ndims` returned a `StaticInt` where it followed from a variate size and an `Int` where a measure type declared it, which made `mspace_ndims(typeof(μ))` and `mspace_ndims(μ)` disagree and forced `IntegerLike` on the dispatch that consumes them. Ranks are `Int`s again, constant-folded through the type-level definitions, and staticness comes from `_static_ndims` as before. Follows StaticThings' rename of the mapped tuple-type fold. Created by generative AI.
Two stream kernels splatted the multiplicity into a size tuple, which only works for tuples, not for the `StaticArrays.Size` that `SizeLike` also allows. They take `size_dims` of it now, like the other kernels do. Created by generative AI.
`_map` passed the mapped function on unspecialized, so drawing the marginals of a tuple or named tuple product ran through a dynamic call and boxed every scalar variate. `map` over a named tuple splats its values on top of that, mapping over the values avoids it. `rand` of a product of scalar measures, and of a bind over one, allocates nothing now. Created by generative AI.
Power kernels name the measure again when a variate isn't an array, instead of letting StaticThings report a dimension mismatch. The shape checks of powers take `Dims` consistently, the dead `_split_after` for tuples with a dynamic split point and the dead `_array_product_kernel` for dynamic ranks are gone, the `StdMeasure` docstring states that variates of standard measures are `Real`s, and the redesign notes name the new multiplicity type. Created by generative AI.
Adds static stream multiplicities (as a tuple of static integers and as a `StaticArrays.Size`) through the batched with-rest transport and density kernels of static powers and combined measures, the batched transports and `logdensities` on a static batch with the broadcast hook, and allocation checks for `rand`. The nested-power test checks the layout instead of pinning the container type. Created by generative AI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Written by Claude (Fable 5.1, high effort) on behalf of the maintainer.
Work in progress. Breaking major upgrade of MeasureBase: batching built into the foundation, GPU (CUDA, JLArrays) and Reactant support, and a rebuilt transport and random variate layer.
The approach, concepts, extension points, layout rules, the list of changes relative to
main, and the open decisions are documented inredesign.mdin the repository root. That file is kept up to date while the branch evolves and will be removed before the merge.In short:
batched_logdensityof_impl,batched_transport_to_std/_from_std,batched_rand_impl) are the primary extension points; single variates are batches with zero batch dimensions.mspace_ndims), sizes are optional declarations. Composed measures consume flat variate streams with the with-rest protocol.GenContextcompute unit.asmeasureget device-friendly kernels: the main univariate families,MvNormalandDirichletevaluate, transport and draw in batches on GPUs and under Reactant (with a few upstream limits noted inredesign.md).test/cudais an opt-in runner.Still to do before merging: the open decisions listed in
redesign.md, a docs pass, NEWS, history curation and a version bump.https://claude.ai/code/session_01L5yPndh2K6u14z3CwF9YXf