From ac8326aecfe9f26e64d2b4a5bf79d26fd6c8c6b7 Mon Sep 17 00:00:00 2001
From: Brad Wootton
Date: Thu, 22 Aug 2024 13:52:19 +1000
Subject: [PATCH 1/2] Discrete entropy is complete I think. Maybe a few more
things moved around. No tests yet.
---
...ontextOfPastMeasureCalculatorDiscrete.java | 2 +-
.../discrete/EntropyCalculatorDiscrete.java | 496 ++++++++++++------
.../InfoMeasureCalculatorDiscrete.java | 116 +++-
.../discrete/SingleAgentMeasureDiscrete.java | 183 +++++--
4 files changed, 558 insertions(+), 239 deletions(-)
diff --git a/java/source/infodynamics/measures/discrete/ContextOfPastMeasureCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/ContextOfPastMeasureCalculatorDiscrete.java
index 2ec38e3..1b19801 100755
--- a/java/source/infodynamics/measures/discrete/ContextOfPastMeasureCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/ContextOfPastMeasureCalculatorDiscrete.java
@@ -104,7 +104,7 @@ 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
*/
diff --git a/java/source/infodynamics/measures/discrete/EntropyCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/EntropyCalculatorDiscrete.java
index 1577ffd..f2efc79 100755
--- a/java/source/infodynamics/measures/discrete/EntropyCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/EntropyCalculatorDiscrete.java
@@ -18,6 +18,8 @@
package infodynamics.measures.discrete;
+import java.util.Hashtable;
+
import infodynamics.utils.MatrixUtils;
/**
@@ -61,63 +63,43 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
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
- */
- 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 hashedStateCount = 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);
}
/**
- * Initialise with new base
+ * Initialise with new alphabet size
*
- * @param base
+ * @param alphabetSize
*/
- public void initialise(int base){
- boolean baseChanged = (this.base != base);
- super.initialise(base);
+ public void initialise(int alphabetSize){
+ boolean sizeChange = (this.alphabetSize != alphabetSize);
+ super.initialise(alphabetSize);
- if (baseChanged || (stateCount == null)) {
+ if (sizeChange || (stateCount == null)) {
// Create storage for counts of observations
try {
- stateCount = new int[base];
+ stateCount = new int[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 + ") is too large for the JVM at this time", e);
+ 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);
@@ -126,11 +108,65 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
@Override
public void initialise(){
- initialise(base);
+ initialise(alphabetSize);
}
-
+
@Override
- public void addObservations(int states[]) {
+ public void addObservations(Object[] 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:
+
+ if (!knownIntegerRange) {
+ Object key = states[r];
+ Integer value = hashedStateCount.getOrDefault(key, 0) + 1;
+ hashedStateCount.put(key, value);
+ continue;
+ }
+
+ // TODO better way to do this??
+ // obviously we can do .getClass() twice in the if statements, I think this is
+ // slightly more readable though.
+ // joe's input:
+ @SuppressWarnings("rawtypes")
+ Class objectClass = states[r].getClass();
+ Integer index;
+ if (objectClass == String.class) {
+ index = Integer.parseInt((String) states[r]);
+ } else if (objectClass == Integer.class) {
+ index = (Integer) states[r];
+ } else {
+ throw new NumberFormatException(String.format(
+ "Cannot parse %s as an Integer for indexing",
+ states[r]));
+ }
+
+ // valid index, check to make sure user didn't break the alphabet size they provided.
+ if (index >= stateCount.length) {
+ // runtime exception I guess...?
+ // TODO joe's input:
+ throw new RuntimeException(String.format(
+ "Observation %s exceeds provided alphabet size %d",
+ states[r], this.alphabetSize));
+ }
+ stateCount[index]++;
+ }
+ }
+
+ // I added this so that computeAverageLocal works, which we were considering deprecating
+ // Though i think keeping the old int[] format is worthwhile for backwards compat.
+ // TODO joe's input:
+ // maybe deprecate (with computeAverageLocal)
+ /**
+ * Add observations in to our estimates of the pdfs.
+ *
+ * @param states
+ */
+ public void addObservations(int[] states) {
int rows = states.length;
// increment the count of observations:
observations += rows;
@@ -139,76 +175,9 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
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]]++;
- }
- }
-
/**
* Return the current count for the given value
*
@@ -236,7 +205,7 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
max = 0;
min = 0;
- for (int stateVal = 0; stateVal < base; stateVal++) {
+ for (int stateVal = 0; stateVal < alphabetSize; stateVal++) {
// compute p_state
double p_state = (double) stateCount[stateVal] / (double) observations;
if (p_state > 0.0) {
@@ -277,13 +246,224 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
min = localEntropy[r];
}
}
+
average = average/(double) rows;
-
return localEntropy;
+ }
+
+ @Override // maybe deprecate
+ public final double computeAverageLocal(int states[]) throws Exception {
+ initialise();
+ startAddObservations();
+ addObservations(states);
+ finaliseAddObservations();
+ return computeAverageLocalOfObservations();
+ }
+
+
+ @Override
+ public void setProperty(String propertyName, String propertyValue) throws Exception {
+ // TODO - I think this should just be the super call, as this class has no new properties.
+ // joe's input:
+ switch(propertyName.toLowerCase()) {
+ case ALPHABET_SIZE:
+ this.alphabetSize = Integer.parseInt(propertyValue);
+ break;
+ case MAX_ALPHA_SIZE_TO_STORE:
+ this.maxAlphabetSize = Integer.parseInt(propertyValue);
+ break;
+ case KNOWN_INTEGER_RANGE:
+ this.knownIntegerRange = Boolean.parseBoolean(propertyValue);
+ break;
+ default:
+ // Assume it's a property of parent class
+ super.setProperty(propertyName, propertyValue);
+ break;
+ }
+
+ }
+
+ @Override
+ public void setObservations(Object[] observations) throws Exception {
+ this.observations = observations.length;
+ this.addObservations(observations);
+ this.finaliseAddObservations();
+ }
+
+ /*
+ ***********************************************************************
+ ******************* ALL METHODS BELOW ARE DEPRECATED ******************
+ ******************* DON'T USE THEM ******************
+ ***********************************************************************
+ */
+
+ @Override
+ @Deprecated
+ public void startAddObservations() {
+
+ // reinitialise if already finalised
+ if (currentState == State.COMPUTING) {
+ initialise();
+ }
+ this.currentState = State.ADDING_OBSERVATIONS;
+
+ }
+
+ @Override
+ @Deprecated
+ public void finaliseAddObservations() throws Exception {
+
+ if (observations == 0) {
+ // TODO better error message. maybe not runtimeExc?
+ // joe's input:
+ throw new RuntimeException("0 observations not allowed.");
+ }
+
+ // I actually think this is useless? It shouldn't ever get here without
+ // throwing the error above.
+ if (currentState == State.SETTING_PROPERTIES) {
+ throw new RuntimeException("Estimator should be initialised before finalised...");
+ }
+
+ this.currentState = State.COMPUTING;
+ }
+
+ @Override
+ @Deprecated
+ 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
+ @Deprecated
+ 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
+ @Deprecated
+ 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
+ @Deprecated
+ 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]]++;
+ }
+ }
+
+ @Override
+ @Deprecated
+ public final double computeAverageLocal(int states[][]) {
+
+ initialise();
+ startAddObservations();
+ addObservations(states);
+ this.currentState = State.COMPUTING;
+ return computeAverageLocalOfObservations();
+ }
+
+ @Override
+ @Deprecated
+ public final double computeAverageLocal(int states[][][]) {
+ initialise();
+ startAddObservations();
+ addObservations(states);
+ this.currentState = State.COMPUTING;
+ return computeAverageLocalOfObservations();
+ }
+
+ @Override
+ @Deprecated
+ public final double[] computeLocal(int states[][], int col) {
+ initialise();
+ startAddObservations();
+ addObservations(states, col);
+ this.currentState = State.COMPUTING;
+ return computeLocalFromPreviousObservations(states, col);
+ }
+
+ @Override
+ @Deprecated
+ public final double[] computeLocal(int states[][][],
+ int agentIndex1, int agentIndex2) {
+ initialise();
+ startAddObservations();
+ addObservations(states, agentIndex1, agentIndex2);
+ this.currentState = State.COMPUTING;
+ return computeLocalFromPreviousObservations(states, agentIndex1, agentIndex2);
+ }
+
+ @Override
+ @Deprecated
+ public final double computeAverageLocal(int states[][], int col) {
+ initialise();
+ startAddObservations();
+ addObservations(states, col);
+ this.currentState = State.COMPUTING;
+ return computeAverageLocalOfObservations();
+ }
+
+ @Override
+ @Deprecated
+ public final double computeAverageLocal(int states[][][], int agentIndex1, int agentIndex2) {
+ initialise();
+ startAddObservations();
+ addObservations(states, agentIndex1, agentIndex2);
+ this.currentState = State.COMPUTING;
+ return computeAverageLocalOfObservations();
+ }
+
+ @Override
+ @Deprecated
public double[][] computeLocalFromPreviousObservations(int states[][]){
int rows = states.length;
int columns = states[0].length;
@@ -312,6 +492,7 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
}
@Override
+ @Deprecated
public double[][][] computeLocalFromPreviousObservations(int states[][][]){
int timeSteps = states.length;
int agentRows, agentColumns;
@@ -326,7 +507,7 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
agentColumns = states[0][0].length;
}
}
-
+
double[][][] localEntropy = new double[timeSteps][agentRows][agentColumns];
average = 0;
max = 0;
@@ -351,12 +532,13 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
return localEntropy;
}
-
+
@Override
+ @Deprecated
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;
@@ -379,10 +561,11 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
}
@Override
+ @Deprecated
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;
@@ -404,80 +587,59 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
return localEntropy;
}
-
+
@Override
+ @Deprecated
public final double[] computeLocal(int states[]) {
-
initialise();
+ startAddObservations();
addObservations(states);
+ this.currentState = State.COMPUTING;
return computeLocalFromPreviousObservations(states);
}
-
+
@Override
+ @Deprecated
public final double[][] computeLocal(int states[][]) {
-
initialise();
+ startAddObservations();
addObservations(states);
+ this.currentState = State.COMPUTING;
return computeLocalFromPreviousObservations(states);
}
-
+
@Override
+ @Deprecated
public final double[][][] computeLocal(int states[][][]) {
-
initialise();
+ startAddObservations();
addObservations(states);
+ this.currentState = State.COMPUTING;
return computeLocalFromPreviousObservations(states);
}
- @Override
- public final double computeAverageLocal(int states[]) {
-
- initialise();
- addObservations(states);
- return computeAverageLocalOfObservations();
+ /**
+ * User was formerly forced to create new instances through this factory method.
+ * Retained for backwards compatibility.
+ *
+ * @param alphabetSize 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
+ */
+ @Deprecated
+ public static EntropyCalculatorDiscrete newInstance(int alphabetSize, int blocksize) {
+ if (blocksize > 1) {
+ return BlockEntropyCalculatorDiscrete.newInstance(blocksize, alphabetSize);
+ } else {
+ return EntropyCalculatorDiscrete.newInstance(alphabetSize);
+ }
+ }
+ @Deprecated
+ public static EntropyCalculatorDiscrete newInstance(int alphabetSize) {
+ return new EntropyCalculatorDiscrete(alphabetSize);
}
- @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();
- }
}
diff --git a/java/source/infodynamics/measures/discrete/InfoMeasureCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/InfoMeasureCalculatorDiscrete.java
index 2a0ecf4..132beda 100755
--- a/java/source/infodynamics/measures/discrete/InfoMeasureCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/InfoMeasureCalculatorDiscrete.java
@@ -74,7 +74,23 @@ public abstract class InfoMeasureCalculatorDiscrete {
* Number of available quantised states for each variable
* (ie binary is base-2).
*/
- protected int base = 0; // number of individual states. Need initialised to 0 for changedSizes
+ protected int alphabetSize = -1; // number of individual states. -1 for unknown number
+ /**
+ * Size of the largest alphabet to support in array based memory management before
+ * switching to Hashtable implementation.
+ */
+ protected int maxAlphabetSize = 100; // largest alphabet size before moving to Hashtable memory management TODO some default value
+ /**
+ * TODO -- make better comments :)
+ * State indicator of what the estimator is expecting to happen next.
+ */
+ protected State currentState = State.SETTING_PROPERTIES;
+
+ /**
+ * Boolean indicating if the size of the alphabet is known to determine the use of a
+ * hash table implementation for memory management.
+ */
+ protected boolean knownIntegerRange = false;
/**
* Cached value of ln(base)
@@ -96,36 +112,49 @@ public abstract class InfoMeasureCalculatorDiscrete {
* Whether we're in debug mode
*/
protected boolean debug = false;
+
+ 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,74 @@ 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
+ *
+ * Property names defined at the interface level, and what their
+ * values should represent, include:
+ *
+ * {@link #ALPHABET_SIZE} -- Defined size of the alphabet for
+ * the data.
+ * {@link #MAX_ALPHA_SIZE_TO_STORE} -- Maximum alphabet size to store
+ * before switching to HashTable memory management.
+ *
+ *
+ * Unknown property values are ignored.
+ *
+ * Note that implementing classes may defined additional properties.
+ *
+ * @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:
+ }
+
+ switch(propertyName.toLowerCase()) {
+ case "ALPHABET_SIZE":
+ this.alphabetSize = Integer.parseInt(propertyValue);
+ break;
+ case "MAX_ALPHA_SIZE_TO_STORE":
+ this.maxAlphabetSize = Integer.parseInt(propertyValue);
+ 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...)
+ }
}
/**
diff --git a/java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscrete.java b/java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscrete.java
index 896b5e4..507e7f6 100755
--- a/java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscrete.java
@@ -43,66 +43,75 @@ package infodynamics.measures.discrete;
public interface SingleAgentMeasureDiscrete {
/**
- * Initialise the calculator with (potentially) a new base
- *
- * @param base
+ * Property name for definite alphabet size. Attempting
+ * to use observations beyond this property will throw
+ * errors.
*/
- public void initialise(int base);
+ public static final String ALPHABET_SIZE = "ALPHABET_SIZE";
+
+ /**
+ * Property name for determining when to switch to HashTable
+ * memory management system. (default is TODO...)
+ */
+ public static final String MAX_ALPHA_SIZE_TO_STORE = "MAX_ALPHA_SIZE_TO_STORE";
+
+ /**
+ * Property name for whether or not the calculator is using
+ * the HashTable memory management.
+ *
+ * TODO -- maybe this shouldn't be a property... it should def be
+ * mutually exclusive with alphaSize.
+ */
+ public static final String KNOWN_INTEGER_RANGE = "KNOWN_INTEGER_RANGE";
+
+
+ /**
+ * Property name for determining whether or not the calculator
+ * is still adding observations.
+ *
+ * TODO -- I think this is the nicest way to do this, though I'd rather a private
+ * boolean not set by setProperties. This probs shouldn't be a property at all...
+ */
+ public static final String EXPECTING_OBSERVATIONS = "EXPECTING_OBSERVATIONS";
+
+ /**
+ * 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.
*
* @param states series of samples
*/
- public void addObservations(int states[]);
+ public void addObservations(Object 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.
@@ -233,7 +242,7 @@ public interface SingleAgentMeasureDiscrete {
* @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
@@ -242,8 +251,9 @@ public interface SingleAgentMeasureDiscrete {
*
* @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[]);
+ public double computeAverageLocal(int states[]) throws Exception;
/**
* Standalone routine to
@@ -341,4 +351,69 @@ public interface SingleAgentMeasureDiscrete {
* @return average of the measure for the given variable.
*/
public double computeAverageLocal(int states[][][], int index1, int index2);
+
+ /**
+ * 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[][]);
+
+ /**
+ * 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.
+ *
+ * @deprecated
+ * @param states multivariate time series
+ * (1st index is time, 2nd index is variable number)
+ * @param col index of agent
+ */
+ @Deprecated
+ 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.
+ *
+ * @deprecated
+ * @param states multivariate time series
+ * (1st index is time, 2nd index is variable row number,
+ * 3rd is variable column number)
+ */
+ @Deprecated
+ 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.
+ *
+ * @deprecated
+ * @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
+ */
+ @Deprecated
+ public void addObservations(int states[][][], int index1, int index2);
+
+ /**
+ * Initialise the calculator with (potentially) a new alphabet size
+ *
+ * TODO - I don't think so anymore... this should be done with set property
+ * Deprecated, use initialise() and setProperty("ALPHABET_SIZE", "n") instead.
+ * @deprecated
+ * @param alphabetSize
+ */
+ @Deprecated
+ public void initialise(int alphabetSize);
}
From de44f67d46ccfa452a7ace646c8217575fcdac9b Mon Sep 17 00:00:00 2001
From: Brad Wootton
Date: Tue, 24 Dec 2024 20:40:51 +1000
Subject: [PATCH 2/2] Final commit for Brad's thesis. All remaining TODO
comments are real TODOs. Support for larger alphabets has been added for
entropy and mutual information, lightly tested. The old misleading 'alphabet
size' has refactored to 'base'.
---
.../ActiveInformationCalculatorDiscrete.java | 90 +-
.../BlockEntropyCalculatorDiscrete.java | 62 +-
...mbinedActiveEntRateCalculatorDiscrete.java | 2 +-
...onalTransferEntropyCalculatorDiscrete.java | 50 +-
...ontextOfPastMeasureCalculatorDiscrete.java | 18 +-
.../discrete/EntropyCalculatorDiscrete.java | 925 +++++++++---------
.../EntropyRateCalculatorDiscrete.java | 76 +-
.../InfoMeasureCalculatorDiscrete.java | 32 +-
.../MultiInformationCalculatorDiscrete.java | 48 +-
...iVariateInfoMeasureCalculatorDiscrete.java | 10 +-
.../MutualInformationCalculatorDiscrete.java | 359 +++----
...edictiveInformationCalculatorDiscrete.java | 110 ++-
.../SeparableInfoCalculatorDiscrete.java | 46 +-
...rableInfoCalculatorDiscreteByAddition.java | 18 +-
.../discrete/SingleAgentMeasureDiscrete.java | 419 --------
.../TransferEntropyCalculatorDiscrete.java | 104 +-
.../discrete/UnivariateMeasureDiscrete.java | 150 +++
...ureDiscreteInContextOfPastCalculator.java} | 340 ++++---
.../measures/discrete/EntropyTester.java | 196 ++++
19 files changed, 1500 insertions(+), 1555 deletions(-)
delete mode 100755 java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscrete.java
create mode 100644 java/source/infodynamics/measures/discrete/UnivariateMeasureDiscrete.java
rename java/source/infodynamics/measures/discrete/{SingleAgentMeasureDiscreteInContextOfPastCalculator.java => UnivariateMeasureDiscreteInContextOfPastCalculator.java} (61%)
mode change 100755 => 100644
create mode 100644 java/unittests/infodynamics/measures/discrete/EntropyTester.java
diff --git a/java/source/infodynamics/measures/discrete/ActiveInformationCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/ActiveInformationCalculatorDiscrete.java
index c8d8aef..e565352 100755
--- a/java/source/infodynamics/measures/discrete/ActiveInformationCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/ActiveInformationCalculatorDiscrete.java
@@ -72,7 +72,7 @@ import infodynamics.utils.RandomGenerator;
* @author Joseph Lizier (email ,
* www )
*/
-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'");
+ }
}
diff --git a/java/source/infodynamics/measures/discrete/BlockEntropyCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/BlockEntropyCalculatorDiscrete.java
index 40bdda3..29eb1fb 100755
--- a/java/source/infodynamics/measures/discrete/BlockEntropyCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/BlockEntropyCalculatorDiscrete.java
@@ -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);
diff --git a/java/source/infodynamics/measures/discrete/CombinedActiveEntRateCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/CombinedActiveEntRateCalculatorDiscrete.java
index 56ee18d..d59505c 100755
--- a/java/source/infodynamics/measures/discrete/CombinedActiveEntRateCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/CombinedActiveEntRateCalculatorDiscrete.java
@@ -32,7 +32,7 @@ import infodynamics.utils.MatrixUtils;
* and typical usage pattern.
*
*
- * TODO Make this inherit from {@link SingleAgentMeasureDiscreteInContextOfPastCalculator}
+ * TODO Make this inherit from {@link UnivariateMeasureDiscreteInContextOfPastCalculator}
* like {@link ActiveInformationCalculatorDiscrete} and fix the Javadocs
*
* @author Joseph Lizier (email ,
diff --git a/java/source/infodynamics/measures/discrete/ConditionalTransferEntropyCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/ConditionalTransferEntropyCalculatorDiscrete.java
index c9e8aef..9f8d13b 100644
--- a/java/source/infodynamics/measures/discrete/ConditionalTransferEntropyCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/ConditionalTransferEntropyCalculatorDiscrete.java
@@ -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];
}
}
diff --git a/java/source/infodynamics/measures/discrete/ContextOfPastMeasureCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/ContextOfPastMeasureCalculatorDiscrete.java
index 1b19801..5e095e2 100755
--- a/java/source/infodynamics/measures/discrete/ContextOfPastMeasureCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/ContextOfPastMeasureCalculatorDiscrete.java
@@ -111,7 +111,7 @@ public abstract class ContextOfPastMeasureCalculatorDiscrete extends
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;
diff --git a/java/source/infodynamics/measures/discrete/EntropyCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/EntropyCalculatorDiscrete.java
index f2efc79..6dfe84d 100755
--- a/java/source/infodynamics/measures/discrete/EntropyCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/EntropyCalculatorDiscrete.java
@@ -19,6 +19,9 @@
package infodynamics.measures.discrete;
import java.util.Hashtable;
+import java.util.Map;
+import java.util.List;
+import java.util.Arrays;
import infodynamics.utils.MatrixUtils;
@@ -58,12 +61,27 @@ Theory' (John Wiley & Sons, New York, 1991).
* www )
*/
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]
+ /**
+ * State counts in a hashtable for observations other than ints
+ * as well as for sparse observations
+ */
protected Hashtable 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 no specified alphabet size.
@@ -80,102 +98,7 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
*/
public EntropyCalculatorDiscrete(int alphabetSize) {
super(alphabetSize);
- }
-
- /**
- * Initialise with new alphabet size
- *
- * @param alphabetSize
- */
- public void initialise(int alphabetSize){
- boolean sizeChange = (this.alphabetSize != alphabetSize);
- super.initialise(alphabetSize);
-
- if (sizeChange || (stateCount == null)) {
- // Create storage for counts of observations
- try {
- stateCount = new int[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 alphabet size (" +
- alphabetSize + ") is too large for the JVM at this time", e);
- }
- } else {
- MatrixUtils.fill(stateCount, 0);
- }
- }
-
- @Override
- public void initialise(){
- initialise(alphabetSize);
- }
-
- @Override
- public void addObservations(Object[] 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:
-
- if (!knownIntegerRange) {
- Object key = states[r];
- Integer value = hashedStateCount.getOrDefault(key, 0) + 1;
- hashedStateCount.put(key, value);
- continue;
- }
-
- // TODO better way to do this??
- // obviously we can do .getClass() twice in the if statements, I think this is
- // slightly more readable though.
- // joe's input:
- @SuppressWarnings("rawtypes")
- Class objectClass = states[r].getClass();
- Integer index;
- if (objectClass == String.class) {
- index = Integer.parseInt((String) states[r]);
- } else if (objectClass == Integer.class) {
- index = (Integer) states[r];
- } else {
- throw new NumberFormatException(String.format(
- "Cannot parse %s as an Integer for indexing",
- states[r]));
- }
-
- // valid index, check to make sure user didn't break the alphabet size they provided.
- if (index >= stateCount.length) {
- // runtime exception I guess...?
- // TODO joe's input:
- throw new RuntimeException(String.format(
- "Observation %s exceeds provided alphabet size %d",
- states[r], this.alphabetSize));
- }
- stateCount[index]++;
- }
- }
-
- // I added this so that computeAverageLocal works, which we were considering deprecating
- // Though i think keeping the old int[] format is worthwhile for backwards compat.
- // TODO joe's input:
- // maybe deprecate (with computeAverageLocal)
- /**
- * Add observations in to our estimates of the pdfs.
- *
- * @param states
- */
- 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]]++;
- }
+ currentState = State.SETTING_PROPERTIES;
}
/**
@@ -185,8 +108,30 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
* @return count of observations of the given state
*/
public int getStateCount(int stateVal) {
+ // stateCount could have overflowed
+ if (stateCount == null) {
+ return hashedStateCount.get((Integer) stateVal);
+ }
return stateCount[stateVal];
}
+
+ /**
+ * Return the current count for the given value
+ *
+ * @param stateVal given value
+ * @return count of observations of the given state
+ */
+ 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];
+ }
+ }
/**
* Return the current probability for the given value
@@ -197,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 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 < alphabetSize; 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 entry : hashedStateCount.entrySet()) {
+ p_state = (double) entry.getValue() / (double) observations;
+ ent += computeEntropyCont(p_state);
}
- ent += entCont;
}
average = ent;
@@ -228,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];
@@ -250,46 +576,6 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
average = average/(double) rows;
return localEntropy;
}
-
- @Override // maybe deprecate
- public final double computeAverageLocal(int states[]) throws Exception {
- initialise();
- startAddObservations();
- addObservations(states);
- finaliseAddObservations();
- return computeAverageLocalOfObservations();
- }
-
-
- @Override
- public void setProperty(String propertyName, String propertyValue) throws Exception {
- // TODO - I think this should just be the super call, as this class has no new properties.
- // joe's input:
-
- switch(propertyName.toLowerCase()) {
- case ALPHABET_SIZE:
- this.alphabetSize = Integer.parseInt(propertyValue);
- break;
- case MAX_ALPHA_SIZE_TO_STORE:
- this.maxAlphabetSize = Integer.parseInt(propertyValue);
- break;
- case KNOWN_INTEGER_RANGE:
- this.knownIntegerRange = Boolean.parseBoolean(propertyValue);
- break;
- default:
- // Assume it's a property of parent class
- super.setProperty(propertyName, propertyValue);
- break;
- }
-
- }
-
- @Override
- public void setObservations(Object[] observations) throws Exception {
- this.observations = observations.length;
- this.addObservations(observations);
- this.finaliseAddObservations();
- }
/*
***********************************************************************
@@ -298,348 +584,29 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
***********************************************************************
*/
+ // TODO protected duplicates, keep public call, that does the same as private.
@Override
@Deprecated
public void startAddObservations() {
-
// reinitialise if already finalised
if (currentState == State.COMPUTING) {
initialise();
}
this.currentState = State.ADDING_OBSERVATIONS;
-
}
@Override
@Deprecated
public void finaliseAddObservations() throws Exception {
- if (observations == 0) {
- // TODO better error message. maybe not runtimeExc?
- // joe's input:
- throw new RuntimeException("0 observations not allowed.");
- }
-
- // I actually think this is useless? It shouldn't ever get here without
- // throwing the error above.
if (currentState == State.SETTING_PROPERTIES) {
throw new RuntimeException("Estimator should be initialised before finalised...");
}
- this.currentState = State.COMPUTING;
- }
+ if (observations == 0) {
+ throw new RuntimeException("Must have some observations to finalise.");
+ }
- @Override
- @Deprecated
- 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
- @Deprecated
- 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
- @Deprecated
- 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
- @Deprecated
- 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]]++;
- }
- }
-
- @Override
- @Deprecated
- public final double computeAverageLocal(int states[][]) {
-
- initialise();
- startAddObservations();
- addObservations(states);
this.currentState = State.COMPUTING;
- return computeAverageLocalOfObservations();
}
-
- @Override
- @Deprecated
- public final double computeAverageLocal(int states[][][]) {
- initialise();
- startAddObservations();
- addObservations(states);
- this.currentState = State.COMPUTING;
- return computeAverageLocalOfObservations();
- }
-
- @Override
- @Deprecated
- public final double[] computeLocal(int states[][], int col) {
- initialise();
- startAddObservations();
- addObservations(states, col);
- this.currentState = State.COMPUTING;
- return computeLocalFromPreviousObservations(states, col);
- }
-
- @Override
- @Deprecated
- public final double[] computeLocal(int states[][][],
- int agentIndex1, int agentIndex2) {
- initialise();
- startAddObservations();
- addObservations(states, agentIndex1, agentIndex2);
- this.currentState = State.COMPUTING;
- return computeLocalFromPreviousObservations(states, agentIndex1, agentIndex2);
- }
-
- @Override
- @Deprecated
- public final double computeAverageLocal(int states[][], int col) {
- initialise();
- startAddObservations();
- addObservations(states, col);
- this.currentState = State.COMPUTING;
- return computeAverageLocalOfObservations();
- }
-
- @Override
- @Deprecated
- public final double computeAverageLocal(int states[][][], int agentIndex1, int agentIndex2) {
- initialise();
- startAddObservations();
- addObservations(states, agentIndex1, agentIndex2);
- this.currentState = State.COMPUTING;
- return computeAverageLocalOfObservations();
- }
-
- @Override
- @Deprecated
- 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];
- }
- }
- }
- average = average/(double) (columns * rows);
-
- return localEntropy;
-
- }
-
- @Override
- @Deprecated
- 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;
- }
- }
-
- 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];
- }
- }
- }
- }
- average = average/(double) (agentRows * agentColumns * timeSteps);
-
- return localEntropy;
-
- }
-
- @Override
- @Deprecated
- 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;
-
- }
-
- @Override
- @Deprecated
- 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
- @Deprecated
- public final double[] computeLocal(int states[]) {
- initialise();
- startAddObservations();
- addObservations(states);
- this.currentState = State.COMPUTING;
- return computeLocalFromPreviousObservations(states);
- }
-
- @Override
- @Deprecated
- public final double[][] computeLocal(int states[][]) {
- initialise();
- startAddObservations();
- addObservations(states);
- this.currentState = State.COMPUTING;
- return computeLocalFromPreviousObservations(states);
- }
-
- @Override
- @Deprecated
- public final double[][][] computeLocal(int states[][][]) {
- initialise();
- startAddObservations();
- addObservations(states);
- this.currentState = State.COMPUTING;
- return computeLocalFromPreviousObservations(states);
- }
-
- /**
- * User was formerly forced to create new instances through this factory method.
- * Retained for backwards compatibility.
- *
- * @param alphabetSize 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
- */
- @Deprecated
- public static EntropyCalculatorDiscrete newInstance(int alphabetSize, int blocksize) {
- if (blocksize > 1) {
- return BlockEntropyCalculatorDiscrete.newInstance(blocksize, alphabetSize);
- } else {
- return EntropyCalculatorDiscrete.newInstance(alphabetSize);
- }
- }
- @Deprecated
- public static EntropyCalculatorDiscrete newInstance(int alphabetSize) {
- return new EntropyCalculatorDiscrete(alphabetSize);
- }
-
-}
+}
\ No newline at end of file
diff --git a/java/source/infodynamics/measures/discrete/EntropyRateCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/EntropyRateCalculatorDiscrete.java
index 9080c30..f090aa2 100755
--- a/java/source/infodynamics/measures/discrete/EntropyRateCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/EntropyRateCalculatorDiscrete.java
@@ -62,7 +62,7 @@ Theory' (John Wiley & Sons, New York, 1991).
* @author Joseph Lizier (email ,
* www )
*/
-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'");
+ }
}
diff --git a/java/source/infodynamics/measures/discrete/InfoMeasureCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/InfoMeasureCalculatorDiscrete.java
index 132beda..e4386eb 100755
--- a/java/source/infodynamics/measures/discrete/InfoMeasureCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/InfoMeasureCalculatorDiscrete.java
@@ -71,24 +71,21 @@ 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 alphabetSize = -1; // number of individual states. -1 for unknown number
+ protected int alphabetSize = 100;
+
/**
- * Size of the largest alphabet to support in array based memory management before
- * switching to Hashtable implementation.
- */
- protected int maxAlphabetSize = 100; // largest alphabet size before moving to Hashtable memory management TODO some default value
- /**
- * TODO -- make better comments :)
- * State indicator of what the estimator is expecting to happen next.
+ * 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 use of a
- * hash table implementation for memory management.
+ * 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;
@@ -113,6 +110,9 @@ public abstract class InfoMeasureCalculatorDiscrete {
*/
protected boolean debug = false;
+ /**
+ * Enum for the states of an estimator
+ */
protected enum State {
SETTING_PROPERTIES,
INITIALISED,
@@ -213,15 +213,13 @@ public abstract class InfoMeasureCalculatorDiscrete {
// 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:
+ // joe's input: yes, check this at all levels.
}
- switch(propertyName.toLowerCase()) {
+ switch(propertyName.toUpperCase()) {
case "ALPHABET_SIZE":
this.alphabetSize = Integer.parseInt(propertyValue);
- break;
- case "MAX_ALPHA_SIZE_TO_STORE":
- this.maxAlphabetSize = Integer.parseInt(propertyValue);
+ this.knownIntegerRange = true;
break;
case "KNOWN_INTEGER_RANGE":
this.knownIntegerRange = Boolean.parseBoolean(propertyValue);
diff --git a/java/source/infodynamics/measures/discrete/MultiInformationCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/MultiInformationCalculatorDiscrete.java
index 56fadac..32855f5 100755
--- a/java/source/infodynamics/measures/discrete/MultiInformationCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/MultiInformationCalculatorDiscrete.java
@@ -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);
}
diff --git a/java/source/infodynamics/measures/discrete/MultiVariateInfoMeasureCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/MultiVariateInfoMeasureCalculatorDiscrete.java
index 1d3f826..82ff22b 100755
--- a/java/source/infodynamics/measures/discrete/MultiVariateInfoMeasureCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/MultiVariateInfoMeasureCalculatorDiscrete.java
@@ -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;
}
diff --git a/java/source/infodynamics/measures/discrete/MutualInformationCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/MutualInformationCalculatorDiscrete.java
index 7cb0c4e..2a2d417 100755
--- a/java/source/infodynamics/measures/discrete/MutualInformationCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/MutualInformationCalculatorDiscrete.java
@@ -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'");
}
}
diff --git a/java/source/infodynamics/measures/discrete/PredictiveInformationCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/PredictiveInformationCalculatorDiscrete.java
index 1d46f7f..b180285 100755
--- a/java/source/infodynamics/measures/discrete/PredictiveInformationCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/PredictiveInformationCalculatorDiscrete.java
@@ -80,7 +80,7 @@ import infodynamics.utils.MatrixUtils;
* @author Joseph Lizier (email ,
* www )
*/
-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'");
+ }
}
diff --git a/java/source/infodynamics/measures/discrete/SeparableInfoCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/SeparableInfoCalculatorDiscrete.java
index 2593484..766cfe6 100755
--- a/java/source/infodynamics/measures/discrete/SeparableInfoCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/SeparableInfoCalculatorDiscrete.java
@@ -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];
}
diff --git a/java/source/infodynamics/measures/discrete/SeparableInfoCalculatorDiscreteByAddition.java b/java/source/infodynamics/measures/discrete/SeparableInfoCalculatorDiscreteByAddition.java
index 2579b2a..37f1677 100755
--- a/java/source/infodynamics/measures/discrete/SeparableInfoCalculatorDiscreteByAddition.java
+++ b/java/source/infodynamics/measures/discrete/SeparableInfoCalculatorDiscreteByAddition.java
@@ -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,
diff --git a/java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscrete.java b/java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscrete.java
deleted file mode 100755
index 507e7f6..0000000
--- a/java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscrete.java
+++ /dev/null
@@ -1,419 +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 .
- */
-
-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.
- *
- * Usage is as per {@link InfoMeasureCalculatorDiscrete}, with
- * many methods for supplying observations and making
- * calculations defined here.
- *
- * 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}.
- *
- *
- * @author Joseph Lizier (email ,
- * www )
- */
-public interface SingleAgentMeasureDiscrete {
-
- /**
- * 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 determining when to switch to HashTable
- * memory management system. (default is TODO...)
- */
- public static final String MAX_ALPHA_SIZE_TO_STORE = "MAX_ALPHA_SIZE_TO_STORE";
-
- /**
- * Property name for whether or not the calculator is using
- * the HashTable memory management.
- *
- * TODO -- maybe this shouldn't be a property... it should def be
- * mutually exclusive with alphaSize.
- */
- public static final String KNOWN_INTEGER_RANGE = "KNOWN_INTEGER_RANGE";
-
-
- /**
- * Property name for determining whether or not the calculator
- * is still adding observations.
- *
- * TODO -- I think this is the nicest way to do this, though I'd rather a private
- * boolean not set by setProperties. This probs shouldn't be a property at all...
- */
- public static final String EXPECTING_OBSERVATIONS = "EXPECTING_OBSERVATIONS";
-
- /**
- * 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.
- *
- * @param states series of samples
- */
- public void addObservations(Object 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[]);
-
- /**
- * 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.
- * @throws Exception if states parameter is empty.
- */
- public double computeAverageLocal(int states[]) throws Exception;
-
- /**
- * 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);
-
- /**
- * 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[][]);
-
- /**
- * 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.
- *
- * @deprecated
- * @param states multivariate time series
- * (1st index is time, 2nd index is variable number)
- * @param col index of agent
- */
- @Deprecated
- 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.
- *
- * @deprecated
- * @param states multivariate time series
- * (1st index is time, 2nd index is variable row number,
- * 3rd is variable column number)
- */
- @Deprecated
- 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.
- *
- * @deprecated
- * @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
- */
- @Deprecated
- public void addObservations(int states[][][], int index1, int index2);
-
- /**
- * Initialise the calculator with (potentially) a new alphabet size
- *
- * TODO - I don't think so anymore... this should be done with set property
- * Deprecated, use initialise() and setProperty("ALPHABET_SIZE", "n") instead.
- * @deprecated
- * @param alphabetSize
- */
- @Deprecated
- public void initialise(int alphabetSize);
-}
diff --git a/java/source/infodynamics/measures/discrete/TransferEntropyCalculatorDiscrete.java b/java/source/infodynamics/measures/discrete/TransferEntropyCalculatorDiscrete.java
index a178b1a..93fa00e 100755
--- a/java/source/infodynamics/measures/discrete/TransferEntropyCalculatorDiscrete.java
+++ b/java/source/infodynamics/measures/discrete/TransferEntropyCalculatorDiscrete.java
@@ -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;
diff --git a/java/source/infodynamics/measures/discrete/UnivariateMeasureDiscrete.java b/java/source/infodynamics/measures/discrete/UnivariateMeasureDiscrete.java
new file mode 100644
index 0000000..6023f94
--- /dev/null
+++ b/java/source/infodynamics/measures/discrete/UnivariateMeasureDiscrete.java
@@ -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 .
+ */
+
+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.
+ *
+ * Usage is as per {@link InfoMeasureCalculatorDiscrete}, with
+ * many methods for supplying observations and making
+ * calculations defined here.
+ *
+ * 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}.
+ *
+ *
+ * @author Joseph Lizier (email ,
+ * www )
+ */
+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);
+}
diff --git a/java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscreteInContextOfPastCalculator.java b/java/source/infodynamics/measures/discrete/UnivariateMeasureDiscreteInContextOfPastCalculator.java
old mode 100755
new mode 100644
similarity index 61%
rename from java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscreteInContextOfPastCalculator.java
rename to java/source/infodynamics/measures/discrete/UnivariateMeasureDiscreteInContextOfPastCalculator.java
index d9af593..253af5d
--- a/java/source/infodynamics/measures/discrete/SingleAgentMeasureDiscreteInContextOfPastCalculator.java
+++ b/java/source/infodynamics/measures/discrete/UnivariateMeasureDiscreteInContextOfPastCalculator.java
@@ -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 .
- */
-
-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.
- *
- * This combines functionality for single agents from
- * {@link SingleAgentMeasureDiscrete} with functionality
- * required in the context of the past provided by
- * {@link ContextOfPastMeasureCalculatorDiscrete}.
- *
- * Usage is as defined in {@link InfoMeasureCalculatorDiscrete}, with
- * extra methods for supplying observations and making
- * calculations defined in {@link SingleAgentMeasureDiscrete}
.
- *
- * Users should not need to deal with this class directly;
- * it is simply used to gather common functionality for several
- * child classes.
- *
- *
- * TODO Make the Active info storage and entropy calculators inherit from this
- *
- * @author Joseph Lizier (email ,
- * www )
- */
-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 .
+ */
+
+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.
+ *
+ * This combines functionality for single agents from
+ * {@link UnivariateMeasureDiscrete} with functionality
+ * required in the context of the past provided by
+ * {@link ContextOfPastMeasureCalculatorDiscrete}.
+ *
+ * Usage is as defined in {@link InfoMeasureCalculatorDiscrete}, with
+ * extra methods for supplying observations and making
+ * calculations defined in {@link UnivariateMeasureDiscrete}
.
+ *
+ * Users should not need to deal with this class directly;
+ * it is simply used to gather common functionality for several
+ * child classes.
+ *
+ *
+ * TODO Make the Active info storage and entropy calculators inherit from this
+ *
+ * @author Joseph Lizier (email ,
+ * www )
+ */
+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'");
+ }
+}
diff --git a/java/unittests/infodynamics/measures/discrete/EntropyTester.java b/java/unittests/infodynamics/measures/discrete/EntropyTester.java
new file mode 100644
index 0000000..7767d83
--- /dev/null
+++ b/java/unittests/infodynamics/measures/discrete/EntropyTester.java
@@ -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 test1 = Arrays.asList(obs[0]);
+ List 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");
+ }
+}