Folded Distributions
Folded Distributions
Here's a Generic implementation for Folded continuous univariate distributions. I worked on this a while ago and only recently cleaned it up. This has been useful to me in my research and hopefully is helpful to others as well.
Definition
A folded distribution $F_{c}(D)$ of a distribution $D$ at crease $c \in \mathbb{R}$ is the reflection of the distribution below $c$ onto the the distribution above $c$.
The pdf of such a distribution is given by:
$$ p(x | F_{c}(D)) = p(x | D) + p(x' | D) $$
where $x' = 2c - x$
Interface
The interface is very very similar to the truncated interface.
You can take any continuous univariate distribution and make it into a folded distribution like so:
julia> normal_absolute = folded(Normal(2.0,1.0), 0.0)
# Folded(Normal{Float64}(μ=2.0, σ=1.0); crease = 0.0 | fold left onto right)
julia> plot(x -> pdf(normal_absolute, x))
This gives the result:

The folded function creates a folded distribution from the original distribution d about the value crease.
This function defaults to folding the left side onto the right, but by using keep_right=false one can reflect the right side onto the left.
This can be implemented for any univariate continuous distribution by using the following method:
folded(d::ContinuousUnivariateDistribution, crease::Real)
If one wants to reflect points above the crease $c$ onto points below $c$ (such that the resultant distribution lives on points below $c$) one can do that using the keep_right=false tag:
folded(d::ContinuousUnivariateDistribution, crease::Real, keep_right=false)
A very useful and oft-occuring example of this is the action of the absolute value function ($|\cdot|$) on random variables. For example if we have a random variable obeying the normal distribution: $$\hat{X} \sim \mathcal{N}(\alpha,\beta)$$
Taking the absolute value of this random variable always follows a folded normal distribution with a crease at $0$
$$|\hat{X}| \sim F_{c=0}(\mathcal{N}(\alpha,\beta))$$ In julia that looks like:
folded_normal = folded(Normal(μ,σ), 0.0)
and then we can ask for many things like the pdf, or sample the distribution. The samples of course will then be positive:
all(rand(folded_normal, 1000) .≥ 0) # True
In general, one can take any univariate continous distribution and fold it using this function.
Example
We can create the absolute value of the laplace distribution by:
folded_laplace = folded(Laplace(μ,b), 0.0)
as a quick check we can see if the 1000 samples generated from this are all greater than 0:
all(rand(folded(Lapace(μ,b),0),1000) .≥ 0) # -> true
For more one can check the docs in the PR.
With this addition one should be able to define stuff like the distribution of the absolute value of any univariate random variable.
Distributions this could lead to
In issue #124 ,there was a desire to implement the following distributions:
- foldcauchy - A folded Cauchy continuous random variable
- foldnorm - A folded normal continuous random variable
- halfcauchy - A Half-Cauchy continuous random variable
- halflogistic - A half-logistic continuous random variable
- halfnorm - A half-normal continuous random variable
and all of these can be implemented very easily using the
foldedfunction.
For example, an implementation of the HalfNormal distribution, would be as simple as
halfnorm(σ) = folded(Normal(zero(σ), σ), zero(σ))
The others can be implemented similarly very easily. The Folded generic subsumes all these cases.
Conclusion & Why would this be useful?
I've added tests and docs, and wanted to see if this is an appropriate inclusion to the package. Let me know if this is would be welcomed by this package, and if there's anything I should add to the tests or the docs, or change the code style.
Thank you for all the work you all do on this amazing package!
This is a brilliant incredibly useful idea!!!
This is a brilliant incredibly useful idea!!!
Thank you so much! Hoping this can get merged soon 🤞
Hi! Just wanted to get an update on this if this is good enough to merge - I think it's ready for review from my end. I understand the maintainers have a limited time so no worries at all, just wanted to bump this.
Hey @Potatoasad, I had just hacked together a Folded distribution for my own research and just now saw your PR. I'd be happy to review it and will try to do so this weekend.
Thank you so much for the detailed review! I'll pour over these and make the changes as needed thank you so much for the feedback and explanations.
Thank you so much for the detailed review! I'll pour over these and make the changes as needed thank you so much for the feedback and explanations.
@Potatoasad have you had any luck with this?
Thank you so much for the detailed review! I'll pour over these and make the changes as needed thank you so much for the feedback and explanations.
@Potatoasad have you had any luck with this?
Hey, sorry. Yes I did make some slight progress, but got sidetracked into a paper I was working on. I think I can finish this up in the next two weeks. Apologies for the very long delay on this.
Thank you so much for the detailed review! I'll pour over these and make the changes as needed thank you so much for the feedback and explanations.
@Potatoasad have you had any luck with this?
Hey, sorry. Yes I did make some slight progress, but got sidetracked into a paper I was working on. I think I can finish this up in the next two weeks. Apologies for the very long delay on this.
Hi, just wanted to know if you're still interested in working on this :)
Codecov Report
Patch coverage is 59.25% of modified lines.
:exclamation: Current head 009f83d differs from pull request most recent head f79504f. Consider uploading reports for the commit f79504f to get more accurate results
| Files Changed | Coverage |
|---|---|
| src/Distributions.jl | ø |
| src/fold.jl | 59.25% |
:loudspeaker: Thoughts on this report? Let us know!.