libbingham C Tutorial


What is a Bingham Distribution?

The Bingham distribution is an antipodally-symmetric probability distribution on a unit hypersphere. Its probability density function (PDF) is

$$ f(\vec{x} ; \Lambda, V) = \frac{1}{F} \exp \{ \sum_{i=1}^d \lambda_i (\vec{v_i}^T \vec{x})^2 \} $$

where $\vec{x}$ is a unit vector on the surface of the sphere $\bf{S}^d \subset \bf{R}^{d+1}$, $F$ is a normalization constant, $\Lambda$ is a vector of non-positive ( $\leq 0$) concentration parameters, and the columns of the $(d+1) \times d$ matrix $V$ are orthogonal unit vectors.

Note that a large-magnitude $\lambda_i$ indicates that the distribution is highly peaked along the direction $\vec{v_i}$, while a small-magnitude $\lambda_i$ indicates that the distribution is spread out along $\vec{v_i}$.

The Bingham distribution is derived from a zero-mean Gaussian on $\bf{R}^{d+1}$, conditioned to lie on the surface of the unit hypersphere $\bf{S}^d$. Thus, the exponent of the Bingham PDF is the same as the exponent of a zero-mean Gaussian distribution (in principal components form, with one of the eigenvalues of the covariance matrix set to infinity).

The Bingham distribution is the maximum entropy distribution on the hypersphere which matches the sample inertia matrix $E[\vec{x} \vec{x}^T]$. Therefore, it may be better suited to representing random process noise on the hypersphere than some other distributions, such as (projected) tangent-space Gaussians. Binghams are also quite flexible, since a concentration parameter, $\lambda_i$, of zero indicates that the distribution is completely uniform in the direction of $\vec{v_i}$. They are therefore very useful in tracking problems where there is high, anisotropic noise.

C Support in libbingham / Installation

In bingham/c, run:

sudo make install

The main C header file in libbingham is located at bingham/c/include/bingham.h. Most functions only support Bingham distributions up to dimension 4. (That is, up to $\bf{S}^3$.)

Usage / Examples

After installation, to use the libbingham in your own project, add "-lbingham" to your linker flags include bingham.h at the top of your program. There are several example programs in bingham/c: bingham_sample.c, fit_bingham.c, bingham_lookup.c, cluster_bingham.c, and test_bingham.c.

Creating a Bingham Distribution in C

Bingham distributions are represented as a C struct, called bingham_t:

typedef struct {
  int d;       // dimensions
  double **V;  // axes
  double *Z;   // concentrations
  double F;    // normalization constant
  bingham_stats_t *stats;
} bingham_t;

The bingham_stats_t struct contains various statistics of the Bingham distribution, such as the entropy, mode, and scatter matrix. (See bingham.h for details.) To create a new bingham_t, use one of

void bingham_new(bingham_t *B, int d, double **V, double *Z);
void bingham_new_uniform(bingham_t *B, int d);
void bingham_new_S1(bingham_t *B, double *v1, double z1);
void bingham_new_S2(bingham_t *B, double *v1, double *v2, double z1, double z2);
void bingham_new_S3(bingham_t *B, double *v1, double *v2, double *v3, double z1, double z2, double z3);

For example,

bingham_t B;
bingham_new_uniform(&B, 4);

will create a new uniform 4-D Bingham distribution, as will

double Z[3] = {0, 0, 0};
double V[3][4] = {{0,1,0,0}, {0,0,1,0}, {0,0,0,1}};
double *Vp[3] = {&V[0][0], &V[1][0], &V[2][0]};
bingham_t B;
bingham_new(&B, 4, Vp, Z);


double v1[4] = {0,1,0,0};
double v2[4] = {0,0,1,0};
double v3[4] = {0,0,0,1};
bingham_t B;
bingham_new(&B, 4, v1, v2, v3, 0, 0, 0);

Note that all of the bingham_new functions will automatically compute the normalization constant, so there is no need to call bingham_F(bingham_t *B) unless you create the bingham_t manually.

Note: When you are finished using a bingham_t, be sure to free its contents with

void bingham_free(bingham_t *B);


Given a matrix X with unit vectors in the rows, you can compute the maximum likelihood Bingham distribution given X with

void bingham_fit(bingham_t *B, double **X, int n, int d);

where X is an n-by-d double matrix created by:

double **new_matrix2(int n, int m);

which can be found in bingham/c/include/bingham/util.h. For example,

// create n 4-D unit vectors
int n = 10;
double **X = new_matrix2(n,4);
for (int i = 0; i < n; i++) {
  for (int j = 0; j < 4; j++)
    X[i][j] = normrand(0,1);
  normalize(X[i], X[i], 4);

// fit a Bingham distribution to X
bingham_t B;
bingham_fit(&B, X, n, 4);

// do something with B here...

// cleanup

Note: bingham_fit() allocates memory in the bingham_t struct, so make sure the bingham_t you pass in is deallocated. Otherwise, calling bingham_fit() will result in a memory leak.


To sample n unit vectors from a Bingham distribution, use:

void bingham_sample(double **X, bingham_t *B, int n);

For example,

bingham_t B;
bingham_new_uniform(&B, 4);
double **X = new_matrix2(100,4);
bingham_sample(X, &B, 100);

Computing the PDF

To compute the PDF of a unit vector x under a Bingham B, use:

double bingham_pdf(double *x, bingham_t *B);

For example, assuming bingham_t B exists with B.d = 4,

double x[4] = {0,1,0,0};
double f = bingham_pdf(x, &B);