mirror of https://github.com/jlizier/jidt
Merge 1fcf2d0136 into fea2cb4bfa
This commit is contained in:
commit
ebcc281b50
|
|
@ -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'");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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'");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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...)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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'");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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'");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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'");
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue