From a9b6b3e77ca8c051f1031003474e2e35dd4a3269 Mon Sep 17 00:00:00 2001 From: Joseph Lizier Date: Sat, 20 Apr 2024 18:52:10 +1000 Subject: [PATCH] Adding property to set random seed for noise addition to EntropyMultiVariate estimators (mimicing that for MI/CMI estimators), extending the fix for issue #99 to Entropy estimators --- .../EntropyCalculatorMultiVariate.java | 22 ++++++++++++ .../EntropyCalculatorMultiVariateCommon.java | 34 +++++++++++++------ 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/java/source/infodynamics/measures/continuous/EntropyCalculatorMultiVariate.java b/java/source/infodynamics/measures/continuous/EntropyCalculatorMultiVariate.java index 77ba113..b534966 100755 --- a/java/source/infodynamics/measures/continuous/EntropyCalculatorMultiVariate.java +++ b/java/source/infodynamics/measures/continuous/EntropyCalculatorMultiVariate.java @@ -61,6 +61,26 @@ public interface EntropyCalculatorMultiVariate * Property name for the number of dimensions */ public static final String NUM_DIMENSIONS_PROP_NAME = "NUM_DIMENSIONS"; + /** + * Property for whether we normalise the incoming observations to mean 0, + * standard deviation 1. + */ + public static final String NORMALISE_PROP_NAME = "NORMALISE"; + /** + * Property name for an amount of random Gaussian noise to be + * added to the data (default is 1e-8, matching the MILCA toolkit). + */ + public static final String PROP_ADD_NOISE = "NOISE_LEVEL_TO_ADD"; + /** + * Property name for the seed for the random number generator for noise to be + * added to the data (default is no seed) + */ + public static final String PROP_NOISE_SEED = "NOISE_SEED"; + /** + * Property value to indicate no seed for the random number generator for noise to be + * added to the data + */ + public static final String NOISE_NO_SEED_VALUE = "NONE"; /** * Set properties for the underlying calculator implementation. @@ -84,6 +104,8 @@ public interface EntropyCalculatorMultiVariate * by Kraskov for the KSG method though, so for the Kozachenko estimator we * use 1e-8 to match the MILCA toolkit (though note it adds in * a random amount of noise in [0,noiseLevel) ). + *
  • {@link #PROP_NOISE_SEED} -- a long value seed for the random noise generator or + * the string {@link MutualInfoCalculatorMultiVariate#NOISE_NO_SEED_VALUE} for no seed (default)
  • * * *

    Unknown property values are ignored.

    diff --git a/java/source/infodynamics/measures/continuous/EntropyCalculatorMultiVariateCommon.java b/java/source/infodynamics/measures/continuous/EntropyCalculatorMultiVariateCommon.java index ec09534..c31eafb 100644 --- a/java/source/infodynamics/measures/continuous/EntropyCalculatorMultiVariateCommon.java +++ b/java/source/infodynamics/measures/continuous/EntropyCalculatorMultiVariateCommon.java @@ -64,16 +64,6 @@ public abstract class EntropyCalculatorMultiVariateCommon implements EntropyCalc * standard deviation 1. */ protected boolean normalise = true; - /** - * Property for whether we normalise the incoming observations to mean 0, - * standard deviation 1. - */ - public static final String NORMALISE_PROP_NAME = "NORMALISE"; - /** - * Property name for an amount of random Gaussian noise to be - * added to the data (default is 1e-8, matching the MILCA toolkit). - */ - public static final String PROP_ADD_NOISE = "NOISE_LEVEL_TO_ADD"; /** * Whether to add an amount of random noise to the incoming data */ @@ -82,6 +72,14 @@ public abstract class EntropyCalculatorMultiVariateCommon implements EntropyCalc * Amount of random Gaussian noise to add to the incoming data */ protected double noiseLevel = (double) 0.0; + /** + * Has the user set a seed for the random noise + */ + protected boolean noiseSeedSet = false; + /** + * Seed that the user set for the random noise + */ + protected long noiseSeed = 0; /** * Storage for observations supplied via {@link #addObservations(double[][])} * type calls @@ -132,6 +130,13 @@ public abstract class EntropyCalculatorMultiVariateCommon implements EntropyCalc addNoise = true; noiseLevel = Double.parseDouble(propertyValue); } + } else if (propertyName.equalsIgnoreCase(PROP_NOISE_SEED)) { + if (propertyValue.equals(NOISE_NO_SEED_VALUE)) { + noiseSeedSet = false; + } else { + noiseSeedSet = true; + noiseSeed = Long.parseLong(propertyValue); + } } else { // No property was set propertySet = false; @@ -150,6 +155,12 @@ public abstract class EntropyCalculatorMultiVariateCommon implements EntropyCalc return Boolean.toString(normalise); } else if (propertyName.equalsIgnoreCase(PROP_ADD_NOISE)) { return Double.toString(noiseLevel); + } else if (propertyName.equalsIgnoreCase(PROP_NOISE_SEED)) { + if (noiseSeedSet) { + return Long.toString(noiseSeed); + } else { + return NOISE_NO_SEED_VALUE; + } } else { // No property was set, and no superclass to call: return null; @@ -188,6 +199,9 @@ public abstract class EntropyCalculatorMultiVariateCommon implements EntropyCalc if (addNoise) { Random random = new Random(); + if (noiseSeedSet) { + random.setSeed(noiseSeed); + } // Add Gaussian noise of std dev noiseLevel to the data for (int r = 0; r < totalObservations; r++) { for (int c = 0; c < dimensions; c++) {