mine_pstats *mine_compute_pstats(mine_matrix *X, mine_parameter *param) { int i, j, k; mine_problem prob; mine_score *score; mine_pstats *stats; /* Allocate memory for stats */ stats = (mine_pstats *) malloc(sizeof(mine_pstats)); stats->n = (X->n * (X->n-1)) / 2; stats->mic = (double *) malloc(stats->n * sizeof(double)); stats->tic = (double *) malloc(stats->n * sizeof(double)); k = 0; prob.n = X->m; for (i=0; i<X->n-1; i++) { prob.x = &X->data[i*X->m]; for (j=i+1; j<X->n; j++) { prob.y = &X->data[j*X->m]; score = mine_compute_score(&prob, param); stats->mic[k] = mine_mic(score); stats->tic[k] = mine_tic(score, TRUE); mine_free_score(&score); k++; } } return stats; }
/* See mine.h */ double mine_mcn_general(mine_score *score) { int i, j; double log_xy; double score_min = DBL_MAX; double delta = 0.0001; /* avoids overestimation of mcn */ double mic = mine_mic(score); for (i=0; i<score->n; i++) for (j=0; j<score->m[i]; j++) { log_xy = log((i+2) * (j+2)) / log(2.0); if (((score->M[i][j]+delta) >= (mic * mic)) && (log_xy < score_min)) score_min = log_xy; } return score_min; }
/* * The gateway function * [A, M] = MINE_MEX(X, Y, ALPHA, C, EST) * A = [MIC, MAS, MEV, MCN, MCN_GENERAL, TIC] * M (optional) = characteristic matrix (square dense matrix) */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *x, *y; double alpha; int c, est; mwSize ncolsx, ncolsy; mine_problem problem; mine_parameter param; mine_score *score; char *ret; double *out; /* check for proper number of outputs */ if(nlhs > 2) mexErrMsgTxt("Too many output arguments."); /* check for proper number of arguments */ if(nrhs != 5) mexErrMsgTxt("Incorrect number of inputs."); /* check that number of rows in first input argument (x) is 1 */ if(mxGetM(prhs[0]) != 1) mexErrMsgTxt("X must be a row vector."); /* check that number of rows in second input argument (y) is 1 */ if(mxGetM(prhs[1]) != 1) mexErrMsgTxt("Y must be a row vector."); /* make sure the thirth input argument (alpha) is scalar */ if(!mxIsDouble(prhs[2]) || mxIsComplex(prhs[2]) || mxGetNumberOfElements(prhs[2]) != 1) mexErrMsgTxt("alpha must be a scalar."); /* make sure the fourth input argument (c) is scalar */ if(!mxIsDouble(prhs[3]) || mxIsComplex(prhs[3]) || mxGetNumberOfElements(prhs[3]) != 1) mexErrMsgTxt("c must be a scalar."); /* make sure the fifth input argument (est) is scalar */ if(!mxIsDouble(prhs[4]) || mxIsComplex(prhs[4]) || mxGetNumberOfElements(prhs[4]) != 1) mexErrMsgTxt("est must be a scalar."); /* get alpha, c and est */ alpha = mxGetScalar(prhs[2]); c = mxGetScalar(prhs[3]); est = (int) mxGetScalar(prhs[4]); /* create a pointers for X and Y */ x = mxGetPr(prhs[0]); y = mxGetPr(prhs[1]); ncolsx = mxGetN(prhs[0]); ncolsy = mxGetN(prhs[1]); /* check the number of elements of X and Y */ if (ncolsx != ncolsy) mexErrMsgTxt("X and Y must have the same number of elements."); /* build param */ param.alpha = alpha; param.c = c; param.est = est; /* check param */ ret = mine_check_parameter(¶m); if(ret) mexErrMsgTxt(ret); /* build problem */ problem.n = (int) ncolsx; problem.x = x; problem.y = y; /* compute the mutual information score */ score = mine_compute_score(&problem, ¶m); if(score == NULL) mexErrMsgTxt("Problem with mine_compute_score()."); /* build the output array*/ plhs[0] = mxCreateDoubleMatrix(1, 6, mxREAL); out = mxGetPr(plhs[0]); out[0] = mine_mic(score); out[1] = mine_mas(score); out[2] = mine_mev(score); out[3] = mine_mcn(score, 0); out[4] = mine_mcn_general(score); out[5] = mine_tic(score); /* return full characteristic matrix */ if (nlhs>1) { mwSize i, j, nrows, ncols; nrows = score->n; ncols = score->m[0]; plhs[1] = mxCreateDoubleMatrix(nrows, ncols, mxREAL); out = mxGetPr(plhs[1]); for (i=0; i<nrows; i++) { for (j=0; j<score->m[i]; j++) out[nrows*j + i] = score->M[i][j]; } } mine_free_score(&score); }
/* See mine.h */ double mine_gmic(mine_score *score, double p) { int i, j, k, Z, B; mine_score *score_sub, *C_star; double gmic; /* alloc score_sub */ score_sub = (mine_score *) malloc (sizeof(mine_score)); /* alloc C_star */ C_star = (mine_score *) malloc (sizeof(mine_score)); C_star->m = (int *) malloc(score->n * sizeof(int)); C_star->M = (double **) malloc (score->n * sizeof(double *)); for (i=0; i<score->n; i++) C_star->M[i] = (double *) malloc ((score->m[i]) * sizeof(double)); /* prepare score_sub */ score_sub->M = score->M; /* prepare C_star */ C_star->n = score->n; for (i=0; i<C_star->n; i++) C_star->m[i] = score->m[i]; /* compute C_star */ for (i=0; i<score->n; i++) for (j=0; j<score->m[i]; j++) { B = (i+2) * (j+2); score_sub->n = MAX((int) floor(B/2.0), 2) - 1; score_sub->m = (int *) malloc(score_sub->n * sizeof(int)); for (k=0; k<score_sub->n; k++) score_sub->m[k] = (int) floor((double) B / (double) (k+2)) - 1; C_star->M[i][j] = mine_mic(score_sub); free(score_sub->m); } /* p=0 -> geometric mean */ if (p == 0.0) { Z = 0; gmic = 1.0; for (i=0; i<C_star->n; i++) for (j=0; j<C_star->m[i]; j++) { gmic *= C_star->M[i][j]; Z++; } gmic = pow(gmic, (double) Z); } /* p!=0 -> generalized mean */ else { Z = 0; gmic = 0.0; for (i=0; i<C_star->n; i++) for (j=0; j<C_star->m[i]; j++) { gmic += pow(C_star->M[i][j], p); Z++; } gmic /= (double) Z; gmic = pow(gmic, 1.0/p); } free(score_sub); if (C_star->n != 0) { free(C_star->m); for (i=0; i<C_star->n; i++) free(C_star->M[i]); free(C_star->M); } free(C_star); return gmic; }
/* The gateway function * [MIC, MAS, MEV, MCN, MCN_GENERAL] = MINE_MEX(X, Y, ALPHA, C) */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *x, *y; double alpha; int c; mwSize ncolsx, ncolsy; mine_problem problem; mine_parameter param; mine_score *score; char *ret; double *out; /* check for proper number of outputs */ if(nlhs != 1) mexErrMsgTxt("One output required."); /* check for proper number of arguments */ if(nrhs != 4) mexErrMsgTxt("Incorrect number of inputs."); /* check that number of rows in first input argument (x) is 1 */ if(mxGetM(prhs[0]) != 1) mexErrMsgTxt("X must be a row vector."); /* check that number of rows in second input argument (y) is 1 */ if(mxGetM(prhs[1]) != 1) mexErrMsgTxt("Y must be a row vector."); /* make sure the thirth input argument (alpha) is scalar */ if(!mxIsDouble(prhs[2]) || mxIsComplex(prhs[2]) || mxGetNumberOfElements(prhs[2]) != 1) mexErrMsgTxt("alpha must be a scalar."); /* make sure the fourth input argument (c) is scalar */ if(!mxIsDouble(prhs[3]) || mxIsComplex(prhs[3]) || mxGetNumberOfElements(prhs[3]) != 1) mexErrMsgTxt("c must be a scalar."); /* get alpha and c */ alpha = mxGetScalar(prhs[2]); c = mxGetScalar(prhs[3]); /* create a pointers for X and Y */ x = mxGetPr(prhs[0]); y = mxGetPr(prhs[1]); ncolsx = mxGetN(prhs[0]); ncolsy = mxGetN(prhs[1]); /* check the number of elements of X and Y */ if (ncolsx != ncolsy) mexErrMsgTxt("X and Y must have the same number of elements."); /* build param */ param.alpha = alpha; param.c = c; /* check param */ ret = mine_check_parameter(¶m); if(ret) mexErrMsgTxt(ret); /* build problem */ problem.n = (int) ncolsx; problem.x = x; problem.y = y; /* compute the mutual information score */ score = mine_compute_score(&problem, ¶m); if(score == NULL) mexErrMsgTxt("Problem with mine_compute_score()."); /* build the output array*/ plhs[0] = mxCreateDoubleMatrix(1, 6, mxREAL); out = mxGetPr(plhs[0]); out[0] = mine_mic(score); out[1] = mine_mas(score); out[2] = mine_mev(score); out[3] = mine_mcn(score, 0); out[4] = mine_mcn_general(score); out[5] = mine_gmic(score); mine_free_score(&score); }