I've looked around and all solutions for generating uniform random points in/on the unit ball are designed for 2 or 3 dimensions.
What is a (tractable) way to generate uniform random points inside a ball in arbitrary dimension? Particularly, not just on the surface of the ball.
To preface, generating random points in the cube and throwing out the points with norm greater than 1 is not feasible in high dimension. The ratio of the volume of a unit ball to the volume of a unit cube in high dimension goes to 0. Even in 10 dimensions only about 0.25% of random points in the unit cube are also inside the unit ball.
The best way to generate uniformly distributed random points in a
d
-dimension ball appears to be by thinking of polar coordinates (directions instead of locations). Code is provided below.d
dimensions.This selection process will (1) make all directions equally likely, and (2) make all points on the surface of balls within the unit ball equally likely. This will generate our desired uniformly random distribution over the entire interior of the ball.
Picking a random direction (on the unit ball)
In order to achieve (1) we can randomly generate a vector from
d
independent draws of a Gaussian distribution normalized to unit length. This works because a Gausssian distribution has a probability distribution function (PDF) withx^2
in an exponent. That implies that the joint distribution (for independent random variables this is the multiplication of their PDFs) will have(x_1^2 + x_2^2 + ... + x_d^2)
in the exponent. Notice that resembles the definition of a sphere in d dimensions, meaning the joint distribution ofd
independent samples from a Gaussian distribution is invariant to rotation (the vectors are uniform over a sphere).Here is what 200 random points generated in 2D looks like.
Picking a random radius (with appropriate probability)
In order to achieve (2) we can generate a radius by using the inverse of a cumulative distribution function (CDF) that corresponds to the surface area of a ball in
d
dimensions with radiusr
. We know that the surface area of an n-ball is proportional tor^d
, meaning we can use this over the range[0,1]
as a CDF. Now a random sample is generated by mapping random numbers in the range[0,1]
through the inverse,r^(1/d)
.Here is a visual of the CDF of
x^2
(for two dimensions), random generated numbers in[0,1]
would get mapped to the corresponding x coordinate on this curve. (e.g..1
➞.317
)Code for the above
Finally, here is some Python code (assumes you have NumPy installed) that computes all of the above.
For posterity, here is a visual of 5000 random points generated with the above code.