C API

This chapter describes the mine C library. These functions and structures are declared in the header file mine.h, located in the libmine/ folder. You need to add #include "mine.h" in your C source files and link your program with mine.c.

Defines

EST_MIC_APPROX 0

Original estimator described in DOI: 10.1126/science.1205438.

EST_MIC_E 1

Estimator described in DOI: arXiv:1505.02213 and DOI: arXiv:1505.02214.

FALSE 0

False value.

TRUE 1

True value.

char *libmine_version

The libmine version in the form X.Y.Z (e.g., 1.0.1).

Structures

mine_problem

The mine_problem structure describes the problem. x and y are the two variables of length n.

typedef struct mine_problem
  {
    int n;
    double *x;
    double *y;
  } mine_problem
mine_parameter

MINE parameters.

alpha : (0, 1.0] or >=4
if alpha is in (0,1] then B will be max(n^alpha, 4) where n is the number of samples. If alpha is >=4 then alpha defines directly the B parameter. If alpha is higher than the number of samples (n) it will be limited to be n, so B = min(alpha, n).
c : (> 0)
determines how many more clumps there will be than columns in every partition. Default value is 15, meaning that when trying to draw x grid lines on the x-axis, the algorithm will start with at most 15*x clumps.
est : (EST_MIC_APPROX, EST_MIC_E)
estimator. With est=EST_MIC_APPROX the original MINE statistics will be computed, with est=EST_MIC_E the equicharacteristic matrix is is evaluated and the mine_mic() and mine_tic() functions will return MIC_e and TIC_e values respectively.
typedef struct mine_parameter
  {
    double alpha;
    double c;
    int est;
  } mine_parameter
mine_score

The mine_score structure contains the maximum normalized mutual information scores (i.e. the characteristic matrix if est=EST_MIC_APPROX, the equicharacteristic matrix instead). M[i][j] contains the score using a grid partitioning x-values into i+2 bins and y-values into j+2 bins. m and M are of length n and each M[i] is of length m[i].

typedef struct mine_score
  {
    int n;      /* number of rows of M */
    int *m;     /* number of cols of M[i] for each i */
    double **M; /* the (equi)characteristic matrix */
  } mine_score

Functions

mine_score *mine_compute_score(mine_problem *prob, mine_parameter *param)

Computes the (equi)characteristic matrix (i.e. maximum normalized mutual information scores) and returns a mine_score structure. Returns NULL if an error occurs.

char *mine_check_parameter(mine_parameter *param)

Checks the parameters. This function should be called before calling mine_compute_score(). It returns NULL if the parameters are feasible, otherwise an error message is returned. See the mine_parameter documentation.

double mine_mic(mine_score *score)

Returns the Maximal Information Coefficient (MIC or MIC_e).

double mine_mas(mine_score *score)

Returns the Maximum Asymmetry Score (MAS).

double mine_mev(mine_score *score)

Returns the Maximum Edge Value (MEV).

double mine_mcn(mine_score *score, double eps)

Returns the Minimum Cell Number (MCN) with epsilon >= 0.

double mine_mcn_general(mine_score *score)

Returns the Minimum Cell Number (MCN) with eps=1 - MIC.

double mine_tic(mine_score *score, int norm)

Returns the Total Information Coefficient (TIC or TIC_e). norm=TRUE normalizes the Total Information Coefficient, returning values in [0, 1].

double mine_gmic(mine_score *score)

Returns the Generalized Mean Information Coefficient (GMIC).

void mine_free_score(mine_score **score)

This function frees the memory used by a mine_score and destroys the score structure.

Convenience structures and functions

mine_matrix

Mine matrix, variables x samples.

typedef struct mine_matrix
  {
    double *data; /* matrix in row-major order */
    int n;        /* number of rows */
    int m;        /* number of cols */
  } mine_matrix
mine_pstats

For each statistic, the upper triangle of the matrix is stored by row (condensed matrix). If m is the number of variables, then for i<j<m, the statistic between (row) i and j is stored in k = m*i - i*(i+1)/2 - i - 1 + j. The length of the vectors is n = m*(m-1)/2.

typedef struct mine_pstats
  {
    double *mic; /* condensed matrix */
    double *tic; /* condensed matrix */
    int n;       /* number of elements */
  } mine_pstats
mine_cstats

For each statistic, the matrix is stored by row. If n and m are the number of variables in X and Y respectively, then the statistic between the (row) i (for X) and j (for Y) is stored in k = i*m + j. The length of the vector is d = n*m.

typedef struct mine_cstats
  {
    double *mic; /* matrix in row-major order */
    double *tic; /* matrix in row-major order */
    int n;       /* number of rows */
    int m;       /* number of cols */
  } mine_cstats
mine_pstats *mine_compute_pstats(mine_matrix *X, mine_parameter *param)

Compute pairwise statistics (MIC and normalized TIC) between variables.

mine_cstats *mine_compute_cstats(mine_matrix *X, mine_matrix *Y, mine_parameter *param)

Compute statistics (MIC and normalized TIC) between each pair of the two collections of variables.

Example

The example is located in examples/c_example.c.

/*
 * $ gcc c_example.c -O3 -Wall ../libmine/mine.c -I../libmine/ -lm
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include "mine.h"


int main (int argc, char **argv)
{
  mine_problem prob;
  mine_parameter param;
  mine_score *score;

  double PI = 3.14159265;
  int i, j;
  char *ret;

  printf("libmine version %s\n", libmine_version);

  /* set the parameters */
  param.alpha = 0.6;
  param.c = 15;
  param.est = EST_MIC_APPROX;

  /* check the parameters */
  ret = mine_check_parameter(&param);
  if (ret)
    {
      printf("ERROR: %s\n\n", ret);
      return 1;
    }

  /* build the problem */
  prob.n = 201;
  prob.x = (double *) malloc (prob.n * sizeof (double));
  prob.y = (double *) malloc (prob.n * sizeof (double));
  for (i=0; i<prob.n; i++)
    {
      /* build x = [0, 0.005, ..., 1] */
      prob.x[i] = (double) i / (double) (prob.n-1);

      /* build y = sin(10 * pi * x) + x */
      prob.y[i] = sin(10 * PI * prob.x[i]) + prob.x[i];
    }

  /* compute score */
  clock_t start = clock();
  score = mine_compute_score(&prob, &param);
  clock_t end = clock();
  printf("Elapsed time: %.6f seconds\n\n",
         (double)(end - start) / CLOCKS_PER_SEC);

  if (score == NULL)
    {
      printf("ERROR: mine_compute_score()\n");
      return 1;
    }

  /* print some MINE statistics */
  printf ("Some MINE statistics:\n\n");
  printf ("MIC: %.3lf\n", mine_mic(score));
  printf ("MEV: %.3lf\n", mine_mev(score));
  printf ("MCN (eps=0): %.3lf\n", mine_mcn(score, 0));


  /* print the characteristic matrix M */
  printf ("\nCharacteristic Matrix:\n\n");

  for (i=0; i<score->n; i++)
    {
      for (j=0; j<score->m[i]; j++)
  	    printf ("%.3lf ", score->M[i][j]);
      printf ("\n");
    }

  /* free score */
  mine_free_score(&score);

  /* free prob */
  free(prob.x);
  free(prob.y);

  return 0;
}

To compile the example, open a terminal, go into the example (examples/) folder and run:

$ gcc c_example.c -Wall ../libmine/mine.c -I../libmine/ -lm

or

$ gcc c_example.c -O3 -Wall ../libmine/mine.c -I../libmine/ -lm

for an extensive optimization. Run the example by typing:

$ ./a.out
libmine version 1.1.0
Elapsed time: 0.011288 seconds

Some MINE statistics:

MIC: 1.000
MEV: 1.000
MCN (eps=0): 4.585

Characteristic Matrix:

0.108 0.146 0.226 0.347 0.434 0.545 0.639 0.740 0.863 0.932 1.000
0.199 0.138 0.169 0.256 0.298 0.379 0.427
0.237 0.190 0.217 0.286 0.324
0.247 0.198 0.191
0.262 0.213 0.232
0.272 0.225
0.286 0.237
0.296
0.308
0.321
0.333

Example (convenience functions)

The example is located in examples/c_conv_example.c.

/*
 * $ gcc c_conv_example.c -O3 -Wall ../libmine/mine.c -I../libmine/ -lm
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include "mine.h"


int main (int argc, char **argv)
{
  mine_parameter param;
  mine_matrix X, Y;
  mine_pstats *pstats;
  mine_cstats *cstats;

  int i, j, k, z;
  char *ret;


  printf("libmine version %s\n\n", libmine_version);

  /* set the parameters */
  param.alpha = 9;
  param.c = 5;
  param.est = EST_MIC_E;

  /* check the parameters */
  ret = mine_check_parameter(&param);
  if (ret)
    {
      printf("ERROR: %s\n", ret);
      return 1;
    }

  /* build the X matrix */
  X.n = 8;   /* 8 variables */
  X.m = 320; /* 320 samples */
  X.data = (double *) malloc ((X.n * X.m) * sizeof(double));
  for (i=0; i<(X.n * X.m); i++)
    X.data[i] = (double) rand() / (RAND_MAX);

  /* build the Y matrix */
  Y.n = 4;    /* 4 variables */
  Y.m = 320;  /* 320 samples */
  Y.data = (double *) malloc ((Y.n * Y.m) * sizeof(double));
  for (i=0; i<(Y.n * Y.m); i++)
    Y.data[i] = (double) rand() / (RAND_MAX);

  /* compute pairwise statistics between samples in X */
  pstats = mine_compute_pstats(&X, &param);

  if (pstats == NULL)
    {
      printf("ERROR: pstats()\n");
      return 1;
    }

  /* print the TIC matrix */
  printf("     ");
  for (j=1; j<X.n; j++)
    printf("X[%d]  ", j);
  printf("\n");
  k = 0;
  for (i=0; i<X.n-1; i++)
    {
      printf("X[%d] ", i);
      for (z=0; z<i; z++)
        printf("      ");

      for (j=i+1; j<X.n; j++)
        {
          printf("%.3lf ", pstats->tic[k]);
          k++;
        }
      printf("\n");
    }

  /* free pstats */
  free(pstats->mic);
  free(pstats->tic);
  free(pstats);

  printf("\n");

  /* compute statistics between each pair of samples in X and Y */
  cstats = mine_compute_cstats(&X, &Y, &param);

  if (cstats == NULL)
    {
      printf("ERROR: cstats()\n");
      return 1;
    }

  /* print the TIC matrix */
  printf("     ");
  for (j=0; j<Y.n; j++)
    printf("Y[%d]  ", j);
  printf("\n");
  for (i=0; i<X.n; i++)
    {
      printf("X[%d] ", i);
      for (j=0; j<Y.n; j++)
        printf("%.3lf ", cstats->tic[(i*Y.n)+j]);
      printf("\n");
    }

  /* free cstats */
  free(cstats->mic);
  free(cstats->tic);
  free(cstats);

  /* free data */
  free(X.data);
  free(Y.data);

  return 0;
}

To compile the example, open a terminal, go into the example (examples/) folder and run:

$ gcc c_conv_example.c -O3 -Wall ../libmine/mine.c -I../libmine/ -lm

Run the example by typing:

$ ./a.out
libmine version 1.2.0

     X[1]  X[2]  X[3]  X[4]  X[5]  X[6]  X[7]
X[0] 0.008 0.011 0.011 0.013 0.011 0.007 0.010
X[1]       0.010 0.012 0.015 0.020 0.010 0.011
X[2]             0.015 0.016 0.013 0.012 0.019
X[3]                   0.016 0.016 0.012 0.017
X[4]                         0.010 0.013 0.016
X[5]                               0.010 0.015
X[6]                                     0.018

     Y[0]  Y[1]  Y[2]  Y[3]
X[0] 0.012 0.012 0.016 0.010
X[1] 0.010 0.011 0.013 0.014
X[2] 0.013 0.011 0.012 0.016
X[3] 0.016 0.009 0.014 0.011
X[4] 0.007 0.022 0.018 0.017
X[5] 0.011 0.015 0.015 0.009
X[6] 0.012 0.007 0.015 0.013
X[7] 0.017 0.010 0.010 0.009