From 492cfe8b53e79c15b23f937a4cf3dd1bd02c5838 Mon Sep 17 00:00:00 2001 From: Pedro Martinez Mediano Date: Tue, 23 May 2017 16:19:33 +1000 Subject: [PATCH] Added Java+JNI support for surrogate reorderings. --- ...tualInfoCalculatorMultiVariateKraskov.java | 39 ++++++++++++++-- .../continuous/kraskov/cuda/kraskovCuda.c | 46 +++++++++++++++++-- 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/java/source/infodynamics/measures/continuous/kraskov/MutualInfoCalculatorMultiVariateKraskov.java b/java/source/infodynamics/measures/continuous/kraskov/MutualInfoCalculatorMultiVariateKraskov.java index 9212244..2343b40 100755 --- a/java/source/infodynamics/measures/continuous/kraskov/MutualInfoCalculatorMultiVariateKraskov.java +++ b/java/source/infodynamics/measures/continuous/kraskov/MutualInfoCalculatorMultiVariateKraskov.java @@ -601,7 +601,8 @@ public abstract class MutualInfoCalculatorMultiVariateKraskov * to the GPU code. */ protected double[] gpuComputeFromObservations(int startTimePoint, - int numTimePoints, boolean returnLocals, int nb_surrogates) throws Exception { + int numTimePoints, boolean returnLocals, int nb_surrogates, + int[][] newOrderings) throws Exception { if (debug) { System.out.println("Start GPU calculation"); @@ -622,8 +623,12 @@ public abstract class MutualInfoCalculatorMultiVariateKraskov double[] res; try { + if (debug) { + System.out.printf("Calling GPU calculation with returnLocals=%b and nb_surrogates=%d\n", returnLocals, nb_surrogates); + } res = MIKraskov(totalObservations, sourceObservations, dimensionsSource, - destObservations, dimensionsDest, k, returnLocals, useMaxNorm, isAlgorithm1, nb_surrogates); + destObservations, dimensionsDest, k, returnLocals, useMaxNorm, + isAlgorithm1, nb_surrogates, null!=newOrderings, newOrderings); if (debug) { System.out.println("GPU calculation finished successfully. Returning results"); } @@ -642,7 +647,16 @@ public abstract class MutualInfoCalculatorMultiVariateKraskov */ protected double[] gpuComputeFromObservations(int startTimePoint, int numTimePoints, boolean returnLocals) throws Exception { - return gpuComputeFromObservations(startTimePoint, numTimePoints, returnLocals, 0); + return gpuComputeFromObservations(startTimePoint, numTimePoints, returnLocals, 0, null); + } + + /** + * FIXME + */ + protected double[] gpuComputeFromObservations(int startTimePoint, + int numTimePoints, boolean returnLocals, int[][] newOrderings) throws Exception { + return gpuComputeFromObservations(startTimePoint, numTimePoints, + returnLocals, newOrderings.length, newOrderings); } /** @@ -651,7 +665,7 @@ public abstract class MutualInfoCalculatorMultiVariateKraskov private native double[] MIKraskov( int N, double[][] source, int dimx, double[][] dest, int dimy, int k, boolean returnLocals, boolean useMaxNorm, boolean isAlgorithm1, - int nb_surrogates); + int nb_surrogates, boolean orderingsGiven, int[][] newOrderings); /** * Internal method to ensure that the Kd-tree data structures to represent the @@ -738,13 +752,28 @@ public abstract class MutualInfoCalculatorMultiVariateKraskov public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception { if (useGPU) { - double[] res = gpuComputeFromObservations(0, totalObservations, false, numPermutationsToCheck); + double[] res = gpuComputeFromObservations(0, totalObservations, false, numPermutationsToCheck, null); return new EmpiricalMeasurementDistribution( MatrixUtils.select(res, 1, res.length - 1), res[0]); } else { return super.computeSignificance(numPermutationsToCheck); } } + + /** + * {@inheritDoc} + */ + @Override + public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) + throws Exception { + if (useGPU) { + double[] res = gpuComputeFromObservations(0, totalObservations, false, newOrderings.length, newOrderings); + return new EmpiricalMeasurementDistribution( + MatrixUtils.select(res, 1, res.length - 1), res[0]); + } else { + return super.computeSignificance(newOrderings); + } + } /** * Compute the prediction error in one variable from the k nearest neighbours (kNNs) of the observation diff --git a/java/source/infodynamics/measures/continuous/kraskov/cuda/kraskovCuda.c b/java/source/infodynamics/measures/continuous/kraskov/cuda/kraskovCuda.c index 77b3843..836154d 100644 --- a/java/source/infodynamics/measures/continuous/kraskov/cuda/kraskovCuda.c +++ b/java/source/infodynamics/measures/continuous/kraskov/cuda/kraskovCuda.c @@ -12,7 +12,7 @@ extern "C" { /* * Class: infodynamics_measures_continuous_kraskov_MutualInfoCalculatorMultiVariateKraskov * Method: MIKraskov - * Signature: (I[DI[DIIZZZI)[D + * Signature: (I[DI[DIIZZZIZ[I)[D */ JNIEXPORT jdoubleArray JNICALL Java_infodynamics_measures_continuous_kraskov_MutualInfoCalculatorMultiVariateKraskov_MIKraskov( @@ -20,7 +20,8 @@ JNIEXPORT jdoubleArray JNICALL jobjectArray j_sourceArray, jint j_dimx, jobjectArray j_destArray, jint j_dimy, jint j_k, jboolean j_returnLocals, jboolean j_useMaxNorm, - jboolean j_isAlgorithm1, jint j_nbSurrogates) { + jboolean j_isAlgorithm1, jint j_nbSurrogates, + jboolean j_reorderingsGiven, jobjectArray j_orderings) { int thelier = 0; @@ -55,6 +56,7 @@ JNIEXPORT jdoubleArray JNICALL int useMaxNorm = j_useMaxNorm ? 1 : 0; int isAlgorithm1 = j_isAlgorithm1 ? 1 : 0; int nb_surrogates = j_nbSurrogates; + int reorderingsGiven = j_reorderingsGiven ? 1 : 0; float *source = (float *) malloc(N * dimx * sizeof(float)); float *dest = (float *) malloc(N * dimy * sizeof(float)); @@ -110,6 +112,24 @@ JNIEXPORT jdoubleArray JNICALL } + int **reorderings = NULL; + if (reorderingsGiven) { + reorderings = (int **) malloc(nb_surrogates * sizeof(int *)); + for (int i = 0; i < nb_surrogates; i++) { + jintArray j_order = (jdoubleArray) (*env)->GetObjectArrayElement(env, j_orderings, i); + jint *order = (*env)->GetIntArrayElements(env, j_order, NULL); + + reorderings[i] = (int *) malloc(N * sizeof(int)); + for (int j = 0; j < N; j++) { + reorderings[i][j] = order[j]; + } + + (*env)->ReleaseIntArrayElements(env, j_order, order, 0); + (*env)->DeleteLocalRef(env, j_order); + } + } + + // Call C function // ========================= @@ -122,9 +142,18 @@ JNIEXPORT jdoubleArray JNICALL resultSize = 3; } float *result = (float *) malloc(resultSize * sizeof(float)); - jidt_error_t ret = MIKraskov_C(N, source, dimx, dest, dimy, - k, thelier, nb_surrogates, returnLocals, useMaxNorm, - isAlgorithm1, result); + jidt_error_t ret; + if (!reorderingsGiven) { + ret = MIKraskov_C(N, source, dimx, dest, dimy, + k, thelier, nb_surrogates, returnLocals, useMaxNorm, + isAlgorithm1, result); + + } else { + ret = MIKraskovWithReorderings(N, source, dimx, dest, dimy, k, thelier, + nb_surrogates, returnLocals, useMaxNorm, + isAlgorithm1, result, reorderingsGiven, + reorderings); + } if (JIDT_ERROR == ret) { jclass Exception = (*env)->FindClass(env, "java/lang/Exception"); @@ -136,6 +165,13 @@ JNIEXPORT jdoubleArray JNICALL if (source) free(source); if (dest) free(dest); + if (reorderingsGiven) { + for (int i = 0; i < nb_surrogates; i++) { + if (reorderings[i]) free(reorderings[i]); + } + if (reorderings) free (reorderings); + } + jdouble outCArray[resultSize]; for (int i = 0; i < resultSize; i++) { outCArray[i] = result[i];