Suppose I wanna compute the mean of every distribution in Distributions.jl.

I create a vector w/ all distributions then loop through each & compute the mean.

Thanks to @tfehring for showing me how to pull all the distributions.

```
using Distributions
subtypes(Distribution) #Vector{Any} with 78 elements
D_m = []; E_m = []; #
for d = subtypes(Distribution)
try
fn = mean(d())
push!(D_m, [d, fn])
catch e
println("Err ", d, e)
push!(E_m, [d, e])
end
end
```

This works for distributions w/ default parameters:

Example: `mean(Arcsine())`

It does not work for distributions w/o default parameter values:

Example: Chi(Î˝) has one parameter w/ no default values.

I need help w/ the following, as I loop over a distribution â€śdâ€ť w/o default parameter values:

- for simplicity letâ€™s choose the first method

methods(d).ms[1]

Example Chi: methods(Chi).ms[1] gives: `(::Type{Chi})(Î˝::Integer)`

- find the number of arguments in the first method
- find the required type of each argument in the first method (real number, matrix etc)
- fill in some arbitrary legal values for each parameter in the first method

Use the simplest for each. Eg if itâ€™s a matrix, set mu= [0], sigma=[1]â€¦
- compute the mean

This turned out to be non-trivial for me.

Yes, I realize some of these distributions are abstract structures for which it wonâ€™t be possible.

Which step is the problem?

The number and types of arguments are `methods(d).ms[1].sig`

. It looks like itâ€™s a tuple where the first element is `typeof(d)`

, and the rest (`Base.tail`

) are the types of expected arguments.

To provide a value of an arbitrary type is the most difficult part to me, Iâ€™ve no idea how to do that in a generic way, thereâ€™s only hope that thereâ€™s a method which accepts types you know how to instantiate.

1 Like

@Vasily_Pisarev

My goal is to compute the mean of every distribution.

- If it has default values for parameters then:
`mean(Normal())`

- If not, to automatically set legal parameter values.

`Chi()`

doesnâ€™t work bc it doesnâ€™t have a default parameter.

methods(Chi).ms[1] tells me it has 1 param which is an Integer: `(::Type{Chi})(Î˝::Integer)`

I want the loop to automatically: `mean(Chi(1))`

This can be tricky: `methods(NormalInverseGaussian).ms[1]`

has four param, all integers

I want: `mean(NormalInverseGaussian(1,1,1,1))`

`methods(MvNormal).ms[1]`

: (ÎĽ::AbstractArray{T,1}, ÎŁ::PDMats.AbstractPDMat{T}) where T<:Real

I want: `mean(MvNormal([1],[1]))`

I want the loop to do this all automatically.

For each method signature in the table, you have a tuple-type like `Tuple{Type{Uniform}, Integer}`

. You can do `Base.tail(Tuple(tuptype.parameters))`

to get the â€śeverything elseâ€ť of that method. From there I suppose you could try calling `one`

on everything in that list and hoping thereâ€™s a method out there . Assuming this works for you, you could ostensibly do it like: `distr(one.(the_tail)...)`

Just as a heads up, I generated the full list (of â€śfirstâ€ť methods) with

```
map(x-> isabstracttype(x) ? nothing : methods(x).ms[1].sig, subtypes(Distribution))
```

and took a look through it. Thereâ€™s some definite oddballs that will give you a hard time time. e.g.

```
Tuple{Type{DirichletMultinomial},Integer,Array{T,1}} where T<:Integer # default array size?
Tuple{Type{Truncated},Distribution{Univariate,S} where S<:ValueSupport,Integer,Integer} # default distribution?
```

You are running into difficulties because this is an ill-defined problem: mostly, the vocabulary of Distributions.jl is not *distributions*, but *functions that generate distributions* (constructors). The distinction is important.

What you would need is either an API that allows you to query the space of valid arguments, or generates â€śsomeâ€ť valid instance of each distribution class. Neither exists, because it is a pretty rare use case.

What are you trying to accomplish?

1 Like