Library · Geometric Probability · Chapter 27
Wendel’s theorem on the sphere
Problem 27.1
Four points are chosen independently and uniformly on a sphere. What is the probability that the tetrahedron they form contains the centre of the sphere?
Solution. By rotational symmetry, a uniform random point on the sphere and its antipode are identically distributed. For four independent uniform points , the configurations obtained by independently reflecting each point through the centre, all have the same joint distribution.
Claim: among these configurations, exactly produce a tetrahedron containing the centre. Given the claim, the probability of interest is .
Proof of the claim. The tetrahedron with vertices contains the origin iff no open hemisphere contains all four vertices. Fix in general position, and consider the sign patterns .
Form the matrix whose columns are the . General position means every three columns are linearly independent, so has rank and its nullspace is one-dimensional. Choose a nonzero vector with . Each is nonzero: otherwise the other three columns would be dependent.
For the sign pattern , the origin lies in the convex hull iff there are weights , with , such that . Thus must be a scalar multiple of . Since every , all must be positive, and this is possible exactly when for every , or when all those signs are reversed. Conversely, for either pattern the weights work. Exactly two of the sixteen patterns therefore contain the origin.
Hence
The pattern fits a more general formula. Wendel (1962) proved that for iid uniform points on the unit sphere in , the probability that their convex hull contains the centre is For this gives ; for it gives . The argument is the same: independence of antipodal flips plus a counting lemma.
import numpy as np
# Uniform on sphere via normalised Gaussian
pts = np.random.randn(3, 4, 10**6)
pts /= np.linalg.norm(pts, axis=0)
def svol(a, b, c, d):
return np.einsum('i...,i...->...', b-a, np.cross((c-a).T, (d-a).T).T)
O = np.zeros_like(pts[:, 0])
s0 = svol(pts[:, 0], pts[:, 1], pts[:, 2], pts[:, 3])
s = [svol(O, pts[:, 1], pts[:, 2], pts[:, 3]),
svol(pts[:, 0], O, pts[:, 2], pts[:, 3]),
svol(pts[:, 0], pts[:, 1], O, pts[:, 3]),
svol(pts[:, 0], pts[:, 1], pts[:, 2], O)]
contains = np.all([np.sign(si) == np.sign(s0) for si in s], axis=0)
print(f"sim: {contains.mean():.5f} exact: 0.125")
# sim: 0.12548 exact: 0.125