mirror of https://github.com/jlizier/jidt
Added functions to discrete Entropy calculators for single dimensional arrays, plus local values of MI for single supplied values and statistical signficance testing for Active info storage.
This commit is contained in:
parent
3e017d1be4
commit
06d0ddf07d
|
|
@ -1,7 +1,9 @@
|
|||
package infodynamics.measures.discrete;
|
||||
|
||||
import infodynamics.utils.EmpiricalMeasurementDistribution;
|
||||
import infodynamics.utils.MathsUtils;
|
||||
import infodynamics.utils.MatrixUtils;
|
||||
import infodynamics.utils.RandomGenerator;
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
|
|
@ -361,7 +363,8 @@ public class ActiveInformationCalculator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Computes local active info storage for the given values
|
||||
* Computes local active info storage for the given (single)
|
||||
* specific values
|
||||
*
|
||||
* @param destNext
|
||||
* @param destPast
|
||||
|
|
@ -863,6 +866,77 @@ public class ActiveInformationCalculator {
|
|||
return computeAverageLocalOfObservations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the significance of obtaining the given average from the given observations
|
||||
*
|
||||
* @param numPermutationsToCheck number of new orderings of the source values to compare against
|
||||
* @return
|
||||
*/
|
||||
public EmpiricalMeasurementDistribution computeSignificance(int numPermutationsToCheck) {
|
||||
RandomGenerator rg = new RandomGenerator();
|
||||
// (Not necessary to check for distinct random perturbations)
|
||||
int[][] newOrderings = rg.generateRandomPerturbations(observations, numPermutationsToCheck);
|
||||
return computeSignificance(newOrderings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the significance of obtaining the given average from the given observations
|
||||
*
|
||||
* @param newOrderings the reorderings to use
|
||||
* @return
|
||||
*/
|
||||
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) {
|
||||
double actualMI = computeAverageLocalOfObservations();
|
||||
|
||||
int numPermutationsToCheck = newOrderings.length;
|
||||
|
||||
// Reconstruct the values of the previous and next variables (not necessarily in order)
|
||||
int[] prevValues = new int[observations];
|
||||
int[] nextValues = new int[observations];
|
||||
int t_prev = 0;
|
||||
int t_next = 0;
|
||||
for (int prevVal = 0; prevVal < prevCount.length; prevVal++) {
|
||||
int numberOfSamplesPrev = prevCount[prevVal];
|
||||
MatrixUtils.fill(prevValues, prevVal, t_prev, numberOfSamplesPrev);
|
||||
t_prev += numberOfSamplesPrev;
|
||||
}
|
||||
for (int nextVal = 0; nextVal < base; nextVal++) {
|
||||
int numberOfSamplesNext = nextCount[nextVal];
|
||||
MatrixUtils.fill(nextValues, nextVal, t_next, numberOfSamplesNext);
|
||||
t_next += numberOfSamplesNext;
|
||||
}
|
||||
|
||||
ActiveInformationCalculator ais2;
|
||||
ais2 = new ActiveInformationCalculator(base, k);
|
||||
ais2.initialise();
|
||||
ais2.observations = observations;
|
||||
ais2.prevCount = prevCount;
|
||||
ais2.nextCount = nextCount;
|
||||
int countWhereMIIsMoreSignificantThanOriginal = 0;
|
||||
EmpiricalMeasurementDistribution measDistribution = new EmpiricalMeasurementDistribution(numPermutationsToCheck);
|
||||
for (int p = 0; p < numPermutationsToCheck; p++) {
|
||||
// Generate a new re-ordered data set for the next variable
|
||||
int[] newDataNext = MatrixUtils.extractSelectedTimePoints(nextValues, newOrderings[p]);
|
||||
// compute the joint probability distribution
|
||||
MatrixUtils.fill(ais2.jointCount, 0);
|
||||
for (int t = 0; t < observations; t++) {
|
||||
ais2.jointCount[newDataNext[t]][prevValues[t]]++;
|
||||
}
|
||||
// And get an MI value for this realisation:
|
||||
double newMI = ais2.computeAverageLocalOfObservations();
|
||||
measDistribution.distribution[p] = newMI;
|
||||
if (newMI >= actualMI) {
|
||||
countWhereMIIsMoreSignificantThanOriginal++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// And return the significance
|
||||
measDistribution.pValue = (double) countWhereMIIsMoreSignificantThanOriginal / (double) numPermutationsToCheck;
|
||||
measDistribution.actualValue = actualMI;
|
||||
return measDistribution;
|
||||
}
|
||||
|
||||
public double getLastAverage() {
|
||||
return average;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,39 @@ public class BlockEntropyCalculator extends EntropyCalculator {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add observations in to our estimates of the pdfs.
|
||||
*
|
||||
* @param states index is time
|
||||
*/
|
||||
public void addObservations(int states[]) {
|
||||
int rows = states.length;
|
||||
// increment the count of observations:
|
||||
observations += (rows - blocksize + 1);
|
||||
|
||||
// Initialise and store the current previous value
|
||||
int stateVal = 0;
|
||||
for (int p = 0; p < blocksize - 1; p++) {
|
||||
// Add the contribution from this observation
|
||||
stateVal += states[p];
|
||||
// And shift up
|
||||
stateVal *= base;
|
||||
}
|
||||
|
||||
// 1. Now count the tuples observed from the next row onwards
|
||||
for (int r = blocksize - 1; r < rows; r++) {
|
||||
// Add the contribution from this observation
|
||||
stateVal += states[r];
|
||||
|
||||
// Add to the count for this particular state:
|
||||
stateCount[stateVal]++;
|
||||
|
||||
// Remove the oldest observation from the state value
|
||||
stateVal -= maxShiftedValue[states[r-blocksize+1]];
|
||||
stateVal *= base;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add observations in to our estimates of the pdfs.
|
||||
* This call suitable only for homogeneous agents, as all
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import infodynamics.utils.MatrixUtils;
|
|||
* </li>
|
||||
* </ol></p>
|
||||
*
|
||||
* TODO Add method calls for single dimensional arrays
|
||||
*
|
||||
* @author Joseph Lizier
|
||||
*/
|
||||
|
|
@ -78,6 +77,23 @@ public class EntropyCalculator extends InfoMeasureCalculator
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add observations in to our estimates of the pdfs.
|
||||
*
|
||||
* @param states 1st index is time
|
||||
*/
|
||||
public void addObservations(int states[]) {
|
||||
int rows = states.length;
|
||||
// increment the count of observations:
|
||||
observations += rows;
|
||||
|
||||
// 1. Count the tuples observed
|
||||
for (int r = 0; r < rows; r++) {
|
||||
// Add to the count for this particular state:
|
||||
stateCount[states[r]]++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add observations in to our estimates of the pdfs.
|
||||
* This call suitable only for homogeneous agents, as all
|
||||
|
|
@ -226,6 +242,38 @@ public class EntropyCalculator extends InfoMeasureCalculator
|
|||
return ent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes local entropy for the given
|
||||
* states, using pdfs built up from observations previously
|
||||
* sent in via the addObservations method
|
||||
*
|
||||
* @param states index is time
|
||||
* @return
|
||||
*/
|
||||
public double[] computeLocalFromPreviousObservations(int states[]){
|
||||
int rows = states.length;
|
||||
|
||||
double[] localEntropy = new double[rows];
|
||||
average = 0;
|
||||
max = 0;
|
||||
min = 0;
|
||||
for (int r = 0; r < rows; r++) {
|
||||
double p_state = (double) stateCount[states[r]] / (double) observations;
|
||||
// Entropy takes the negative log:
|
||||
localEntropy[r] = - Math.log(p_state) / log_2;
|
||||
average += localEntropy[r];
|
||||
if (localEntropy[r] > max) {
|
||||
max = localEntropy[r];
|
||||
} else if (localEntropy[r] < min) {
|
||||
min = localEntropy[r];
|
||||
}
|
||||
}
|
||||
average = average/(double) rows;
|
||||
|
||||
return localEntropy;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes local entropy for the given
|
||||
* states, using pdfs built up from observations previously
|
||||
|
|
@ -239,7 +287,6 @@ public class EntropyCalculator extends InfoMeasureCalculator
|
|||
int rows = states.length;
|
||||
int columns = states[0].length;
|
||||
|
||||
// Allocate for all rows even though we may not be assigning all of them
|
||||
double[][] localEntropy = new double[rows][columns];
|
||||
average = 0;
|
||||
max = 0;
|
||||
|
|
@ -287,7 +334,6 @@ public class EntropyCalculator extends InfoMeasureCalculator
|
|||
}
|
||||
}
|
||||
|
||||
// Allocate for all rows even though we may not be assigning all of them
|
||||
double[][][] localEntropy = new double[timeSteps][agentRows][agentColumns];
|
||||
average = 0;
|
||||
max = 0;
|
||||
|
|
@ -327,7 +373,6 @@ public class EntropyCalculator extends InfoMeasureCalculator
|
|||
int rows = states.length;
|
||||
//int columns = states[0].length;
|
||||
|
||||
// Allocate for all rows even though we'll leave the first ones as zeros
|
||||
double[] localEntropy = new double[rows];
|
||||
average = 0;
|
||||
max = 0;
|
||||
|
|
@ -386,6 +431,23 @@ public class EntropyCalculator extends InfoMeasureCalculator
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute local information theoretic measure across a 1D temporal
|
||||
* array of the states of homogeneous agents
|
||||
* Return a 1D temporal array of local values.
|
||||
* First history rows are zeros
|
||||
*
|
||||
* @param states - 1D array of states
|
||||
* @return
|
||||
*/
|
||||
public final double[] computeLocal(int states[]) {
|
||||
|
||||
initialise();
|
||||
addObservations(states);
|
||||
return computeLocalFromPreviousObservations(states);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute local information theoretic measure across a 2D spatiotemporal
|
||||
|
|
@ -420,6 +482,22 @@ public class EntropyCalculator extends InfoMeasureCalculator
|
|||
return computeLocalFromPreviousObservations(states);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute average local information theoretic measure across a 1D temporal
|
||||
* array of the states of homogeneous agents
|
||||
* Return the average
|
||||
*
|
||||
* @param states - 1D array of states
|
||||
* @return
|
||||
*/
|
||||
public final double computeAverageLocal(int states[]) {
|
||||
|
||||
initialise();
|
||||
addObservations(states);
|
||||
return computeAverageLocalOfObservations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute average local information theoretic measure across a 2D spatiotemporal
|
||||
|
|
|
|||
|
|
@ -221,6 +221,32 @@ public class MutualInformationCalculator extends InfoMeasureCalculator
|
|||
return measDistribution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes local mutual information (or pointwise mutual information)
|
||||
* for the given (single) specific values, using pdfs built up from observations previously
|
||||
* sent in via the addObservations method.
|
||||
*
|
||||
* @param val1 single specific value of variable 1
|
||||
* @param val2 single specific value of variable 2
|
||||
* @return a local mutual information value for this pair of observations
|
||||
* @throws Exception if this pair were not observed together in the
|
||||
* previously supplied observations
|
||||
*/
|
||||
public double computeLocalFromPreviousObservations(int val1, int val2) throws Exception{
|
||||
|
||||
double logTerm = ( (double) jointCount[val1][val2] ) /
|
||||
( (double) jCount[val2] *
|
||||
(double) iCount[val1] );
|
||||
// Now account for the fact that we've
|
||||
// just used counts rather than probabilities,
|
||||
// and we've got two counts on the bottom
|
||||
// but one count on the top:
|
||||
logTerm *= (double) observations;
|
||||
double localMI = Math.log(logTerm) / log_2;
|
||||
|
||||
return localMI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes local mutual information (or pointwise mutual information)
|
||||
* for the given states, using pdfs built up from observations previously
|
||||
|
|
|
|||
Loading…
Reference in New Issue