mirror of https://github.com/jlizier/jidt
Updating all discrete calculators (except SeparableInfo, since it's outmoded) to have a default empty constructor, with an overloaded initialise method added that provides all relevant properties. Fixes #77, and provides a first step for #66. Also aligned PredictiveInfo and ConditionalTE calculators to use the appropriate super classes.
This commit is contained in:
parent
d545793bc5
commit
1dc2dc8b86
|
|
@ -90,6 +90,13 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
|
|||
return new ActiveInformationCalculatorDiscrete(base, history);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance with default base 2 and history 1
|
||||
*/
|
||||
public ActiveInformationCalculatorDiscrete() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance
|
||||
*
|
||||
|
|
@ -104,10 +111,14 @@ public class ActiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscr
|
|||
|
||||
@Override
|
||||
public void initialise() {
|
||||
super.initialise();
|
||||
aisComputed = false;
|
||||
initialise(base, k);
|
||||
}
|
||||
|
||||
public void initialise(int base, int history) {
|
||||
super.initialise(base, history);
|
||||
aisComputed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addObservations(int states[]) {
|
||||
int timeSteps = states.length;
|
||||
|
|
|
|||
|
|
@ -82,6 +82,13 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
|
|||
return new BlockEntropyCalculatorDiscrete(blocksize, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance with default blocksize 1 and base 2
|
||||
*/
|
||||
public BlockEntropyCalculatorDiscrete() {
|
||||
this(1, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance
|
||||
*
|
||||
|
|
@ -92,7 +99,10 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
|
|||
public BlockEntropyCalculatorDiscrete(int blocksize, int base) {
|
||||
|
||||
super(base);
|
||||
|
||||
resetBlocksize(blocksize);
|
||||
}
|
||||
|
||||
private void resetBlocksize(int blocksize) {
|
||||
this.blocksize = blocksize;
|
||||
base_power_blocksize = MathsUtils.power(base, blocksize);
|
||||
|
||||
|
|
@ -102,19 +112,7 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
|
|||
if (blocksize > Math.log(Integer.MAX_VALUE) / log_base) {
|
||||
throw new RuntimeException("Base and blocksize combination too large");
|
||||
}
|
||||
|
||||
// Create storage for counts of observations.
|
||||
// We're recreating stateCount, which was created in super()
|
||||
// however the super() didn't create it for blocksize > 1
|
||||
try {
|
||||
stateCount = new int[MathsUtils.power(base, blocksize)];
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Allow any Exceptions to be thrown, but catch and wrap
|
||||
// Error as a Runtimexception
|
||||
throw new RuntimeException("Requested memory for the base " +
|
||||
base + " and k=" + blocksize+ " is too large for the JVM at this time", e);
|
||||
}
|
||||
|
||||
|
||||
// Create constants for tracking stateValues
|
||||
maxShiftedValue = new int[base];
|
||||
for (int v = 0; v < base; v++) {
|
||||
|
|
@ -122,10 +120,35 @@ public class BlockEntropyCalculatorDiscrete extends EntropyCalculatorDiscrete {
|
|||
}
|
||||
}
|
||||
|
||||
public void initialise(int blocksize, int base) {
|
||||
boolean baseOrBlocksizeChanged = (this.blocksize != blocksize) || (this.base != base);
|
||||
|
||||
super.initialise(base);
|
||||
if (baseOrBlocksizeChanged) {
|
||||
resetBlocksize(blocksize);
|
||||
}
|
||||
|
||||
if (baseOrBlocksizeChanged || (stateCount == null)) {
|
||||
// Create storage for counts of observations.
|
||||
// We're recreating stateCount, which was created in super()
|
||||
// however the super() didn't create it for blocksize > 1
|
||||
try {
|
||||
stateCount = new int[MathsUtils.power(base, blocksize)];
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Allow any Exceptions to be thrown, but catch and wrap
|
||||
// Error as a Runtimexception
|
||||
throw new RuntimeException("Requested memory for the base " +
|
||||
base + " and k=" + blocksize+ " is too large for the JVM at this time", e);
|
||||
}
|
||||
} else {
|
||||
// Storage for sample counts exists and needs to be reset
|
||||
MatrixUtils.fill(stateCount, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
super.initialise();
|
||||
MatrixUtils.fill(stateCount, 0);
|
||||
public void initialise() {
|
||||
initialise(blocksize, base);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -72,9 +72,16 @@ public class CombinedActiveEntRateCalculatorDiscrete {
|
|||
}
|
||||
|
||||
public CombinedActiveEntRateCalculatorDiscrete() {
|
||||
super();
|
||||
// TODO Make this inherit from InfoMeasureCalculatorDiscrete
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise with the existing history and base
|
||||
*/
|
||||
public void initialise() {
|
||||
initialise(k, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise calculator, preparing to take observation sets in
|
||||
* Should be called prior to any of the addObservations() methods.
|
||||
|
|
|
|||
|
|
@ -98,6 +98,15 @@ public class ConditionalMutualInformationCalculatorDiscrete
|
|||
return new ConditionalMutualInformationCalculatorDiscrete(base1, base2, condBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance with default bases
|
||||
*/
|
||||
public ConditionalMutualInformationCalculatorDiscrete() {
|
||||
|
||||
// Create super object, just with first base defaulting to 2
|
||||
this(2, 2, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance
|
||||
*
|
||||
|
|
@ -110,39 +119,68 @@ public class ConditionalMutualInformationCalculatorDiscrete
|
|||
|
||||
// Create super object, just with first base
|
||||
super(base1);
|
||||
|
||||
changeBases(base1, base2, condBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common code to be called when bases are changed (does not update arrays though)
|
||||
*
|
||||
* @param base1
|
||||
* @param base2
|
||||
* @param condBase
|
||||
*/
|
||||
private boolean changeBases(int base1, int base2, int condBase) {
|
||||
boolean basesChanged = false;
|
||||
if ((this.base1 != base1) || (this.base2 != base2) || (this.condBase != condBase)) {
|
||||
basesChanged = true;
|
||||
}
|
||||
// Store the bases
|
||||
this.base1 = base1;
|
||||
this.base2 = base2;
|
||||
this.condBase = condBase;
|
||||
return basesChanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
initialise(base1, base2, condBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise with new bases
|
||||
*
|
||||
* @param base1
|
||||
* @param base2
|
||||
* @param condBase
|
||||
*/
|
||||
public void initialise(int base1, int base2, int condBase){
|
||||
boolean basesChanged = changeBases(base1, base2, condBase);
|
||||
super.initialise(base1);
|
||||
|
||||
// Create storage for extra counts of observations
|
||||
try {
|
||||
firstSecondCondCount = new int[base1][base2][condBase];
|
||||
firstCondCount = new int[base1][condBase];
|
||||
secondCondCount = new int[base2][condBase];
|
||||
condCount = new int[condBase];
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Allow any Exceptions to be thrown, but catch and wrap
|
||||
// Error as an Exception
|
||||
throw new RuntimeException("Requested memory for the MI bases (" +
|
||||
base1 + ", " + base2 + ", " + condBase +
|
||||
") is too large for the JVM at this time", e);
|
||||
condMiComputed = false;
|
||||
|
||||
if (basesChanged || (firstSecondCondCount == null)) {
|
||||
// Create storage for extra counts of observations
|
||||
try {
|
||||
firstSecondCondCount = new int[base1][base2][condBase];
|
||||
firstCondCount = new int[base1][condBase];
|
||||
secondCondCount = new int[base2][condBase];
|
||||
condCount = new int[condBase];
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Allow any Exceptions to be thrown, but catch and wrap
|
||||
// Error as an Exception
|
||||
throw new RuntimeException("Requested memory for the MI bases (" +
|
||||
base1 + ", " + base2 + ", " + condBase +
|
||||
") is too large for the JVM at this time", e);
|
||||
}
|
||||
} else {
|
||||
MatrixUtils.fill(firstSecondCondCount, 0);
|
||||
MatrixUtils.fill(firstCondCount, 0);
|
||||
MatrixUtils.fill(secondCondCount, 0);
|
||||
MatrixUtils.fill(condCount,0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
super.initialise();
|
||||
|
||||
condMiComputed = false;
|
||||
|
||||
MatrixUtils.fill(firstSecondCondCount, 0);
|
||||
MatrixUtils.fill(firstCondCount, 0);
|
||||
MatrixUtils.fill(secondCondCount, 0);
|
||||
MatrixUtils.fill(condCount,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add observations for the given var1,var2,cond tuples
|
||||
* of the variables
|
||||
|
|
|
|||
|
|
@ -77,12 +77,6 @@ import infodynamics.utils.RandomGenerator;
|
|||
* be incorrect.
|
||||
* </p>
|
||||
*
|
||||
* <p><i>Note for developers</i>: Ideally, this class would extend ContextOfPastMeasure, however
|
||||
* by conditioning on other info contributors, we need to alter
|
||||
* the arrays pastCount and nextPastCount to consider all
|
||||
* conditioned variables (i.e. other sources) also.
|
||||
* </p>
|
||||
*
|
||||
* TODO Add methods for passing in single time series.
|
||||
* This is done for addObservations, but not other routines.
|
||||
*
|
||||
|
|
@ -111,19 +105,17 @@ import infodynamics.utils.RandomGenerator;
|
|||
*
|
||||
*/
|
||||
public class ConditionalTransferEntropyCalculatorDiscrete
|
||||
extends InfoMeasureCalculatorDiscrete
|
||||
extends ContextOfPastMeasureCalculatorDiscrete
|
||||
implements EmpiricalNullDistributionComputer {
|
||||
|
||||
protected int k = 0; // history length k.
|
||||
protected int base_others = 0; // base of the conditional variables
|
||||
protected int base_power_k = 0;
|
||||
protected int base_power_num_others = 0;
|
||||
protected int numOtherInfoContributors = 0;
|
||||
|
||||
protected int[][][][] sourceDestPastOthersCount = null; // count for (i-j[n],i[n+1],i[n]^k,others) tuples
|
||||
protected int[][][] sourcePastOthersCount = null; // count for (i-j[n],i[n]^k,others) tuples
|
||||
protected int[][][] destPastOthersCount = null; // Count for (i[n+1], i[n]^k,others) tuples
|
||||
protected int[][] pastOthersCount = null; // Count for (i[n]^k,others)
|
||||
protected int[] maxShiftedValue = null; // states * (base^(k-1))
|
||||
|
||||
/**
|
||||
* First time step at which we can take an observation
|
||||
|
|
@ -159,6 +151,13 @@ public class ConditionalTransferEntropyCalculatorDiscrete
|
|||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with default parameters of base 2, history 1 and 1 other contributor
|
||||
*/
|
||||
public ConditionalTransferEntropyCalculatorDiscrete() {
|
||||
this(2, 1, 1, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance. This constructor allows the source and
|
||||
* destination variables to have a different base from the other contributors
|
||||
|
|
@ -177,53 +176,8 @@ public class ConditionalTransferEntropyCalculatorDiscrete
|
|||
public ConditionalTransferEntropyCalculatorDiscrete
|
||||
(int base, int history, int numOtherInfoContributors, int base_others) {
|
||||
|
||||
super(base);
|
||||
|
||||
k = history;
|
||||
this.base_others = base_others;
|
||||
this.numOtherInfoContributors = numOtherInfoContributors;
|
||||
base_power_k = MathsUtils.power(base, k);
|
||||
base_power_num_others = MathsUtils.power(base_others, numOtherInfoContributors);
|
||||
|
||||
// Relaxing this assumption so we can use this calculation as
|
||||
// a time-lagged conditional MI at will:
|
||||
//if (k < 1) {
|
||||
// throw new RuntimeException("History k " + history + " is not >= 1 a ContextOfPastMeasureCalculator");
|
||||
//}
|
||||
|
||||
// Which time step do we start taking observations from?
|
||||
// Normally this is k (to allow k previous time steps)
|
||||
// but if k==0 (becoming a lagged MI), it's 1.
|
||||
startObservationTime = Math.max(k, 1);
|
||||
|
||||
// check that we can convert the base tuple into an integer ok
|
||||
if (k > Math.log(Integer.MAX_VALUE) / log_base) {
|
||||
throw new RuntimeException("Base and history combination too large");
|
||||
}
|
||||
if (numOtherInfoContributors < 1) {
|
||||
throw new RuntimeException("Number of other info contributors < 1 for CompleteTECalculator");
|
||||
}
|
||||
|
||||
// Create storage for counts of observations
|
||||
try {
|
||||
sourceDestPastOthersCount = new int[base][base][base_power_k][base_power_num_others];
|
||||
sourcePastOthersCount = new int[base][base_power_k][base_power_num_others];
|
||||
destPastOthersCount = new int [base][base_power_k][base_power_num_others];
|
||||
pastOthersCount = new int[base_power_k][base_power_num_others];
|
||||
} 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 + ", k=" + k + " num of others " + numOtherInfoContributors +
|
||||
" with base " + base_others + ") is too large for the JVM at this time", e);
|
||||
}
|
||||
|
||||
// Create constants for tracking prevValues
|
||||
maxShiftedValue = new int[base];
|
||||
for (int v = 0; v < base; v++) {
|
||||
maxShiftedValue[v] = v * MathsUtils.power(base, k-1);
|
||||
}
|
||||
|
||||
super(base, history, true);
|
||||
updateParameters(base, history, numOtherInfoContributors, base_others);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -243,14 +197,78 @@ public class ConditionalTransferEntropyCalculatorDiscrete
|
|||
this(base, history, numOtherInfoContributors, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private method to update the parameters,
|
||||
* save for parts only concerning base and history
|
||||
* which are to be handled before this by the super
|
||||
*
|
||||
* @param base
|
||||
* @param history
|
||||
* @param numOtherInfoContributors
|
||||
* @param base_others
|
||||
*/
|
||||
private void updateParameters(int base, int history,
|
||||
int numOtherInfoContributors, int base_others) {
|
||||
|
||||
this.base_others = base_others;
|
||||
this.numOtherInfoContributors = numOtherInfoContributors;
|
||||
base_power_num_others = MathsUtils.power(base_others, numOtherInfoContributors);
|
||||
|
||||
// Which time step do we start taking observations from?
|
||||
// Normally this is k (to allow k previous time steps)
|
||||
// but if k==0 (becoming a lagged MI), it's 1.
|
||||
startObservationTime = Math.max(k, 1);
|
||||
|
||||
if (numOtherInfoContributors < 1) {
|
||||
throw new RuntimeException("Number of other info contributors < 1 for CompleteTECalculator");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise with (potentially) new parameters
|
||||
*
|
||||
* @param base
|
||||
* @param history
|
||||
* @param numOtherInfoContributors
|
||||
* @param base_others
|
||||
*/
|
||||
public void initialise(int base, int history,
|
||||
int numOtherInfoContributors, int base_others) {
|
||||
|
||||
boolean paramsChanged = (this.base != base) || (k != history) ||
|
||||
(this.numOtherInfoContributors != numOtherInfoContributors) ||
|
||||
(this.base_others != base_others);
|
||||
super.initialise(base, history);
|
||||
if (paramsChanged) {
|
||||
updateParameters(base, history, numOtherInfoContributors, base_others);
|
||||
}
|
||||
|
||||
if (paramsChanged || (sourceDestPastOthersCount == null)) {
|
||||
// Create new storage for counts of observations
|
||||
try {
|
||||
sourceDestPastOthersCount = new int[base][base][base_power_k][base_power_num_others];
|
||||
sourcePastOthersCount = new int[base][base_power_k][base_power_num_others];
|
||||
destPastOthersCount = new int [base][base_power_k][base_power_num_others];
|
||||
pastOthersCount = new int[base_power_k][base_power_num_others];
|
||||
} 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 + ", k=" + k + " num of others " + numOtherInfoContributors +
|
||||
" with base " + base_others + ") is too large for the JVM at this time", e);
|
||||
}
|
||||
} else {
|
||||
MatrixUtils.fill(sourceDestPastOthersCount, 0);
|
||||
MatrixUtils.fill(sourcePastOthersCount, 0);
|
||||
MatrixUtils.fill(destPastOthersCount, 0);
|
||||
MatrixUtils.fill(pastOthersCount, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
super.initialise();
|
||||
|
||||
MatrixUtils.fill(sourceDestPastOthersCount, 0);
|
||||
MatrixUtils.fill(sourcePastOthersCount, 0);
|
||||
MatrixUtils.fill(destPastOthersCount, 0);
|
||||
MatrixUtils.fill(pastOthersCount, 0);
|
||||
initialise(base, k, numOtherInfoContributors, base_others);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -65,6 +65,14 @@ public abstract class ContextOfPastMeasureCalculatorDiscrete extends
|
|||
*/
|
||||
protected int base_power_k = 0;
|
||||
|
||||
/**
|
||||
* Construct an instance with default base 2 and history 1
|
||||
* and not keeping sample counts
|
||||
*/
|
||||
public ContextOfPastMeasureCalculatorDiscrete() {
|
||||
this(2, 1, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance
|
||||
*
|
||||
|
|
@ -90,7 +98,18 @@ public abstract class ContextOfPastMeasureCalculatorDiscrete extends
|
|||
*/
|
||||
protected ContextOfPastMeasureCalculatorDiscrete(int base, int history, boolean dontCreateObsStorage) {
|
||||
super(base);
|
||||
resetHistory(history);
|
||||
|
||||
noObservationStorage = dontCreateObsStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called after {@link #resetBase(int)} has just been called.
|
||||
*
|
||||
* @param history
|
||||
*/
|
||||
private void resetHistory(int history) {
|
||||
|
||||
k = history;
|
||||
base_power_k = MathsUtils.power(base, k);
|
||||
|
||||
|
|
@ -108,31 +127,51 @@ public abstract class ContextOfPastMeasureCalculatorDiscrete extends
|
|||
for (int v = 0; v < base; v++) {
|
||||
maxShiftedValue[v] = v * MathsUtils.power(base, k-1);
|
||||
}
|
||||
|
||||
noObservationStorage = dontCreateObsStorage;
|
||||
if (!dontCreateObsStorage) {
|
||||
// Create storage for counts of observations
|
||||
try {
|
||||
nextPastCount = new int[base][base_power_k];
|
||||
pastCount = new int[base_power_k];
|
||||
nextCount = new int[base];
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Allow any Exceptions to be thrown, but catch and wrap
|
||||
// Error as a RuntimeException
|
||||
throw new RuntimeException("Requested memory for the base " +
|
||||
base + " and k=" + k + " is too large for the JVM at this time", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise() {
|
||||
super.initialise();
|
||||
initialise(base, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the calculator with (potentially new)
|
||||
* specified base and history
|
||||
*
|
||||
* @param base
|
||||
* @param history
|
||||
*/
|
||||
public void initialise(int base, int history) {
|
||||
boolean baseOrHistoryChanged = false;
|
||||
if ((this.base != base) || (k != history)) {
|
||||
baseOrHistoryChanged = true;
|
||||
}
|
||||
|
||||
super.initialise(base);
|
||||
if (baseOrHistoryChanged) {
|
||||
resetHistory(history);
|
||||
}
|
||||
|
||||
if (!noObservationStorage) {
|
||||
MatrixUtils.fill(nextPastCount, 0);
|
||||
MatrixUtils.fill(pastCount, 0);
|
||||
MatrixUtils.fill(nextCount, 0);
|
||||
// We manage storage for relevant sample counts here:
|
||||
if (baseOrHistoryChanged || (nextPastCount == null)) {
|
||||
// Create new storage for counts of observations
|
||||
try {
|
||||
nextPastCount = new int[base][base_power_k];
|
||||
pastCount = new int[base_power_k];
|
||||
nextCount = new int[base];
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Allow any Exceptions to be thrown, but catch and wrap
|
||||
// Error as a RuntimeException
|
||||
throw new RuntimeException("Requested memory for the base " +
|
||||
base + " and k=" + k + " is too large for the JVM at this time", e);
|
||||
}
|
||||
} else {
|
||||
// Storage for sample counts exists and needs to be reset
|
||||
MatrixUtils.fill(nextPastCount, 0);
|
||||
MatrixUtils.fill(pastCount, 0);
|
||||
MatrixUtils.fill(nextCount, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,13 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
|
|||
return new EntropyCalculatorDiscrete(base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance with default base of 2
|
||||
*/
|
||||
public EntropyCalculatorDiscrete() {
|
||||
this(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contruct a new instance
|
||||
*
|
||||
|
|
@ -90,25 +97,36 @@ public class EntropyCalculatorDiscrete extends InfoMeasureCalculatorDiscrete
|
|||
* E.g. binary variables are in base-2.
|
||||
*/
|
||||
public EntropyCalculatorDiscrete(int base) {
|
||||
|
||||
super(base);
|
||||
|
||||
// Create storage for counts of observations
|
||||
try {
|
||||
stateCount = new int[base];
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Allow any Exceptions to be thrown, but catch and wrap
|
||||
// Error as a RuntimeException
|
||||
throw new RuntimeException("Requested memory for the base (" +
|
||||
base + ") is too large for the JVM at this time", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise with new base
|
||||
*
|
||||
* @param base
|
||||
*/
|
||||
public void initialise(int base){
|
||||
boolean baseChanged = (this.base != base);
|
||||
super.initialise(base);
|
||||
|
||||
if (baseChanged || (stateCount == null)) {
|
||||
// Create storage for counts of observations
|
||||
try {
|
||||
stateCount = new int[base];
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Allow any Exceptions to be thrown, but catch and wrap
|
||||
// Error as a RuntimeException
|
||||
throw new RuntimeException("Requested memory for the base (" +
|
||||
base + ") is too large for the JVM at this time", e);
|
||||
}
|
||||
} else {
|
||||
MatrixUtils.fill(stateCount, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
super.initialise();
|
||||
MatrixUtils.fill(stateCount, 0);
|
||||
initialise(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -77,6 +77,13 @@ public class EntropyRateCalculatorDiscrete extends SingleAgentMeasureDiscreteInC
|
|||
return new EntropyRateCalculatorDiscrete(base, history);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance with default base 2 and history 1
|
||||
*/
|
||||
public EntropyRateCalculatorDiscrete() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance
|
||||
*
|
||||
|
|
|
|||
|
|
@ -97,6 +97,13 @@ public abstract class InfoMeasureCalculatorDiscrete {
|
|||
*/
|
||||
protected boolean debug = false;
|
||||
|
||||
/**
|
||||
* Construct an instance with default base of 2
|
||||
*/
|
||||
protected InfoMeasureCalculatorDiscrete() {
|
||||
this(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance
|
||||
*
|
||||
|
|
@ -104,7 +111,10 @@ public abstract class InfoMeasureCalculatorDiscrete {
|
|||
* E.g. binary variables are in base-2.
|
||||
*/
|
||||
protected InfoMeasureCalculatorDiscrete(int base) {
|
||||
|
||||
resetBase(base);
|
||||
}
|
||||
|
||||
protected void resetBase(int base) {
|
||||
this.base = base;
|
||||
log_base = Math.log(base);
|
||||
|
||||
|
|
@ -122,15 +132,26 @@ public abstract class InfoMeasureCalculatorDiscrete {
|
|||
/**
|
||||
* Initialise the calculator for re-use with new observations.
|
||||
* (Child classes should clear the existing PDFs)
|
||||
* @throws Exception
|
||||
*/
|
||||
public void initialise(){
|
||||
public void initialise() {
|
||||
initialise(base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the calculator for re-use with new observations,
|
||||
* and a new base.
|
||||
* (Child classes should clear the existing PDFs)
|
||||
*/
|
||||
public void initialise(int base){
|
||||
resetBase(base);
|
||||
average = 0.0;
|
||||
max = 0.0;
|
||||
min = 0.0;
|
||||
std = 0.0;
|
||||
observations = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the measure last calculated in a call to
|
||||
* {@link #computeAverageLocalOfObservations()}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,13 @@ public class MultiInformationCalculatorDiscrete extends InfoMeasureCalculatorDis
|
|||
private int jointStates;
|
||||
private boolean checkedFirst = false;
|
||||
|
||||
/**
|
||||
* Construct new instance with default base 2 and numVars 2
|
||||
*/
|
||||
public MultiInformationCalculatorDiscrete() {
|
||||
this(2, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance
|
||||
*
|
||||
|
|
@ -78,25 +85,55 @@ public class MultiInformationCalculatorDiscrete extends InfoMeasureCalculatorDis
|
|||
*/
|
||||
public MultiInformationCalculatorDiscrete(int base, int numVars) {
|
||||
super(base);
|
||||
this.numVars = numVars;
|
||||
jointStates = MathsUtils.power(base, numVars);
|
||||
try {
|
||||
jointCount = new int[jointStates];
|
||||
marginalCounts = new int[numVars][base];
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Allow any Exceptions to be thrown, but catch and wrap
|
||||
// Error as a RuntimeException
|
||||
throw new RuntimeException("Requested memory for the base " +
|
||||
base + " with " + numVars +
|
||||
" variables is too large for the JVM at this time", e);
|
||||
}
|
||||
changeParams(base, numVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the parameters using numVars
|
||||
*
|
||||
* @param base
|
||||
* @param numVars
|
||||
* @return
|
||||
*/
|
||||
private boolean changeParams(int base, int numVars) {
|
||||
boolean paramsChanged = (this.base != base) || (this.numVars != numVars);
|
||||
|
||||
this.numVars = numVars;
|
||||
jointStates = MathsUtils.power(base, numVars);
|
||||
return paramsChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise (possible) updating the base and number of variables
|
||||
*
|
||||
* @param base
|
||||
* @param numVars
|
||||
*/
|
||||
public void initialise(int base, int numVars) {
|
||||
boolean paramsChanged = changeParams(base, numVars);
|
||||
super.initialise(base);
|
||||
|
||||
if(paramsChanged || (jointCount == null)) {
|
||||
// Create storage for counts of observations
|
||||
try {
|
||||
jointCount = new int[jointStates];
|
||||
marginalCounts = new int[numVars][base];
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Allow any Exceptions to be thrown, but catch and wrap
|
||||
// Error as a RuntimeException
|
||||
throw new RuntimeException("Requested memory for the base " +
|
||||
base + " with " + numVars +
|
||||
" variables is too large for the JVM at this time", e);
|
||||
}
|
||||
} else {
|
||||
MatrixUtils.fill(jointCount, 0);
|
||||
MatrixUtils.fill(marginalCounts, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
super.initialise();
|
||||
MatrixUtils.fill(jointCount, 0);
|
||||
MatrixUtils.fill(marginalCounts, 0);
|
||||
initialise(base, numVars);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -79,6 +79,16 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
|
|||
|
||||
protected boolean miComputed = false;
|
||||
|
||||
/**
|
||||
* Construct a new MI calculator with default bases of 2 and time difference of 0
|
||||
* between the variables
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public MutualInformationCalculatorDiscrete() throws Exception {
|
||||
this(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new MI calculator with default time difference of 0
|
||||
* between the variables
|
||||
|
|
@ -109,35 +119,78 @@ public class MutualInformationCalculatorDiscrete extends InfoMeasureCalculatorDi
|
|||
// Create super object, just with first base
|
||||
super(base1);
|
||||
|
||||
changeBases(base1, base2, timeDiff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common code to be called when bases are changed (does not update arrays though)
|
||||
*
|
||||
* @param base1
|
||||
* @param base2
|
||||
* @param timeDiff
|
||||
* @throws Exception
|
||||
*/
|
||||
private boolean changeBases(int base1, int base2, int timeDiff) throws Exception {
|
||||
boolean basesChanged = false;
|
||||
if ((this.base1 != base1) || (this.base2 != base2)) {
|
||||
basesChanged = true;
|
||||
}
|
||||
|
||||
// Store the bases
|
||||
this.base1 = base1;
|
||||
this.base2 = base2;
|
||||
|
||||
|
||||
if (timeDiff < 0) {
|
||||
throw new Exception("timeDiff must be >= 0");
|
||||
}
|
||||
this.timeDiff = timeDiff;
|
||||
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);
|
||||
}
|
||||
|
||||
return basesChanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
super.initialise();
|
||||
miComputed = false;
|
||||
MatrixUtils.fill(iCount, 0);
|
||||
MatrixUtils.fill(jCount, 0);
|
||||
MatrixUtils.fill(jointCount, 0);
|
||||
public void initialise() {
|
||||
try {
|
||||
initialise(base1, base2, 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
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialise with new bases and time diff
|
||||
*
|
||||
* @param base1
|
||||
* @param base2
|
||||
* @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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
package infodynamics.measures.discrete;
|
||||
|
||||
import infodynamics.utils.MathsUtils;
|
||||
import infodynamics.utils.MatrixUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -63,8 +62,7 @@ import infodynamics.utils.MatrixUtils;
|
|||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>TODO Inherit from {@link SingleAgentMeasureDiscreteInContextOfPastCalculator}
|
||||
* as {@link ActiveInformationCalculatorDiscrete} does; Tidy up the Javadocs for
|
||||
* <p>TODO Tidy up the Javadocs for
|
||||
* the methods, which are somewhat preliminary</p>
|
||||
*
|
||||
* <p><b>References:</b><br/>
|
||||
|
|
@ -82,22 +80,8 @@ import infodynamics.utils.MatrixUtils;
|
|||
* @author Joseph Lizier (<a href="joseph.lizier at gmail.com">email</a>,
|
||||
* <a href="http://lizier.me/joseph/">www</a>)
|
||||
*/
|
||||
public class PredictiveInformationCalculatorDiscrete {
|
||||
public class PredictiveInformationCalculatorDiscrete extends SingleAgentMeasureDiscreteInContextOfPastCalculator {
|
||||
|
||||
private double average = 0.0;
|
||||
private double max = 0.0;
|
||||
private double min = 0.0;
|
||||
private int observations = 0;
|
||||
private int k = 0; // history/future block length k.
|
||||
private int numDiscreteValues = 0; // number of individual states.
|
||||
private int[][] jointCount = null; // Count for (x[t+1], x[t]) tuples
|
||||
private int[] prevCount = null; // Count for x[t]
|
||||
private int[] nextCount = null; // Count for x[t+1]
|
||||
private int[] maxShiftedValue = null; // states * (base^(history-1))
|
||||
|
||||
private int base_power_k = 0;
|
||||
private double log_base = 0;
|
||||
|
||||
/**
|
||||
* User was formerly forced to create new instances through this factory method.
|
||||
* Retained for backwards compatibility.
|
||||
|
|
@ -111,6 +95,13 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
return new PredictiveInformationCalculatorDiscrete(numDiscreteValues, blockLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance with default base 2 and history 1
|
||||
*/
|
||||
public PredictiveInformationCalculatorDiscrete() {
|
||||
this(2, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance
|
||||
*
|
||||
|
|
@ -120,55 +111,38 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
* this is k in Schreiber's notation.
|
||||
*/
|
||||
public PredictiveInformationCalculatorDiscrete(int numDiscreteValues, int blockLength) {
|
||||
super();
|
||||
|
||||
this.numDiscreteValues = numDiscreteValues;
|
||||
k = blockLength;
|
||||
base_power_k = MathsUtils.power(numDiscreteValues, k);
|
||||
log_base = Math.log(numDiscreteValues);
|
||||
|
||||
if (blockLength < 1) {
|
||||
throw new RuntimeException("History k " + blockLength + " is not >= 1 for Predictive information calculator");
|
||||
}
|
||||
if (k > Math.log(Integer.MAX_VALUE) / log_base) {
|
||||
throw new RuntimeException("Base and history combination too large");
|
||||
}
|
||||
|
||||
// Create storage for counts of observations
|
||||
try {
|
||||
jointCount = new int[base_power_k][base_power_k];
|
||||
prevCount = new int[base_power_k];
|
||||
nextCount = new int[base_power_k];
|
||||
} 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 " +
|
||||
numDiscreteValues + " with k=" + blockLength +
|
||||
") is too large for the JVM at this time", e);
|
||||
}
|
||||
|
||||
// Create constants for tracking prevValues and nextValues
|
||||
maxShiftedValue = new int[numDiscreteValues];
|
||||
for (int v = 0; v < numDiscreteValues; v++) {
|
||||
maxShiftedValue[v] = v * MathsUtils.power(numDiscreteValues, k-1);
|
||||
}
|
||||
super(numDiscreteValues, blockLength, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise calculator, preparing to take observation sets in
|
||||
* Should be called prior to any of the addObservations() methods.
|
||||
* You can reinitialise without needing to create a new object.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void initialise(int base, int blockLength) {
|
||||
boolean baseOrHistoryChanged = (this.base != base) || (k != blockLength);
|
||||
super.initialise(base, blockLength);
|
||||
|
||||
if (baseOrHistoryChanged || (nextPastCount == null)) {
|
||||
// Create new storage for counts of observations.
|
||||
// Need to manage this here since next is now a block variable rather than univariate in the super.
|
||||
try {
|
||||
nextPastCount = new int[base_power_k][base_power_k];
|
||||
pastCount = new int[base_power_k];
|
||||
nextCount = new int[base_power_k];
|
||||
} 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 k=" + blockLength +
|
||||
") is too large for the JVM at this time", e);
|
||||
}
|
||||
} else {
|
||||
MatrixUtils.fill(nextPastCount, 0);
|
||||
MatrixUtils.fill(pastCount, 0);
|
||||
MatrixUtils.fill(nextCount, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
average = 0.0;
|
||||
max = 0.0;
|
||||
min = 0.0;
|
||||
observations = 0;
|
||||
|
||||
MatrixUtils.fill(jointCount, 0);
|
||||
MatrixUtils.fill(prevCount, 0);
|
||||
MatrixUtils.fill(nextCount, 0);
|
||||
initialise(base, k);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -191,9 +165,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
int prevVal = 0;
|
||||
int nextVal = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += timeSeries[p];
|
||||
nextVal *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
nextVal += timeSeries[k-1+p];
|
||||
}
|
||||
|
||||
|
|
@ -201,15 +175,15 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
for (int t = k; t < timeSteps - (k-1); t++) {
|
||||
// Update the next value:
|
||||
nextVal -= maxShiftedValue[timeSeries[t-1]];
|
||||
nextVal *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
nextVal += timeSeries[k-1+t];
|
||||
// Update the counts
|
||||
jointCount[nextVal][prevVal]++;
|
||||
prevCount[prevVal]++;
|
||||
nextPastCount[nextVal][prevVal]++;
|
||||
pastCount[prevVal]++;
|
||||
nextCount[nextVal]++;
|
||||
// Update the previous value:
|
||||
prevVal -= maxShiftedValue[timeSeries[t-k]];
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += timeSeries[t];
|
||||
}
|
||||
}
|
||||
|
|
@ -239,9 +213,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
prevVal[c] = 0;
|
||||
nextVal[c] = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
prevVal[c] *= numDiscreteValues;
|
||||
prevVal[c] *= base;
|
||||
prevVal[c] += states[p][c];
|
||||
nextVal[c] *= numDiscreteValues;
|
||||
nextVal[c] *= base;
|
||||
nextVal[c] += states[k-1+p][c];
|
||||
}
|
||||
}
|
||||
|
|
@ -251,15 +225,15 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
for (int c = 0; c < columns; c++) {
|
||||
// Update the next value:
|
||||
nextVal[c] -= maxShiftedValue[states[r-1][c]];
|
||||
nextVal[c] *= numDiscreteValues;
|
||||
nextVal[c] *= base;
|
||||
nextVal[c] += states[k-1+r][c];
|
||||
// Update the counts
|
||||
jointCount[nextVal[c]][prevVal[c]]++;
|
||||
prevCount[prevVal[c]]++;
|
||||
nextPastCount[nextVal[c]][prevVal[c]]++;
|
||||
pastCount[prevVal[c]]++;
|
||||
nextCount[nextVal[c]]++;
|
||||
// Update the previous value:
|
||||
prevVal[c] -= maxShiftedValue[states[r-k][c]];
|
||||
prevVal[c] *= numDiscreteValues;
|
||||
prevVal[c] *= base;
|
||||
prevVal[c] += states[r][c];
|
||||
}
|
||||
}
|
||||
|
|
@ -296,9 +270,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
prevVal[r][c] = 0;
|
||||
nextVal[r][c] = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
prevVal[r][c] *= numDiscreteValues;
|
||||
prevVal[r][c] *= base;
|
||||
prevVal[r][c] += states[p][r][c];
|
||||
nextVal[r][c] *= numDiscreteValues;
|
||||
nextVal[r][c] *= base;
|
||||
nextVal[r][c] += states[k-1+p][r][c];
|
||||
}
|
||||
}
|
||||
|
|
@ -310,15 +284,15 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
for (int c = 0; c < agentColumns; c++) {
|
||||
// Update the next value:
|
||||
nextVal[r][c] -= maxShiftedValue[states[t-1][r][c]];
|
||||
nextVal[r][c] *= numDiscreteValues;
|
||||
nextVal[r][c] *= base;
|
||||
nextVal[r][c] += states[k-1+t][r][c];
|
||||
// Update the counts
|
||||
jointCount[nextVal[r][c]][prevVal[r][c]]++;
|
||||
prevCount[prevVal[r][c]]++;
|
||||
nextPastCount[nextVal[r][c]][prevVal[r][c]]++;
|
||||
pastCount[prevVal[r][c]]++;
|
||||
nextCount[nextVal[r][c]]++;
|
||||
// Update the previous value:
|
||||
prevVal[r][c] -= maxShiftedValue[states[t-k][r][c]];
|
||||
prevVal[r][c] *= numDiscreteValues;
|
||||
prevVal[r][c] *= base;
|
||||
prevVal[r][c] += states[t][r][c];
|
||||
}
|
||||
}
|
||||
|
|
@ -347,9 +321,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
int prevVal = 0;
|
||||
int nextVal = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += states[p][col];
|
||||
nextVal *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
nextVal += states[k-1+p][col];
|
||||
}
|
||||
|
||||
|
|
@ -357,16 +331,16 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
for (int r = k; r < rows - (k-1); r++) {
|
||||
// Update the next value:
|
||||
nextVal -= maxShiftedValue[states[r-1][col]];
|
||||
nextVal *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
nextVal += states[k-1+r][col];
|
||||
// Add to the count for this particular transition:
|
||||
// (cell's assigned as above)
|
||||
jointCount[nextVal][prevVal]++;
|
||||
prevCount[prevVal]++;
|
||||
nextPastCount[nextVal][prevVal]++;
|
||||
pastCount[prevVal]++;
|
||||
nextCount[nextVal]++;
|
||||
// Update the previous value:
|
||||
prevVal -= maxShiftedValue[states[r-k][col]];
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += states[r][col];
|
||||
}
|
||||
}
|
||||
|
|
@ -394,9 +368,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
int prevVal = 0;
|
||||
int nextVal = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += states[p][agentIndex1][agentIndex2];
|
||||
nextVal *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
nextVal += states[k-1+p][agentIndex1][agentIndex2];
|
||||
}
|
||||
|
||||
|
|
@ -404,26 +378,21 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
for (int t = k; t < timeSteps - (k-1); t++) {
|
||||
// Update the next value:
|
||||
nextVal -= maxShiftedValue[states[t-1][agentIndex1][agentIndex2]];
|
||||
nextVal *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
nextVal += states[k-1+t][agentIndex1][agentIndex2];
|
||||
// Add to the count for this particular transition:
|
||||
// (cell's assigned as above)
|
||||
jointCount[nextVal][prevVal]++;
|
||||
prevCount[prevVal]++;
|
||||
nextPastCount[nextVal][prevVal]++;
|
||||
pastCount[prevVal]++;
|
||||
nextCount[nextVal]++;
|
||||
// Update the previous value:
|
||||
prevVal -= maxShiftedValue[states[t-k][agentIndex1][agentIndex2]];
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += states[t][agentIndex1][agentIndex2];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the average predictive information from
|
||||
* the observed values which have been passed in previously.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public double computeAverageLocalOfObservations() {
|
||||
double mi = 0.0;
|
||||
double miCont = 0.0;
|
||||
|
|
@ -435,9 +404,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
double p_next = (double) nextCount[nextVal] / (double) observations;
|
||||
for (int prevVal = 0; prevVal < base_power_k; prevVal++) {
|
||||
// compute p_prev
|
||||
double p_prev = (double) prevCount[prevVal] / (double) observations;
|
||||
double p_prev = (double) pastCount[prevVal] / (double) observations;
|
||||
// compute p(prev, next)
|
||||
double p_joint = (double) jointCount[nextVal][prevVal] / (double) observations;
|
||||
double p_joint = (double) nextPastCount[nextVal][prevVal] / (double) observations;
|
||||
// Compute MI contribution:
|
||||
if (p_joint > 0.0) {
|
||||
double logTerm = p_joint / (p_next * p_prev);
|
||||
|
|
@ -469,9 +438,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
* @return
|
||||
*/
|
||||
public double computeLocalFromPreviousObservations(int next, int past){
|
||||
double logTerm = ( (double) jointCount[next][past] ) /
|
||||
double logTerm = ( (double) nextPastCount[next][past] ) /
|
||||
( (double) nextCount[next] *
|
||||
(double) prevCount[past] );
|
||||
(double) pastCount[past] );
|
||||
logTerm *= (double) observations;
|
||||
return Math.log(logTerm) / log_base;
|
||||
}
|
||||
|
|
@ -503,9 +472,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
int prevVal = 0;
|
||||
int nextVal = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += timeSeries[p];
|
||||
nextVal *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
nextVal += timeSeries[k-1+p];
|
||||
}
|
||||
|
||||
|
|
@ -513,11 +482,11 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
for (int t = k; t < timeSteps - (k-1); t++) {
|
||||
// Update the next value:
|
||||
nextVal -= maxShiftedValue[timeSeries[t-1]];
|
||||
nextVal *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
nextVal += timeSeries[k-1+t];
|
||||
logTerm = ( (double) jointCount[nextVal][prevVal] ) /
|
||||
logTerm = ( (double) nextPastCount[nextVal][prevVal] ) /
|
||||
( (double) nextCount[nextVal] *
|
||||
(double) prevCount[prevVal] );
|
||||
(double) pastCount[prevVal] );
|
||||
// Now account for the fact that we've
|
||||
// just used counts rather than probabilities,
|
||||
// and we've got two counts on the bottom
|
||||
|
|
@ -532,7 +501,7 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
}
|
||||
// Update the previous value:
|
||||
prevVal -= maxShiftedValue[timeSeries[t-k]];
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += timeSeries[t];
|
||||
}
|
||||
average = average/(double) (timeSteps - k - (k-1));
|
||||
|
|
@ -574,9 +543,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
prevVal[c] = 0;
|
||||
nextVal[c] = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
prevVal[c] *= numDiscreteValues;
|
||||
prevVal[c] *= base;
|
||||
prevVal[c] += timeSeries[p][c];
|
||||
nextVal[c] *= numDiscreteValues;
|
||||
nextVal[c] *= base;
|
||||
nextVal[c] += timeSeries[k-1+p][c];
|
||||
}
|
||||
}
|
||||
|
|
@ -585,11 +554,11 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
for (int c = 0; c < columns; c++) {
|
||||
// Update the next value:
|
||||
nextVal[c] -= maxShiftedValue[timeSeries[r-1][c]];
|
||||
nextVal[c] *= numDiscreteValues;
|
||||
nextVal[c] *= base;
|
||||
nextVal[c] += timeSeries[k-1+r][c];
|
||||
logTerm = ( (double) jointCount[nextVal[c]][prevVal[c]] ) /
|
||||
logTerm = ( (double) nextPastCount[nextVal[c]][prevVal[c]] ) /
|
||||
( (double) nextCount[nextVal[c]] *
|
||||
(double) prevCount[prevVal[c]] );
|
||||
(double) pastCount[prevVal[c]] );
|
||||
// Now account for the fact that we've
|
||||
// just used counts rather than probabilities,
|
||||
// and we've got two counts on the bottom
|
||||
|
|
@ -604,7 +573,7 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
}
|
||||
// Update the previous value:
|
||||
prevVal[c] -= maxShiftedValue[timeSeries[r-k][c]];
|
||||
prevVal[c] *= numDiscreteValues;
|
||||
prevVal[c] *= base;
|
||||
prevVal[c] += timeSeries[r][c];
|
||||
}
|
||||
}
|
||||
|
|
@ -649,9 +618,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
prevVal[r][c] = 0;
|
||||
nextVal[r][c] = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
prevVal[r][c] *= numDiscreteValues;
|
||||
prevVal[r][c] *= base;
|
||||
prevVal[r][c] += timeSeries[p][r][c];
|
||||
nextVal[r][c] *= numDiscreteValues;
|
||||
nextVal[r][c] *= base;
|
||||
nextVal[r][c] += timeSeries[k-1+p][r][c];
|
||||
}
|
||||
}
|
||||
|
|
@ -662,11 +631,11 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
for (int c = 0; c < agentColumns; c++) {
|
||||
// Update the next value:
|
||||
nextVal[r][c] -= maxShiftedValue[timeSeries[t-1][r][c]];
|
||||
nextVal[r][c] *= numDiscreteValues;
|
||||
nextVal[r][c] *= base;
|
||||
nextVal[r][c] += timeSeries[k-1+t][r][c];
|
||||
logTerm = ( (double) jointCount[nextVal[r][c]][prevVal[r][c]] ) /
|
||||
logTerm = ( (double) nextPastCount[nextVal[r][c]][prevVal[r][c]] ) /
|
||||
( (double) nextCount[nextVal[r][c]] *
|
||||
(double) prevCount[prevVal[r][c]] );
|
||||
(double) pastCount[prevVal[r][c]] );
|
||||
// Now account for the fact that we've
|
||||
// just used counts rather than probabilities,
|
||||
// and we've got two counts on the bottom
|
||||
|
|
@ -681,7 +650,7 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
}
|
||||
// Update the previous value:
|
||||
prevVal[r][c] -= maxShiftedValue[timeSeries[t-k][r][c]];
|
||||
prevVal[r][c] *= numDiscreteValues;
|
||||
prevVal[r][c] *= base;
|
||||
prevVal[r][c] += timeSeries[t][r][c];
|
||||
}
|
||||
}
|
||||
|
|
@ -721,20 +690,20 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
int prevVal = 0;
|
||||
int nextVal = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += states[p][col];
|
||||
nextVal *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
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 *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
nextVal += states[k-1+r][col];
|
||||
logTerm = ( (double) jointCount[nextVal][prevVal] ) /
|
||||
logTerm = ( (double) nextPastCount[nextVal][prevVal] ) /
|
||||
( (double) nextCount[nextVal] *
|
||||
(double) prevCount[prevVal] );
|
||||
(double) pastCount[prevVal] );
|
||||
// Now account for the fact that we've
|
||||
// just used counts rather than probabilities,
|
||||
// and we've got two counts on the bottom
|
||||
|
|
@ -749,7 +718,7 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
}
|
||||
// Update the previous value:
|
||||
prevVal -= maxShiftedValue[states[r-k][col]];
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += states[r][col];
|
||||
}
|
||||
average = average/(double) (rows - k - (k-1));
|
||||
|
|
@ -789,20 +758,20 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
int prevVal = 0;
|
||||
int nextVal = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += timeSeries[p][agentIndex1][agentIndex2];
|
||||
nextVal *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
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 *= numDiscreteValues;
|
||||
nextVal *= base;
|
||||
nextVal += timeSeries[k-1+t][agentIndex1][agentIndex2];
|
||||
logTerm = ( (double) jointCount[nextVal][prevVal] ) /
|
||||
logTerm = ( (double) nextPastCount[nextVal][prevVal] ) /
|
||||
( (double) nextCount[nextVal] *
|
||||
(double) prevCount[prevVal] );
|
||||
(double) pastCount[prevVal] );
|
||||
// Now account for the fact that we've
|
||||
// just used counts rather than probabilities,
|
||||
// and we've got two counts on the bottom
|
||||
|
|
@ -817,7 +786,7 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
}
|
||||
// Update the previous value:
|
||||
prevVal -= maxShiftedValue[timeSeries[t-k][agentIndex1][agentIndex2]];
|
||||
prevVal *= numDiscreteValues;
|
||||
prevVal *= base;
|
||||
prevVal += timeSeries[t][agentIndex1][agentIndex2];
|
||||
}
|
||||
average = average/(double) (timeSteps - k - (k-1));
|
||||
|
|
@ -826,215 +795,6 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute local predictive information from a time series.
|
||||
* Return an array of local values.
|
||||
* First k and last k-1 rows are zeros.
|
||||
*
|
||||
* @param timeSeries time series array of states
|
||||
* @return time series of local predictive information values
|
||||
*/
|
||||
public double[] computeLocal(int timeSeries[]) {
|
||||
|
||||
initialise();
|
||||
addObservations(timeSeries);
|
||||
return computeLocalFromPreviousObservations(timeSeries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute local predictive information across a 2D spatiotemporal
|
||||
* time series of the observations of homogeneous agents.
|
||||
* This method to be called for homogeneous agents only, as all
|
||||
* observations are pooled together.
|
||||
* First k and last k-1 rows are zeros.
|
||||
*
|
||||
* @param timeSeries 2D array of states (first index is time, second is variable id)
|
||||
* @return multivariate time series of local predictive information values
|
||||
* (1st index is time, second is variable id)
|
||||
*/
|
||||
public double[][] computeLocal(int timeSeries[][]) {
|
||||
|
||||
initialise();
|
||||
addObservations(timeSeries);
|
||||
return computeLocalFromPreviousObservations(timeSeries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute local predictive information across a 3D spatiotemporal
|
||||
* array of the states of homogeneous agents
|
||||
* This method to be called for homogeneous agents only, as all
|
||||
* observations are pooled together.
|
||||
* First k and last k-1 rows are zeros.
|
||||
*
|
||||
* @param timeSeries 2D array of states (first index is time, second
|
||||
* and third are variable ids)
|
||||
* @return multivariate time series of local predictive information values
|
||||
* (1st index is time, second and third are variable ids)
|
||||
*/
|
||||
public double[][][] computeLocal(int timeSeries[][][]) {
|
||||
|
||||
initialise();
|
||||
addObservations(timeSeries);
|
||||
return computeLocalFromPreviousObservations(timeSeries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute average predictive information across a
|
||||
* time series.
|
||||
*
|
||||
* @param timeSeries time series array of states
|
||||
* @return average predictive information values
|
||||
*/
|
||||
public double computeAverageLocal(int timeSeries[]) {
|
||||
|
||||
initialise();
|
||||
addObservations(timeSeries);
|
||||
return computeAverageLocalOfObservations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute average predictive information across a 2D spatiotemporal
|
||||
* array of the states of homogeneous agents.
|
||||
* This method to be called for homogeneous agents only, as all
|
||||
* observations are pooled together.
|
||||
*
|
||||
* @param timeSeries 2D array of states (first index is time, second is variable id)
|
||||
* @return average predictive information value
|
||||
*/
|
||||
public double computeAverageLocal(int timeSeries[][]) {
|
||||
|
||||
initialise();
|
||||
addObservations(timeSeries);
|
||||
return computeAverageLocalOfObservations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute average predictive information across a 3D spatiotemporal
|
||||
* array of the states of homogeneous agents
|
||||
* This method to be called for homogeneous agents only, as all
|
||||
* observations are pooled together.
|
||||
*
|
||||
* @param timeSeries 2D array of states (first index is time, second
|
||||
* and third are variable ids)
|
||||
* @return average predictive information value
|
||||
*/
|
||||
public double computeAverageLocal(int timeSeries[][][]) {
|
||||
|
||||
initialise();
|
||||
addObservations(timeSeries);
|
||||
return computeAverageLocalOfObservations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute local predictive information for one agent in a 2D spatiotemporal
|
||||
* array of the states of agents
|
||||
* First k and last k-1 rows are zeros.
|
||||
*
|
||||
* This method should be used for heterogeneous agents.
|
||||
*
|
||||
* @param timeSeries 2D array of states (first index is time, second is variable id)
|
||||
* @param col index of the agent whose local values should be calculated
|
||||
* @return time series of local predictive information values for the given agent id
|
||||
*/
|
||||
public double[] computeLocal(int timeSeries[][], int col) {
|
||||
|
||||
initialise();
|
||||
addObservations(timeSeries, col);
|
||||
return computeLocalFromPreviousObservations(timeSeries, col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute local predictive information for one agent in a 3D spatiotemporal
|
||||
* array of the states of agents
|
||||
* First k and last k-1 rows are zeros.
|
||||
* This method should be used for heterogeneous agents.
|
||||
*
|
||||
* @param timeSeries 3D array of states (first index is time, second
|
||||
* and third are variable id)
|
||||
* @param agentIndex1 row index of agent
|
||||
* @param agentIndex2 column index of agent
|
||||
* @return time series of local predictive information values for the given agent id
|
||||
*/
|
||||
public double[] computeLocal(int timeSeries[][][], int agentIndex1, int agentIndex2) {
|
||||
|
||||
initialise();
|
||||
addObservations(timeSeries, agentIndex1, agentIndex2);
|
||||
return computeLocalFromPreviousObservations(timeSeries, agentIndex1, agentIndex2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute average local predictive information
|
||||
* for a single agent in a 2D spatiotemporal time series.
|
||||
* This method suitable for heterogeneous agents, since the agent
|
||||
* to be investigated is named.
|
||||
*
|
||||
* @param timeSeries 2D array of states (first index is time, second is variable id)
|
||||
* @param col index of the agent whose local values should be calculated
|
||||
* @return average predictive info for the given agent id
|
||||
*/
|
||||
public double computeAverageLocal(int timeSeries[][], int col) {
|
||||
|
||||
initialise();
|
||||
addObservations(timeSeries, col);
|
||||
return computeAverageLocalOfObservations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone routine to
|
||||
* compute average local active information storage
|
||||
* for a single agent in a 3D spatiotemporal time series.
|
||||
* This method suitable for heterogeneous agents, since the agent
|
||||
* to be investigated is named.
|
||||
*
|
||||
* @param timeSeries 3D array of states (first index is time, second
|
||||
* and third are variable id)
|
||||
* @param agentIndex1 row index of agent
|
||||
* @param agentIndex2 column index of agent
|
||||
* @return average predictive info for the given agent id
|
||||
*/
|
||||
public double computeAverageLocal(int timeSeries[][][], int agentIndex1, int agentIndex2) {
|
||||
|
||||
initialise();
|
||||
addObservations(timeSeries, agentIndex1, agentIndex2);
|
||||
return computeAverageLocalOfObservations();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the last predictive information computed since the
|
||||
* previous {@link #initialise()} call.
|
||||
*/
|
||||
public double getLastAverage() {
|
||||
return average;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the last maximum local predictive information computed since the
|
||||
* previous {@link #initialise()} call.
|
||||
*/
|
||||
public double getLastMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the last minimum local predictive information computed since the
|
||||
* previous {@link #initialise()} call.
|
||||
*/
|
||||
public double getLastMin() {
|
||||
return min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the current probability distribution functions
|
||||
*
|
||||
|
|
@ -1050,9 +810,9 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
double p_next = (double) nextCount[nextVal] / (double) observations;
|
||||
for (int prevVal = 0; prevVal < base_power_k; prevVal++) {
|
||||
// compute p_prev
|
||||
double p_prev = (double) prevCount[prevVal] / (double) observations;
|
||||
double p_prev = (double) pastCount[prevVal] / (double) observations;
|
||||
// compute p(prev, next)
|
||||
double p_joint = (double) jointCount[nextVal][prevVal] / (double) observations;
|
||||
double p_joint = (double) nextPastCount[nextVal][prevVal] / (double) observations;
|
||||
// Compute MI contribution:
|
||||
if (p_joint > 0.0) {
|
||||
double logTerm = p_joint / (p_next * p_prev);
|
||||
|
|
@ -1084,7 +844,7 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
public int computePastValue(int[] x, int t) {
|
||||
int pastVal = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
pastVal *= numDiscreteValues;
|
||||
pastVal *= base;
|
||||
pastVal += x[t - k + 1 + p];
|
||||
}
|
||||
return pastVal;
|
||||
|
|
@ -1103,7 +863,7 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
public int computePastValue(int[][] x, int i, int t) {
|
||||
int pastVal = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
pastVal *= numDiscreteValues;
|
||||
pastVal *= base;
|
||||
pastVal += x[t - k + 1 + p][i];
|
||||
}
|
||||
return pastVal;
|
||||
|
|
@ -1123,7 +883,7 @@ public class PredictiveInformationCalculatorDiscrete {
|
|||
public int computePastValue(int[][][] x, int i, int j, int t) {
|
||||
int pastVal = 0;
|
||||
for (int p = 0; p < k; p++) {
|
||||
pastVal *= numDiscreteValues;
|
||||
pastVal *= base;
|
||||
pastVal += x[t - k + 1 + p][i][j];
|
||||
}
|
||||
return pastVal;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,13 @@ package infodynamics.measures.discrete;
|
|||
*/
|
||||
public interface SingleAgentMeasureDiscrete {
|
||||
|
||||
/**
|
||||
* Initialise the calculator with (potentially) a new base
|
||||
*
|
||||
* @param base
|
||||
*/
|
||||
public void initialise(int base);
|
||||
|
||||
/**
|
||||
* Add observations in to our estimates of the pdfs.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -46,6 +46,13 @@ package infodynamics.measures.discrete;
|
|||
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
|
||||
*
|
||||
|
|
@ -57,6 +64,20 @@ public abstract class SingleAgentMeasureDiscreteInContextOfPastCalculator extend
|
|||
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();
|
||||
|
|
|
|||
|
|
@ -173,6 +173,15 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
|
|||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TE calculator with all parameters as default
|
||||
* (base 2 and all embedding/delay parameters 1)
|
||||
*
|
||||
*/
|
||||
public TransferEntropyCalculatorDiscrete() {
|
||||
this(2, 1, 1, 1, 1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TE calculator for the given base and destination history embedding length
|
||||
* (leave the other embedding parameters as default)
|
||||
|
|
@ -223,6 +232,25 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
|
|||
int sourceHistoryEmbeddingLength, int sourceEmbeddingDelay, int delay) {
|
||||
|
||||
super(base, destHistoryEmbedLength);
|
||||
updateParameters(base, destHistoryEmbedLength, destEmbeddingDelay,
|
||||
sourceHistoryEmbeddingLength, sourceEmbeddingDelay, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private method to update the estimators parameters,
|
||||
* save for parts only concerning base and destHistoryEmbedLength
|
||||
* which are to be handled before this by the super
|
||||
*
|
||||
* @param base
|
||||
* @param destHistoryEmbedLength
|
||||
* @param destEmbeddingDelay
|
||||
* @param sourceHistoryEmbeddingLength
|
||||
* @param sourceEmbeddingDelay
|
||||
* @param delay
|
||||
*/
|
||||
private void updateParameters(int base, int destHistoryEmbedLength, int destEmbeddingDelay,
|
||||
int sourceHistoryEmbeddingLength, int sourceEmbeddingDelay, int delay) {
|
||||
|
||||
this.destEmbeddingDelay = destEmbeddingDelay;
|
||||
if (sourceHistoryEmbeddingLength <= 0) {
|
||||
throw new RuntimeException("Cannot have source embedding length of zero or less");
|
||||
|
|
@ -243,18 +271,6 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
|
|||
maxShiftedSourceValue[v] = v * MathsUtils.power(base, sourceHistoryEmbedLength-1);
|
||||
}
|
||||
|
||||
// Create storage for extra counts of observations
|
||||
try {
|
||||
sourceNextPastCount = new int[base_power_l][base][base_power_k];
|
||||
sourcePastCount = new int[base_power_l][base_power_k];
|
||||
} 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 + ", k=" + k + ", l=" + sourceHistoryEmbedLength +
|
||||
" is too large for the JVM at this time", e);
|
||||
}
|
||||
|
||||
// Which time step do we start taking observations from?
|
||||
// These two integers represent the earliest next time step, in the cases where the destination
|
||||
// embedding itself determines where we can start taking observations, or
|
||||
|
|
@ -263,16 +279,53 @@ public class TransferEntropyCalculatorDiscrete extends ContextOfPastMeasureCalcu
|
|||
int startTimeBasedOnDestPast = (k-1)*destEmbeddingDelay + 1;
|
||||
int startTimeBasedOnSourcePast = (sourceHistoryEmbedLength-1)*sourceEmbeddingDelay + delay;
|
||||
startObservationTime = Math.max(startTimeBasedOnDestPast, startTimeBasedOnSourcePast);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialise with (potentially) new parameters
|
||||
*
|
||||
* @param base
|
||||
* @param destHistoryEmbedLength
|
||||
* @param destEmbeddingDelay
|
||||
* @param sourceHistoryEmbeddingLength
|
||||
* @param sourceEmbeddingDelay
|
||||
* @param delay
|
||||
*/
|
||||
public void initialise(int base, int destHistoryEmbedLength, int destEmbeddingDelay,
|
||||
int sourceHistoryEmbeddingLength, int sourceEmbeddingDelay, int delay) {
|
||||
|
||||
boolean paramsChanged = (this.base != base) || (k != destHistoryEmbedLength) ||
|
||||
(this.destEmbeddingDelay != destEmbeddingDelay) || (this.sourceHistoryEmbedLength != sourceHistoryEmbeddingLength) ||
|
||||
(this.sourceEmbeddingDelay != sourceEmbeddingDelay) || (this.delay != delay);
|
||||
super.initialise(base, destHistoryEmbedLength);
|
||||
if (paramsChanged) {
|
||||
updateParameters(base, destHistoryEmbedLength, destEmbeddingDelay,
|
||||
sourceHistoryEmbeddingLength, sourceEmbeddingDelay, delay);
|
||||
}
|
||||
|
||||
if (paramsChanged || (sourceNextPastCount == null)) {
|
||||
// Create new storage for extra counts of observations
|
||||
try {
|
||||
sourceNextPastCount = new int[base_power_l][base][base_power_k];
|
||||
sourcePastCount = new int[base_power_l][base_power_k];
|
||||
} 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 + ", k=" + k + ", l=" + sourceHistoryEmbedLength +
|
||||
" is too large for the JVM at this time", e);
|
||||
}
|
||||
} else {
|
||||
MatrixUtils.fill(sourceNextPastCount, 0);
|
||||
MatrixUtils.fill(sourcePastCount, 0);
|
||||
}
|
||||
estimateComputed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
super.initialise();
|
||||
estimateComputed = false;
|
||||
|
||||
MatrixUtils.fill(sourceNextPastCount, 0);
|
||||
MatrixUtils.fill(sourcePastCount, 0);
|
||||
initialise(base, k, destEmbeddingDelay, sourceHistoryEmbedLength,
|
||||
sourceEmbeddingDelay, delay);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue