This commit is contained in:
Brad 2025-10-28 22:53:24 +08:00 committed by GitHub
commit ebcc281b50
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 1608 additions and 1344 deletions

View File

@ -72,7 +72,7 @@ import infodynamics.utils.RandomGenerator;
* @author Joseph Lizier (<a href="joseph.lizier at gmail.com">email</a>,
* <a href="http://lizier.me/joseph/">www</a>)
*/
public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscreteInContextOfPastCalculator
public class ActiveInformationCalculatorDiscrete extends UnivariateMeasureDiscreteInContextOfPastCalculator
implements EmpiricalNullDistributionComputer, AnalyticNullDistributionComputer {
protected boolean aisComputed = false;
@ -111,7 +111,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
@Override
public void initialise() {
initialise(base, k);
initialise(alphabetSize, k);
}
public void initialise(int base, int history) {
@ -128,7 +128,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
// Initialise and store the current previous value for each column
int prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p];
}
@ -142,7 +142,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
nextCount[nextVal]++;
// Update the previous value:
prevVal -= maxShiftedValue[states[t-k]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[t];
}
}
@ -159,7 +159,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
for (int c = 0; c < columns; c++) {
prevVal[c] = 0;
for (int p = 0; p < k; p++) {
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += states[p][c];
}
}
@ -176,13 +176,12 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
nextCount[nextVal]++;
// Update the previous value:
prevVal[c] -= maxShiftedValue[states[r-k][c]];
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += states[r][c];
}
}
}
@Override
public void addObservations(int states[][][]) {
int timeSteps = states.length;
if (timeSteps == 0) {
@ -202,7 +201,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
for (int c = 0; c < agentColumns; c++) {
prevVal[r][c] = 0;
for (int p = 0; p < k; p++) {
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += states[p][r][c];
}
}
@ -221,14 +220,13 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
nextCount[nextVal]++;
// Update the previous value:
prevVal[r][c] -= maxShiftedValue[states[t-k][r][c]];
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += states[t][r][c];
}
}
}
}
@Override
public void addObservations(int states[][], int col) {
int rows = states.length;
// increment the count of observations:
@ -238,7 +236,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
int prevVal = 0;
prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][col];
}
@ -253,12 +251,11 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
nextCount[nextVal]++;
// Update the previous value:
prevVal -= maxShiftedValue[states[r-k][col]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[r][col];
}
}
@Override
public void addObservations(int states[][][], int agentIndex1, int agentIndex2) {
int timeSteps = states.length;
// increment the count of observations:
@ -268,7 +265,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
int prevVal = 0;
prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][agentIndex1][agentIndex2];
}
@ -283,7 +280,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
nextCount[nextVal]++;
// Update the previous value:
prevVal -= maxShiftedValue[states[t-k][agentIndex1][agentIndex2]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[t][agentIndex1][agentIndex2];
}
}
@ -295,7 +292,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
max = 0;
min = 0;
for (int nextVal = 0; nextVal < base; nextVal++) {
for (int nextVal = 0; nextVal < alphabetSize; nextVal++) {
// compute p_next
double p_next = (double) nextCount[nextVal] / (double) observations;
for (int prevVal = 0; prevVal < base_power_k; prevVal++) {
@ -335,7 +332,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
double entRate = 0.0;
double entRateCont = 0.0;
for (int nextVal = 0; nextVal < base; nextVal++) {
for (int nextVal = 0; nextVal < alphabetSize; nextVal++) {
for (int prevVal = 0; prevVal < base_power_k; prevVal++) {
// compute p_prev
double p_prev = (double) pastCount[prevVal] / (double) observations;
@ -389,7 +386,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
// Initialise and store the current previous value for each column
int prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p];
}
@ -414,7 +411,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
}
// Update the previous value:
prevVal -= maxShiftedValue[states[t-k]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[t];
}
average = average/(double) (timeSteps - k);
@ -423,7 +420,6 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
}
@Override
public double[][] computeLocalFromPreviousObservations(int states[][]){
int rows = states.length;
int columns = states[0].length;
@ -439,7 +435,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
for (int c = 0; c < columns; c++) {
prevVal[c] = 0;
for (int p = 0; p < k; p++) {
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += states[p][c];
}
}
@ -465,7 +461,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
}
// Update the previous value:
prevVal[c] -= maxShiftedValue[states[r-k][c]];
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += states[r][c];
}
}
@ -475,7 +471,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
}
@Override
public double[][][] computeLocalFromPreviousObservations(int states[][][]){
int timeSteps = states.length;
int agentRows = states[0].length;
@ -493,7 +489,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
for (int c = 0; c < agentColumns; c++) {
prevVal[r][c] = 0;
for (int p = 0; p < k; p++) {
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += states[p][r][c];
}
}
@ -521,7 +517,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
}
// Update the previous value:
prevVal[r][c] -= maxShiftedValue[states[t-k][r][c]];
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += states[t][r][c];
}
}
@ -531,7 +527,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
return localActive;
}
@Override
public double[] computeLocalFromPreviousObservations(int states[][], int col){
int rows = states.length;
//int columns = states[0].length;
@ -546,7 +542,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
int prevVal = 0;
prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][col];
}
int nextVal;
@ -570,7 +566,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
}
// Update the previous value:
prevVal -= maxShiftedValue[states[r-k][col]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[r][col];
}
average = average/(double) (rows - k);
@ -579,7 +575,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
}
@Override
public double[] computeLocalFromPreviousObservations(int states[][][],
int agentIndex1, int agentIndex2){
int timeSteps = states.length;
@ -595,7 +591,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
int prevVal = 0;
prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][agentIndex1][agentIndex2];
}
int nextVal;
@ -619,7 +615,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
}
// Update the previous value:
prevVal -= maxShiftedValue[states[t-k][agentIndex1][agentIndex2]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[t][agentIndex1][agentIndex2];
}
average = average/(double) (timeSteps - k);
@ -709,14 +705,14 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
MatrixUtils.fill(prevValues, prevVal, t_prev, numberOfSamplesPrev);
t_prev += numberOfSamplesPrev;
}
for (int nextVal = 0; nextVal < base; nextVal++) {
for (int nextVal = 0; nextVal < alphabetSize; nextVal++) {
int numberOfSamplesNext = nextCount[nextVal];
MatrixUtils.fill(nextValues, nextVal, t_next, numberOfSamplesNext);
t_next += numberOfSamplesNext;
}
ActiveInformationCalculatorDiscrete ais2;
ais2 = new ActiveInformationCalculatorDiscrete(base, k);
ais2 = new ActiveInformationCalculatorDiscrete(alphabetSize, k);
ais2.initialise();
ais2.observations = observations;
ais2.pastCount = pastCount;
@ -754,7 +750,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
}
return new ChiSquareMeasurementDistribution(average,
observations,
(base - 1) * (base_power_k - 1));
(alphabetSize - 1) * (base_power_k - 1));
}
/**
@ -767,7 +763,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
double miCont = 0.0;
System.out.println("nextVal p(next) prevVal p(prev) p(joint) logTerm localVal");
for (int nextVal = 0; nextVal < base; nextVal++) {
for (int nextVal = 0; nextVal < alphabetSize; nextVal++) {
// compute p_next
double p_next = (double) nextCount[nextVal] / (double) observations;
for (int prevVal = 0; prevVal < base_power_k; prevVal++) {
@ -811,7 +807,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
public int computePastValue(int[] x, int t) {
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += x[t - k + 1 + p];
}
return pastVal;
@ -835,7 +831,7 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
public int computePastValue(int[][] data, int column, int t) {
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += data[t - k + 1 + p][column];
}
return pastVal;
@ -863,9 +859,27 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
int agentColumn, int t) {
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += data[t - k + 1 + p][agentRow][agentColumn];
}
return pastVal;
}
@Override
public void setObservations(Object[] observations) throws Exception {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'setObservations'");
}
@Override
public void startAddObservations() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'startAddObservations'");
}
@Override
public void finaliseAddObservations() throws Exception {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'finaliseAddObservations'");
}
}

View File

@ -104,7 +104,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
private void resetBlocksize(int blocksize) {
this.blocksize = blocksize;
base_power_blocksize = MathsUtils.power(base, blocksize);
base_power_blocksize = MathsUtils.power(alphabetSize, blocksize);
if (blocksize <= 1) {
throw new RuntimeException("Blocksize " + blocksize + " is not > 1 for Block Entropy Calculator");
@ -114,14 +114,14 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
}
// Create constants for tracking stateValues
maxShiftedValue = new int[base];
for (int v = 0; v < base; v++) {
maxShiftedValue[v] = v * MathsUtils.power(base, blocksize-1);
maxShiftedValue = new int[alphabetSize];
for (int v = 0; v < alphabetSize; v++) {
maxShiftedValue[v] = v * MathsUtils.power(alphabetSize, blocksize-1);
}
}
public void initialise(int blocksize, int base) {
boolean baseOrBlocksizeChanged = (this.blocksize != blocksize) || (this.base != base);
boolean baseOrBlocksizeChanged = (this.blocksize != blocksize) || (this.alphabetSize != base);
super.initialise(base);
if (baseOrBlocksizeChanged) {
@ -148,7 +148,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
@Override
public void initialise() {
initialise(blocksize, base);
initialise(blocksize, alphabetSize);
}
@Override
@ -163,7 +163,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Add the contribution from this observation
stateVal += states[p];
// And shift up
stateVal *= base;
stateVal *= alphabetSize;
}
// 1. Now count the tuples observed from the next row onwards
@ -176,7 +176,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Remove the oldest observation from the state value
stateVal -= maxShiftedValue[states[r-blocksize+1]];
stateVal *= base;
stateVal *= alphabetSize;
}
}
@ -195,7 +195,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Add the contribution from this observation
stateVal[c] += states[p][c];
// And shift up
stateVal[c] *= base;
stateVal[c] *= alphabetSize;
}
}
@ -210,12 +210,12 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Remove the oldest observation from the state value
stateVal[c] -= maxShiftedValue[states[r-blocksize+1][c]];
stateVal[c] *= base;
stateVal[c] *= alphabetSize;
}
}
}
@Override
public void addObservations(int states[][][]) {
int timeSteps = states.length;
if (timeSteps == 0) {
@ -238,7 +238,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Add the contribution from this observation
stateVal[r][c] += states[p][r][c];
// And shift up
stateVal[r][c] *= base;
stateVal[r][c] *= alphabetSize;
}
}
}
@ -255,13 +255,13 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Remove the oldest observation from the state value
stateVal[r][c] -= maxShiftedValue[states[t-blocksize+1][r][c]];
stateVal[r][c] *= base;
stateVal[r][c] *= alphabetSize;
}
}
}
}
@Override
public void addObservations(int states[][], int col) {
int rows = states.length;
// increment the count of observations:
@ -273,7 +273,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Add the contribution from this observation
stateVal += states[p][col];
// And shift up
stateVal *= base;
stateVal *= alphabetSize;
}
// 1. Count the tuples observed
@ -286,11 +286,11 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Remove the oldest observation from the state value
stateVal -= maxShiftedValue[states[r-blocksize+1][col]];
stateVal *= base;
stateVal *= alphabetSize;
}
}
@Override
public void addObservations(int states[][][], int agentIndex1, int agentIndex2) {
int timeSteps = states.length;
// increment the count of observations:
@ -302,7 +302,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Add the contribution from this observation
stateVal += states[p][agentIndex1][agentIndex2];
// And shift up
stateVal *= base;
stateVal *= alphabetSize;
}
// 1. Count the tuples observed
@ -315,7 +315,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Remove the oldest observation from the state value
stateVal -= maxShiftedValue[states[t-blocksize+1][agentIndex1][agentIndex2]];
stateVal *= base;
stateVal *= alphabetSize;
}
}
@ -348,7 +348,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
return ent;
}
@Override
public double[][] computeLocalFromPreviousObservations(int states[][]){
int rows = states.length;
int columns = states[0].length;
@ -365,7 +365,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
stateVal[c] = 0;
for (int p = 0; p < blocksize - 1; p++) {
stateVal[c] += states[p][c];
stateVal[c] *= base;
stateVal[c] *= alphabetSize;
}
}
// StateVal just needs the next value put in before processing
@ -387,7 +387,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Subtract out the oldest part of the state value:
stateVal[c] -= maxShiftedValue[states[r-blocksize+1][c]];
// And shift all upwards
stateVal[c] *= base;
stateVal[c] *= alphabetSize;
}
}
average = average/(double) (columns * (rows - blocksize + 1));
@ -396,7 +396,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
}
@Override
public double[][][] computeLocalFromPreviousObservations(int states[][][]){
int timeSteps = states.length;
int agentRows, agentColumns;
@ -425,7 +425,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
stateVal[r][c] = 0;
for (int p = 0; p < blocksize - 1; p++) {
stateVal[r][c] += states[p][r][c];
stateVal[r][c] *= base;
stateVal[r][c] *= alphabetSize;
}
}
}
@ -449,7 +449,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Subtract out the oldest part of the state value:
stateVal[r][c] -= maxShiftedValue[states[t-blocksize+1][r][c]];
// And shift all upwards
stateVal[r][c] *= base;
stateVal[r][c] *= alphabetSize;
}
}
}
@ -459,7 +459,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
}
@Override
public double[] computeLocalFromPreviousObservations(int states[][], int col){
int rows = states.length;
//int columns = states[0].length;
@ -476,7 +476,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
int stateVal = 0;
for (int p = 0; p < blocksize - 1; p++) {
stateVal += states[p][col];
stateVal *= base;
stateVal *= alphabetSize;
}
// StateVal just needs the next value put in before processing
@ -496,7 +496,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Subtract out the oldest part of the state value:
stateVal -= maxShiftedValue[states[r-blocksize+1][col]];
// And shift all upwards
stateVal *= base;
stateVal *= alphabetSize;
}
average = average/(double) (rows - blocksize + 1);
@ -504,7 +504,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
}
@Override
public double[] computeLocalFromPreviousObservations(int states[][][], int agentIndex1, int agentIndex2){
int timeSteps = states.length;
//int columns = states[0].length;
@ -521,7 +521,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
int stateVal = 0;
for (int p = 0; p < blocksize - 1; p++) {
stateVal += states[p][agentIndex1][agentIndex2];
stateVal *= base;
stateVal *= alphabetSize;
}
// StateVal just needs the next value put in before processing
@ -541,7 +541,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
// Subtract out the oldest part of the state value:
stateVal -= maxShiftedValue[states[t-blocksize+1][agentIndex1][agentIndex2]];
// And shift all upwards
stateVal *= base;
stateVal *= alphabetSize;
}
average = average/(double) (timeSteps - blocksize + 1);

View File

@ -32,7 +32,7 @@ import infodynamics.utils.MatrixUtils;
* and typical usage pattern.
* </p>
*
* TODO Make this inherit from {@link SingleAgentMeasureDiscreteInContextOfPastCalculator}
* TODO Make this inherit from {@link UnivariateMeasureDiscreteInContextOfPastCalculator}
* like {@link ActiveInformationCalculatorDiscrete} and fix the Javadocs
*
* @author Joseph Lizier (<a href="joseph.lizier at gmail.com">email</a>,

View File

@ -242,7 +242,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
public void initialise(int base, int history,
int numOtherInfoContributors, int base_others) {
boolean paramsChanged = (this.base != base) || (k != history) ||
boolean paramsChanged = (this.alphabetSize != base) || (k != history) ||
(this.numOtherInfoContributors != numOtherInfoContributors) ||
(this.base_others != base_others);
super.initialise(base, history);
@ -275,7 +275,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
@Override
public void initialise(){
initialise(base, k, numOtherInfoContributors, base_others);
initialise(alphabetSize, k, numOtherInfoContributors, base_others);
}
/**
@ -313,7 +313,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Initialise and store the current previous value
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += dest[p];
}
@ -336,7 +336,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Update the previous value:
if (k > 0) {
pastVal -= maxShiftedValue[dest[r-k]];
pastVal *= base;
pastVal *= alphabetSize;
pastVal += dest[r];
}
}
@ -386,7 +386,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Initialise and store the current previous value
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += dest[p];
}
@ -404,7 +404,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Update the previous value:
if (k > 0) {
pastVal -= maxShiftedValue[dest[r-k]];
pastVal *= base;
pastVal *= alphabetSize;
pastVal += dest[r];
}
}
@ -468,7 +468,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
for (int c = 0; c < columns; c++) {
pastVal[c] = 0;
for (int p = 0; p < k; p++) {
pastVal[c] *= base;
pastVal[c] *= alphabetSize;
pastVal[c] += states[p][c];
}
}
@ -494,7 +494,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Update the previous value:
if (k > 0) {
pastVal[c] -= maxShiftedValue[states[r-k][c]];
pastVal[c] *= base;
pastVal[c] *= alphabetSize;
pastVal[c] += states[r][c];
}
}
@ -551,7 +551,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Initialise and store the current previous value for each column
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[p][destCol];
}
@ -575,7 +575,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Update the previous value:
if (k > 0) {
pastVal -= maxShiftedValue[states[r-k][destCol]];
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[r][destCol];
}
}
@ -591,8 +591,8 @@ public class ConditionalTransferEntropyCalculatorDiscrete
double meanSqLocals = 0;
for (int othersVal = 0; othersVal < this.base_power_num_others; othersVal++) {
for (int pastVal = 0; pastVal < base_power_k; pastVal++) {
for (int destVal = 0; destVal < base; destVal++) {
for (int sourceVal = 0; sourceVal < base; sourceVal++) {
for (int destVal = 0; destVal < alphabetSize; destVal++) {
for (int sourceVal = 0; sourceVal < alphabetSize; sourceVal++) {
// Compute TE contribution:
if (sourceDestPastOthersCount[sourceVal][destVal][pastVal][othersVal] != 0) {
/* Double check: should never happen
@ -650,7 +650,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Reconstruct the source values (not necessarily in order)
int[] sourceValues = new int[observations];
int t_s = 0;
for (int sourceVal = 0; sourceVal < base; sourceVal++) {
for (int sourceVal = 0; sourceVal < alphabetSize; sourceVal++) {
// Count up the number of times this source value was observed:
int numberOfSamples = 0;
for (int pastVal = 0; pastVal < base_power_k; pastVal++) {
@ -683,7 +683,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
MatrixUtils.fill(othersValues, othersVal, t_o,
pastOthersCount[pastVal][othersVal]);
t_o += pastOthersCount[pastVal][othersVal];
for (int destVal = 0; destVal < base; destVal++) {
for (int destVal = 0; destVal < alphabetSize; destVal++) {
MatrixUtils.fill(destValues, destVal, t_d,
destPastOthersCount[destVal][pastVal][othersVal]);
t_d += destPastOthersCount[destVal][pastVal][othersVal];
@ -692,7 +692,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
}
// TODO stop using deprecated method
ConditionalTransferEntropyCalculatorDiscrete cte = newInstance(base, k, numOtherInfoContributors);
ConditionalTransferEntropyCalculatorDiscrete cte = newInstance(alphabetSize, k, numOtherInfoContributors);
cte.initialise();
cte.observations = observations;
cte.pastOthersCount = pastOthersCount;
@ -733,7 +733,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
}
return new ChiSquareMeasurementDistribution(average,
observations,
(base - 1)*(base - 1)*(base_power_k*base_power_num_others));
(alphabetSize - 1)*(alphabetSize - 1)*(base_power_k*base_power_num_others));
}
/**
@ -804,7 +804,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
for (int c = 0; c < columns; c++) {
pastVal[c] = 0;
for (int p = 0; p < k; p++) {
pastVal[c] *= base;
pastVal[c] *= alphabetSize;
pastVal[c] += states[p][c];
}
}
@ -834,7 +834,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Update the previous value:
if (k > 0) {
pastVal[c] -= maxShiftedValue[states[r-k][c]];
pastVal[c] *= base;
pastVal[c] *= alphabetSize;
pastVal[c] += states[r][c];
}
}
@ -905,7 +905,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
int pastVal = 0;
pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[p][destCol];
}
int destVal, sourceVal, othersVal;
@ -932,7 +932,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Update the previous value:
if (k > 0) {
pastVal -= maxShiftedValue[states[r-k][destCol]];
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[r][destCol];
}
}
@ -975,7 +975,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
int pastVal = 0;
pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += dest[p];
}
int destVal, sourceVal, conditionalVal;
@ -997,7 +997,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Update the previous value:
if (k > 0) {
pastVal -= maxShiftedValue[dest[r-k]];
pastVal *= base;
pastVal *= alphabetSize;
pastVal += dest[r];
}
}
@ -1033,7 +1033,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
int pastVal = 0;
pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += dest[p];
}
int destVal, sourceVal, conditionalsVal;
@ -1044,7 +1044,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
conditionalsVal = 0;
for (int o = 0; o < conditionals[r-1].length; o++) {
// Include this other contributor
conditionalsVal *= base;
conditionalsVal *= alphabetSize;
conditionalsVal += conditionals[r-1][o];
}
// Now compute the local value
@ -1060,7 +1060,7 @@ public class ConditionalTransferEntropyCalculatorDiscrete
// Update the previous value:
if (k > 0) {
pastVal -= maxShiftedValue[dest[r-k]];
pastVal *= base;
pastVal *= alphabetSize;
pastVal += dest[r];
}
}

View File

@ -104,14 +104,14 @@ public abstract class ContextOfPastMeasureCalculatorDiscrete extends
}
/**
* Should be called after {@link #resetBase(int)} has just been called.
* Should be called after {@link #resetAlphabetSize(int)} has just been called.
*
* @param history
*/
private void resetHistory(int history) {
k = history;
base_power_k = MathsUtils.power(base, k);
base_power_k = MathsUtils.power(alphabetSize, k);
if (k < 0) {
throw new RuntimeException("History k " + history + " is not >= 0 for a ContextOfPastMeasureCalculator");
@ -123,15 +123,15 @@ public abstract class ContextOfPastMeasureCalculatorDiscrete extends
}
// Create constants for tracking prevValues
maxShiftedValue = new int[base];
for (int v = 0; v < base; v++) {
maxShiftedValue[v] = v * MathsUtils.power(base, k-1);
maxShiftedValue = new int[alphabetSize];
for (int v = 0; v < alphabetSize; v++) {
maxShiftedValue[v] = v * MathsUtils.power(alphabetSize, k-1);
}
}
@Override
public void initialise() {
initialise(base, k);
initialise(alphabetSize, k);
}
/**
@ -143,7 +143,7 @@ public abstract class ContextOfPastMeasureCalculatorDiscrete extends
*/
public void initialise(int base, int history) {
boolean baseOrHistoryChanged = false;
if ((this.base != base) || (k != history)) {
if ((this.alphabetSize != base) || (k != history)) {
baseOrHistoryChanged = true;
}
@ -189,7 +189,7 @@ public abstract class ContextOfPastMeasureCalculatorDiscrete extends
public int computePastValue(int[] x, int t) {
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += x[t - k + 1 + p];
}
return pastVal;
@ -212,7 +212,7 @@ public abstract class ContextOfPastMeasureCalculatorDiscrete extends
public int computePastValue(int[][] data, int columnNumber, int t) {
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += data[t - k + 1 + p][columnNumber];
}
return pastVal;
@ -238,7 +238,7 @@ public abstract class ContextOfPastMeasureCalculatorDiscrete extends
public int computePastValue(int[][][] data, int rowNumber, int columnNumber, int t) {
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += data[t - k + 1 + p][rowNumber][columnNumber];
}
return pastVal;

View File

@ -18,6 +18,11 @@
package infodynamics.measures.discrete;
import java.util.Hashtable;
import java.util.Map;
import java.util.List;
import java.util.Arrays;
import infodynamics.utils.MatrixUtils;
/**
@ -56,157 +61,58 @@ Theory' (John Wiley & Sons, New York, 1991).</li>
* <a href="http://lizier.me/joseph/">www</a>)
*/
public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
implements SingleAgentMeasureDiscrete
implements UnivariateMeasureDiscrete
{
// TODO -- find or calculate reasonable max value. Currently 100.
protected int[] stateCount = null; // Count for i[t]
/**
* User was formerly forced to create new instances through this factory method.
* Retained for backwards compatibility.
*
* @param base number of symbols for each variable.
* E.g. binary variables are in base-2.
* @param blocksize number of consecutive joint values to include
* in the calculation.
* @deprecated
* @return a new EntropyCalculator
* State counts in a hashtable for observations other than ints
* as well as for sparse observations
*/
public static EntropyCalculatorDiscrete newInstance(int base, int blocksize) {
if (blocksize > 1) {
return BlockEntropyCalculatorDiscrete.newInstance(blocksize, base);
} else {
return EntropyCalculatorDiscrete.newInstance(base);
}
}
public static EntropyCalculatorDiscrete newInstance(int base) {
return new EntropyCalculatorDiscrete(base);
}
protected Hashtable<Object, Integer> hashedStateCount = null;
/**
* Number of dimensions for multi-dimensional calculations
*/
protected int numDimensions = 1;
/**
* Sizes of each dimension's alphabet
*/
protected int[] alphabetSizes = null;
/**
* Construct a new instance with default base of 2
* Construct a new instance with no specified alphabet size.
*/
public EntropyCalculatorDiscrete() {
this(2);
this(-1);
}
/**
* Contruct a new instance
*
* @param base number of quantisation levels for each variable.
* @param alphabetSize number of quantisation levels for each variable.
* E.g. binary variables are in base-2.
*/
public EntropyCalculatorDiscrete(int base) {
super(base);
public EntropyCalculatorDiscrete(int alphabetSize) {
super(alphabetSize);
currentState = State.SETTING_PROPERTIES;
}
/**
* Initialise with new base
* Return the current count for the given value
*
* @param base
* @param stateVal given value
* @return count of observations of the given state
*/
public void initialise(int base){
boolean baseChanged = (this.base != base);
super.initialise(base);
if (baseChanged || (stateCount == null)) {
// Create storage for counts of observations
try {
stateCount = new int[base];
} catch (OutOfMemoryError e) {
// Allow any Exceptions to be thrown, but catch and wrap
// Error as a RuntimeException
throw new RuntimeException("Requested memory for the base (" +
base + ") is too large for the JVM at this time", e);
}
} else {
MatrixUtils.fill(stateCount, 0);
}
}
@Override
public void initialise(){
initialise(base);
}
@Override
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]]++;
}
}
@Override
public void addObservations(int states[][]) {
int rows = states.length;
int columns = states[0].length;
// increment the count of observations:
observations += rows * columns;
// 1. Count the tuples observed
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
// Add to the count for this particular state:
stateCount[states[r][c]]++;
}
}
}
@Override
public void addObservations(int states[][][]) {
int timeSteps = states.length;
if (timeSteps == 0) {
return;
}
int agentRows = states[0].length;
if (agentRows == 0) {
return;
}
int agentColumns = states[0][0].length;
// increment the count of observations:
observations += timeSteps * agentRows * agentColumns;
// 1. Count the tuples observed
for (int t = 0; t < timeSteps; t++) {
for (int i = 0; i < agentRows; i++) {
for (int j = 0; j < agentColumns; j++) {
// Add to the count for this particular state:
stateCount[states[t][i][j]]++;
}
}
}
}
@Override
public void addObservations(int states[][], int agentNumber) {
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][agentNumber]]++;
}
}
@Override
public void addObservations(int states[][][], int agentIndex1, int agentIndex2) {
int timeSteps = states.length;
// increment the count of observations:
observations += timeSteps;
// 1. Count the tuples observed
for (int r = 0; r < timeSteps; r++) {
// Add to the count for this particular state:
stateCount[states[r][agentIndex1][agentIndex2]]++;
public int getStateCount(int stateVal) {
// stateCount could have overflowed
if (stateCount == null) {
return hashedStateCount.get((Integer) stateVal);
}
return stateCount[stateVal];
}
/**
@ -215,8 +121,16 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
* @param stateVal given value
* @return count of observations of the given state
*/
public int getStateCount(int stateVal) {
return stateCount[stateVal];
public int getStateCount(Object stateVal) {
if (stateCount == null) {
return hashedStateCount.get(stateVal);
} else if (stateVal instanceof String) {
int index = Integer.parseInt((String) stateVal);
return stateCount[index];
} else {
int index = (Integer) stateVal;
return stateCount[index];
}
}
/**
@ -228,30 +142,385 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
public double getStateProbability(int stateVal) {
return (double) stateCount[stateVal] / (double) observations;
}
/**
* Initialise with new alphabet size
*
* @param alphabetSize
*/
public void initialise(int alphabetSize){
boolean sizeChange = (this.alphabetSize != alphabetSize);
super.initialise(alphabetSize);
// if alphabet size is unknown, use large but managable array
// only moving to hash table for arrays exceeding this temp limit.
int temp = alphabetSize;
if (temp == -1) {
// TODO -- This is where we set the reasonable max value. See top of class.
temp = 100;
}
if (sizeChange || stateCount == null) {
// Create storage for counts of observations
try {
stateCount = new int[temp];
} catch (OutOfMemoryError e) {
// Allow any Exceptions to be thrown, but catch and wrap
// Error as a RuntimeException
throw new RuntimeException("Requested memory for the alphabet size (" +
alphabetSize + ") is too large for the JVM at this time", e);
}
} else {
MatrixUtils.fill(stateCount, 0);
}
hashedStateCount = new Hashtable<>();
currentState = State.INITIALISED;
}
@Override
public void initialise(){
initialise(alphabetSize);
}
@Override
public void setProperty(String propertyName, String propertyValue) throws Exception {
// TODO -- set states here too, enforce correct workflow
// I believe this has been done
if (currentState != State.SETTING_PROPERTIES) {
stateCount = null;
hashedStateCount = new Hashtable<>();
knownIntegerRange = false;
alphabetSizes = null;
numDimensions = 1;
currentState = State.SETTING_PROPERTIES;
// TODO -- This is where we set the reasonable max value. See top of class.
alphabetSize = 100;
}
switch(propertyName.toUpperCase()) {
case "NUM_DIMENSIONS":
try {
this.numDimensions = Integer.parseInt(propertyValue);
if (numDimensions < 0) {
throw new NumberFormatException("propertyValue for NUM_DIMENSIONS must be at least 0.");
}
} catch (NumberFormatException e) {
throw new NumberFormatException("propertyValue for NUM_DIMENSIONS must be interpretable as an integer.");
}
break;
case "ALPHABET_SIZES":
/*
* Currently accepts '1,2,3' or '[1,2,3]' formats, as this seemed
* easiest for importing data as well as manual input.
* '1, 2, 3' and '[1, 2, 3]' should also work with parseInt, though I'm unsure.
*/
propertyValue.replaceFirst("[", "");
propertyValue.replaceFirst("]", "");
String[] temp = propertyValue.split(",");
this.alphabetSizes = new int[temp.length];
for (int i = 0; i < temp.length; i++) {
try {
alphabetSizes[i] = Integer.parseInt(temp[i]);
} catch (NumberFormatException e) {
throw new NumberFormatException("propertyValue for ALPHABET_SIZES must be interpretable as an integer array.\n"
+ "Input should look like [1,2,3]");
}
}
break;
default:
super.setProperty(propertyName, propertyValue);
break;
}
}
public void addObservations(Object[] states) throws NumberFormatException, RuntimeException {
// if user has set numDimensions, they intend for multi-dimensional, and
// should not be using this function
if (numDimensions != 1) {
throw new RuntimeException(
"numDimensions was not 1. " +
"If you intend to use multi-dimensional observations, use addObservations(Object[][] states)."
);
}
if (currentState == State.COMPUTING ||
currentState == State.SETTING_PROPERTIES) {
initialise();
}
currentState = State.ADDING_OBSERVATIONS;
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:
if (!hashedStateCount.isEmpty()) {
Object key = states[r];
Integer value = hashedStateCount.getOrDefault(key, 0) + 1;
hashedStateCount.put(key, value);
continue;
}
Integer index = this.alphabetSize;
if (states[r] instanceof String ) {
if (((String) states[r]).matches("[0-9]+")) {
index = Integer.parseInt((String) states[r]);
} else if (!knownIntegerRange) {
// First observation ever is non-integer string, right to hashtable
hashedStateCount.put((Object) states[r], 1);
stateCount = null;
continue;
}
} else if (states[r] instanceof Integer) {
index = (Integer) states[r];
} else {
throw new NumberFormatException(
"Cannot parse " + states[r] + " as an Integer for indexing.");
}
// valid index, check to make sure user didn't break the alphabet size they provided.
if (knownIntegerRange && index >= alphabetSize) {
throw new RuntimeException("Observation " + states[r] +
" exceeds provided alphabet size " + alphabetSize);
}
// if array is still a managable size...
if (index < stateCount.length) {
stateCount[index]++;
} else {
// otherwise array has grown too large, move to hash table.
for (int i = 0; i < stateCount.length; i++) {
hashedStateCount.put(i, stateCount[i]);
}
hashedStateCount.put(index, 1);
stateCount = null;
}
}
}
/**
* Add observations in to our estimates of the pdfs.
*
* @param states
*/
public void addObservations(int[] states) {
// if user has set numDimensions, they intend for multi-dimensional, and
// should not be using this function
if (numDimensions != 1) {
throw new RuntimeException(
"numDimensions was not 1. " +
"If you intend to use multi-dimensional observations, use addObservations(int[][] states)."
);
}
if (currentState == State.COMPUTING ||
currentState == State.SETTING_PROPERTIES) {
initialise();
}
currentState = State.ADDING_OBSERVATIONS;
int rows = states.length;
// increment the count of observations:
observations += rows;
// 1. Count the tuples observed
for (int r = 0; r < rows; r++) {
if (!hashedStateCount.isEmpty()) {
Object key = states[r];
Integer value = hashedStateCount.getOrDefault(key, 0) + 1;
hashedStateCount.put(key, value);
continue;
}
Integer index = states[r];
// check to make sure user didn't break the alphabet size they provided.
if (knownIntegerRange && index >= this.alphabetSize) {
throw new RuntimeException("Observation " + states[r] +
" exceeds provided alphabet size " + alphabetSize);
}
// if array is still a managable size...
if (index < alphabetSize) {
stateCount[index]++;
} else {
// Otherwise array has grown too large, move to hash table.
hashedStateCount = new Hashtable<>();
for (int i = 0; i < stateCount.length; i++) {
if (stateCount[i] != 0) {
hashedStateCount.put(i, stateCount[i]);
}
}
hashedStateCount.put(index, 1);
stateCount = null;
}
}
}
/**
* This method is intended for multi-dimensional use, and adds the observations
* into our estimates of the pdfs.
*
* @param states - the observations of all dimensions at each time step
* states[i][j] represents the ith observed state of the jth dimension.
* states[i] is the array of observations at time step i.
*/
@Override
public void addObservations(int[][] states) throws RuntimeException {
// ensure correct number of dimensions are provided
for (int i = 0; i < states.length; i++) {
if (states[i].length != numDimensions) {
throw new RuntimeException(String.format(
"Incorrect number of dimensions were given. Expected %d got %d.", numDimensions, states[i].length));
}
}
if (currentState == State.COMPUTING ||
currentState == State.SETTING_PROPERTIES) {
initialise();
}
currentState = State.ADDING_OBSERVATIONS;
// Unwrap unecessary single dimensional arrays, allows additional calls
// to the single dimensional version without issue.
if (numDimensions == 1) {
for (int i = 0; i < states.length; i++) {
this.stateCount[i] = states[i][0];
}
return;
}
int[] result;
if (alphabetSizes != null) {
result = computeCombinedValues(states, alphabetSizes, alphabetSize);
} else {
result = computeCombinedValues(states, alphabetSize);
}
for (int i = 0; i < result.length; i++) {
this.stateCount[i] += result[i];
}
}
/**
* This method is intended for multi-dimensional use, and adds the observations
* into our estimates of the pdfs.
*
* @param states - the observations of all dimensions at each time step
*/
public void addObservations(Object[][] states) {
// ensure correct number of dimensions are provided
for (int i = 0; i < states.length; i++) {
if (states[i].length != numDimensions) {
throw new RuntimeException(String.format(
"Incorrect number of dimensions were given. Expected %d got %d.", numDimensions, states[i].length));
}
}
if (currentState == State.COMPUTING ||
currentState == State.SETTING_PROPERTIES) {
initialise();
}
currentState = State.ADDING_OBSERVATIONS;
// Unwrap unecessary single dimensional arrays, allows additional calls
// to the single dimensional version without issue.
if (numDimensions == 1) {
Object[] temp = new Object[states.length];
for (int i = 0; i < states.length; i++) {
temp[i] = states[i][0];
}
addObservations(temp);
return;
}
for (int i = 0; i < states.length; i++) {
List<Object> key = Arrays.asList(states[i]);
Integer value = hashedStateCount.getOrDefault(key, 0) + 1;
hashedStateCount.put(key, value);
}
}
protected int[] computeCombinedValues(int[][] separatedValues, int maxSize) throws RuntimeException {
int[] sizes = new int[numDimensions];
MatrixUtils.fill(sizes, alphabetSize);
return computeCombinedValues(separatedValues, sizes, maxSize);
}
// TODO -- move to MatrixUtils.
protected int[] computeCombinedValues(int[][] separateValues, int[] alphabetSizes, int maxSize) throws RuntimeException {
// Make sure we won't get any overflow here
if (MatrixUtils.combinedValuesOverflow(numDimensions, alphabetSize)) {
// multiplier has overflown
throw new RuntimeException("Too many numDimensions " + numDimensions + " for the given alphabetSize " + alphabetSize +
" for this call to computeCombinedValues");
}
int size = 1;
for (int s : alphabetSizes) {
size *= s;
}
if (size >= maxSize) {
throw new RuntimeException("Size of combined observations exceeds capacity.");
}
int[] combinedValues = new int[size];
for (int r = 0; r < separateValues.length; r++) {
if (separateValues[r].length != alphabetSizes.length) {
throw new RuntimeException("alphabetSize and given input size do not match");
}
int combinedRowValue = 0;
int multiplier = 1;
for (int c = numDimensions - 1; c >= 0; c--) {
// check alphabet size restriction is maintained.
if (separateValues[r][c] >= alphabetSizes[r]) {
throw new RuntimeException("input value " + separateValues[r][c]
+ " exceeded alphabet size" + alphabetSizes[c]);
}
combinedRowValue += separateValues[r][c] * multiplier;
multiplier *= alphabetSizes[r];
}
combinedValues[r] = combinedRowValue;
}
return combinedValues;
}
@Override
public void setObservations(Object[] observations) throws Exception {
this.observations = observations.length;
this.addObservations(observations);
this.finaliseAddObservations();
}
@Override
public double computeAverageLocalOfObservations() {
double ent = 0.0;
double entCont = 0.0;
double p_state;
max = 0;
min = 0;
for (int stateVal = 0; stateVal < base; stateVal++) {
// compute p_state
double p_state = (double) stateCount[stateVal] / (double) observations;
if (p_state > 0.0) {
// Entropy takes the negative log:
double localValue = - Math.log(p_state) / log_2;
entCont = p_state * localValue;
if (localValue > max) {
max = localValue;
} else if (localValue < min) {
min = localValue;
}
} else {
entCont = 0.0;
currentState = State.COMPUTING;
if (hashedStateCount.isEmpty()) {
for (int count: stateCount) {
// compute p_state
p_state = (double) count / (double) observations;
ent += computeEntropyCont(p_state);
}
} else {
for (Map.Entry<Object, Integer> entry : hashedStateCount.entrySet()) {
p_state = (double) entry.getValue() / (double) observations;
ent += computeEntropyCont(p_state);
}
ent += entCont;
}
average = ent;
@ -259,7 +528,33 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
}
@Override
public double[] computeLocalFromPreviousObservations(int states[]){
public final double computeAverageLocal(int states[]) throws Exception {
if (states.length == 0) {
throw new RuntimeException("States cannot be empty.");
}
addObservations(states);
return computeAverageLocalOfObservations();
}
protected double computeEntropyCont(double p_state) {
double entCont = 0.0;
if (p_state > 0.0) {
// Entropy takes the negative log:
double localValue = - Math.log(p_state) / log_2;
entCont = p_state * localValue;
if (localValue > max) {
max = localValue;
} else if (localValue < min) {
min = localValue;
}
}
return entCont;
}
@Override
public double[] computeLocalFromPreviousObservations(int states[]) {
this.currentState = State.COMPUTING;
int rows = states.length;
double[] localEntropy = new double[rows];
@ -277,207 +572,41 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
min = localEntropy[r];
}
}
average = average/(double) rows;
return localEntropy;
}
/*
***********************************************************************
******************* ALL METHODS BELOW ARE DEPRECATED ******************
******************* DON'T USE THEM ******************
***********************************************************************
*/
// TODO protected duplicates, keep public call, that does the same as private.
@Override
public double[][] computeLocalFromPreviousObservations(int states[][]){
int rows = states.length;
int columns = states[0].length;
double[][] localEntropy = new double[rows][columns];
average = 0;
max = 0;
min = 0;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
double p_state = (double) stateCount[states[r][c]] / (double) observations;
// Entropy takes the negative log:
localEntropy[r][c] = - Math.log(p_state) / log_2;
average += localEntropy[r][c];
if (localEntropy[r][c] > max) {
max = localEntropy[r][c];
} else if (localEntropy[r][c] < min) {
min = localEntropy[r][c];
}
}
@Deprecated
public void startAddObservations() {
// reinitialise if already finalised
if (currentState == State.COMPUTING) {
initialise();
}
average = average/(double) (columns * rows);
return localEntropy;
this.currentState = State.ADDING_OBSERVATIONS;
}
@Override
public double[][][] computeLocalFromPreviousObservations(int states[][][]){
int timeSteps = states.length;
int agentRows, agentColumns;
if (timeSteps == 0) {
agentRows = 0;
agentColumns = 0;
} else {
agentRows = states[0].length;
if (agentRows == 0) {
agentColumns = 0;
} else {
agentColumns = states[0][0].length;
}
@Deprecated
public void finaliseAddObservations() throws Exception {
if (currentState == State.SETTING_PROPERTIES) {
throw new RuntimeException("Estimator should be initialised before finalised...");
}
double[][][] localEntropy = new double[timeSteps][agentRows][agentColumns];
average = 0;
max = 0;
min = 0;
for (int r = 0; r < timeSteps; r++) {
for (int i = 0; i < agentRows; i++) {
for (int j = 0; j < agentColumns; j++) {
double p_state = (double) stateCount[states[r][i][j]] / (double) observations;
// Entropy takes the negative log:
localEntropy[r][i][j] = - Math.log(p_state) / log_2;
average += localEntropy[r][i][j];
if (localEntropy[r][i][j] > max) {
max = localEntropy[r][i][j];
} else if (localEntropy[r][i][j] < min) {
min = localEntropy[r][i][j];
}
}
}
if (observations == 0) {
throw new RuntimeException("Must have some observations to finalise.");
}
average = average/(double) (agentRows * agentColumns * timeSteps);
return localEntropy;
}
@Override
public double[] computeLocalFromPreviousObservations(int states[][], int agentNumber){
int rows = states.length;
//int columns = states[0].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][agentNumber]] / (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;
this.currentState = State.COMPUTING;
}
@Override
public double[] computeLocalFromPreviousObservations(int states[][][], int agentIndex1, int agentIndex2){
int timeSteps = 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[timeSteps];
average = 0;
max = 0;
min = 0;
for (int r = 0; r < timeSteps; r++) {
double p_state = (double) stateCount[states[r][agentIndex1][agentIndex2]] / (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) (timeSteps);
return localEntropy;
}
@Override
public final double[] computeLocal(int states[]) {
initialise();
addObservations(states);
return computeLocalFromPreviousObservations(states);
}
@Override
public final double[][] computeLocal(int states[][]) {
initialise();
addObservations(states);
return computeLocalFromPreviousObservations(states);
}
@Override
public final double[][][] computeLocal(int states[][][]) {
initialise();
addObservations(states);
return computeLocalFromPreviousObservations(states);
}
@Override
public final double computeAverageLocal(int states[]) {
initialise();
addObservations(states);
return computeAverageLocalOfObservations();
}
@Override
public final double computeAverageLocal(int states[][]) {
initialise();
addObservations(states);
return computeAverageLocalOfObservations();
}
@Override
public final double computeAverageLocal(int states[][][]) {
initialise();
addObservations(states);
return computeAverageLocalOfObservations();
}
@Override
public final double[] computeLocal(int states[][], int col) {
initialise();
addObservations(states, col);
return computeLocalFromPreviousObservations(states, col);
}
@Override
public final double[] computeLocal(int states[][][],
int agentIndex1, int agentIndex2) {
initialise();
addObservations(states, agentIndex1, agentIndex2);
return computeLocalFromPreviousObservations(states, agentIndex1, agentIndex2);
}
@Override
public final double computeAverageLocal(int states[][], int col) {
initialise();
addObservations(states, col);
return computeAverageLocalOfObservations();
}
@Override
public final double computeAverageLocal(int states[][][], int agentIndex1, int agentIndex2) {
initialise();
addObservations(states, agentIndex1, agentIndex2);
return computeAverageLocalOfObservations();
}
}
}

View File

@ -62,7 +62,7 @@ Theory' (John Wiley & Sons, New York, 1991).</li>
* @author Joseph Lizier (<a href="joseph.lizier at gmail.com">email</a>,
* <a href="http://lizier.me/joseph/">www</a>)
*/
public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInContextOfPastCalculator {
public class EntropyRateCalculatorDiscrete extends UnivariateMeasureDiscreteInContextOfPastCalculator {
/**
* User was formerly forced to create new instances through this factory method.
@ -105,7 +105,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
// Initialise and store the current previous value for each column
int prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p];
}
@ -119,7 +119,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
pastCount[prevVal]++;
// Update the previous value:
prevVal -= maxShiftedValue[states[r-k]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[r];
}
}
@ -136,7 +136,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
for (int c = 0; c < columns; c++) {
prevVal[c] = 0;
for (int p = 0; p < k; p++) {
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += states[p][c];
}
}
@ -152,13 +152,13 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
pastCount[prevVal[c]]++;
// Update the previous value:
prevVal[c] -= maxShiftedValue[states[r-k][c]];
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += states[r][c];
}
}
}
@Override
public void addObservations(int states[][][]) {
int timeSteps = states.length;
if (timeSteps == 0) {
@ -178,7 +178,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
for (int c = 0; c < agentColumns; c++) {
prevVal[r][c] = 0;
for (int p = 0; p < k; p++) {
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += states[p][r][c];
}
}
@ -196,14 +196,14 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
pastCount[prevVal[r][c]]++;
// Update the previous value:
prevVal[r][c] -= maxShiftedValue[states[t-k][r][c]];
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += states[t][r][c];
}
}
}
}
@Override
public void addObservations(int states[][], int col) {
int rows = states.length;
// increment the count of observations:
@ -213,7 +213,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
int prevVal = 0;
prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][col];
}
@ -227,12 +227,12 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
pastCount[prevVal]++;
// Update the previous value:
prevVal -= maxShiftedValue[states[r-k][col]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[r][col];
}
}
@Override
public void addObservations(int states[][][], int agentIndex1, int agentIndex2) {
int timeSteps = states.length;
// increment the count of observations:
@ -242,7 +242,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
int prevVal = 0;
prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][agentIndex1][agentIndex2];
}
@ -256,7 +256,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
pastCount[prevVal]++;
// Update the previous value:
prevVal -= maxShiftedValue[states[r-k][agentIndex1][agentIndex2]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[r][agentIndex1][agentIndex2];
}
}
@ -269,7 +269,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
max = 0;
min = 0;
double logTerm = 0;
for (int nextVal = 0; nextVal < base; nextVal++) {
for (int nextVal = 0; nextVal < alphabetSize; nextVal++) {
for (int prevVal = 0; prevVal < base_power_k; prevVal++) {
// compute p_prev
double p_prev = (double) pastCount[prevVal] / (double) observations;
@ -310,7 +310,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
// Initialise and store the current previous value for each column
int prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p];
}
@ -330,7 +330,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
}
// Update the previous value:
prevVal -= maxShiftedValue[states[r-k]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[r];
}
average = average/(double) (rows - k);
@ -338,7 +338,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
return localEntRate;
}
@Override
public double[][] computeLocalFromPreviousObservations(int states[][]){
int rows = states.length;
int columns = states[0].length;
@ -354,7 +354,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
for (int c = 0; c < columns; c++) {
prevVal[c] = 0;
for (int p = 0; p < k; p++) {
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += states[p][c];
}
}
@ -375,7 +375,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
}
// Update the previous value:
prevVal[c] -= maxShiftedValue[states[r-k][c]];
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += states[r][c];
}
}
@ -384,7 +384,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
return localEntRate;
}
@Override
public double[][][] computeLocalFromPreviousObservations(int states[][][]){
int timeSteps = states.length;
int agentRows = states[0].length;
@ -402,7 +402,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
for (int c = 0; c < agentColumns; c++) {
prevVal[r][c] = 0;
for (int p = 0; p < k; p++) {
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += states[p][r][c];
}
}
@ -426,7 +426,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
}
// Update the previous value:
prevVal[r][c] -= maxShiftedValue[states[t-k][r][c]];
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += states[t][r][c];
}
}
@ -436,7 +436,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
return localEntRate;
}
@Override
public double[] computeLocalFromPreviousObservations(int states[][], int col){
int rows = states.length;
//int columns = states[0].length;
@ -451,7 +451,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
int prevVal = 0;
prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][col];
}
int nextVal;
@ -470,7 +470,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
}
// Update the previous value:
prevVal -= maxShiftedValue[states[r-k][col]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[r][col];
}
average = average/(double) (rows - k);
@ -479,7 +479,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
}
@Override
public double[] computeLocalFromPreviousObservations(int states[][][], int agentIndex1, int agentIndex2){
int timeSteps = states.length;
//int columns = states[0].length;
@ -494,7 +494,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
int prevVal = 0;
prevVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][agentIndex1][agentIndex2];
}
int nextVal;
@ -513,7 +513,7 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
}
// Update the previous value:
prevVal -= maxShiftedValue[states[t-k][agentIndex1][agentIndex2]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[t][agentIndex1][agentIndex2];
}
average = average/(double) (timeSteps - k);
@ -521,4 +521,22 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
return localEntRate;
}
@Override
public void setObservations(Object[] observations) throws Exception {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'setObservations'");
}
@Override
public void startAddObservations() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'startAddObservations'");
}
@Override
public void finaliseAddObservations() throws Exception {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'finaliseAddObservations'");
}
}

View File

@ -71,10 +71,23 @@ public abstract class InfoMeasureCalculatorDiscrete {
*/
protected int observations = 0;
/**
* Number of available quantised states for each variable
* (ie binary is base-2).
* Number of available quantised states for each variable.
* (ie binary is 2).
*/
protected int base = 0; // number of individual states. Need initialised to 0 for changedSizes
protected int alphabetSize = 100;
/**
* Variable to keep track of where the estimator is within its workflow.
* The estimator can be in four states; Setting Properties, Initialised,
* Adding Observations, and Computing.
*/
protected State currentState = State.SETTING_PROPERTIES;
/**
* Boolean indicating if the size of the alphabet is known to determine the
* potnetial use of a hash table implementation for memory management.
*/
protected boolean knownIntegerRange = false;
/**
* Cached value of ln(base)
@ -96,36 +109,52 @@ public abstract class InfoMeasureCalculatorDiscrete {
* Whether we're in debug mode
*/
protected boolean debug = false;
/**
* Enum for the states of an estimator
*/
protected enum State {
SETTING_PROPERTIES,
INITIALISED,
ADDING_OBSERVATIONS,
COMPUTING
}
/**
* Construct an instance with default base of 2
* Construct an instance with no specified alphabet size.
*/
protected InfoMeasureCalculatorDiscrete() {
this(2);
this(-1);
}
/**
* Construct an instance
*
* @param base number of quantisation levels for each variable.
* @param alphabetSize number of quantisation levels for each variable.
* E.g. binary variables are in base-2.
*/
protected InfoMeasureCalculatorDiscrete(int base) {
resetBase(base);
protected InfoMeasureCalculatorDiscrete(int alphabetSize) {
resetAlphabetSize(alphabetSize);
}
protected void resetBase(int base) {
this.base = base;
log_base = Math.log(base);
protected void resetAlphabetSize(int alphabetSize) {
this.alphabetSize = alphabetSize;
if (base < 2) {
throw new RuntimeException("Can't calculate info theoretic measures for base " + base);
// indicator of unknown alphabet size
if (alphabetSize == -1) {
return;
}
log_base = Math.log(alphabetSize);
if (alphabetSize < 2) {
throw new RuntimeException("Can't calculate info theoretic measures for alphabet size " + alphabetSize);
}
// Check if we've got a power of 2
power_of_2_base = isPowerOf2(base);
power_of_2_base = isPowerOf2(alphabetSize);
if (power_of_2_base) {
log_2_base = (int) Math.round(Math.log(base) / Math.log(2));
log_2_base = (int) Math.round(Math.log(alphabetSize) / Math.log(2));
}
}
@ -135,21 +164,72 @@ public abstract class InfoMeasureCalculatorDiscrete {
* @throws Exception
*/
public void initialise() {
initialise(base);
initialise(-1);
}
/**
* Initialise the calculator for re-use with new observations,
* and a new base.
* and a new alphabet size.
* (Child classes should clear the existing PDFs)
*/
public void initialise(int base){
resetBase(base);
public void initialise(int alphabetSize){
resetAlphabetSize(alphabetSize);
average = 0.0;
max = 0.0;
min = 0.0;
std = 0.0;
observations = 0;
currentState = State.INITIALISED;
}
/**
* Set properties for the underlying calculator implementation.
* New property values are not guaranteed to take effect until the next call
* to an initialise method.
*
* TODO -- word the property descr. nicely
*
* <p>Property names defined at the interface level, and what their
* values should represent, include:</p>
* <ul>
* <li>{@link #ALPHABET_SIZE} -- Defined size of the alphabet for
* the data.</li>
* <li>{@link #MAX_ALPHA_SIZE_TO_STORE} -- Maximum alphabet size to store
* before switching to HashTable memory management. </li>
* </ul>
*
* <p>Unknown property values are ignored.</p>
*
* <p>Note that implementing classes may defined additional properties.</p>
*
* @param propertyName name of the property
* @param propertyValue value of the property
* @throws Exception for invalid property names or values
*/
public void setProperty(String propertyName, String propertyValue) throws Exception {
if (currentState != State.SETTING_PROPERTIES) {
currentState = State.SETTING_PROPERTIES;
// TODO I think there are things here to do to go back to this state but I don't remember them rn
// Actually do we want this here...? it should definitely be in the lower levels, so it should be
// caught then...
// joe's input: yes, check this at all levels.
}
switch(propertyName.toUpperCase()) {
case "ALPHABET_SIZE":
this.alphabetSize = Integer.parseInt(propertyValue);
this.knownIntegerRange = true;
break;
case "KNOWN_INTEGER_RANGE":
this.knownIntegerRange = Boolean.parseBoolean(propertyValue);
break;
default:
// This is the highest level in which this method should get called, if the property
// hasn't been recognised yet, it doesn't exist, throw an exception
throw new IllegalArgumentException(String.format("Property name: %s was not recognised", propertyName));
// break; (but it's unreachable...)
}
}
/**

View File

@ -78,51 +78,51 @@ public class MultiInformationCalculatorDiscrete extends InfoMeasureCalculatorDis
/**
* Construct an instance
*
* @base number of symbols for each variable.
* E.g. binary variables are in base-2.
* @alphabetSize number of symbols for each variable.
* E.g. binary variables are in base-2, so alphabetSize would be 2.
* @numVars numbers of joint variables that multi-info
* will be computed over.
*/
public MultiInformationCalculatorDiscrete(int base, int numVars) {
super(base);
changeParams(base, numVars);
public MultiInformationCalculatorDiscrete(int alphabetSize, int numVars) {
super(alphabetSize);
changeParams(alphabetSize, numVars);
}
/**
* Update the parameters using numVars
*
* @param base
* @param alphabetSize
* @param numVars
* @return
*/
private boolean changeParams(int base, int numVars) {
boolean paramsChanged = (this.base != base) || (this.numVars != numVars);
private boolean changeParams(int alphabetSize, int numVars) {
boolean paramsChanged = (this.alphabetSize != alphabetSize) || (this.numVars != numVars);
this.numVars = numVars;
jointStates = MathsUtils.power(base, numVars);
jointStates = MathsUtils.power(alphabetSize, numVars);
return paramsChanged;
}
/**
* Initialise (possible) updating the base and number of variables
* Initialise (possible) updating the alphabetSize and number of variables
*
* @param base
* @param alphabetSize
* @param numVars
*/
public void initialise(int base, int numVars) {
boolean paramsChanged = changeParams(base, numVars);
super.initialise(base);
public void initialise(int alphabetSize, int numVars) {
boolean paramsChanged = changeParams(alphabetSize, numVars);
super.initialise(alphabetSize);
if(paramsChanged || (jointCount == null)) {
// Create storage for counts of observations
try {
jointCount = new int[jointStates];
marginalCounts = new int[numVars][base];
marginalCounts = new int[numVars][alphabetSize];
} catch (OutOfMemoryError e) {
// Allow any Exceptions to be thrown, but catch and wrap
// Error as a RuntimeException
throw new RuntimeException("Requested memory for the base " +
base + " with " + numVars +
throw new RuntimeException("Requested memory for the alphabetSize " +
alphabetSize + " with " + numVars +
" variables is too large for the JVM at this time", e);
}
} else {
@ -133,7 +133,7 @@ public class MultiInformationCalculatorDiscrete extends InfoMeasureCalculatorDis
@Override
public void initialise(){
initialise(base, numVars);
initialise(alphabetSize, numVars);
}
/**
@ -152,7 +152,7 @@ public class MultiInformationCalculatorDiscrete extends InfoMeasureCalculatorDis
for (int i = 0; i < numVars; i++) {
int thisValue = states[t][i];
marginalCounts[i][thisValue]++;
jointValue *= base;
jointValue *= alphabetSize;
jointValue += thisValue;
}
jointCount[jointValue]++;
@ -176,7 +176,7 @@ public class MultiInformationCalculatorDiscrete extends InfoMeasureCalculatorDis
for (int i = 0; i < numVars; i++) {
int thisValue = states[(c + groupOffsets[i] + states.length) % states.length];
marginalCounts[i][thisValue]++;
jointValue *= base;
jointValue *= alphabetSize;
jointValue += thisValue;
}
jointCount[jointValue]++;
@ -201,7 +201,7 @@ public class MultiInformationCalculatorDiscrete extends InfoMeasureCalculatorDis
for (int i = 0; i < numVars; i++) {
int thisValue = states[(destinationIndex + groupOffsets[i] + states.length) % states.length];
marginalCounts[i][thisValue]++;
jointValue *= base;
jointValue *= alphabetSize;
jointValue += thisValue;
}
jointCount[jointValue]++;
@ -227,7 +227,7 @@ public class MultiInformationCalculatorDiscrete extends InfoMeasureCalculatorDis
for (int i = 0; i < numVars; i++) {
int thisValue = states[t][(c + groupOffsets[i] + states.length) % states.length];
marginalCounts[i][thisValue]++;
jointValue *= base;
jointValue *= alphabetSize;
jointValue += thisValue;
}
jointCount[jointValue]++;
@ -261,7 +261,7 @@ public class MultiInformationCalculatorDiscrete extends InfoMeasureCalculatorDis
int jointValue = 0;
for (int i = 0; i < numVars; i++) {
prodMarginalProbs *= (double) marginalCounts[i][tuple[i]] / (double) observations;
jointValue *= base;
jointValue *= alphabetSize;
jointValue += tuple[i];
}
if (jointCount[jointValue] == 0) {
@ -288,7 +288,7 @@ public class MultiInformationCalculatorDiscrete extends InfoMeasureCalculatorDis
miCont = jointProb * localValue;
} else {
// Fill out the next part of the tuple and make the recursive calls
for (int v = 0; v < base; v++) {
for (int v = 0; v < alphabetSize; v++) {
tuple[fromIndex] = v;
miCont += computeMiOfGivenTupleFromVarIndex(tuple, fromIndex + 1);
}

View File

@ -144,7 +144,7 @@ public abstract class MultiVariateInfoMeasureCalculatorDiscrete
* at many observations (first index is time, second is variable index)
*/
public void addObservations(int[][] states) throws Exception {
int[] jointStates = MatrixUtils.computeCombinedValues(states, base);
int[] jointStates = MatrixUtils.computeCombinedValues(states, alphabetSize);
for (int t = 0; t < states.length; t++) {
for (int i = 0; i < numVars; i++) {
// Extract values of the 1D and the (N-1)D marginals
@ -187,7 +187,7 @@ public abstract class MultiVariateInfoMeasureCalculatorDiscrete
double miCont = 0;
if (fromIndex == numVars) {
// The whole tuple is filled in, so compute the contribution to the MI from this tuple
int jointValue = MatrixUtils.computeCombinedValues(new int[][] {tuple}, base)[0];
int jointValue = MatrixUtils.computeCombinedValues(new int[][] {tuple}, alphabetSize)[0];
if (jointCount[jointValue] == 0) {
// This joint state does not occur, so it makes no contribution here
@ -200,7 +200,7 @@ public abstract class MultiVariateInfoMeasureCalculatorDiscrete
} else {
// Fill out the next part of the tuple and make the recursive calls
for (int v = 0; v < base; v++) {
for (int v = 0; v < alphabetSize; v++) {
tuple[fromIndex] = v;
miCont += computeForGivenTupleFromVarIndex(tuple, fromIndex + 1);
}
@ -259,7 +259,7 @@ public abstract class MultiVariateInfoMeasureCalculatorDiscrete
* @param tuple state of the system at a given time (index is variable number)
*/
protected double computeLocalValueForTuple(int[] tuple) throws Exception {
int jointValue = MatrixUtils.computeCombinedValues(new int[][] {tuple}, base)[0];
int jointValue = MatrixUtils.computeCombinedValues(new int[][] {tuple}, alphabetSize)[0];
return computeLocalValueForTuple(tuple, jointValue);
}
@ -271,7 +271,7 @@ public abstract class MultiVariateInfoMeasureCalculatorDiscrete
* @param varValue value of the variable in question in the system state
*/
protected int computeBigMarginalState(int jointState, int varIdx, int varValue) {
int bigMarginalState = jointState - varValue*MathsUtils.power(base, numVars - varIdx - 1);
int bigMarginalState = jointState - varValue*MathsUtils.power(alphabetSize, numVars - varIdx - 1);
return bigMarginalState;
}

View File

@ -69,15 +69,16 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
/**
* Store the number of symbols for each variable
*/
protected int base1;
protected int base2;
protected int alphabetSize1;
protected int alphabetSize2;
protected int timeDiff = 0;
protected int[][] jointCount = null; // Count for (i[t-timeDiff], j[t]) tuples
protected int[] iCount = null; // Count for i[t-timeDiff]
protected int[] jCount = null; // Count for j[t]
private EntropyCalculatorDiscrete jointEntropyCalc;
private EntropyCalculatorDiscrete entropyCalc2;
private EntropyCalculatorDiscrete entropyCalc1;
protected boolean miComputed = false;
private boolean miComputed = false;
/**
* Construct a new MI calculator with default bases of 2 and time difference of 0
@ -86,7 +87,7 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
* @throws Exception
*/
public MutualInformationCalculatorDiscrete() throws Exception {
this(2);
this(-1);
}
/**
@ -97,48 +98,60 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
* E.g. binary variables are in base-2.
* @throws Exception
*/
public MutualInformationCalculatorDiscrete(int base) throws Exception {
this(base, base, 0);
public MutualInformationCalculatorDiscrete(int alphabetSize) throws Exception {
this(alphabetSize, alphabetSize, 0);
}
// TODO Bring in a MutualInformationCalculatorDiscrete(int base1, int base2) constructor
// TODO Bring in a MutualInformationCalculatorDiscrete(int alphabetSize1, int alphabetSize2) constructor
// but don't do this yet since it will override the previous MutualInformationCalculatorDiscrete(int base, int timeDiff)
// constructor present up until v1.4 and that may lead to errors.
/**
* Create a new mutual information calculator
*
* @param base1 number of symbols for first variable.
* @param alphabetSize1 number of symbols for first variable.
* E.g. binary variables are in base-2.
* @param base2 number of symbols for second variable.
* @param alphabetSize2 number of symbols for second variable.
* @param timeDiff number of time steps across which to compute
* MI for given time series
* @throws Exception when timeDiff < 0
*/
public MutualInformationCalculatorDiscrete(int base1, int base2, int timeDiff) throws Exception {
public MutualInformationCalculatorDiscrete(int alphabetSize1, int alphabetSize2, int timeDiff) throws Exception {
// Create super object, just with first base
super(base1);
super(alphabetSize1);
// For unknown alphabet sizes
if (alphabetSize1 == -1 || alphabetSize2 == -1) {
this.entropyCalc1 = new EntropyCalculatorDiscrete();
this.entropyCalc2 = new EntropyCalculatorDiscrete();
}
// For known alphabet sizes
else {
this.entropyCalc1 = new EntropyCalculatorDiscrete(alphabetSize1);
this.entropyCalc2 = new EntropyCalculatorDiscrete(alphabetSize2);
}
this.jointEntropyCalc = new EntropyCalculatorDiscrete();
changeBases(base1, base2, timeDiff);
changeBases(alphabetSize1, alphabetSize2, timeDiff);
}
/**
* Common code to be called when bases are changed (does not update arrays though)
*
* @param base1
* @param base2
* @param alphabetSize1
* @param alphabetSize2
* @param timeDiff
* @throws Exception
*/
private boolean changeBases(int base1, int base2, int timeDiff) throws Exception {
private boolean changeBases(int alphabetSize1, int alphabetSize2, int timeDiff) throws Exception {
boolean basesChanged = false;
if ((this.base1 != base1) || (this.base2 != base2)) {
if ((this.alphabetSize1 != alphabetSize1) || (this.alphabetSize2 != alphabetSize2)) {
basesChanged = true;
}
// Store the bases
this.base1 = base1;
this.base2 = base2;
this.alphabetSize1 = alphabetSize1;
this.alphabetSize2 = alphabetSize2;
if (timeDiff < 0) {
throw new Exception("timeDiff must be >= 0");
@ -151,7 +164,7 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
@Override
public void initialise() {
try {
initialise(base1, base2, timeDiff);
initialise(alphabetSize1, alphabetSize2, timeDiff);
} catch (Exception e) {
// The only possible (non runtime) exception here is that the timeDiff was < 0
// which we've already checked, so we can cast this as a Runtime Exception
@ -162,33 +175,17 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
/**
* Initialise with new bases and time diff
*
* @param base1
* @param base2
* @param alphabetSize1
* @param alphabetSize2
* @param timeDiff
* @throws Exception
*/
public void initialise(int base1, int base2, int timeDiff) throws Exception {
boolean basesChanged = changeBases(base1, base2, timeDiff);
super.initialise(base1);
if (basesChanged || (jointCount == null)) {
try {
jointCount = new int[base1][base2];
iCount = new int[base1];
jCount = new int[base2];
} catch (OutOfMemoryError e) {
// Allow any Exceptions to be thrown, but catch and wrap
// Error as a RuntimeException
throw new RuntimeException("Requested memory for the MI bases (" +
base1 + ", " + base2 + ") is too large for the JVM at this time", e);
}
} else {
MatrixUtils.fill(iCount, 0);
MatrixUtils.fill(jCount, 0);
MatrixUtils.fill(jointCount, 0);
}
miComputed = false;
public void initialise(int alphabetSize1, int alphabetSize2, int timeDiff) {
super.initialise(alphabetSize1);
this.entropyCalc1.initialise(alphabetSize1);
this.entropyCalc2.initialise(alphabetSize2);
this.jointEntropyCalc.initialise();
jointEntropyCalc.alphabetSizes = new int[] {alphabetSize1, alphabetSize2};
}
/**
@ -200,95 +197,91 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
*/
@Override
public void addObservations(int[] var1, int[] var2) {
int timeSteps = var1.length;
// int columns = states[0].length;
// increment the count of observations:
observations += (timeSteps - timeDiff);
// 1. Count the tuples observed
int iVal, jVal;
for (int r = timeDiff; r < timeSteps; r++) {
// Add to the count for this particular pair:
iVal = var1[r-timeDiff];
jVal = var2[r];
jointCount[iVal][jVal]++;
iCount[iVal]++;
jCount[jVal]++;
// I think this won't work if these aren't the same length...
// Could make it work with different lengths, unsure if this
// is ever useful.
if (var1.length != var2.length) {
throw new RuntimeException("Array lengths do not match. "
+ "var1: " + var1.length + ", var2: " + var2.length);
}
// adjust var1 observations for the time difference
int[] temp1 = new int[var1.length - timeDiff];
for (int i = 0; i < var1.length; i++) {
if (i < timeDiff) {
continue;
}
temp1[i-timeDiff] = var1[i];
}
// adjust var2 osbervations for the time difference
int[] temp2 = new int[var2.length - timeDiff];
for (int i = 0; i < var2.length - timeDiff; i++) {
temp2[i-timeDiff] = var2[i];
}
entropyCalc1.addObservations(temp1);
entropyCalc2.addObservations(temp2);
// Create the joint observations
int[][] jointObservations = new int[temp1.length][2];
for (int i = 0; i < temp1.length; i++) {
jointObservations[i][0] = temp1[i];
jointObservations[i][1] = temp2[i];
}
// This will throw a runtime error if format is somehow incorrect
jointEntropyCalc.addObservations(jointObservations);
observations += (var1.length - timeDiff);
}
/**
* {@inheritDoc}
*
* Pairs for MI are between columns iCol and jCol, separated in time by timeDiff (i is first).
*
*/
@Override
public void addObservations(int states[][], int iCol, int jCol) {
int rows = states.length;
// int columns = states[0].length;
// increment the count of observations:
observations += (rows - timeDiff);
// 1. Count the tuples observed
int iVal, jVal;
for (int r = timeDiff; r < rows; r++) {
// Add to the count for this particular pair:
iVal = states[r-timeDiff][iCol];
jVal = states[r][jCol];
jointCount[iVal][jVal]++;
iCount[iVal]++;
jCount[jVal]++;
public void addObservations(Object[] var1, Object[] var2) {
// I think this won't work if these aren't the same length...
if (var1.length != var2.length) {
throw new RuntimeException("Array lengths do not match. "
+ "var1: " + var1.length + ", var2: " + var2.length);
}
// adjust var1 observations for the time difference
Object[] temp1 = new Object[var1.length - timeDiff];
for (int i = 0; i < var1.length; i++) {
if (i < timeDiff) {
continue;
}
temp1[i-timeDiff] = var1[i];
}
// adjust var2 osbervations for the time difference
Object[] temp2 = new Object[var2.length - timeDiff];
for (int i = 0; i < var2.length - timeDiff; i++) {
temp2[i-timeDiff] = var2[i];
}
entropyCalc1.addObservations(temp1);
entropyCalc2.addObservations(temp2);
// Create the joint observations
Object[][] jointObservations = new Object[temp1.length][2];
for (int i = 0; i < temp1.length; i++) {
jointObservations[i][0] = temp1[i];
jointObservations[i][1] = temp2[i];
}
// This will throw a runtime error if format is somehow incorrect
jointEntropyCalc.addObservations(jointObservations);
observations += (var1.length - timeDiff);
}
@Override
public double computeAverageLocalOfObservations() {
double mi = 0.0;
double miCont = 0.0;
double entropy1 = entropyCalc1.computeAverageLocalOfObservations();
double entropy2 = entropyCalc2.computeAverageLocalOfObservations();
double jointEntropy = jointEntropyCalc.computeAverageLocalOfObservations();
max = 0;
min = 0;
double meanSqLocals = 0;
if (debug) {
System.out.println("i\tj\tp_i\tp_j\tp_joint\tlocal");
}
for (int i = 0; i < base1; i++) {
// compute p_i
double probi = (double) iCount[i] / (double) observations;
for (int j = 0; j < base2; j++) {
// compute p_j
double probj = (double) jCount[j] / (double) observations;
// compute p(veci=i, vecj=j)
double jointProb = (double) jointCount[i][j] / (double) observations;
// Compute MI contribution:
if (jointProb * probi * probj > 0.0) {
double localValue = Math.log(jointProb / (probi * probj)) / log_2;
miCont = jointProb * localValue;
if (debug) {
System.out.printf("%d\t%d\t%.4f\t%.4f\t%.4f\t%.4f\n",
i, j, probi, probj, jointProb, localValue);
}
if (localValue > max) {
max = localValue;
} else if (localValue < min) {
min = localValue;
}
// Add this contribution to the mean
// of the squared local values
meanSqLocals += miCont * localValue;
} else {
miCont = 0.0;
}
mi += miCont;
}
}
average = mi;
miComputed = true;
std = Math.sqrt(meanSqLocals - average * average);
return mi;
// computeFromPreviousObservations relies on average, so I've kept that being set.
average = entropy1 + entropy2 - jointEntropy;
return average;
}
@Override
@ -299,8 +292,23 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
return computeSignificance(newOrderings);
}
// TODO Implement this method. Old code has been left for reference.
/*
* For Brad's understanding, free to delete this comment.
* This is:
* > calculate MI
* > shuffle all observations
* > recalculate MI for each permutation
* > count number of recalcs > original MI
* > p = count / numPerms
*/
@Override
public EmpiricalMeasurementDistribution computeSignificance(int[][] newOrderings) {
// 1/3 temporary fix to get it to compile
// all original code is commented out below
return null;
/*
double actualMI = computeAverageLocalOfObservations();
int numPermutationsToCheck = newOrderings.length;
@ -308,14 +316,14 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
// Reconstruct the values of the first and second variables (not necessarily in order)
int[] iValues = new int[observations];
int t_i = 0;
for (int iVal = 0; iVal < base1; iVal++) {
for (int iVal = 0; iVal < alphabetSize1; iVal++) {
int numberOfSamplesI = iCount[iVal];
MatrixUtils.fill(iValues, iVal, t_i, numberOfSamplesI);
t_i += numberOfSamplesI;
}
int[] jValues = new int[observations];
int t_j = 0;
for (int jVal = 0; jVal < base2; jVal++) {
for (int jVal = 0; jVal < alphabetSize2; jVal++) {
int numberOfSamplesJ = jCount[jVal];
MatrixUtils.fill(jValues, jVal, t_j, numberOfSamplesJ);
t_j += numberOfSamplesJ;
@ -323,7 +331,7 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
MutualInformationCalculatorDiscrete mi2;
try {
mi2 = new MutualInformationCalculatorDiscrete(base1, base2, timeDiff);
mi2 = new MutualInformationCalculatorDiscrete(alphabetSize1, alphabetSize2, timeDiff);
} catch (Exception e) {
// The only possible exception is if timeDiff < 0, which
// it cannot be. Shut down the JVM
@ -356,6 +364,7 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
measDistribution.pValue = (double) countWhereMIIsMoreSignificantThanOriginal / (double) numPermutationsToCheck;
measDistribution.actualValue = actualMI;
return measDistribution;
*/
}
@Override
@ -363,9 +372,17 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
if (!miComputed) {
computeAverageLocalOfObservations();
}
int a1 = alphabetSize1;
int a2 = alphabetSize2;
if (alphabetSize1 <= -1 || alphabetSize2 == -1) {
a1 = entropyCalc1.hashedStateCount.keySet().size();
a2 = entropyCalc2.hashedStateCount.keySet().size();
}
return new ChiSquareMeasurementDistribution(average,
observations,
(base1 - 1) * (base2 - 1));
(a1 - 1) * (a2 - 1));
}
/**
@ -381,6 +398,9 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
*/
public double computeLocalFromPreviousObservations(int val1, int val2) throws Exception{
// 2/3 temporary fix to get this to compile
return 0;
/*
double logTerm = ( (double) jointCount[val1][val2] ) /
( (double) jCount[val2] *
(double) iCount[val1] );
@ -392,6 +412,7 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
double localMI = Math.log(logTerm) / log_2;
return localMI;
*/
}
/**
@ -407,6 +428,9 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
*/
public double[] computeLocalFromPreviousObservations(int[] var1, int[] var2) throws Exception{
// 3/3 temporary fix to get it to compile
return null;
/*
if (var1.length != var2.length) {
throw new Exception("var1 and var2 must have the same number of observations");
}
@ -435,74 +459,13 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
average = average/(double) observations;
return localMI;
*/
}
/**
* Computes local mutual information (or pointwise mutual information)
* for the given states, using pdfs built up from observations previously
* sent in via the addObservations method
*
* @param states 2D time series of observations (first index time,
* second is variable index)
* @param iCol column number for first variable
* @param jCol column number for second variable
* @return array of local mutual information values for each
* observation of (var1, var2). Note - if timeDiff > 0, then the
* return length will be var1.length - timeDiff.
*/
public double[] computeLocalFromPreviousObservations(int states[][], int iCol, int jCol){
int rows = states.length;
//int columns = states[0].length;
// Allocate for all rows even though we'll leave the first ones as zeros
double[] localMI = new double[rows];
int iVal, jVal;
double logTerm = 0.0;
for (int r = timeDiff; r < rows; r++) {
iVal = states[r-timeDiff][iCol];
jVal = states[r][jCol];
logTerm = ( (double) jointCount[iVal][jVal] ) /
( (double) jCount[jVal] *
(double) iCount[iVal] );
// 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;
localMI[r] = Math.log(logTerm) / log_2;
average += localMI[r];
if (localMI[r] > max) {
max = localMI[r];
} else if (localMI[r] < min) {
min = localMI[r];
}
}
average = average/(double) observations;
return localMI;
}
/**
* Standalone routine to
* compute local mutual information (or pointwise mutual information)
* across a 2D spatiotemporal
* array of the states of homogeneous agents
* Return a 2D spatiotemporal array of local values.
* First history rows are zeros
*
* @param states 2D time series of observations (first index time,
* second is variable index)
* @param iCol column number for first variable
* @param jCol column number for second variable
* @return array of local mutual information values for each
* observation of (var1, var2). Note - if timeDiff > 0, then the
* return length will be var1.length - timeDiff.
*/
public double[] computeLocal(int states[][], int iCol, int jCol) {
initialise();
addObservations(states, iCol, jCol);
return computeLocalFromPreviousObservations(states, iCol, jCol);
// TODO -- do not implement, just remove this from the interface
@Override
public void addObservations(int[][] states, int sourceIndex, int destIndex) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'addObservations'");
}
}

View File

@ -80,7 +80,7 @@ import infodynamics.utils.MatrixUtils;
* @author Joseph Lizier (<a href="joseph.lizier at gmail.com">email</a>,
* <a href="http://lizier.me/joseph/">www</a>)
*/
public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscreteInContextOfPastCalculator {
public class PredictiveInformationCalculatorDiscrete extends UnivariateMeasureDiscreteInContextOfPastCalculator {
/**
* User was formerly forced to create new instances through this factory method.
@ -116,7 +116,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
@Override
public void initialise(int base, int blockLength) {
boolean baseOrHistoryChanged = (this.base != base) || (k != blockLength);
boolean baseOrHistoryChanged = (this.alphabetSize != base) || (k != blockLength);
super.initialise(base, blockLength);
if (baseOrHistoryChanged || (nextPastCount == null)) {
@ -142,7 +142,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
@Override
public void initialise(){
initialise(base, k);
initialise(alphabetSize, k);
}
/**
@ -165,9 +165,9 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
int prevVal = 0;
int nextVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += timeSeries[p];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += timeSeries[k-1+p];
}
@ -175,7 +175,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
for (int t = k; t < timeSteps - (k-1); t++) {
// Update the next value:
nextVal -= maxShiftedValue[timeSeries[t-1]];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += timeSeries[k-1+t];
// Update the counts
nextPastCount[nextVal][prevVal]++;
@ -183,7 +183,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
nextCount[nextVal]++;
// Update the previous value:
prevVal -= maxShiftedValue[timeSeries[t-k]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += timeSeries[t];
}
}
@ -213,9 +213,9 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
prevVal[c] = 0;
nextVal[c] = 0;
for (int p = 0; p < k; p++) {
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += states[p][c];
nextVal[c] *= base;
nextVal[c] *= alphabetSize;
nextVal[c] += states[k-1+p][c];
}
}
@ -225,7 +225,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
for (int c = 0; c < columns; c++) {
// Update the next value:
nextVal[c] -= maxShiftedValue[states[r-1][c]];
nextVal[c] *= base;
nextVal[c] *= alphabetSize;
nextVal[c] += states[k-1+r][c];
// Update the counts
nextPastCount[nextVal[c]][prevVal[c]]++;
@ -233,7 +233,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
nextCount[nextVal[c]]++;
// Update the previous value:
prevVal[c] -= maxShiftedValue[states[r-k][c]];
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += states[r][c];
}
}
@ -270,9 +270,9 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
prevVal[r][c] = 0;
nextVal[r][c] = 0;
for (int p = 0; p < k; p++) {
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += states[p][r][c];
nextVal[r][c] *= base;
nextVal[r][c] *= alphabetSize;
nextVal[r][c] += states[k-1+p][r][c];
}
}
@ -284,7 +284,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
for (int c = 0; c < agentColumns; c++) {
// Update the next value:
nextVal[r][c] -= maxShiftedValue[states[t-1][r][c]];
nextVal[r][c] *= base;
nextVal[r][c] *= alphabetSize;
nextVal[r][c] += states[k-1+t][r][c];
// Update the counts
nextPastCount[nextVal[r][c]][prevVal[r][c]]++;
@ -292,7 +292,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
nextCount[nextVal[r][c]]++;
// Update the previous value:
prevVal[r][c] -= maxShiftedValue[states[t-k][r][c]];
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += states[t][r][c];
}
}
@ -321,9 +321,9 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
int prevVal = 0;
int nextVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][col];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += states[k-1+p][col];
}
@ -331,7 +331,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
for (int r = k; r < rows - (k-1); r++) {
// Update the next value:
nextVal -= maxShiftedValue[states[r-1][col]];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += states[k-1+r][col];
// Add to the count for this particular transition:
// (cell's assigned as above)
@ -340,7 +340,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
nextCount[nextVal]++;
// Update the previous value:
prevVal -= maxShiftedValue[states[r-k][col]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[r][col];
}
}
@ -368,9 +368,9 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
int prevVal = 0;
int nextVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][agentIndex1][agentIndex2];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += states[k-1+p][agentIndex1][agentIndex2];
}
@ -378,7 +378,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
for (int t = k; t < timeSteps - (k-1); t++) {
// Update the next value:
nextVal -= maxShiftedValue[states[t-1][agentIndex1][agentIndex2]];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += states[k-1+t][agentIndex1][agentIndex2];
// Add to the count for this particular transition:
// (cell's assigned as above)
@ -387,7 +387,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
nextCount[nextVal]++;
// Update the previous value:
prevVal -= maxShiftedValue[states[t-k][agentIndex1][agentIndex2]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[t][agentIndex1][agentIndex2];
}
}
@ -472,9 +472,9 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
int prevVal = 0;
int nextVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += timeSeries[p];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += timeSeries[k-1+p];
}
@ -482,7 +482,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
for (int t = k; t < timeSteps - (k-1); t++) {
// Update the next value:
nextVal -= maxShiftedValue[timeSeries[t-1]];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += timeSeries[k-1+t];
logTerm = ( (double) nextPastCount[nextVal][prevVal] ) /
( (double) nextCount[nextVal] *
@ -501,7 +501,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
}
// Update the previous value:
prevVal -= maxShiftedValue[timeSeries[t-k]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += timeSeries[t];
}
average = average/(double) (timeSteps - k - (k-1));
@ -543,9 +543,9 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
prevVal[c] = 0;
nextVal[c] = 0;
for (int p = 0; p < k; p++) {
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += timeSeries[p][c];
nextVal[c] *= base;
nextVal[c] *= alphabetSize;
nextVal[c] += timeSeries[k-1+p][c];
}
}
@ -554,7 +554,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
for (int c = 0; c < columns; c++) {
// Update the next value:
nextVal[c] -= maxShiftedValue[timeSeries[r-1][c]];
nextVal[c] *= base;
nextVal[c] *= alphabetSize;
nextVal[c] += timeSeries[k-1+r][c];
logTerm = ( (double) nextPastCount[nextVal[c]][prevVal[c]] ) /
( (double) nextCount[nextVal[c]] *
@ -573,7 +573,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
}
// Update the previous value:
prevVal[c] -= maxShiftedValue[timeSeries[r-k][c]];
prevVal[c] *= base;
prevVal[c] *= alphabetSize;
prevVal[c] += timeSeries[r][c];
}
}
@ -618,9 +618,9 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
prevVal[r][c] = 0;
nextVal[r][c] = 0;
for (int p = 0; p < k; p++) {
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += timeSeries[p][r][c];
nextVal[r][c] *= base;
nextVal[r][c] *= alphabetSize;
nextVal[r][c] += timeSeries[k-1+p][r][c];
}
}
@ -631,7 +631,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
for (int c = 0; c < agentColumns; c++) {
// Update the next value:
nextVal[r][c] -= maxShiftedValue[timeSeries[t-1][r][c]];
nextVal[r][c] *= base;
nextVal[r][c] *= alphabetSize;
nextVal[r][c] += timeSeries[k-1+t][r][c];
logTerm = ( (double) nextPastCount[nextVal[r][c]][prevVal[r][c]] ) /
( (double) nextCount[nextVal[r][c]] *
@ -650,7 +650,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
}
// Update the previous value:
prevVal[r][c] -= maxShiftedValue[timeSeries[t-k][r][c]];
prevVal[r][c] *= base;
prevVal[r][c] *= alphabetSize;
prevVal[r][c] += timeSeries[t][r][c];
}
}
@ -690,16 +690,16 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
int prevVal = 0;
int nextVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[p][col];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += states[k-1+p][col];
}
double logTerm = 0.0;
for (int r = k; r < rows - (k-1); r++) {
// Update the next value:
nextVal -= maxShiftedValue[states[r-1][col]];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += states[k-1+r][col];
logTerm = ( (double) nextPastCount[nextVal][prevVal] ) /
( (double) nextCount[nextVal] *
@ -718,7 +718,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
}
// Update the previous value:
prevVal -= maxShiftedValue[states[r-k][col]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += states[r][col];
}
average = average/(double) (rows - k - (k-1));
@ -758,16 +758,16 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
int prevVal = 0;
int nextVal = 0;
for (int p = 0; p < k; p++) {
prevVal *= base;
prevVal *= alphabetSize;
prevVal += timeSeries[p][agentIndex1][agentIndex2];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += timeSeries[k-1+p][agentIndex1][agentIndex2];
}
double logTerm = 0.0;
for (int t = k; t < timeSteps - (k-1); t++) {
// Update the next value:
nextVal -= maxShiftedValue[timeSeries[t-1][agentIndex1][agentIndex2]];
nextVal *= base;
nextVal *= alphabetSize;
nextVal += timeSeries[k-1+t][agentIndex1][agentIndex2];
logTerm = ( (double) nextPastCount[nextVal][prevVal] ) /
( (double) nextCount[nextVal] *
@ -786,7 +786,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
}
// Update the previous value:
prevVal -= maxShiftedValue[timeSeries[t-k][agentIndex1][agentIndex2]];
prevVal *= base;
prevVal *= alphabetSize;
prevVal += timeSeries[t][agentIndex1][agentIndex2];
}
average = average/(double) (timeSteps - k - (k-1));
@ -844,7 +844,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
public int computePastValue(int[] x, int t) {
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += x[t - k + 1 + p];
}
return pastVal;
@ -863,7 +863,7 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
public int computePastValue(int[][] x, int i, int t) {
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += x[t - k + 1 + p][i];
}
return pastVal;
@ -883,9 +883,27 @@ public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureD
public int computePastValue(int[][][] x, int i, int j, int t) {
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += x[t - k + 1 + p][i][j];
}
return pastVal;
}
@Override
public void setObservations(Object[] observations) throws Exception {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'setObservations'");
}
@Override
public void startAddObservations() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'startAddObservations'");
}
@Override
public void finaliseAddObservations() throws Exception {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'finaliseAddObservations'");
}
}

View File

@ -255,7 +255,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
for (int c = 0; c < numAgents; c++) {
pastVal[c] = 0;
for (int p = 0; p < k; p++) {
pastVal[c] *= base;
pastVal[c] *= alphabetSize;
pastVal[c] += states[p][c];
}
}
@ -277,13 +277,13 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
sourceVal = states[t-1][(c-cleanedSourcesOffsets[sIndex]+numAgents) % numAgents];
sourceNumValueNextPastCount[sIndex][sourceVal][destVal][pastVal[c]]++;
sourceNumValuePastCount[sIndex][sourceVal][pastVal[c]]++;
jointSourcesVal *= base;
jointSourcesVal *= alphabetSize;
jointSourcesVal += sourceVal;
}
sourcesNextPastCount[jointSourcesVal][destVal][pastVal[c]]++;
// Update the previous value:
pastVal[c] -= maxShiftedValue[states[t-k][c]];
pastVal[c] *= base;
pastVal[c] *= alphabetSize;
pastVal[c] += states[t][c];
}
}
@ -346,7 +346,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
for (int c = 0; c < agentColumns; c++) {
pastVal[r][c] = 0;
for (int p = 0; p < k; p++) {
pastVal[r][c] *= base;
pastVal[r][c] *= alphabetSize;
pastVal[r][c] += states[p][r][c];
}
}
@ -377,13 +377,13 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
[(c-cleanedSourcesOffsets[sIndex][COLUMN_INDEX]+agentColumns) % agentColumns];
sourceNumValueNextPastCount[sIndex][sourceVal][destVal][pastVal[r][c]]++;
sourceNumValuePastCount[sIndex][sourceVal][pastVal[r][c]]++;
jointSourcesVal *= base;
jointSourcesVal *= alphabetSize;
jointSourcesVal += sourceVal;
}
sourcesNextPastCount[jointSourcesVal][destVal][pastVal[r][c]]++;
// Update the previous value:
pastVal[r][c] -= maxShiftedValue[states[t-k][r][c]];
pastVal[r][c] *= base;
pastVal[r][c] *= alphabetSize;
pastVal[r][c] += states[t][r][c];
}
}
@ -421,7 +421,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
// Initialise and store the current previous value for each column
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[p][destCol];
}
@ -439,13 +439,13 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
sourceVal = states[r-1][cleanedSourcesAbsolute[sIndex]];
sourceNumValueNextPastCount[sIndex][sourceVal][destVal][pastVal]++;
sourceNumValuePastCount[sIndex][sourceVal][pastVal]++;
jointSourcesVal *= base;
jointSourcesVal *= alphabetSize;
jointSourcesVal += sourceVal;
}
sourcesNextPastCount[jointSourcesVal][destVal][pastVal]++;
// Update the previous value:
pastVal -= maxShiftedValue[states[r-k][destCol]];
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[r][destCol];
}
}
@ -483,7 +483,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
// Initialise and store the current previous value for each column
int pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[p][destAgentRow][destAgentColumn];
}
@ -502,13 +502,13 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
[cleanedSourcesAbsolute[sIndex][COLUMN_INDEX]];
sourceNumValueNextPastCount[sIndex][sourceVal][destVal][pastVal]++;
sourceNumValuePastCount[sIndex][sourceVal][pastVal]++;
jointSourcesVal *= base;
jointSourcesVal *= alphabetSize;
jointSourcesVal += sourceVal;
}
sourcesNextPastCount[jointSourcesVal][destVal][pastVal]++;
// Update the previous value:
pastVal -= maxShiftedValue[states[t-k][destAgentRow][destAgentColumn]];
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[t][destAgentRow][destAgentColumn];
}
}
@ -560,7 +560,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
if (indexToModify < sourceValues.length) {
// Assign values to our variables and make the recursive call
for (int s = 0; s < base; s++) {
for (int s = 0; s < alphabetSize; s++) {
sourceValues[indexToModify] = s;
computeAverageLocalOfObservations(sourceValues, indexToModify + 1);
}
@ -575,7 +575,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
// Compute the joint source value first:
jointSourcesVal = 0;
for (int sIndex = 0; sIndex < numSources; sIndex++) {
jointSourcesVal *= base;
jointSourcesVal *= alphabetSize;
jointSourcesVal += sourceValues[sIndex];
}
@ -584,7 +584,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
// contributions for each tuple.
double[] localActAndTes = new double[numSources + 1];
for (int pastVal = 0; pastVal < base_power_k; pastVal++) {
for (int destVal = 0; destVal < base; destVal++) {
for (int destVal = 0; destVal < alphabetSize; destVal++) {
if (sourcesNextPastCount[jointSourcesVal][destVal][pastVal] != 0) {
// Add in the local active information storage first:
logTerm = ( (double) nextPastCount[destVal][pastVal] ) /
@ -692,7 +692,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
for (int c = 0; c < numAgents; c++) {
pastVal[c] = 0;
for (int p = 0; p < k; p++) {
pastVal[c] *= base;
pastVal[c] *= alphabetSize;
pastVal[c] += states[p][c];
}
}
@ -751,7 +751,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
}
// Update the previous value:
pastVal[c] -= maxShiftedValue[states[t-k][c]];
pastVal[c] *= base;
pastVal[c] *= alphabetSize;
pastVal[c] += states[t][c];
}
}
@ -838,7 +838,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
for (int c = 0; c < numAgentColumns; c++) {
pastVal[r][c] = 0;
for (int p = 0; p < k; p++) {
pastVal[r][c] *= base;
pastVal[r][c] *= alphabetSize;
pastVal[r][c] += states[p][r][c];
}
}
@ -906,7 +906,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
}
// Update the previous value:
pastVal[r][c] -= maxShiftedValue[states[t-k][r][c]];
pastVal[r][c] *= base;
pastVal[r][c] *= alphabetSize;
pastVal[r][c] += states[t][r][c];
}
}
@ -983,7 +983,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
int pastVal = 0;
pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[p][destCol];
}
@ -1038,7 +1038,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
}
// Update the previous value:
pastVal -= maxShiftedValue[states[r-k][destCol]];
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[r][destCol];
}
@ -1107,7 +1107,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
int pastVal = 0;
pastVal = 0;
for (int p = 0; p < k; p++) {
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[p][destAgentRow][destAgentColumn];
}
@ -1163,7 +1163,7 @@ public class SeparableInfoCalculatorDiscrete extends ContextOfPastMeasureCalcula
}
// Update the previous value:
pastVal -= maxShiftedValue[states[t-k][destAgentRow][destAgentColumn]];
pastVal *= base;
pastVal *= alphabetSize;
pastVal += states[t][destAgentRow][destAgentColumn];
}

View File

@ -66,7 +66,7 @@ public class SeparableInfoCalculatorDiscreteByAddition extends SeparableInfoCalc
private void createAppTeCalculators() {
ateCalcs = new TransferEntropyCalculatorDiscrete[numSources];
for (int i = 0; i < numSources; i++) {
ateCalcs[i] = TransferEntropyCalculatorDiscrete.newInstance(base, k);
ateCalcs[i] = TransferEntropyCalculatorDiscrete.newInstance(alphabetSize, k);
ateCalcs[i].setPeriodicBoundaryConditions(periodicBoundaryConditions);
}
}
@ -276,7 +276,7 @@ public class SeparableInfoCalculatorDiscreteByAddition extends SeparableInfoCalc
}
int[] cleanedOffsets = cleanOffsetOfDestFromSources(offsetOfDestFromSources);
TransferEntropyCalculatorDiscrete ateCalc =
TransferEntropyCalculatorDiscrete.newInstance(base, k);
TransferEntropyCalculatorDiscrete.newInstance(alphabetSize, k);
ateCalc.setPeriodicBoundaryConditions(periodicBoundaryConditions);
double[][] temp;
for (int i = 0; i < numSources; i++) {
@ -312,7 +312,7 @@ public class SeparableInfoCalculatorDiscreteByAddition extends SeparableInfoCalc
}
int[][] cleanedOffsets = cleanOffsetOfDestFromSources(offsetOfDestFromSources);
TransferEntropyCalculatorDiscrete ateCalc =
TransferEntropyCalculatorDiscrete.newInstance(base, k);
TransferEntropyCalculatorDiscrete.newInstance(alphabetSize, k);
ateCalc.setPeriodicBoundaryConditions(periodicBoundaryConditions);
double[][][] temp;
for (int i = 0; i < numSources; i++) {
@ -346,7 +346,7 @@ public class SeparableInfoCalculatorDiscreteByAddition extends SeparableInfoCalc
average = aiCalc.computeAverageLocal(states);
int[] cleanedOffsets = cleanOffsetOfDestFromSources(sourceOffsets);
TransferEntropyCalculatorDiscrete ateCalc =
TransferEntropyCalculatorDiscrete.newInstance(base, k);
TransferEntropyCalculatorDiscrete.newInstance(alphabetSize, k);
ateCalc.setPeriodicBoundaryConditions(periodicBoundaryConditions);
for (int i = 0; i < numSources; i++) {
average += ateCalc.computeAverageLocal(states, cleanedOffsets[i]);
@ -363,7 +363,7 @@ public class SeparableInfoCalculatorDiscreteByAddition extends SeparableInfoCalc
average = aiCalc.computeAverageLocal(states);
int[][] cleanedOffsets = cleanOffsetOfDestFromSources(sourceOffsets);
TransferEntropyCalculatorDiscrete ateCalc =
TransferEntropyCalculatorDiscrete.newInstance(base, k);
TransferEntropyCalculatorDiscrete.newInstance(alphabetSize, k);
ateCalc.setPeriodicBoundaryConditions(periodicBoundaryConditions);
for (int i = 0; i < numSources; i++) {
average += ateCalc.computeAverageLocal(states,
@ -385,7 +385,7 @@ public class SeparableInfoCalculatorDiscreteByAddition extends SeparableInfoCalc
}
int[] cleanedOffsets = cleanAbsoluteSources(sourcesAbsolute, destCol);
TransferEntropyCalculatorDiscrete ateCalc =
TransferEntropyCalculatorDiscrete.newInstance(base, k);
TransferEntropyCalculatorDiscrete.newInstance(alphabetSize, k);
ateCalc.setPeriodicBoundaryConditions(periodicBoundaryConditions);
double[] temp;
for (int i = 0; i < numSources; i++) {
@ -421,7 +421,7 @@ public class SeparableInfoCalculatorDiscreteByAddition extends SeparableInfoCalc
}
int[][] cleanedSourcesAbsolute = cleanAbsoluteSources(sourcesAbsolute, destAgentRow, destAgentColumn);
TransferEntropyCalculatorDiscrete ateCalc =
TransferEntropyCalculatorDiscrete.newInstance(base, k);
TransferEntropyCalculatorDiscrete.newInstance(alphabetSize, k);
ateCalc.setPeriodicBoundaryConditions(periodicBoundaryConditions);
double[] temp;
for (int i = 0; i < numSources; i++) {
@ -454,7 +454,7 @@ public class SeparableInfoCalculatorDiscreteByAddition extends SeparableInfoCalc
average = aiCalc.computeAverageLocal(states, destCol);
int[] cleanedSourcesAbsolute = cleanAbsoluteSources(sourcesAbsolute, destCol);
TransferEntropyCalculatorDiscrete ateCalc =
TransferEntropyCalculatorDiscrete.newInstance(base, k);
TransferEntropyCalculatorDiscrete.newInstance(alphabetSize, k);
ateCalc.setPeriodicBoundaryConditions(periodicBoundaryConditions);
for (int i = 0; i < numSources; i++) {
average += ateCalc.computeAverageLocal(states, cleanedSourcesAbsolute[i], destCol);
@ -472,7 +472,7 @@ public class SeparableInfoCalculatorDiscreteByAddition extends SeparableInfoCalc
average = aiCalc.computeAverageLocal(states);
int[][] cleanedSourcesAbsolute = cleanAbsoluteSources(sourcesAbsolute, destAgentRow, destAgentColumn);
TransferEntropyCalculatorDiscrete ateCalc =
TransferEntropyCalculatorDiscrete.newInstance(base, k);
TransferEntropyCalculatorDiscrete.newInstance(alphabetSize, k);
ateCalc.setPeriodicBoundaryConditions(periodicBoundaryConditions);
for (int i = 0; i < numSources; i++) {
average += ateCalc.computeAverageLocal(states,

View File

@ -1,344 +0,0 @@
/*
* Java Information Dynamics Toolkit (JIDT)
* Copyright (C) 2012, Joseph T. Lizier
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package infodynamics.measures.discrete;
/**
* Interface for calculators of information-theoretic measures
* for single variables (e.g. entropy, active information storage).
* The interface defines common operations such as
* adding observations and calculating
* local and average values, etc.
*
* <p>Usage is as per {@link InfoMeasureCalculatorDiscrete}, with
* many methods for supplying observations and making
* calculations defined here.</p>
*
* <p>It would ideally be an abstract class to be inherited from, but
* it's more important for some of our calculators to have inheritance from
* ContextOfPastCalculator, and since java doesn't allow multiple
* inheritance, one of them has to miss out.
* To get around this, we combine the two in
* {@link SingleAgentMeasureDiscreteInContextOfPastCalculator}.
* </p>
*
* @author Joseph Lizier (<a href="joseph.lizier at gmail.com">email</a>,
* <a href="http://lizier.me/joseph/">www</a>)
*/
public interface SingleAgentMeasureDiscrete {
/**
* Initialise the calculator with (potentially) a new base
*
* @param base
*/
public void initialise(int base);
/**
* Add observations in to our estimates of the pdfs.
*
* @param states series of samples
*/
public void addObservations(int states[]);
/**
* Add observations in to our estimates of the pdfs.
* This call suitable only for homogeneous agents, as all
* agents will contribute to the PDFs.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable number)
*/
public void addObservations(int states[][]);
/**
* Add observations for a single variable of the multi-agent system
* to our estimates of the pdfs.
* This call should be made as opposed to {@link #addObservations(int[][])}
* for computing active info for heterogeneous agents.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable number)
* @param col index of agent
*/
public void addObservations(int states[][], int col);
/**
* Add observations in to our estimates of the pdfs.
* This call suitable only for homogeneous agents, as all
* agents will contribute to single pdfs.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable row number,
* 3rd is variable column number)
*/
public void addObservations(int states[][][]);
/**
* Add observations for a single agent of the multi-agent system
* to our estimates of the pdfs.
* This call should be made as opposed to {@link #addObservations(int[][][])}
* for computing active info for heterogeneous agents.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable row number,
* 3rd is variable column number)
* @param index1 row index index the variable
* @param index2 column index of the variable
*/
public void addObservations(int states[][][], int index1, int index2);
/**
* Compute the average value of the measure
* from the previously-supplied samples.
*
* Must set average, min and max
*
* @return the estimate of the measure
*/
public double computeAverageLocalOfObservations();
/**
* Computes local information theoretic measure for the given
* states, using pdfs built up from observations previously
* sent in via the addObservations method.
*
* Must set average, min and max
*
* @param states time series of samples
* @return time-series of local values (indexed as per states)
*/
public double[] computeLocalFromPreviousObservations(int states[]);
/**
* Computes local information theoretic measure for the given
* states, using pdfs built up from observations previously
* sent in via the addObservations method.
* This method to be used for homogeneous agents only,
* since the local values will be computed for all variables.
*
* Must set average, min and max
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable number)
* @return 2D time-series of local values (indexed as per states)
*/
public double[][] computeLocalFromPreviousObservations(int states[][]);
/**
* Computes local information theoretic measure for the given
* variable in the 2D time-series
* states, using pdfs built up from observations previously
* sent in via the addObservations method.
* This method is suitable for heterogeneous agents, since
* the specific variable is identified.
*
* Must set average, min and max.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable number)
* @param col index of the given variable
* @return time-series of local values for the variable
*/
public double[] computeLocalFromPreviousObservations(int states[][], int col);
/**
* Computes local information theoretic measure for the given
* states, using pdfs built up from observations previously
* sent in via the addObservations method
* This method to be used for homogeneous agents only,
* since the local values will be computed for all variables.
*
* Must set average, min and max
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable row number,
* 3rd is variable column number)
* @return 3D time-series of local values (indexed as per states)
*/
public double[][][] computeLocalFromPreviousObservations(int states[][][]);
/**
* Computes the local information theoretic measure for the given
* variable in the 3D time-series
* states, using pdfs built up from observations previously
* sent in via the addObservations method
* This method is suitable for heterogeneous agents, since
* the specific variable is identified.
*
* Must set average, min and max
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable row number,
* 3rd is variable column number)
* @param index1 row index of the given variable
* @param index2 column index of the given variable
* @return time-series of local values for the variable
*/
public double[] computeLocalFromPreviousObservations(int states[][][], int index1, int index2);
/**
* Standalone routine to
* compute the local information-theoretic measure across a
* time-series of states.
* Return a time-series array of local values.
* First history rows are zeros when the measure must build up
* embedded history of the variable.
*
* @param states time series of samples
* @return time-series of local values (indexed as per states)
*/
public double[] computeLocal(int states[]);
/**
* Standalone routine to
* compute the local information-theoretic measure across a 2D spatiotemporal
* array of the states of homogeneous agents,
* Return a 2D spatiotemporal array of local values.
* First history rows are zeros when the measure must build up
* embedded history of the variable.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable number)
* @return 2D time-series of local values (indexed as per states)
*/
public double[][] computeLocal(int states[][]);
/**
* Standalone routine to
* compute the local information theoretic measure across a 3D spatiotemporal
* array of the states of homogeneous agents
* Return a 3D spatiotemporal array of local values.
* First history rows are zeros when the measure must build up
* embedded history of the variable.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable row number,
* 3rd is variable column number)
* @return 3D time-series of local values (indexed as per states)
*/
public double[][][] computeLocal(int states[][][]);
/**
* Standalone routine to
* compute the average information theoretic measure across a time-series
* of states.
* Return the average.
*
* @param states time series of samples
* @return average of the information-theoretic measure.
*/
public double computeAverageLocal(int states[]);
/**
* Standalone routine to
* compute the average information theoretic measure across a 2D spatiotemporal
* array of the states of homogeneous agents.
* Return the average.
* This method to be called for homogeneous agents only,
* since all variables are used in the PDFs.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable number)
* @return average of the information-theoretic measure.
*/
public double computeAverageLocal(int states[][]);
/**
* Standalone routine to
* compute the average information theoretic measure across a 3D spatiotemporal
* array of the states of homogeneous agents.
* Return the average.
* This method to be called for homogeneous agents only,
* since all variables are used in the PDFs.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable row number,
* 3rd is variable column number)
* @return average of the information-theoretic measure.
*/
public double computeAverageLocal(int states[][][]);
/**
* Standalone routine to
* compute local information theoretic measure for one variable
* in a 2D spatiotemporal
* multivariate array.
* Return a time-series array of local values.
* First history rows are zeros when the measure must build up
* embedded history of the variable.
* This method should be used for heterogeneous agents
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable number)
* @param col index of the given variable
* @return time-series of local values of the measure for
* the given variable
*/
public double[] computeLocal(int states[][], int col);
/**
* Standalone routine to
* compute local information theoretic measure for one variable
* in a 3D spatiotemporal
* multivariate array.
* Return a time-series array of local values.
* First history rows are zeros when the measure must build up
* embedded history of the variable.
* This method should be used for heterogeneous agents
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable row number,
* 3rd is variable column number)
* @param index1 row index of the given variable
* @param index2 column index of the given variable
* @return time-series of local values of the measure for
* the given variable
*/
public double[] computeLocal(int states[][][], int index1, int index2);
/**
* Standalone routine to
* compute the average information theoretic measure
* for a single agent in a multivariate time series.
* Returns the average.
* This method suitable for heterogeneous agents.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable number)
* @param col index of the given variable
* @return average of the measure for the given variable.
*/
public double computeAverageLocal(int states[][], int col);
/**
* Standalone routine to
* compute the average information theoretic measure
* for a single agent in a multivariate time series.
* Returns the average.
* This method suitable for heterogeneous agents.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable row number,
* 3rd is variable column number)
* @param index1 row index of the given variable
* @param index2 column index of the given variable
* @return average of the measure for the given variable.
*/
public double computeAverageLocal(int states[][][], int index1, int index2);
}

View File

@ -294,7 +294,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
public void initialise(int base, int destHistoryEmbedLength, int destEmbeddingDelay,
int sourceHistoryEmbeddingLength, int sourceEmbeddingDelay, int delay) {
boolean paramsChanged = (this.base != base) || (k != destHistoryEmbedLength) ||
boolean paramsChanged = (this.alphabetSize != base) || (k != destHistoryEmbedLength) ||
(this.destEmbeddingDelay != destEmbeddingDelay) || (this.sourceHistoryEmbedLength != sourceHistoryEmbeddingLength) ||
(this.sourceEmbeddingDelay != sourceEmbeddingDelay) || (this.delay != delay);
super.initialise(base, destHistoryEmbedLength);
@ -324,7 +324,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
@Override
public void initialise(){
initialise(base, k, destEmbeddingDelay, sourceHistoryEmbedLength,
initialise(this.alphabetSize, k, destEmbeddingDelay, sourceHistoryEmbedLength,
sourceEmbeddingDelay, delay);
}
@ -374,7 +374,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[d] += dest[startTime + startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay];
pastVal[d] *= base;
pastVal[d] *= this.alphabetSize;
}
}
// Next for the source:
@ -389,7 +389,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[d] += source[startTime + startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay];
sourcePastVal[d] *= base;
sourcePastVal[d] *= this.alphabetSize;
}
}
@ -416,12 +416,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[destEmbeddingPhase] -= maxShiftedValue[dest[r-1-(k-1)*destEmbeddingDelay]];
pastVal[destEmbeddingPhase] *= base; // and shift the others up
pastVal[destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[sourceEmbeddingPhase] -=
maxShiftedSourceValue[
source[r-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay]];
sourcePastVal[sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
// then update the phase
destEmbeddingPhase = (destEmbeddingPhase + 1) % destEmbeddingDelay;
sourceEmbeddingPhase = (sourceEmbeddingPhase + 1) % sourceEmbeddingDelay;
@ -463,7 +463,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[d] += dest[startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay];
pastVal[d] *= base;
pastVal[d] *= this.alphabetSize;
}
}
// We can take an observation if timeSinceLastDestInvalid >= minDestLengthRequired
@ -489,7 +489,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[d] += source[startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay];
sourcePastVal[d] *= base;
sourcePastVal[d] *= this.alphabetSize;
}
}
// We can take an observation if timeSinceLastSourceInvalid >= minSourceLengthRequired
@ -551,12 +551,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[destEmbeddingPhase] -= maxShiftedValue[dest[r-1-(k-1)*destEmbeddingDelay]];
pastVal[destEmbeddingPhase] *= base; // and shift the others up
pastVal[destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[sourceEmbeddingPhase] -=
maxShiftedSourceValue[
source[r-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay]];
sourcePastVal[sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
// then update the phase
destEmbeddingPhase = (destEmbeddingPhase + 1) % destEmbeddingDelay;
sourceEmbeddingPhase = (sourceEmbeddingPhase + 1) % sourceEmbeddingDelay;
@ -606,7 +606,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[c][d] += states[startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay][c];
pastVal[c][d] *= base;
pastVal[c][d] *= this.alphabetSize;
}
}
}
@ -633,7 +633,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[c][d] += states[startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay][sourceVariable];
sourcePastVal[c][d] *= base;
sourcePastVal[c][d] *= this.alphabetSize;
}
}
}
@ -674,12 +674,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[c][destEmbeddingPhase] -= maxShiftedValue[states[r-1-(k-1)*destEmbeddingDelay][c]];
pastVal[c][destEmbeddingPhase] *= base; // and shift the others up
pastVal[c][destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[c][sourceEmbeddingPhase] -=
maxShiftedSourceValue[
states[r-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay][sourceVariable]];
sourcePastVal[c][sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[c][sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
// then update the phase
destEmbeddingPhase = (destEmbeddingPhase + 1) % destEmbeddingDelay;
@ -737,7 +737,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[r][c][d] += states[startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay][r][c];
pastVal[r][c][d] *= base;
pastVal[r][c][d] *= this.alphabetSize;
}
}
}
@ -777,7 +777,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[r][c][d] += states[startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay][sourceAgentRow][sourceAgentColumn];
sourcePastVal[r][c][d] *= base;
sourcePastVal[r][c][d] *= this.alphabetSize;
}
}
}
@ -830,12 +830,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[r][c][destEmbeddingPhase] -= maxShiftedValue[states[t-1-(k-1)*destEmbeddingDelay][r][c]];
pastVal[r][c][destEmbeddingPhase] *= base; // and shift the others up
pastVal[r][c][destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[r][c][sourceEmbeddingPhase] -=
maxShiftedSourceValue[
states[t-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay][sourceAgentRow][sourceAgentColumn]];
sourcePastVal[r][c][sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[r][c][sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
}
// then update the phase
@ -879,7 +879,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[d] += states[startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay][destIndex];
pastVal[d] *= base;
pastVal[d] *= this.alphabetSize;
}
}
// Next for the source:
@ -894,7 +894,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[d] += states[startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay][sourceIndex];
sourcePastVal[d] *= base;
sourcePastVal[d] *= this.alphabetSize;
}
}
@ -921,12 +921,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[destEmbeddingPhase] -= maxShiftedValue[states[r-1-(k-1)*destEmbeddingDelay][destIndex]];
pastVal[destEmbeddingPhase] *= base; // and shift the others up
pastVal[destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[sourceEmbeddingPhase] -=
maxShiftedSourceValue[
states[r-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay][sourceIndex]];
sourcePastVal[sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
// then update the phase
destEmbeddingPhase = (destEmbeddingPhase + 1) % destEmbeddingDelay;
sourceEmbeddingPhase = (sourceEmbeddingPhase + 1) % sourceEmbeddingDelay;
@ -972,7 +972,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[d] += states[startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay][destRowIndex][destColumnIndex];
pastVal[d] *= base;
pastVal[d] *= this.alphabetSize;
}
}
// Next for the source:
@ -987,7 +987,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[d] += states[startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay][sourceRowIndex][sourceColumnIndex];
sourcePastVal[d] *= base;
sourcePastVal[d] *= this.alphabetSize;
}
}
@ -1014,12 +1014,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[destEmbeddingPhase] -= maxShiftedValue[states[r-1-(k-1)*destEmbeddingDelay][destRowIndex][destColumnIndex]];
pastVal[destEmbeddingPhase] *= base; // and shift the others up
pastVal[destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[sourceEmbeddingPhase] -=
maxShiftedSourceValue[
states[r-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay][sourceRowIndex][sourceColumnIndex]];
sourcePastVal[sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
// then update the phase
destEmbeddingPhase = (destEmbeddingPhase + 1) % destEmbeddingDelay;
sourceEmbeddingPhase = (sourceEmbeddingPhase + 1) % sourceEmbeddingDelay;
@ -1171,7 +1171,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
if (pastCount[pastVal] == 0) {
continue;
}
for (int destVal = 0; destVal < base; destVal++) {
for (int destVal = 0; destVal < this.alphabetSize; destVal++) {
// compute p(dest,past)
// double p_dest_past = (double) destPastCount[destVal][pastVal] / (double) observations;
if (nextPastCount[destVal][pastVal] == 0) {
@ -1234,7 +1234,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
double active = 0.0;
double activeCont = 0.0;
for (int nextVal = 0; nextVal < base; nextVal++) {
for (int nextVal = 0; nextVal < this.alphabetSize; nextVal++) {
// compute p_next
double p_next = (double) nextCount[nextVal] / (double) observations;
for (int prevVal = 0; prevVal < base_power_k; prevVal++) {
@ -1263,7 +1263,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
System.out.println("Src\tDst\tPast\tc(s,d,p)\tc(s,p)\tc(d,p)\tc(p)");
for (int pastVal = 0; pastVal < base_power_k; pastVal++) {
for (int destVal = 0; destVal < base; destVal++) {
for (int destVal = 0; destVal < this.alphabetSize; destVal++) {
for (int sourceVal = 0; sourceVal < base_power_l; sourceVal++) {
// Compute TE contribution:
System.out.println(sourceVal + "\t" + destVal + "\t" + pastVal + "\t" +
@ -1315,7 +1315,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
for (int pastVal = 0; pastVal < base_power_k; pastVal++) {
MatrixUtils.fill(pastValues, pastVal, t_p, pastCount[pastVal]);
t_p += pastCount[pastVal];
for (int destVal = 0; destVal < base; destVal++) {
for (int destVal = 0; destVal < this.alphabetSize; destVal++) {
MatrixUtils.fill(destValues, destVal, t_d, nextPastCount[destVal][pastVal]);
t_d += nextPastCount[destVal][pastVal];
}
@ -1324,7 +1324,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// If we want a calculator just like this one, we should provide all of
// the same parameters:
TransferEntropyCalculatorDiscrete ate2 =
new TransferEntropyCalculatorDiscrete(base, k, destEmbeddingDelay,
new TransferEntropyCalculatorDiscrete(this.alphabetSize, k, destEmbeddingDelay,
sourceHistoryEmbedLength, sourceEmbeddingDelay, delay);
ate2.initialise();
ate2.observations = observations;
@ -1366,7 +1366,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
}
return new ChiSquareMeasurementDistribution(average,
observations,
(base_power_l - 1)*(base - 1)*(base_power_k));
(base_power_l - 1)*(this.alphabetSize - 1)*(base_power_k));
}
/**
@ -1425,7 +1425,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[d] += dest[startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay];
pastVal[d] *= base;
pastVal[d] *= this.alphabetSize;
}
}
// Next for the source:
@ -1440,7 +1440,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[d] += source[startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay];
sourcePastVal[d] *= base;
sourcePastVal[d] *= this.alphabetSize;
}
}
@ -1472,12 +1472,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[destEmbeddingPhase] -= maxShiftedValue[dest[t-1-(k-1)*destEmbeddingDelay]];
pastVal[destEmbeddingPhase] *= base; // and shift the others up
pastVal[destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[sourceEmbeddingPhase] -=
maxShiftedSourceValue[
source[t-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay]];
sourcePastVal[sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
// then update the phase
destEmbeddingPhase = (destEmbeddingPhase + 1) % destEmbeddingDelay;
sourceEmbeddingPhase = (sourceEmbeddingPhase + 1) % sourceEmbeddingDelay;
@ -1537,7 +1537,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[c][d] += states[startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay][c];
pastVal[c][d] *= base;
pastVal[c][d] *= this.alphabetSize;
}
}
}
@ -1564,7 +1564,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[c][d] += states[startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay][sourceVariable];
sourcePastVal[c][d] *= base;
sourcePastVal[c][d] *= this.alphabetSize;
}
}
}
@ -1608,12 +1608,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[c][destEmbeddingPhase] -= maxShiftedValue[states[t-1-(k-1)*destEmbeddingDelay][c]];
pastVal[c][destEmbeddingPhase] *= base; // and shift the others up
pastVal[c][destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[c][sourceEmbeddingPhase] -=
maxShiftedSourceValue[
states[t-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay][sourceVariable]];
sourcePastVal[c][sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[c][sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
// then update the phase
destEmbeddingPhase = (destEmbeddingPhase + 1) % destEmbeddingDelay;
@ -1689,7 +1689,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[r][c][d] += states[startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay][r][c];
pastVal[r][c][d] *= base;
pastVal[r][c][d] *= this.alphabetSize;
}
}
}
@ -1729,7 +1729,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[r][c][d] += states[startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay][sourceAgentRow][sourceAgentColumn];
sourcePastVal[r][c][d] *= base;
sourcePastVal[r][c][d] *= this.alphabetSize;
}
}
}
@ -1787,12 +1787,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[r][c][destEmbeddingPhase] -= maxShiftedValue[states[t-1-(k-1)*destEmbeddingDelay][r][c]];
pastVal[r][c][destEmbeddingPhase] *= base; // and shift the others up
pastVal[r][c][destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[r][c][sourceEmbeddingPhase] -=
maxShiftedSourceValue[
states[t-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay][sourceAgentRow][sourceAgentColumn]];
sourcePastVal[r][c][sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[r][c][sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
}
// then update the phase
@ -1852,7 +1852,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[d] += states[startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay][destIndex];
pastVal[d] *= base;
pastVal[d] *= this.alphabetSize;
}
}
// Next for the source:
@ -1867,7 +1867,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[d] += states[startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay][sourceIndex];
sourcePastVal[d] *= base;
sourcePastVal[d] *= this.alphabetSize;
}
}
@ -1899,12 +1899,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[destEmbeddingPhase] -= maxShiftedValue[states[r-1-(k-1)*destEmbeddingDelay][destIndex]];
pastVal[destEmbeddingPhase] *= base; // and shift the others up
pastVal[destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[sourceEmbeddingPhase] -=
maxShiftedSourceValue[
states[r-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay][sourceIndex]];
sourcePastVal[sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
// then update the phase
destEmbeddingPhase = (destEmbeddingPhase + 1) % destEmbeddingDelay;
sourceEmbeddingPhase = (sourceEmbeddingPhase + 1) % sourceEmbeddingDelay;
@ -1958,7 +1958,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
pastVal[d] += states[startObservationTime + d - 1
- (k-1)*destEmbeddingDelay
+ p*destEmbeddingDelay][destRowIndex][destColumnIndex];
pastVal[d] *= base;
pastVal[d] *= this.alphabetSize;
}
}
// Next for the source:
@ -1973,7 +1973,7 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
sourcePastVal[d] += states[startObservationTime + d - delay
- (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay
+ p*sourceEmbeddingDelay][sourceRowIndex][sourceColumnIndex];
sourcePastVal[d] *= base;
sourcePastVal[d] *= this.alphabetSize;
}
}
@ -2005,12 +2005,12 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
// for this phase we back out the oldest value which we'll no longer need:
if (k > 0) {
pastVal[destEmbeddingPhase] -= maxShiftedValue[states[r-1-(k-1)*destEmbeddingDelay][destRowIndex][destColumnIndex]];
pastVal[destEmbeddingPhase] *= base; // and shift the others up
pastVal[destEmbeddingPhase] *= this.alphabetSize; // and shift the others up
}
sourcePastVal[sourceEmbeddingPhase] -=
maxShiftedSourceValue[
states[r-delay-(sourceHistoryEmbedLength-1)*sourceEmbeddingDelay][sourceRowIndex][sourceColumnIndex]];
sourcePastVal[sourceEmbeddingPhase] *= base; // and shift the others up
sourcePastVal[sourceEmbeddingPhase] *= this.alphabetSize; // and shift the others up
// then update the phase
destEmbeddingPhase = (destEmbeddingPhase + 1) % destEmbeddingDelay;
sourceEmbeddingPhase = (sourceEmbeddingPhase + 1) % sourceEmbeddingDelay;

View File

@ -0,0 +1,150 @@
/*
* Java Information Dynamics Toolkit (JIDT)
* Copyright (C) 2012, Joseph T. Lizier
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package infodynamics.measures.discrete;
/**
* Interface for calculators of information-theoretic measures
* for single variables (e.g. entropy, active information storage).
* The interface defines common operations such as
* adding observations and calculating
* local and average values, etc.
*
* <p>Usage is as per {@link InfoMeasureCalculatorDiscrete}, with
* many methods for supplying observations and making
* calculations defined here.</p>
*
* <p>It would ideally be an abstract class to be inherited from, but
* it's more important for some of our calculators to have inheritance from
* ContextOfPastCalculator, and since java doesn't allow multiple
* inheritance, one of them has to miss out.
* To get around this, we combine the two in
* {@link UnivariateMeasureDiscreteInContextOfPastCalculator}.
* </p>
*
* @author Joseph Lizier (<a href="joseph.lizier at gmail.com">email</a>,
* <a href="http://lizier.me/joseph/">www</a>)
*/
public interface UnivariateMeasureDiscrete {
/**
* Property name for definite alphabet size. Attempting
* to use observations beyond this property will throw
* errors.
*/
public static final String ALPHABET_SIZE = "ALPHABET_SIZE";
/**
* Property name for if the alphabet size is known.
*/
public static final String KNOWN_INTEGER_RANGE = "KNOWN_INTEGER_RANGE";
/**
* Initialise the calculator with same or unknown alphabet size
*/
public void initialise();
/**
* Sets the samples from which to compute the PDF for the entropy.
* Should only be called once, the last call contains the
* observations that are used (they are not accumulated).
*
* @param observations array of (univariate) samples
* @throws Exception
*/
public void setObservations(Object[] observations) throws Exception;
/**
* Signal that we will add in the samples for computing the PDF
* from several disjoint time-series or trials via calls to
* "addObservations" rather than "setObservations" type methods
* (defined by the child interfaces and classes).
*/
public void startAddObservations();
/**
* Signal that the observations are now all added, PDFs can now be constructed.
*
* @throws Exception when the estimator has no observations.
*/
public void finaliseAddObservations() throws Exception;
/**
* Add observations in to our estimates of the pdfs.
* Univariate.
*
* @param states series of samples
*/
public void addObservations(int[] states);
/**
* Compute the average value of the measure
* from the previously-supplied samples.
*
* Must set average, min and max
*
* @return the estimate of the measure
*/
public double computeAverageLocalOfObservations();
/**
* Computes local information theoretic measure for the given
* states, using pdfs built up from observations previously
* sent in via the addObservations method.
*
* Must set average, min and max
*
* @param states time series of samples
* @return time-series of local values (indexed as per states)
*/
public double[] computeLocalFromPreviousObservations(int states[]);
/**
* Standalone routine to
* compute the average information theoretic measure across a time-series
* of states.
* Return the average.
*
* @param states time series of samples
* @return average of the information-theoretic measure.
* @throws Exception if states parameter is empty.
*/
public double computeAverageLocal(int states[]) throws Exception;
/**
* Add observations in to our estimates of the pdfs.
* This call suitable only for homogeneous agents, as all
* agents will contribute to the PDFs.
*
* @param states multivariate time series
* (1st index is time, 2nd index is variable number)
*/
@Deprecated
public void addObservations(int states[][]) throws Exception;
/**
* Initialise the calculator with (potentially) a new alphabet size
*
* Deprecated, use initialise() and setProperty("ALPHABET_SIZE", "n") instead.
* @deprecated
* @param alphabetSize
*/
@Deprecated
public void initialise(int alphabetSize);
}

View File

@ -1,150 +1,190 @@
/*
* Java Information Dynamics Toolkit (JIDT)
* Copyright (C) 2012, Joseph T. Lizier
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package infodynamics.measures.discrete;
/**
* A base class for calculators computing measures for
* a single variable which
* require knowledge of the embedded past state of a univariate
* discrete (ie int[]) variable.
*
* <p>This combines functionality for single agents from
* {@link SingleAgentMeasureDiscrete} with functionality
* required in the context of the past provided by
* {@link ContextOfPastMeasureCalculatorDiscrete}.</p>
*
* <p>Usage is as defined in {@link InfoMeasureCalculatorDiscrete}, with
* extra methods for supplying observations and making
* calculations defined in {@link SingleAgentMeasureDiscrete}</p>.
*
* <p>Users should not need to deal with this class directly;
* it is simply used to gather common functionality for several
* child classes.
* </p>
*
* TODO Make the Active info storage and entropy calculators inherit from this
*
* @author Joseph Lizier (<a href="joseph.lizier at gmail.com">email</a>,
* <a href="http://lizier.me/joseph/">www</a>)
*/
public abstract class SingleAgentMeasureDiscreteInContextOfPastCalculator extends
ContextOfPastMeasureCalculatorDiscrete implements SingleAgentMeasureDiscrete {
/**
* Construct the calculator with default base of 2 and history 1
*/
public SingleAgentMeasureDiscreteInContextOfPastCalculator() {
super(2, 1);
}
/**
* Construct the calculator
*
* @param base number of quantisation levels for each variable.
* E.g. binary variables are in base-2.
* @param history embedding length
*/
public SingleAgentMeasureDiscreteInContextOfPastCalculator(int base, int history) {
super(base, history);
}
/**
* Construct the calculator
*
* @param base number of quantisation levels for each variable.
* E.g. binary variables are in base-2.
* @param history embedding length
* @param dontCreateObsStorage do not create storage
* for observations of the embedded past (as the child
* class is signalling that it does not need it)
*/
public SingleAgentMeasureDiscreteInContextOfPastCalculator(int base, int history, boolean dontCreateObsStorage) {
super(base, history, dontCreateObsStorage);
}
@Override
public final double[] computeLocal(int[] states) {
initialise();
addObservations(states);
return computeLocalFromPreviousObservations(states);
}
@Override
public final double[][] computeLocal(int[][] states) {
initialise();
addObservations(states);
return computeLocalFromPreviousObservations(states);
}
@Override
public final double[][][] computeLocal(int[][][] states) {
initialise();
addObservations(states);
return computeLocalFromPreviousObservations(states);
}
@Override
public final double computeAverageLocal(int[] states) {
initialise();
addObservations(states);
return computeAverageLocalOfObservations();
}
@Override
public final double computeAverageLocal(int[][] states) {
initialise();
addObservations(states);
return computeAverageLocalOfObservations();
}
@Override
public final double computeAverageLocal(int[][][] states) {
initialise();
addObservations(states);
return computeAverageLocalOfObservations();
}
@Override
public final double[] computeLocal(int[][] states, int col) {
initialise();
addObservations(states, col);
return computeLocalFromPreviousObservations(states, col);
}
@Override
public final double[] computeLocal(int[][][] states, int index1, int index2) {
initialise();
addObservations(states, index1, index2);
return computeLocalFromPreviousObservations(states, index1, index2);
}
@Override
public final double computeAverageLocal(int[][] states, int col) {
initialise();
addObservations(states, col);
return computeAverageLocalOfObservations();
}
@Override
public final double computeAverageLocal(int[][][] states, int index1, int index2) {
initialise();
addObservations(states, index1, index2);
return computeAverageLocalOfObservations();
}
}
/*
* Java Information Dynamics Toolkit (JIDT)
* Copyright (C) 2012, Joseph T. Lizier
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package infodynamics.measures.discrete;
/**
* A base class for calculators computing measures for
* a single variable which
* require knowledge of the embedded past state of a univariate
* discrete (ie int[]) variable.
*
* <p>This combines functionality for single agents from
* {@link UnivariateMeasureDiscrete} with functionality
* required in the context of the past provided by
* {@link ContextOfPastMeasureCalculatorDiscrete}.</p>
*
* <p>Usage is as defined in {@link InfoMeasureCalculatorDiscrete}, with
* extra methods for supplying observations and making
* calculations defined in {@link UnivariateMeasureDiscrete}</p>.
*
* <p>Users should not need to deal with this class directly;
* it is simply used to gather common functionality for several
* child classes.
* </p>
*
* TODO Make the Active info storage and entropy calculators inherit from this
*
* @author Joseph Lizier (<a href="joseph.lizier at gmail.com">email</a>,
* <a href="http://lizier.me/joseph/">www</a>)
*/
public abstract class UnivariateMeasureDiscreteInContextOfPastCalculator extends
ContextOfPastMeasureCalculatorDiscrete implements UnivariateMeasureDiscrete {
/**
* Construct the calculator with default base of 2 and history 1
*/
public UnivariateMeasureDiscreteInContextOfPastCalculator() {
super(2, 1);
}
/**
* Construct the calculator
*
* @param base number of quantisation levels for each variable.
* E.g. binary variables are in base-2.
* @param history embedding length
*/
public UnivariateMeasureDiscreteInContextOfPastCalculator(int base, int history) {
super(base, history);
}
/**
* Construct the calculator
*
* @param base number of quantisation levels for each variable.
* E.g. binary variables are in base-2.
* @param history embedding length
* @param dontCreateObsStorage do not create storage
* for observations of the embedded past (as the child
* class is signalling that it does not need it)
*/
public UnivariateMeasureDiscreteInContextOfPastCalculator(int base, int history, boolean dontCreateObsStorage) {
super(base, history, dontCreateObsStorage);
}
public final double[] computeLocal(int[] states) {
initialise();
addObservations(states);
return computeLocalFromPreviousObservations(states);
}
@Override
public final double computeAverageLocal(int[] states) {
initialise();
addObservations(states);
return computeAverageLocalOfObservations();
}
public final double[][] computeLocal(int[][] states) {
initialise();
try {
addObservations(states);
} catch (Exception e) {
throw new RuntimeException(e);
}
return computeLocalFromPreviousObservations(states);
}
public final double[][][] computeLocal(int[][][] states) {
initialise();
addObservations(states);
return computeLocalFromPreviousObservations(states);
}
public final double computeAverageLocal(int[][] states) {
initialise();
try {
addObservations(states);
} catch (Exception e) {
throw new RuntimeException(e);
}
return computeAverageLocalOfObservations();
}
public final double computeAverageLocal(int[][][] states) {
initialise();
addObservations(states);
return computeAverageLocalOfObservations();
}
public final double[] computeLocal(int[][] states, int col) {
initialise();
addObservations(states, col);
return computeLocalFromPreviousObservations(states, col);
}
public final double[] computeLocal(int[][][] states, int index1, int index2) {
initialise();
addObservations(states, index1, index2);
return computeLocalFromPreviousObservations(states, index1, index2);
}
public final double computeAverageLocal(int[][] states, int col) {
initialise();
addObservations(states, col);
return computeAverageLocalOfObservations();
}
public final double computeAverageLocal(int[][][] states, int index1, int index2) {
initialise();
addObservations(states, index1, index2);
return computeAverageLocalOfObservations();
}
// these are only here to get this thing to compile, they were in
// the interface, and maybe I could or should have done this in the classes
// that don't need them at all, but whatever, I think these should be
// removed or only added to the classes that need them.
private double[][] computeLocalFromPreviousObservations(int[][] states) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'computeLocalFromPreviousObservations'");
}
private void addObservations(int[][][] states) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'addObservations'");
}
private double[][][] computeLocalFromPreviousObservations(int[][][] states) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'computeLocalFromPreviousObservations'");
}
private double[] computeLocalFromPreviousObservations(int[][] states, int col) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'computeLocalFromPreviousObservations'");
}
private double[] computeLocalFromPreviousObservations(int[][][] states, int index1, int index2) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'computeLocalFromPreviousObservations'");
}
private void addObservations(int[][] states, int col) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'addObservations'");
}
private void addObservations(int[][][] states, int index1, int index2) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'addObservations'");
}
}

View File

@ -0,0 +1,196 @@
package infodynamics.measures.discrete;
import static org.junit.Assert.assertThrows;
import org.junit.Test;
import infodynamics.measures.discrete.InfoMeasureCalculatorDiscrete.State;
import junit.framework.TestCase;
import java.util.Arrays;
import java.util.List;
public class EntropyTester extends TestCase {
private EntropyCalculatorDiscrete calc;
private static double ERR_ALLOWANCE = 0.02;
public void setup() {
calc = new EntropyCalculatorDiscrete();
}
@Test
public void testHashTableUseBasic() throws Exception {
setup();
// 1. check the state machine is in the correct state
assertEquals(State.SETTING_PROPERTIES, calc.currentState);
calc.initialise();
String[] obs = new String[] {"a", "b", "b"};
calc.addObservations(obs);
// 2. check that the integer range is infact unknown
// 3. check the state machine
assertEquals(false, calc.knownIntegerRange);
assertEquals(State.ADDING_OBSERVATIONS, calc.currentState);
// 4. check the hash table and it's values
assertEquals((Integer) 1, calc.hashedStateCount.get("a"));
assertEquals((Integer) 2, calc.hashedStateCount.get("b"));
double ent = calc.computeAverageLocalOfObservations();
// 5. check result of entropy calculations - allowing small error margin
assertTrue(Math.abs(ent-0.918)/0.918 <= ERR_ALLOWANCE);
assertEquals(State.COMPUTING, calc.currentState);
}
@Test
public void testArrayUseBasic() throws Exception {
setup();
calc.setProperty("ALPHABET_SIZE", "2");
assertEquals(State.SETTING_PROPERTIES, calc.currentState);
assertEquals(true, calc.knownIntegerRange);
int[] obs = new int[] {0,0,1,1};
calc.addObservations(obs);
assertEquals(State.ADDING_OBSERVATIONS, calc.currentState);
double ent = calc.computeAverageLocalOfObservations();
assertEquals(1.0, ent);
assertEquals(State.COMPUTING, calc.currentState);
}
@Test
public void testArrayUseOverflowAlphaSize() throws Exception {
setup();
calc.setProperty("ALPHABET_SIZE", "2");
int[] obs = new int[] { 0, 1, 2 };
assertThrows(RuntimeException.class, () -> {
calc.addObservations(obs);
});
}
@Test
public void testArrayUseOverflowAlphaSize2() throws Exception {
setup();
calc.setProperty("ALPHABET_SIZE", "2");
Integer[] obs = new Integer[] { 0, 1, 2 };
assertThrows(RuntimeException.class, () -> {
calc.addObservations(obs);
});
}
@Test
public void testStringIntegerInterpretation() throws Exception {
setup();
calc.setProperty("ALPHABET_SIZE", "2");
String[] obs = new String[] { "0", "1", "1" };
calc.addObservations(obs);
double ent = calc.computeAverageLocalOfObservations();
// ensure we did use the array implementation
assertEquals(calc.knownIntegerRange, true);
assertNotNull(calc.stateCount);
assertTrue(calc.hashedStateCount.isEmpty());
// ensure it gets correct output - allowing small error margin
assertTrue(Math.abs(ent-0.918)/0.918 <= ERR_ALLOWANCE);
}
@Test
public void testUninterpretableInput() throws Exception {
setup();
calc.setProperty("ALPHABET_SIZE", "2");
String[] obs = new String[] { "0", "1", "a" };
// we specified an alphabet size, but cannot interpret "a" as an integer
assertThrows(RuntimeException.class, () ->{
calc.addObservations(obs);
});
}
@Test
public void testNegativeNums() throws Exception {
setup();
calc.setProperty("ALPHABET_SIZE", "4");
int[] obs = new int[] { 0, 1, -1, 2 };
// Negative numbers are invalid observations.
assertThrows(RuntimeException.class, () -> {
calc.addObservations(obs);
});
}
@Test
public void testExceedMaxAlphaSize() throws Exception {
setup();
// TODO -- This test is under the assumption of the temporary max alphabet size of 100
// when this number is solidified, this test needs to change (it will fail when it does change.)
int[] obs = new int[] { 99, 100, 101 };
calc.addObservations(obs);
assertFalse(calc.hashedStateCount.isEmpty());
assertNull(calc.stateCount);
}
@Test
public void testMultiDimensionalIntObservations() throws Exception {
setup();
calc.setProperty("NUM_DIMENSIONS", "3");
int[][] obs = new int[][] {
{1, 2, 3},
{4, 5, 6},
{1, 2, 3}
};
calc.addObservations(obs);
// TODO -- compute combined values
// assertEquals((Integer) 2, calc.hashedStateCount.get(test1));
// assertEquals((Integer) 1, calc.hashedStateCount.get(test2));
}
@Test
public void testMultiDimensionalObjObservations() throws Exception {
setup();
calc.setProperty("NUM_DIMENSIONS", "3");
Object[][] obs = new Object[][] {
{"A", "B", "C"},
{"D", "E", "F"},
{"A", "B", "C"}
};
calc.addObservations(obs);
List<Object> test1 = Arrays.asList(obs[0]);
List<Object> test2 = Arrays.asList(obs[1]);
assertEquals((Integer) 2, calc.hashedStateCount.get(test1));
assertEquals((Integer) 1, calc.hashedStateCount.get(test2));
}
// TODO -- implement this test.
@Test
public void testZeroDimensions() throws Exception {
setup();
calc.setProperty("NUM_DIMENSIONS", "0");
}
}