Added classes for joint entropy and multivariate mutual information calculation with gaussian assumption.

Restructured MeasurementDistribution to have child classes EmpiricalMeasurementDistribution and AnalyticMeasurementDistribution - this resulted in many classes being altered.

Added ChiSquare distribution methods to MathsUtils.

Added more covariance methods to MatrixUtils.
This commit is contained in:
joseph.lizier 2012-08-01 07:26:18 +00:00
parent 6af2a5b0a1
commit 9a86ee8152
35 changed files with 938 additions and 186 deletions

View File

@ -1,6 +1,6 @@
package infodynamics.measures.continuous;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
public interface ActiveInfoStorageCalculator {
@ -77,9 +77,9 @@ public interface ActiveInfoStorageCalculator {
public double[] computeLocalOfPreviousObservations() throws Exception;
public MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception;
public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception;
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int[][] newOrderings) throws Exception;
public void setDebug(boolean debug);

View File

@ -1,6 +1,6 @@
package infodynamics.measures.continuous;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
/**
* An abstract interface for calculators computing measures from a source to a destination.
@ -51,7 +51,7 @@ public abstract interface ChannelCalculatorCommon {
* @param numPermutationsToCheck number of new orderings of the source values to compare against
* @return
*/
public MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception;
public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception;
/**
* <p>As per {@link computeSignificance(int) computeSignificance()} but supplies
@ -64,7 +64,7 @@ public abstract interface ChannelCalculatorCommon {
* @return
* @throws Exception
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int[][] newOrderings) throws Exception;
public void setDebug(boolean debug);

View File

@ -1,6 +1,6 @@
package infodynamics.measures.continuous;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
/**
* A conditional mutual information calculator between a joint set of continuous variables,
@ -31,9 +31,9 @@ public interface ConditionalMutualInfoCalculatorMultiVariateWithDiscrete {
public double[] computeLocalUsingPreviousObservations(double[][] contStates,
int[] discreteStates, int[] conditionedStates) throws Exception;
public MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception;
public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception;
public MeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception;
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception;
public void setDebug(boolean debug);

View File

@ -1,6 +1,6 @@
package infodynamics.measures.continuous;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
/**
* A conditional mutual information calculator between a joint set of continuous variables,
@ -32,9 +32,9 @@ public interface ConditionalMutualInfoCalculatorMultiVariateWithDiscreteSource {
public double[] computeLocalUsingPreviousObservations(double[][] contStates,
int[] discreteStates, double[][] conditionedStates) throws Exception;
public MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception;
public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception;
public MeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception;
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception;
public void setDebug(boolean debug);

View File

@ -1,6 +1,6 @@
package infodynamics.measures.continuous;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
public interface MutualInfoCalculatorMultiVariateWithDiscrete {
@ -15,9 +15,9 @@ public interface MutualInfoCalculatorMultiVariateWithDiscrete {
public double[] computeLocalUsingPreviousObservations(double[][] contStates, int[] discreteStates) throws Exception;
public MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception;
public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception;
public MeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception;
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception;
public void setDebug(boolean debug);

View File

@ -2,7 +2,7 @@ package infodynamics.measures.continuous.kernel;
import infodynamics.measures.continuous.ActiveInfoStorageCalculator;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
/**
*
@ -207,7 +207,7 @@ public class ActiveInfoStorageCalculatorKernel
* @param numPermutationsToCheck number of new orderings of the source values to compare against
* @return
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
return miKernel.computeSignificance(numPermutationsToCheck);
}
@ -222,7 +222,7 @@ public class ActiveInfoStorageCalculatorKernel
* @return
* @throws Exception
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int[][] newOrderings) throws Exception {
return miKernel.computeSignificance(newOrderings);

View File

@ -2,7 +2,7 @@ package infodynamics.measures.continuous.kernel;
import infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
public class MutualInfoCalculatorMultiVariateKernel implements
@ -187,7 +187,7 @@ public class MutualInfoCalculatorMultiVariateKernel implements
* @param numPermutationsToCheck
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public synchronized MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
public synchronized EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
int[][] newOrderings = rg.generateDistinctRandomPerturbations(observations1.length, numPermutationsToCheck);
@ -206,7 +206,7 @@ public class MutualInfoCalculatorMultiVariateKernel implements
* @param newOrderings the specific new orderings to use
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public MeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
if (!miComputed) {
computeAverageLocalOfObservations();
@ -217,7 +217,7 @@ public class MutualInfoCalculatorMultiVariateKernel implements
double[][] originalData2 = observations2;
double[][] data2;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
int countWhereMiIsMoreSignificantThanOriginal = 0;
for (int i = 0; i < numPermutationsToCheck; i++) {

View File

@ -4,7 +4,7 @@ import java.util.Arrays;
import infodynamics.measures.continuous.MutualInfoCalculatorMultiVariateWithDiscrete;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
public class MutualInfoCalculatorMultiVariateWithDiscreteKernel implements
@ -219,7 +219,7 @@ public class MutualInfoCalculatorMultiVariateWithDiscreteKernel implements
* @param numPermutationsToCheck
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public synchronized MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
public synchronized EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
int[][] newOrderings = rg.generateDistinctRandomPerturbations(contObservations.length, numPermutationsToCheck);
@ -238,7 +238,7 @@ public class MutualInfoCalculatorMultiVariateWithDiscreteKernel implements
* @param newOrderings the specific new orderings to use
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public MeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
if (!miComputed) {
computeAverageLocalOfObservations();
@ -247,7 +247,7 @@ public class MutualInfoCalculatorMultiVariateWithDiscreteKernel implements
double actualMI = lastAverage;
int[] originalDiscrete = discObservations;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
int countWhereMiIsMoreSignificantThanOriginal = 0;
for (int i = 0; i < numPermutationsToCheck; i++) {

View File

@ -5,7 +5,7 @@ import infodynamics.measures.continuous.TransferEntropyCommon;
import infodynamics.measures.continuous.kernel.TransferEntropyKernelCounts;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
import java.util.Iterator;
@ -379,7 +379,7 @@ public class TransferEntropyCalculatorKernel
* @param numPermutationsToCheck number of new orderings of the source values to compare against
* @return
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
@ -397,7 +397,7 @@ public class TransferEntropyCalculatorKernel
* @return
* @throws Exception
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
@ -408,7 +408,7 @@ public class TransferEntropyCalculatorKernel
double[] oldSourceValues = sourceValues;
int countWhereTeIsMoreSignificantThanOriginal = 0;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
for (int p = 0; p < numPermutationsToCheck; p++) {
// Generate a new re-ordered data set for the source in the destPastSourceVectors
// and destNextPastSourceVectors vectors

View File

@ -4,7 +4,7 @@ import infodynamics.measures.continuous.TransferEntropyCalculator;
import infodynamics.measures.continuous.TransferEntropyCommon;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import java.util.Iterator;
@ -420,12 +420,12 @@ public class TransferEntropyCalculatorKernelPlain
return true;
}
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
throw new RuntimeException("Not implemented in this calculator");
}
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int[][] newOrderings) throws Exception {
throw new RuntimeException("Not implemented in this calculator");
}

View File

@ -3,7 +3,7 @@ package infodynamics.measures.continuous.kernel;
import infodynamics.measures.continuous.TransferEntropyCalculator;
import infodynamics.measures.continuous.TransferEntropyCommon;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import java.util.Iterator;
@ -426,12 +426,12 @@ public class TransferEntropyCalculatorKernelPlainIterators
return true;
}
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
throw new RuntimeException("Not implemented in this calculator");
}
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int[][] newOrderings) throws Exception {
throw new RuntimeException("Not implemented in this calculator");
}

View File

@ -5,7 +5,7 @@ import infodynamics.measures.continuous.TransferEntropyCommon;
import infodynamics.measures.continuous.kernel.KernelEstimatorMultiVariate;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
import java.util.Iterator;
@ -531,7 +531,7 @@ public class TransferEntropyCalculatorKernelSeparate
* @param numPermutationsToCheck number of new orderings of the source values to compare against
* @return
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
@ -549,7 +549,7 @@ public class TransferEntropyCalculatorKernelSeparate
* @return
* @throws Exception
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
@ -560,7 +560,7 @@ public class TransferEntropyCalculatorKernelSeparate
double[] originalSourceValuesInJoint = MatrixUtils.selectColumn(destPastSourceVectors, k);
int countWhereTeIsMoreSignificantThanOriginal = 0;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
for (int p = 0; p < numPermutationsToCheck; p++) {
// Check that the length of the reorderings is OK
if (newOrderings[p].length != totalObservations) {

View File

@ -5,7 +5,7 @@ import infodynamics.measures.continuous.TransferEntropyCommon;
import infodynamics.measures.continuous.kernel.TransferEntropyKernelCounts;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
import java.util.Iterator;
@ -578,7 +578,7 @@ public class TransferEntropyCalculatorMultiVariateKernel
* @param numPermutationsToCheck number of new orderings of the source values to compare against
* @return
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
@ -596,7 +596,7 @@ public class TransferEntropyCalculatorMultiVariateKernel
* @return
* @throws Exception
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
@ -607,7 +607,7 @@ public class TransferEntropyCalculatorMultiVariateKernel
double[][] oldSourceValues = sourceVectors;
int countWhereTeIsMoreSignificantThanOriginal = 0;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
for (int p = 0; p < numPermutationsToCheck; p++) {
// Generate a new re-ordered data set for the source in the destPastSourceVectors
// and destNextPastSourceVectors vectors

View File

@ -2,7 +2,7 @@ package infodynamics.measures.continuous.kraskov;
import infodynamics.utils.EuclideanUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
/**
@ -174,7 +174,7 @@ public abstract class ConditionalMutualInfoCalculatorMultiVariateKraskov {
* @param numPermutationsToCheck
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public synchronized MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
public synchronized EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
int[][] newOrderings = rg.generateDistinctRandomPerturbations(data1.length, numPermutationsToCheck);
@ -193,7 +193,7 @@ public abstract class ConditionalMutualInfoCalculatorMultiVariateKraskov {
* @param newOrderings the specific new orderings to use
* @return the proportion of conditional MI scores from the distribution which have higher or equal MIs to ours.
*/
public MeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
if (!condMiComputed) {
computeAverageLocalOfObservations();
@ -201,7 +201,7 @@ public abstract class ConditionalMutualInfoCalculatorMultiVariateKraskov {
// Store the real observations and their MI:
double actualMI = condMi;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
int countWhereMiIsMoreSignificantThanOriginal = 0;
for (int i = 0; i < numPermutationsToCheck; i++) {

View File

@ -4,7 +4,7 @@ import infodynamics.measures.continuous.ConditionalMutualInfoCalculatorMultiVari
import infodynamics.utils.EuclideanUtils;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
/**
@ -487,7 +487,7 @@ public class ConditionalMutualInfoCalculatorMultiVariateWithDiscreteKraskov impl
* @param numPermutationsToCheck
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public synchronized MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
public synchronized EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
int[][] newOrderings = rg.generateDistinctRandomPerturbations(continuousDataX.length, numPermutationsToCheck);
@ -506,7 +506,7 @@ public class ConditionalMutualInfoCalculatorMultiVariateWithDiscreteKraskov impl
* @param newOrderings the specific new orderings to use
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public MeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
if (!miComputed) {
@ -515,7 +515,7 @@ public class ConditionalMutualInfoCalculatorMultiVariateWithDiscreteKraskov impl
// Store the real observations and their MI:
double actualMI = condMi;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
int countWhereMiIsMoreSignificantThanOriginal = 0;
for (int i = 0; i < numPermutationsToCheck; i++) {

View File

@ -2,7 +2,7 @@ package infodynamics.measures.continuous.kraskov;
import infodynamics.measures.continuous.MultiInfoCalculator;
import infodynamics.utils.EuclideanUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
import java.util.Vector;
@ -184,7 +184,7 @@ public abstract class MultiInfoCalculatorKraskov implements
* @param numPermutationsToCheck
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public synchronized MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
public synchronized EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
int[][][] newOrderings = new int[numPermutationsToCheck][][];
@ -209,7 +209,7 @@ public abstract class MultiInfoCalculatorKraskov implements
* third index is the reordered variable number for that position.
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public MeasurementDistribution computeSignificance(int[][][] newOrderings) throws Exception {
public EmpiricalMeasurementDistribution computeSignificance(int[][][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
if (!miComputed) {
computeAverageLocalOfObservations();
@ -217,7 +217,7 @@ public abstract class MultiInfoCalculatorKraskov implements
// Store the real observations and their MI:
double actualMI = mi;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
int countWhereMiIsMoreSignificantThanOriginal = 0;
for (int i = 0; i < numPermutationsToCheck; i++) {

View File

@ -3,7 +3,7 @@ package infodynamics.measures.continuous.kraskov;
import infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate;
import infodynamics.utils.EuclideanUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
/**
@ -175,7 +175,7 @@ public abstract class MutualInfoCalculatorMultiVariateKraskov implements
* @param numPermutationsToCheck
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public synchronized MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
public synchronized EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
int[][] newOrderings = rg.generateDistinctRandomPerturbations(data1.length, numPermutationsToCheck);
@ -194,7 +194,7 @@ public abstract class MutualInfoCalculatorMultiVariateKraskov implements
* @param newOrderings the specific new orderings to use
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public MeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
if (!miComputed) {
computeAverageLocalOfObservations();
@ -202,7 +202,7 @@ public abstract class MutualInfoCalculatorMultiVariateKraskov implements
// Store the real observations and their MI:
double actualMI = mi;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
int countWhereMiIsMoreSignificantThanOriginal = 0;
for (int i = 0; i < numPermutationsToCheck; i++) {

View File

@ -2,7 +2,7 @@ package infodynamics.measures.continuous.kraskov;
import infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
import java.util.Hashtable;
@ -262,7 +262,7 @@ public abstract class MutualInfoCalculatorMultiVariateKraskovByMulti implements
* @param numPermutationsToCheck
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public synchronized MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
public synchronized EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
int[][] newOrderings = rg.generateDistinctRandomPerturbations(data1.length, numPermutationsToCheck);
@ -281,7 +281,7 @@ public abstract class MutualInfoCalculatorMultiVariateKraskovByMulti implements
* @param newOrderings the specific new orderings to use
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public MeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
if (!miComputed) {
computeAverageLocalOfObservations();
@ -289,7 +289,7 @@ public abstract class MutualInfoCalculatorMultiVariateKraskovByMulti implements
// Store the real observations and their MI:
double actualMI = mi;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
int countWhereMiIsMoreSignificantThanOriginal = 0;
for (int i = 0; i < numPermutationsToCheck; i++) {

View File

@ -4,7 +4,7 @@ import infodynamics.measures.continuous.MutualInfoCalculatorMultiVariateWithDisc
import infodynamics.utils.EuclideanUtils;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
/**
@ -361,7 +361,7 @@ public class MutualInfoCalculatorMultiVariateWithDiscreteKraskov implements Mutu
* @param numPermutationsToCheck
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public synchronized MeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
public synchronized EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
int[][] newOrderings = rg.generateDistinctRandomPerturbations(continuousData.length, numPermutationsToCheck);
@ -380,7 +380,7 @@ public class MutualInfoCalculatorMultiVariateWithDiscreteKraskov implements Mutu
* @param newOrderings the specific new orderings to use
* @return the proportion of MI scores from the distribution which have higher or equal MIs to ours.
*/
public MeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
if (!miComputed) {
@ -389,7 +389,7 @@ public class MutualInfoCalculatorMultiVariateWithDiscreteKraskov implements Mutu
// Store the real observations and their MI:
double actualMI = mi;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
int countWhereMiIsMoreSignificantThanOriginal = 0;
for (int i = 0; i < numPermutationsToCheck; i++) {

View File

@ -4,7 +4,7 @@ import infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate;
import infodynamics.measures.continuous.TransferEntropyCalculator;
import infodynamics.measures.continuous.TransferEntropyCommon;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
import java.util.Hashtable;
@ -351,7 +351,7 @@ public class TransferEntropyCalculatorKraskovByMulti
* @param numPermutationsToCheck number of new orderings of the source values to compare against
* @return
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
// Generate the re-ordered indices:
RandomGenerator rg = new RandomGenerator();
@ -373,7 +373,7 @@ public class TransferEntropyCalculatorKraskovByMulti
* @return
* @throws Exception
*/
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
@ -381,7 +381,7 @@ public class TransferEntropyCalculatorKraskovByMulti
double actualTE = computeAverageLocalOfObservations();
int countWhereTeIsMoreSignificantThanOriginal = 0;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
for (int p = 0; p < numPermutationsToCheck; p++) {
// Generate a new re-ordered data set for the source in the destPastSourceVectors
// and destNextPastSourceVectors vectors
@ -423,7 +423,7 @@ public class TransferEntropyCalculatorKraskovByMulti
* @return
* @throws Exception
*/
public MeasurementDistribution computeSignificanceExplicitlyReordering(
public EmpiricalMeasurementDistribution computeSignificanceExplicitlyReordering(
int[][] newOrderings) throws Exception {
int numPermutationsToCheck = newOrderings.length;
@ -437,7 +437,7 @@ public class TransferEntropyCalculatorKraskovByMulti
}
int countWhereTeIsMoreSignificantThanOriginal = 0;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
for (int p = 0; p < numPermutationsToCheck; p++) {
// Generate a new re-ordered data set for the source in the destPastSourceVectors
// and destNextPastSourceVectors vectors

View File

@ -0,0 +1,177 @@
package infodynamics.measures.continuous.lineargaussian;
import infodynamics.measures.continuous.EntropyCalculatorMultiVariate;
import infodynamics.utils.MatrixUtils;
/**
* <p>Computes the differential entropy of a given multivariate set of observations,
* assuming that the probability distribution function for these observations is
* a multivariate Gaussian distribution.</p>
*
* <p>
* Usage:
* <ol>
* <li>Construct</li>
* <li>initialise()</li>
* <li>setObservations(), or setCovariance().</li>
* <li>computeAverageLocalOfObservations() to return the average differential
* entropy based on either the set variance or the variance of
* the supplied observations, or computeLocalUsingPrevious</li>
* </ol>
* </p>
*
* @see Differential entropy for Gaussian random variables defined at
* {@link http://mathworld.wolfram.com/DifferentialEntropy.html}
* @author Joseph Lizier joseph.lizier_at_gmail.com
*
*/
public class EntropyCalculatorMultiVariateLinearGaussian implements EntropyCalculatorMultiVariate {
/**
* Covariance matrix of the most recently supplied observations
*/
protected double[][] covariance;
/**
* The set of observations, retained in case the user wants to retrieve the local
* entropy values of these
*/
protected double[][] observations;
/**
* Number of dimenions for our multivariate data
*/
protected int dimensions;
protected double lastAverage;
protected boolean debug;
/**
* Constructor
*/
public EntropyCalculatorMultiVariateLinearGaussian() {
// Nothing to do
}
/**
* Initialise the calculator ready for reuse
*/
public void initialise(int dimensions) {
covariance = null;
observations = null;
this.dimensions = dimensions;
}
/**
* Provide the multivariate observations from which to compute the entropy
*
* @param observations the observations to compute the entropy from.
* First index is time, second index is variable number.
*/
public void setObservations(double[][] observations) {
this.observations = observations;
covariance = MatrixUtils.covarianceMatrix(observations);
// Check that the observations was of the correct number of dimensions:
// (done afterwards since the covariance matrix computation checks that
// all rows had the right number of columns
if (covariance.length != dimensions) {
throw new RuntimeException("Supplied observations does not match initialised number of dimensions");
}
}
/**
* Set the covariance of the distribution for which we will compute the
* entropy.
*
* @param covariance covariance matrix
*/
public void setCovariance(double[][] covariance) throws Exception {
observations = null;
// Make sure the supplied covariance matrix is square:
int rows = covariance.length;
if (rows != dimensions) {
throw new Exception("Supplied covariance matrix does not match initialised number of dimensions");
}
for (int r = 0; r < rows; r++) {
if (covariance[r].length != rows) {
throw new Exception("Cannot compute the determinant of a non-square matrix");
}
}
this.covariance = covariance;
}
/**
* <p>The joint entropy for a multivariate Gaussian-distribution of dimension n
* with covariance matrix C is 0.5*\log_e{(2*pi*e)^n*|det(C)|},
* where det() is the matrix determinant of C.</p>
*
* <p>Here we compute the joint entropy assuming that the recorded estimation of the
* covariance is correct (i.e. we will not make a bias correction for limited
* observations here).</p>
*
* @return the joint entropy of the previously provided observations or from the
* supplied covariance matrix.
*/
public double computeAverageLocalOfObservations() {
try {
lastAverage = 0.5 * (dimensions* (1 + Math.log(2.0*Math.PI)) +
Math.log(Math.abs(MatrixUtils.determinant(covariance))));
return lastAverage;
} catch (Exception e) {
// Should not happen, since we check the validity of the supplied
// matrix beforehand; so we'll throw an Error in this case
throw new Error(e);
}
}
public void setDebug(boolean debug) {
this.debug = debug;
}
/**
* <p>Set the given property to the given value.</p>
*
* <p>There are currently no properties to set for this calculator</p>
*
* @param propertyName name of the property
* @param propertyValue value of the property.
* @throws Exception
*/
public void setProperty(String propertyName, String propertyValue)
throws Exception {
// No properties to set here
}
/**
* @return the lastAverage
*/
public double getLastAverage() {
return lastAverage;
}
public double[] computeLocalUsingPreviousObservations(double[][] states)
throws Exception {
// TODO Implement me
throw new RuntimeException("Not implemented yet");
}
public double[] computeLocalOfPreviousObservations() {
// TODO Implement this function
if (true)
throw new RuntimeException("Not implemented yet");
if (observations == null) {
throw new RuntimeException("Cannot compute local values since no observations were supplied");
}
double[] localEntropy = new double[observations.length];
for (int t=0; t < observations.length; t++) {
// Compute the probability for the given observation, based on
// the assumption of a multivariate Gaussian PDF:
}
return null;
}
}

View File

@ -0,0 +1,307 @@
package infodynamics.measures.continuous.lineargaussian;
import infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate;
import infodynamics.utils.ChiSquareMeasurementDistribution;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.EmpiricalMeasurementDistribution;
/**
* <p>Computes the differential mutual information of two given multivariate sets of
* observations,
* assuming that the probability distribution function for these observations is
* a multivariate Gaussian distribution.</p>
*
* <p>
* Usage:
* <ol>
* <li>Construct {@link #MutualInfoCalculatorMultiVariateLinearGaussian()}</li>
* <li>{@link #initialise(int, int)}</li>
* <li>Provide the observations to the calculator using:
* {@link #setObservations(double[][], double[][])}, or
* {@link #setCovariance(double[][])}, or
* a sequence of:
* {@link #startAddObservations()},
* multiple calls to either {@link #addObservations(double[][], double[][])}
* or @{link {@link #addObservations(double[][], double[][], int, int)}, and then
* @{link {@link #finaliseAddObservations()}.</li>
* <li>Compute the required information-theoretic results, primarily:
* @{link #computeAverageLocalOfObservations()} to return the average differential
* entropy based on either the set variance or the variance of
* the supplied observations; or other calls to compute
* local values or statistical significance.</li>
* </ol>
* </p>
*
* @see Differential entropy for Gaussian random variables defined at
* {@link http://mathworld.wolfram.com/DifferentialEntropy.html}
* @author Joseph Lizier joseph.lizier_at_gmail.com
*
*/
public class MutualInfoCalculatorMultiVariateLinearGaussian implements
MutualInfoCalculatorMultiVariate {
/**
* Covariance matrix of the most recently supplied observations
*/
protected double[][] covariance;
/**
* The set of source observations, retained in case the user wants to retrieve the local
* entropy values of these.
* They're held in the order in which they were supplied in the
* {@link addObservations(double[][], double[][])} functions.
*/
protected double[][] sourceObservations;
/**
* The set of destination observations, retained in case the user wants to retrieve the local
* entropy values of these.
* They're held in the order in which they were supplied in the
* {@link addObservations(double[][], double[][])} functions.
*/
protected double[][] destObservations;
/**
* Number of dimenions for each of our multivariate data sets
*/
protected int dimensionsDest;
protected int dimensionsSource;
protected double lastAverage;
protected boolean debug;
public MutualInfoCalculatorMultiVariateLinearGaussian() {
// Nothing to do
}
/**
* Clear any previously supplied probability distributions and prepare
* the calculator to be used again.
*
* @param sourceDimensions number of joing variables in the source
* @param destDimensions number of joing variables in the destination
*/
public void initialise(int sourceDimensions, int destDimensions) {
covariance = null;
sourceObservations = null;
destObservations = null;
dimensionsSource = sourceDimensions;
dimensionsDest = destDimensions;
}
/**
* Provide the complete set of observations to use to compute the
* mutual information.
* One cannot use the {@link addObservations(double[][], double[][])}
* style methods after this without calling initialise again first.
*
*/
public void setObservations(double[][] source, double[][] destination)
throws Exception {
sourceObservations = source;
destObservations = destination;
covariance = MatrixUtils.covarianceMatrix(source, destination);
// Check that the observations was of the correct number of dimensions:
// (done afterwards since the covariance matrix computation checks that
// all rows had the right number of columns
if (covariance.length != dimensionsSource + dimensionsDest) {
throw new RuntimeException("Supplied observations do not match initialised number of dimensions");
}
}
public void addObservations(double[][] source, double[][] destination)
throws Exception {
// TODO implement these addObservations style functions.
// This will not be hard to implement - see the implementation
// for TE in TransferEntropyCommon. It might be useful
// to have a MutualInfoCommon which pulls the same functionality
// together for the MI calculators anyway.
throw new RuntimeException("Not implemented yet");
}
public void addObservations(double[][] source, double[][] destination,
int startTime, int numTimeSteps) throws Exception {
throw new RuntimeException("Not implemented yet");
}
public void setObservations(double[][] source, double[][] destination,
boolean[] sourceValid, boolean[] destValid) throws Exception {
throw new RuntimeException("Not implemented yet");
}
public void setObservations(double[][] source, double[][] destination,
boolean[][] sourceValid, boolean[][] destValid) throws Exception {
throw new RuntimeException("Not implemented yet");
}
public void startAddObservations() {
throw new RuntimeException("Not implemented yet");
}
public void finaliseAddObservations() {
throw new RuntimeException("Not implemented yet");
}
/**
* Set the covariance of the distribution for which we will compute the
* mutual information.
*
* @param covariance covariance matrix of the source and destination
* variables, considered together (variable indices start with the source
* and continue into the destination).
*/
public void setCovariance(double[][] covariance) throws Exception {
sourceObservations = null;
destObservations = null;
// Make sure the supplied covariance matrix is square:
int rows = covariance.length;
if (rows != dimensionsSource + dimensionsDest) {
throw new Exception("Supplied covariance matrix does not match initialised number of dimensions");
}
for (int r = 0; r < rows; r++) {
if (covariance[r].length != rows) {
throw new Exception("Cannot compute the determinant of a non-square matrix");
}
}
this.covariance = covariance;
}
/**
* <p>The joint entropy for a multivariate Gaussian-distribution of dimension n
* with covariance matrix C is 0.5*\log_e{(2*pi*e)^n*|det(C)|},
* where det() is the matrix determinant of C.</p>
*
* <p>Here we compute the mutual information from the joint entropies
* of the source variables (H_s), destination variables (H_d), and all variables
* taken together (H_sd), giving MI = H_s + H_d - H_sd.
* We assume that the recorded estimation of the
* covariance is correct (i.e. we will not make a bias correction for limited
* observations here).</p>
*
* @return the mutual information of the previously provided observations or from the
* supplied covariance matrix.
*/
public double computeAverageLocalOfObservations() throws Exception {
try {
int[] sourceIndicesInCovariance = MatrixUtils.range(0, dimensionsSource - 1);
int[] destIndicesInCovariance = MatrixUtils.range(dimensionsSource,
dimensionsSource + dimensionsDest - 1);
double[][] sourceCovariance =
MatrixUtils.selectRowsAndColumns(covariance,
sourceIndicesInCovariance, sourceIndicesInCovariance);
double[][] destCovariance =
MatrixUtils.selectRowsAndColumns(covariance,
destIndicesInCovariance, destIndicesInCovariance);
double sourceEntropy = 0.5 *
Math.log(Math.abs(MatrixUtils.determinant(sourceCovariance)));
double destEntropy = 0.5 *
Math.log(Math.abs(MatrixUtils.determinant(destCovariance)));
double jointEntropy = 0.5 *
Math.log(Math.abs(MatrixUtils.determinant(covariance)));
lastAverage = sourceEntropy + destEntropy - jointEntropy;
return lastAverage;
} catch (Exception e) {
// Should not happen, since we check the validity of the supplied
// matrix beforehand; so we'll throw an Error in this case
throw new Error(e);
}
}
public double[] computeLocalOfPreviousObservations() throws Exception {
// TODO Implement me
throw new RuntimeException("Not implemented yet");
}
/**
* <p>Compute the statistical significance of the mutual information
* result analytically, without creating a distribution
* under the null hypothesis by bootstrapping.</p>
*
* <p>Brillinger (see reference below) shows that under the null hypothesis
* of no source-destination relationship, the MI for two
* Gaussian distributions follows a chi-square distribution with
* degrees of freedom equal to the product of the number of variables
* in each joint variable.</p>
*
* @return MeasurementDistribution object with only the
* {@link EmpiricalMeasurementDistribution#actualValue} and
* {@link EmpiricalMeasurementDistribution#pValue} fields filled out.
* This object contains the proportion of MI scores from the distribution
* which have higher or equal MIs to ours.
*
* @see Brillinger, "Some data analyses using mutual information",
* {@link http://www.stat.berkeley.edu/~brill/Papers/MIBJPS.pdf}
* @see Cheng et al., "Data Information in Contingency Tables: A
* Fallacy of Hierarchical Loglinear Models",
* {@link http://www.jds-online.com/file_download/112/JDS-369.pdf}
* @see Barnett and Bossomaier, "Transfer Entropy as a Log-likelihood Ratio"
* {@link http://arxiv.org/abs/1205.6339}
*/
public ChiSquareMeasurementDistribution computeSignificance() {
// TODO Check that the null distribution actually follows chi with
// these degrees of freedom
return new ChiSquareMeasurementDistribution(lastAverage,
dimensionsSource * dimensionsDest);
}
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
// TODO Implement me
throw new RuntimeException("Not implemented yet");
}
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings)
throws Exception {
// TODO Implement me
throw new RuntimeException("Not implemented yet");
}
/**
* <p>Set the given property to the given value.</p>
*
* <p>There are currently no properties to set for this calculator</p>
*
* @param propertyName name of the property
* @param propertyValue value of the property.
* @throws Exception
*/
public void setProperty(String propertyName, String propertyValue)
throws Exception {
// No properties to set here
}
public void setDebug(boolean debug) {
this.debug = debug;
}
/**
* @return the previously computed average mutual information
*/
public double getLastAverage() {
return lastAverage;
}
/**
* @return the number of previously supplied observations for which
* the mutual information will be / was computed.
*/
public int getNumObservations() {
return destObservations.length;
}
public double computeAverageLocalOfObservations(int[] newOrdering)
throws Exception {
// TODO Implement me
throw new RuntimeException("Not implemented yet");
}
public double[] computeLocalUsingPreviousObservations(double[][] states1,
double[][] states2) throws Exception {
// TODO Implement me
throw new RuntimeException("Not implemented yet");
}
}

View File

@ -5,7 +5,7 @@ import infodynamics.measures.discrete.ConditionalMutualInformationCalculator;
import infodynamics.utils.FirstIndexComparatorDouble;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
public class ConditionalMutualInfoCalculatorMultiVariateWithDiscreteSymbolic implements
@ -131,12 +131,12 @@ public class ConditionalMutualInfoCalculatorMultiVariateWithDiscreteSymbolic imp
throw new Exception("Local method not implemented yet");
}
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
return condMiCalc.computeSignificance(numPermutationsToCheck);
}
public MeasurementDistribution computeSignificance(int[][] newOrderings)
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings)
throws Exception {
return condMiCalc.computeSignificance(newOrderings);
}

View File

@ -5,7 +5,7 @@ import infodynamics.measures.discrete.MutualInformationCalculator;
import infodynamics.utils.FirstIndexComparatorDouble;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
public class MutualInfoCalculatorMultiVariateWithDiscreteSymbolic implements
@ -139,12 +139,12 @@ public class MutualInfoCalculatorMultiVariateWithDiscreteSymbolic implements
throw new Exception("Local method not implemented yet");
}
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
return miCalc.computeSignificance(numPermutationsToCheck);
}
public MeasurementDistribution computeSignificance(int[][] newOrderings)
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings)
throws Exception {
return miCalc.computeSignificance(newOrderings);
}

View File

@ -6,7 +6,7 @@ import infodynamics.measures.discrete.ApparentTransferEntropyCalculator;
import infodynamics.utils.FirstIndexComparatorDouble;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
import java.util.Iterator;
@ -300,7 +300,7 @@ public class TransferEntropyCalculatorSymbolic
return locals;
}
public MeasurementDistribution computeSignificance(
public EmpiricalMeasurementDistribution computeSignificance(
int numPermutationsToCheck) throws Exception {
return teCalc.computeSignificance(numPermutationsToCheck);
}
@ -310,7 +310,7 @@ public class TransferEntropyCalculatorSymbolic
* which is not strictly what this method is meant to do.
*
*/
public MeasurementDistribution computeSignificance(int[][] newOrderings)
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings)
throws Exception {
System.out.println("TESymbolic.computeSignificance(): Not using the new orderings supplied");
return teCalc.computeSignificance(newOrderings.length);

View File

@ -1,7 +1,7 @@
package infodynamics.measures.discrete;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
/**
@ -653,7 +653,7 @@ public class ApparentTransferEntropyCalculator extends ContextOfPastMeasureCalcu
* @param numPermutationsToCheck number of new orderings of the source values to compare against
* @return
*/
public MeasurementDistribution computeSignificance(int numPermutationsToCheck) {
public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) {
double actualTE = computeAverageLocalOfObservations();
// Reconstruct the source values (not necessarily in order)
@ -698,7 +698,7 @@ public class ApparentTransferEntropyCalculator extends ContextOfPastMeasureCalcu
ate2.pastCount = pastCount;
ate2.nextPastCount = nextPastCount;
int countWhereTeIsMoreSignificantThanOriginal = 0;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
for (int p = 0; p < numPermutationsToCheck; p++) {
// Generate a new re-ordered data set for the source
int[] newSourceData = MatrixUtils.extractSelectedTimePoints(sourceValues, newOrderings[p]);

View File

@ -1,6 +1,6 @@
package infodynamics.measures.discrete;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
/**
* An interface for calculators computing measures from a source to a destination.
@ -47,5 +47,5 @@ public interface ChannelCalculator {
* @param numPermutationsToCheck
* @return
*/
public MeasurementDistribution computeSignificance(int numPermutationsToCheck);
public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck);
}

View File

@ -2,7 +2,7 @@ package infodynamics.measures.discrete;
import infodynamics.utils.MathsUtils;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
@ -342,7 +342,7 @@ public class CompleteTransferEntropyCalculator extends InfoMeasureCalculator {
* @param numPermutationsToCheck number of new orderings of the source values to compare against
* @return
*/
public MeasurementDistribution computeSignificance(int numPermutationsToCheck) {
public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) {
double actualTE = computeAverageLocalOfObservations();
// Reconstruct the source values (not necessarily in order)
@ -400,7 +400,7 @@ public class CompleteTransferEntropyCalculator extends InfoMeasureCalculator {
cte.pastOthersCount = pastOthersCount;
cte.destPastOthersCount = destPastOthersCount;
int countWhereTeIsMoreSignificantThanOriginal = 0;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
for (int p = 0; p < numPermutationsToCheck; p++) {
// Generate a new re-ordered data set for the source
int[] newSourceData = MatrixUtils.extractSelectedTimePoints(sourceValues, newOrderings[p]);

View File

@ -1,7 +1,7 @@
package infodynamics.measures.discrete;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.RandomGenerator;
@ -185,7 +185,7 @@ public class MutualInformationCalculator extends InfoMeasureCalculator
* @param numPermutationsToCheck number of new orderings of the source values to compare against
* @return
*/
public MeasurementDistribution computeSignificance(int numPermutationsToCheck) {
public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) {
RandomGenerator rg = new RandomGenerator();
int[][] newOrderings = rg.generateDistinctRandomPerturbations(observations, numPermutationsToCheck);
return computeSignificance(newOrderings);
@ -197,7 +197,7 @@ public class MutualInformationCalculator extends InfoMeasureCalculator
* @param newOrderings the reorderings to use
* @return
*/
public MeasurementDistribution computeSignificance(int[][] newOrderings) {
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) {
double actualMI = computeAverageLocalOfObservations();
int numPermutationsToCheck = newOrderings.length;
@ -222,7 +222,7 @@ public class MutualInformationCalculator extends InfoMeasureCalculator
mi2.iCount = iCount;
mi2.jCount = jCount;
int countWhereMIIsMoreSignificantThanOriginal = 0;
MeasurementDistribution measDistribution = new MeasurementDistribution(numPermutationsToCheck);
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
for (int p = 0; p < numPermutationsToCheck; p++) {
// Generate a new re-ordered data set for the i variable
int[] newDataI = MatrixUtils.extractSelectedTimePoints(iValues, newOrderings[p]);

View File

@ -5,7 +5,7 @@ import infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate;
import infodynamics.measures.continuous.TransferEntropyCalculatorMultiVariate;
import infodynamics.utils.ArrayFileReader;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.ParsedProperties;
import infodynamics.utils.RandomGenerator;
@ -455,7 +455,7 @@ public abstract class InterregionalChannelMeasure {
// Compute the measure for set s
measureForEachSet[s] = channelCalc.computeAverageLocalOfObservations();
MeasurementDistribution measDist;
EmpiricalMeasurementDistribution measDist;
if (allValid || !validityForIndividualElements) {
// Ask the TE calculator to work out the significance for us
measDist = channelCalc.computeSignificance(reorderings);
@ -463,7 +463,7 @@ public abstract class InterregionalChannelMeasure {
// We need to explicitly reorder including the individual validities.
// Can't ask the calculator to do it, as it will only use the source-dest
// pairings it originally used, which won't match across all subsets
measDist = new MeasurementDistribution(reorderingsForSignificance);
measDist = new EmpiricalMeasurementDistribution(reorderingsForSignificance);
measDist.actualValue = measureForEachSet[s];
int countWhereReorderedIsMoreSignificantThanOriginal = 0;
for (int p = 0; p < reorderingsForSignificance; p++) {

View File

@ -4,7 +4,7 @@
package infodynamics.networkinference.interregional;
import infodynamics.utils.MatrixUtils;
import infodynamics.utils.MeasurementDistribution;
import infodynamics.utils.EmpiricalMeasurementDistribution;
/**
* Extends MeasurementDistribution for computations over
@ -17,7 +17,7 @@ import infodynamics.utils.MeasurementDistribution;
* @author Joseph Lizier
*
*/
public class MeasurementDistributionPermutationsOverSubsets extends MeasurementDistribution {
public class MeasurementDistributionPermutationsOverSubsets extends EmpiricalMeasurementDistribution {
// The true measurements for each subset s
double[] actualValues;

View File

@ -0,0 +1,88 @@
package infodynamics.utils;
/**
*
* Structure to hold a distribution of info-theoretic measurements,
* and a significance value for how an original measurement compared
* with these.
*
* @author Joseph Lizier
*
*/
public class EmpiricalMeasurementDistribution extends MeasurementDistribution {
/**
* Distribution of surrogate measurement values
*/
public double[] distribution;
/**
* Whether the mean of the surrogate measurement distribution has
* been computed
*/
protected boolean computedMean = false;
/**
* Computed mean of the surrogate measurement distribution
*/
protected double meanOfDist;
/**
* Computed mean of the surrogate measurement distribution
*/
protected double stdOfDist;
public EmpiricalMeasurementDistribution(int size) {
super(); // Creating the super class with mean and pValue 0
// These value will be filled out by the caller later.
distribution = new double[size];
}
public EmpiricalMeasurementDistribution(double[] distribution, double actualValue) {
super(actualValue, 0); // Using pValue = 0 temporarily ...
this.distribution = distribution;
int countWhereActualIsNotGreater = 0;
for (int i = 0; i < distribution.length; i++) {
if (distribution[i] >= actualValue) {
countWhereActualIsNotGreater++;
}
}
pValue = (double) countWhereActualIsNotGreater / (double) distribution.length;
}
// TODO Compute the significance under the assumption of a Gaussian distribution
/*
public double computeGaussianSignificance() {
// Need to conpute the significance based on the assumption of
// an underlying Gaussian distribution.
// Use the t distribution for analysis, since we have a finite
// number of samples to comptue the mean and std from.
return 0;
}
*/
public double getTSscore() {
if (! computedMean) {
meanOfDist = MatrixUtils.mean(distribution);
stdOfDist = MatrixUtils.stdDev(distribution, meanOfDist);
computedMean = true;
}
double t = (actualValue - meanOfDist) / stdOfDist;
return t;
}
public double getMeanOfDistribution() {
if (! computedMean) {
meanOfDist = MatrixUtils.mean(distribution);
stdOfDist = MatrixUtils.stdDev(distribution, meanOfDist);
computedMean = true;
}
return meanOfDist;
}
public double getStdOfDistribution() {
if (! computedMean) {
meanOfDist = MatrixUtils.mean(distribution);
stdOfDist = MatrixUtils.stdDev(distribution, meanOfDist);
computedMean = true;
}
return stdOfDist;
}
}

View File

@ -281,6 +281,98 @@ public class MathsUtils {
return result;
}
/**
* <p>Return the value of the cummulative distribution function of the
* chi-square distribution, evaluated at x, for k degrees of freedom.</p>
*
* <p>Note that this relies on our approximation of the error function,
* which is the limiting part of the accuracy. Testing against
* values produced by octave indicates this is accurate to 5-6
* decimal places.</p>
*
* @param x value at which to evaluate the CDF
* @param k degrees of freedom (must have k>0)
* @return chi squared CDF evaluated at x given k degrees of freedom
* @see {@link http://en.wikipedia.org/wiki/Chi-squared_distribution}
*/
public static double chiSquareCdf(double x, int k) {
if (k <= 0) {
throw new IllegalArgumentException("k (" + k + ") must be > 0");
}
return lowerIncompleteGammaFunctionOfArgsOn2(k,x) /
gammaOfArgOn2Plus1(k-2); // denominator is Gamma(k/2)
}
/**
* Return the value of the lower Incomplete Gamma function,
* given arguments s/2 and x/2.
* We assume postive integer parameter s (s could be complex in general,
* with positive real part, but we restrict it to real and integer for
* this method). We make the evaluation using a recurrence relation,
* which terminates at s/2 = 1 or 1/2 (i.e. s = 2 or 1)
*
* @param s for parameter s/2 to lower incomplete gamma
* @param x for value x/2 to lower incomplete gamma
* @return value of lower gamma incomplete function
* @see {@link http://en.wikipedia.org/wiki/Incomplete_Gamma_function}
*/
public static double lowerIncompleteGammaFunctionOfArgsOn2(int s, double x) {
if (s <= 0) {
throw new IllegalArgumentException("s must be > 0");
}
if (s == 2) {
// Terminating condition: evaluate lower gamma(1, x/2):
return 1 - Math.exp(-x/2.0);
} else if (s == 1) {
// Terminating condition: evaluate lower gamma(1/2, x/2):
return Math.sqrt(Math.PI) * erf(Math.sqrt(x/2.0));
} else {
// Else evaluate recurrence relation:
return (s/2.0-1.0)*lowerIncompleteGammaFunctionOfArgsOn2(s-2,x) -
Math.pow(x/2.0, s/2.0 - 1.0) * Math.exp(-x/2.0);
}
}
/**
* Return the value of the error function at a given x.
* We approximate the error function using elementary functions
* as described at the link below (quoting Abramowitz and Stegun).
* This approximation is quoted to
* have maximum error 1.5e-7 (and indeed this appears to be the
* case in comparison to values produced by octave).
*
* @param x value at which to evaluate the error function
* @return erf(x)
* @see {@link http://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions}
* @see Abramowitz, Milton; Stegun, Irene A., eds. (1972),
* "Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables",
* New York: Dover Publications, ISBN 978-0-486-61272-0
*/
public static double erf(double x) {
// Constants:
double p = 0.3275911;
double[] a = {0.254829592, -0.284496736, 1.421413741,
-1.453152027, 1.061405429};
boolean negArg = (x < 0);
if (negArg) {
// The rest of the method requires x >= 0, but since erf(x)
// is an odd function, we just reflect x.
x = -x;
}
double t = 1.0 / (1 + p * x);
double multiplier = 0.0;
double tToPower = t;
for (int i = 0; i < 5; i++) {
multiplier += a[i] * tToPower;
tToPower *= t;
}
double retVal = 1.0 - multiplier * Math.exp(-x*x);
// Remember that erf(x) was an odd function:
return negArg ? - retVal: retVal;
}
/**
* Return the number of possible combinations of p from n (i.e. n choose p)
*
@ -359,6 +451,12 @@ public class MathsUtils {
return upToSetNum;
}
/**
* Perform some testing:
*
* @param args
* @throws Exception
*/
public static void main(String args[]) throws Exception {
/*
System.out.println(numOfSets(158,4));
@ -368,6 +466,7 @@ public class MathsUtils {
// int[][] sets = generateAllSets(6,4);
// MatrixUtils.printMatrix(System.out, sets);
/*
System.out.printf("digamma() digammaOld()\n");
for (int n = 0; n < 100; n++) {
System.out.printf("%d %.3f %.3f\n", n, MathsUtils.digamma(n), MathsUtils.digammaByDefinition(n));
@ -375,5 +474,23 @@ public class MathsUtils {
for (int n = 0; n < 101; n++) {
System.out.printf("%d %.3f %.3f\n", n, MathsUtils.digamma(n), MathsUtils.digammaByDefinition(n));
}
*/
/*
System.out.println("erf(" + 1 + ")= " + MathsUtils.erf(1));
System.out.println("erf(" + 2 + ")= " + MathsUtils.erf(2));
System.out.println("erf(" + 0 + ")= " + MathsUtils.erf(0));
for (int n=0; n<100; n++) {
System.out.println("erf(" + n*0.1 + ")= " + MathsUtils.erf(n*0.1));
}*/
int degFree = 10;
System.out.println("chi2cdf(1," + degFree +")= " + MathsUtils.chiSquareCdf(1, degFree));
System.out.println("chi2cdf(2," + degFree +")= " + MathsUtils.chiSquareCdf(2, degFree));
System.out.println("chi2cdf(3," + degFree +")= " + MathsUtils.chiSquareCdf(3, degFree));
for (int n=0; n<100; n++) {
System.out.println("chi2cdf(" + n*0.1 + "," + degFree +")= " + MathsUtils.chiSquareCdf(n*0.1, degFree));
}
}
}

View File

@ -13,6 +13,21 @@ import java.util.Vector;
*/
public class MatrixUtils {
/**
* Return an array with values enumerated through the given range
*
* @param startValue first value for the array
* @param endValue last value for the array
* @return
*/
public static int[] range(int startValue, int endValue) {
int[] array = new int[endValue - startValue + 1];
for (int i = 0; i < endValue - startValue + 1; i++) {
array[i] = startValue + i;
}
return array;
}
public static double sum(double[] input) {
double total = 0;
for (int i = 0; i < input.length; i++) {
@ -2249,6 +2264,32 @@ public class MatrixUtils {
return c / (double) data.length;
}
/**
* <p>Returns the covariance between two columns of data in
* two multivariate arrays.</p>
* <p>See - <a href="http://mathworld.wolfram.com/Covariance.html">Mathworld</a>
* </p>
*
* @param data1 first multivariate array of data; first index is time, second is
* variable number
* @param data2 second multivariate array of data; first index is time, second is
* variable number
* @param col1 variable number 1 to compute the covariance to
* @param col2 variable number 2 to compute the covariance to
* @param mean1 mean of variable 1
* @param mean2 mean of variable 2
* @return the covariance
*/
public static double covarianceTwoColumns(
double[][] data1, double[][] data2, int col1, int col2,
double mean1, double mean2) {
double c = 0;
for (int t = 0; t < data1.length; t++) {
c += (data1[t][col1] - mean1)*(data2[t][col2]-mean2);
}
return c / (double) data1.length;
}
/**
* Compute the covariance matrix between all column pairs (variables) in the
* multivariate data set
@ -2274,9 +2315,72 @@ public class MatrixUtils {
covariances[c][r] = covariances[r][c];
}
}
return null;
return covariances;
}
/**
* Compute the covariance matrix between all column pairs (variables) in the
* multivariate data set, which consists of two separate
* multivariate vectors.
*
* @param data1 multivariate array of data; first index is time, second is
* variable number
* @param data2 a second multivariate array of data, which can be though
* of as extensions of rows of the first.
* @return covariance matrix, where the columns of dat1 are numbered
* first, and the columns of data2 after that.
*/
public static double[][] covarianceMatrix(
double[][] data1, double[][] data2) {
int numVariables1 = data1[0].length;
int numVariables2 = data2[0].length;
int numVariables = numVariables1 + numVariables2;
double[][] covariances = new double[numVariables][numVariables];
// Compute means of each variable once up front to save time
double[] means1 = new double[numVariables1];
double[] means2 = new double[numVariables2];
for (int r = 0; r < numVariables1; r++) {
means1[r] = mean(data1, r);
}
for (int r = 0; r < numVariables2; r++) {
means2[r] = mean(data2, r);
}
// Now compute the covariances:
for (int r = 0; r < numVariables1; r++) {
// Compute the covariances internal to data1:
for (int c = r; c < numVariables1; c++) {
// Compute the covariance between variable r and c:
covariances[r][c] = covarianceTwoColumns(data1, r, c,
means1[r], means1[c]);
// And of course this is symmetric between c and r:
covariances[c][r] = covariances[r][c];
}
// Compute the covariances between data1 and data2
for (int c = 0; c < numVariables2; c++) {
// Compute the covariance between variable r and c:
covariances[r][numVariables1 + c] =
covarianceTwoColumns(data1, data2,
r, c, means1[r], means2[c]);
// And of course this is symmetric between c and r:
covariances[numVariables1 + c][r] =
covariances[r][numVariables1 + c];
}
}
// Now compute the covariances internal to data2:
for (int r = 0; r < numVariables2; r++) {
for (int c = r; c < numVariables2; c++) {
// Compute the covariance between variable r and c:
covariances[numVariables1 + r][numVariables1 + c] =
covarianceTwoColumns(data2, r, c,
means2[r], means2[c]);
// And of course this is symmetric between c and r:
covariances[numVariables1 + c][numVariables1 + r] =
covariances[numVariables1 + r][numVariables1 + c];
}
}
return covariances;
}
/**
* <p>Returns the correlation between the two arrays of data.</p>
* <p>The arrays are asssumed to have the same lengths</p>

View File

@ -1,85 +1,44 @@
package infodynamics.utils;
/**
*
* Structure to hold a distribution of info-theoretic measurements,
* and a significance value for how an original measurement compared
* with these.
*
* @author Joseph Lizier
*
*/
public class MeasurementDistribution {
/**
* Distribution of surrogate measurement values
*/
public double[] distribution;
/**
* Actual observed value of the measurement
*/
public double actualValue;
/**
* Probability that surrogate measurement is greater than
* the observed value
*/
public double pValue;
protected boolean computedMean = false;
protected double meanOfDist;
protected double stdOfDist;
public MeasurementDistribution(int size) {
distribution = new double[size];
}
public MeasurementDistribution(double[] distribution, double actualValue) {
this.actualValue = actualValue;
this.distribution = distribution;
int countWhereActualIsNotGreater = 0;
for (int i = 0; i < distribution.length; i++) {
if (distribution[i] >= actualValue) {
countWhereActualIsNotGreater++;
}
}
pValue = (double) countWhereActualIsNotGreater / (double) distribution.length;
}
/*
public double computeGaussianSignificance() {
// Need to conpute the significance based on the assumption of
// an underlying Gaussian distribution.
// Use the t distribution for analysis, since we have a finite
// number of samples to comptue the mean and std from.
return 0;
}
*/
public double getTSscore() {
if (! computedMean) {
meanOfDist = MatrixUtils.mean(distribution);
stdOfDist = MatrixUtils.stdDev(distribution, meanOfDist);
computedMean = true;
}
double t = (actualValue - meanOfDist) / stdOfDist;
return t;
}
public double getMeanOfDistribution() {
if (! computedMean) {
meanOfDist = MatrixUtils.mean(distribution);
stdOfDist = MatrixUtils.stdDev(distribution, meanOfDist);
computedMean = true;
}
return meanOfDist;
}
public double getStdOfDistribution() {
if (! computedMean) {
meanOfDist = MatrixUtils.mean(distribution);
stdOfDist = MatrixUtils.stdDev(distribution, meanOfDist);
computedMean = true;
}
return stdOfDist;
}
}
package infodynamics.utils;
/**
* <p>Structure to hold a distribution of info-theoretic measurements,
* and a significance value for how an original measurement compared
* with these.</p>
*
* <p>While in theory this class could be directly used, it is it's
* children which are intended to be used.</p>
*
* @author Joseph Lizier
*
*/
public class MeasurementDistribution {
/**
* Actual observed value of the measurement
*/
public double actualValue;
/**
* Probability that surrogate measurement is greater than
* the observed value.
* (Small pValue means that the observed value is highly significant).
*/
public double pValue;
/**
* Allow empty constructor for internal use only when actualValue and
* pValue will be supplied later
*/
protected MeasurementDistribution() {
}
/**
* Construct with supplied actual value and p-value for it.
*
* @param actualValue actual observed value
* @param pValue p-value that the surrogate measurement is larger
* than the observed value
*/
public MeasurementDistribution(double actualValue, double pValue) {
this.actualValue = actualValue;
this.pValue = pValue;
}
}