mirror of https://github.com/jlizier/jidt
Added Gaussian implementation of various multivariate IT measures and unit tests.
This commit is contained in:
parent
403745800e
commit
f67e274819
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Java Information Dynamics Toolkit (JIDT)
|
||||
* Copyright (C) 2017, Joseph T. Lizier, Ipek Oezdemir and Pedro Mediano
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package infodynamics.measures.continuous.gaussian;
|
||||
|
||||
import infodynamics.utils.MatrixUtils;
|
||||
|
||||
/**
|
||||
* <p>Computes the differential dual total correlation (DTC) of a given multivariate
|
||||
* <code>double[][]</code> set of
|
||||
* observations (extending {@link MultiVariateInfoMeasureCalculatorGaussian}),
|
||||
* assuming that the probability distribution function for these observations is
|
||||
* a multivariate Gaussian distribution.</p>
|
||||
*
|
||||
* <p>Usage is as per the paradigm outlined for {@link MultiVariateInfoMeasureCalculatorCommon}.
|
||||
* </p>
|
||||
*
|
||||
* <p><b>References:</b><br/>
|
||||
* <ul>
|
||||
* <li>Rosas, F., Mediano, P., Gastpar, M, Jensen, H.,
|
||||
* <a href="http://dx.doi.org/10.1103/PhysRevE.100.032305">"Quantifying high-order
|
||||
* interdependencies via multivariate extensions of the mutual information"</a>,
|
||||
* Physical Review E 100, (2019) 032305.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Pedro A.M. Mediano (<a href="pmediano at pm.me">email</a>,
|
||||
* <a href="http://www.doc.ic.ac.uk/~pam213">www</a>)
|
||||
*/
|
||||
public class DualTotalCorrelationCalculatorGaussian
|
||||
extends MultiVariateInfoMeasureCalculatorGaussian {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public DualTotalCorrelationCalculatorGaussian() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return the average DTC in nats (not bits!)
|
||||
* @throws Exception if not sufficient data have been provided, or if the
|
||||
* supplied covariance matrix is invalid.
|
||||
*/
|
||||
public double computeAverageLocalOfObservations() throws Exception {
|
||||
|
||||
if (covariance == null) {
|
||||
throw new Exception("Cannot calculate DTC without having " +
|
||||
"a covariance either supplied or computed via setObservations()");
|
||||
}
|
||||
|
||||
if (!isComputed) {
|
||||
double dtc = - (dimensions - 1)*Math.log(MatrixUtils.determinantSymmPosDefMatrix(covariance));
|
||||
for (int i = 0; i < dimensions; i++) {
|
||||
int[] idx = allExcept(i, dimensions);
|
||||
double[][] marginal_cov = MatrixUtils.selectRowsAndColumns(covariance, idx, idx);
|
||||
dtc += Math.log(MatrixUtils.determinantSymmPosDefMatrix(marginal_cov));
|
||||
}
|
||||
// This "0.5" comes from the entropy formula for Gaussians: h = 0.5*logdet(2*pi*e*Sigma)
|
||||
lastAverage = 0.5*dtc;;
|
||||
isComputed = true;
|
||||
}
|
||||
|
||||
return lastAverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return the "time-series" of local DTC values in nats (not bits!)
|
||||
* for the supplied states.
|
||||
* @throws Exception if not sufficient data have been provided, or if the
|
||||
* supplied covariance matrix is invalid.
|
||||
*/
|
||||
public double[] computeLocalUsingPreviousObservations(double[][] states) throws Exception {
|
||||
|
||||
if ((means == null) || (covariance == null)) {
|
||||
throw new Exception("Cannot compute local values without having means " +
|
||||
"and covariance either supplied or computed via setObservations()");
|
||||
}
|
||||
|
||||
EntropyCalculatorMultiVariateGaussian hCalc = new EntropyCalculatorMultiVariateGaussian();
|
||||
hCalc.initialise(dimensions);
|
||||
hCalc.setCovarianceAndMeans(covariance, means);
|
||||
double[] localValues = MatrixUtils.multiply(hCalc.computeLocalUsingPreviousObservations(states), -(dimensions - 1));
|
||||
|
||||
for (int i = 0; i < dimensions; i++) {
|
||||
int[] idx = allExcept(i, dimensions);
|
||||
double[][] marginal_cov = MatrixUtils.selectRowsAndColumns(covariance, idx, idx);
|
||||
double[] marginal_means = MatrixUtils.select(means, idx);
|
||||
double[][] marginal_state = MatrixUtils.selectColumns(states, idx);
|
||||
|
||||
hCalc.initialise(dimensions - 1);
|
||||
hCalc.setCovarianceAndMeans(marginal_cov, marginal_means);
|
||||
double[] thisLocals = hCalc.computeLocalUsingPreviousObservations(marginal_state);
|
||||
|
||||
localValues = MatrixUtils.add(localValues, thisLocals);
|
||||
|
||||
}
|
||||
|
||||
return localValues;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Java Information Dynamics Toolkit (JIDT)
|
||||
* Copyright (C) 2017, Joseph T. Lizier, Ipek Oezdemir and Pedro Mediano
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package infodynamics.measures.continuous.gaussian;
|
||||
|
||||
import infodynamics.measures.continuous.MultiVariateInfoMeasureCalculatorCommon;
|
||||
import infodynamics.utils.MatrixUtils;
|
||||
|
||||
/**
|
||||
* <p>Base class with common functionality for child class implementations of
|
||||
* multivariate information measures on a given multivariate
|
||||
* <code>double[][]</code> set of
|
||||
* observations (extending {@link MultiVariateInfoMeasureCalculatorCommon}),
|
||||
* assuming that the probability distribution function for these observations is
|
||||
* a multivariate Gaussian distribution.</p>
|
||||
*
|
||||
* <p>Usage is as per the paradigm outlined for {@link MultiVariateInfoMeasureCalculatorCommon},
|
||||
* with:
|
||||
* <ul>
|
||||
* <li>For constructors see the child classes.</li>
|
||||
* <li>Further properties are defined in {@link #setProperty(String, String)}.</li>
|
||||
* <li>Computed values are in <b>nats</b>, not bits!</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* <p><b>References:</b><br/>
|
||||
* <ul>
|
||||
* <li>Rosas, F., Mediano, P., Gastpar, M, Jensen, H.,
|
||||
* <a href="http://dx.doi.org/10.1103/PhysRevE.100.032305">"Quantifying high-order
|
||||
* interdependencies via multivariate extensions of the mutual information"</a>,
|
||||
* Physical Review E 100, (2019) 032305.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Pedro A.M. Mediano (<a href="pmediano at pm.me">email</a>,
|
||||
* <a href="http://www.doc.ic.ac.uk/~pam213">www</a>)
|
||||
*/
|
||||
public abstract class MultiVariateInfoMeasureCalculatorGaussian
|
||||
extends MultiVariateInfoMeasureCalculatorCommon {
|
||||
|
||||
/**
|
||||
* Covariance of the system. Can be calculated from supplied observations
|
||||
* or supplied directly by the user.
|
||||
*/
|
||||
double[][] covariance = null;
|
||||
|
||||
/**
|
||||
* Means of the system. Can be calculated from supplied observations
|
||||
* or supplied directly by the user.
|
||||
*/
|
||||
double[] means = null;
|
||||
|
||||
/**
|
||||
* Whether the current covariance matrix has been determined from data or
|
||||
* supplied directly. This changes the approach to local measures and
|
||||
* significance testing.
|
||||
*/
|
||||
boolean covFromObservations;
|
||||
|
||||
@Override
|
||||
public void finaliseAddObservations() throws Exception {
|
||||
super.finaliseAddObservations();
|
||||
|
||||
this.means = MatrixUtils.means(observations);
|
||||
setCovariance(MatrixUtils.covarianceMatrix(observations), true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set the covariance of the distribution for which we will compute the
|
||||
* measure directly, without supplying observations.</p>
|
||||
*
|
||||
* <p>See {@link #setCovariance(double[][], boolean)}.
|
||||
*
|
||||
* @param covariance covariance matrix of the system
|
||||
* @throws Exception for covariance matrix not matching the expected dimensions,
|
||||
* being non-square, asymmetric or non-positive definite
|
||||
*/
|
||||
public void setCovariance(double[][] covariance) throws Exception {
|
||||
setCovariance(covariance, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set the covariance of the distribution for which we will compute the
|
||||
* measure.</p>
|
||||
*
|
||||
* <p>This is an alternative to sequences of calls to {@link #setObservations(double[][])} or
|
||||
* {@link #addObservations(double[][])} etc.
|
||||
* Note that without setting any observations, you cannot later
|
||||
* call {@link #computeLocalOfPreviousObservations()}.</p>
|
||||
*
|
||||
* @param covariance covariance matrix of the system
|
||||
* @param means mean of the system
|
||||
*/
|
||||
public void setCovarianceAndMeans(double[][] covariance, double[] means)
|
||||
throws Exception {
|
||||
this.means = means;
|
||||
setCovariance(covariance, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set the covariance of the distribution for which we will compute the
|
||||
* measure.</p>
|
||||
*
|
||||
* <p>This is an alternative to sequences of calls to {@link #setObservations(double[][])} or
|
||||
* {@link #addObservations(double[][])} etc.
|
||||
* Note that without setting any observations, you cannot later
|
||||
* call {@link #computeLocalOfPreviousObservations()}, and without
|
||||
* providing the means of the variables, you cannot later call
|
||||
* {@link #computeLocalUsingPreviousObservations(double[][])}.</p>
|
||||
*
|
||||
* @param covariance covariance matrix of the system
|
||||
* @param covFromObservations whether the covariance matrix
|
||||
* was determined internally from observations or not
|
||||
* @throws Exception for covariance matrix not matching the expected dimensions,
|
||||
* being non-square, asymmetric or non-positive definite
|
||||
*/
|
||||
public void setCovariance(double[][] cov, boolean covFromObservations) throws Exception {
|
||||
|
||||
if (!covFromObservations) {
|
||||
// Make sure we're not keeping any observations
|
||||
observations = null;
|
||||
}
|
||||
if (cov.length != dimensions) {
|
||||
throw new Exception("Supplied covariance matrix does not match initialised number of dimensions");
|
||||
}
|
||||
if (cov.length != cov[0].length) {
|
||||
throw new Exception("Covariance matrices must be square");
|
||||
}
|
||||
|
||||
this.covFromObservations = covFromObservations;
|
||||
this.covariance = cov;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Java Information Dynamics Toolkit (JIDT)
|
||||
* Copyright (C) 2017, Joseph T. Lizier, Ipek Oezdemir and Pedro Mediano
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package infodynamics.measures.continuous.gaussian;
|
||||
|
||||
import infodynamics.utils.MatrixUtils;
|
||||
|
||||
/**
|
||||
* <p>Computes the differential O-information of a given multivariate
|
||||
* <code>double[][]</code> set of
|
||||
* observations (extending {@link MultiVariateInfoMeasureCalculatorGaussian}),
|
||||
* assuming that the probability distribution function for these observations is
|
||||
* a multivariate Gaussian distribution.</p>
|
||||
*
|
||||
* <p>Usage is as per the paradigm outlined for {@link MultiVariateInfoMeasureCalculatorCommon}.
|
||||
* </p>
|
||||
*
|
||||
* <p><b>References:</b><br/>
|
||||
* <ul>
|
||||
* <li>Rosas, F., Mediano, P., Gastpar, M, Jensen, H.,
|
||||
* <a href="http://dx.doi.org/10.1103/PhysRevE.100.032305">"Quantifying high-order
|
||||
* interdependencies via multivariate extensions of the mutual information"</a>,
|
||||
* Physical Review E 100, (2019) 032305.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Pedro A.M. Mediano (<a href="pmediano at pm.me">email</a>,
|
||||
* <a href="http://www.doc.ic.ac.uk/~pam213">www</a>)
|
||||
*/
|
||||
public class OInfoCalculatorGaussian
|
||||
extends MultiVariateInfoMeasureCalculatorGaussian {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public OInfoCalculatorGaussian() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return the average O-info in nats (not bits!)
|
||||
* @throws Exception if not sufficient data have been provided, or if the
|
||||
* supplied covariance matrix is invalid.
|
||||
*/
|
||||
public double computeAverageLocalOfObservations() throws Exception {
|
||||
|
||||
if (covariance == null) {
|
||||
throw new Exception("Cannot calculate O-Info without having " +
|
||||
"a covariance either supplied or computed via setObservations()");
|
||||
}
|
||||
|
||||
if (!isComputed) {
|
||||
double oinfo = (dimensions - 2)*Math.log(MatrixUtils.determinantSymmPosDefMatrix(covariance));
|
||||
for (int i = 0; i < dimensions; i++) {
|
||||
int[] idx = allExcept(i, dimensions);
|
||||
double[][] marginal_cov = MatrixUtils.selectRowsAndColumns(covariance, idx, idx);
|
||||
oinfo += Math.log(covariance[i][i]) - Math.log(MatrixUtils.determinantSymmPosDefMatrix(marginal_cov));
|
||||
}
|
||||
// This "0.5" comes from the entropy formula for Gaussians: h = 0.5*logdet(2*pi*e*Sigma)
|
||||
lastAverage = 0.5*oinfo;;
|
||||
isComputed = true;
|
||||
}
|
||||
|
||||
return lastAverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return the "time-series" of local O-info values in nats (not bits!)
|
||||
* for the supplied states.
|
||||
* @throws Exception if not sufficient data have been provided, or if the
|
||||
* supplied covariance matrix is invalid.
|
||||
*/
|
||||
public double[] computeLocalUsingPreviousObservations(double[][] states) throws Exception {
|
||||
|
||||
if ((means == null) || (covariance == null)) {
|
||||
throw new Exception("Cannot compute local values without having means " +
|
||||
"and covariance either supplied or computed via setObservations()");
|
||||
}
|
||||
|
||||
EntropyCalculatorMultiVariateGaussian hCalc = new EntropyCalculatorMultiVariateGaussian();
|
||||
hCalc.initialise(dimensions);
|
||||
hCalc.setCovarianceAndMeans(covariance, means);
|
||||
double[] localValues = MatrixUtils.multiply(hCalc.computeLocalUsingPreviousObservations(states), dimensions - 2);
|
||||
|
||||
for (int i = 0; i < dimensions; i++) {
|
||||
int[] idx = allExcept(i, dimensions);
|
||||
|
||||
// Local entropy of this variable (i) only
|
||||
double[][] this_cov = MatrixUtils.selectRowsAndColumns(covariance, i, 1, i, 1);
|
||||
double[] this_means = MatrixUtils.select(means, i, 1);
|
||||
double[][] this_state = MatrixUtils.selectColumns(states, i, 1);
|
||||
|
||||
hCalc.initialise(1);
|
||||
hCalc.setCovarianceAndMeans(this_cov, this_means);
|
||||
double[] thisLocals = hCalc.computeLocalUsingPreviousObservations(this_state);
|
||||
|
||||
// Local entropy of the rest of the variables (0, ... i-1, i+1, ... D)
|
||||
double[][] rest_cov = MatrixUtils.selectRowsAndColumns(covariance, idx, idx);
|
||||
double[] rest_means = MatrixUtils.select(means, idx);
|
||||
double[][] rest_state = MatrixUtils.selectColumns(states, idx);
|
||||
|
||||
hCalc.initialise(dimensions - 1);
|
||||
hCalc.setCovarianceAndMeans(rest_cov, rest_means);
|
||||
double[] restLocals = hCalc.computeLocalUsingPreviousObservations(rest_state);
|
||||
|
||||
localValues = MatrixUtils.add(localValues, MatrixUtils.subtract(thisLocals, restLocals));
|
||||
|
||||
}
|
||||
|
||||
return localValues;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Java Information Dynamics Toolkit (JIDT)
|
||||
* Copyright (C) 2017, Joseph T. Lizier, Ipek Oezdemir and Pedro Mediano
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package infodynamics.measures.continuous.gaussian;
|
||||
|
||||
import infodynamics.utils.MatrixUtils;
|
||||
|
||||
/**
|
||||
* <p>Computes the differential S-information of a given multivariate
|
||||
* <code>double[][]</code> set of
|
||||
* observations (extending {@link MultiVariateInfoMeasureCalculatorGaussian}),
|
||||
* assuming that the probability distribution function for these observations is
|
||||
* a multivariate Gaussian distribution.</p>
|
||||
*
|
||||
* <p>Usage is as per the paradigm outlined for {@link MultiVariateInfoMeasureCalculatorCommon}.
|
||||
* </p>
|
||||
*
|
||||
* <p><b>References:</b><br/>
|
||||
* <ul>
|
||||
* <li>Rosas, F., Mediano, P., Gastpar, M, Jensen, H.,
|
||||
* <a href="http://dx.doi.org/10.1103/PhysRevE.100.032305">"Quantifying high-order
|
||||
* interdependencies via multivariate extensions of the mutual information"</a>,
|
||||
* Physical Review E 100, (2019) 032305.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Pedro A.M. Mediano (<a href="pmediano at pm.me">email</a>,
|
||||
* <a href="http://www.doc.ic.ac.uk/~pam213">www</a>)
|
||||
*/
|
||||
public class SInfoCalculatorGaussian
|
||||
extends MultiVariateInfoMeasureCalculatorGaussian {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public SInfoCalculatorGaussian() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return the average S-info in nats (not bits!)
|
||||
* @throws Exception if not sufficient data have been provided, or if the
|
||||
* supplied covariance matrix is invalid.
|
||||
*/
|
||||
public double computeAverageLocalOfObservations() throws Exception {
|
||||
|
||||
if (covariance == null) {
|
||||
throw new Exception("Cannot calculate O-Info without having " +
|
||||
"a covariance either supplied or computed via setObservations()");
|
||||
}
|
||||
|
||||
if (!isComputed) {
|
||||
|
||||
MultiInfoCalculatorGaussian tcCalc = new MultiInfoCalculatorGaussian();
|
||||
tcCalc.initialise(dimensions);
|
||||
tcCalc.setCovariance(covariance);
|
||||
double tc = tcCalc.computeAverageLocalOfObservations();
|
||||
|
||||
DualTotalCorrelationCalculatorGaussian dtcCalc = new DualTotalCorrelationCalculatorGaussian();
|
||||
dtcCalc.initialise(dimensions);
|
||||
dtcCalc.setCovariance(covariance);
|
||||
double dtc = dtcCalc.computeAverageLocalOfObservations();
|
||||
|
||||
lastAverage = tc + dtc;
|
||||
isComputed = true;
|
||||
}
|
||||
|
||||
return lastAverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return the "time-series" of local S-info values in nats (not bits!)
|
||||
* for the supplied states.
|
||||
* @throws Exception if not sufficient data have been provided, or if the
|
||||
* supplied covariance matrix is invalid.
|
||||
*/
|
||||
public double[] computeLocalUsingPreviousObservations(double[][] states) throws Exception {
|
||||
|
||||
if ((means == null) || (covariance == null)) {
|
||||
throw new Exception("Cannot compute local values without having means " +
|
||||
"and covariance either supplied or computed via setObservations()");
|
||||
}
|
||||
|
||||
MultiInfoCalculatorGaussian tcCalc = new MultiInfoCalculatorGaussian();
|
||||
tcCalc.initialise(dimensions);
|
||||
tcCalc.setCovarianceAndMeans(covariance, means);
|
||||
double[] localTC = tcCalc.computeLocalUsingPreviousObservations(states);
|
||||
|
||||
DualTotalCorrelationCalculatorGaussian dtcCalc = new DualTotalCorrelationCalculatorGaussian();
|
||||
dtcCalc.initialise(dimensions);
|
||||
dtcCalc.setCovarianceAndMeans(covariance, means);
|
||||
double[] localDTC = dtcCalc.computeLocalUsingPreviousObservations(states);
|
||||
|
||||
double[] localValues = MatrixUtils.add(localTC, localDTC);
|
||||
|
||||
return localValues;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Java Information Dynamics Toolkit (JIDT)
|
||||
* Copyright (C) 2012, Joseph T. Lizier
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package infodynamics.measures.continuous.gaussian;
|
||||
|
||||
import infodynamics.utils.MatrixUtils;
|
||||
import infodynamics.utils.RandomGenerator;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class DualTotalCorrelationCalculatorGaussianTester extends TestCase {
|
||||
|
||||
/**
|
||||
* For two variables, DTC is equal to mutual information.
|
||||
*/
|
||||
public void testTwoVariables() throws Exception {
|
||||
double[][] cov = new double[][] {{1, 0.5}, {0.5, 1}};
|
||||
|
||||
DualTotalCorrelationCalculatorGaussian dtcCalc = new DualTotalCorrelationCalculatorGaussian();
|
||||
dtcCalc.initialise(2);
|
||||
dtcCalc.setCovariance(cov);
|
||||
double dtc = dtcCalc.computeAverageLocalOfObservations();
|
||||
|
||||
MutualInfoCalculatorMultiVariateGaussian miCalc = new MutualInfoCalculatorMultiVariateGaussian();
|
||||
miCalc.initialise(1,1);
|
||||
miCalc.setCovariance(cov, 1);
|
||||
double mi = miCalc.computeAverageLocalOfObservations();
|
||||
|
||||
assertEquals(dtc, mi, 1e-6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare against the direct calculation of DTC as a sum of entropies using the
|
||||
* entropy calculator.
|
||||
*/
|
||||
public void testCompareWithEntropy() throws Exception {
|
||||
double[][] cov = new double[][] {{1, 0.4, 0.3}, {0.4, 1, 0.2}, {0.3, 0.2, 1}};
|
||||
|
||||
DualTotalCorrelationCalculatorGaussian dtcCalc = new DualTotalCorrelationCalculatorGaussian();
|
||||
dtcCalc.initialise(3);
|
||||
dtcCalc.setCovariance(cov);
|
||||
double dtc = dtcCalc.computeAverageLocalOfObservations();
|
||||
|
||||
// Calculate using an entropy calculator and picking submatrices manually
|
||||
EntropyCalculatorMultiVariateGaussian hCalc = new EntropyCalculatorMultiVariateGaussian();
|
||||
hCalc.initialise(3);
|
||||
hCalc.setCovariance(cov);
|
||||
double dtc_hCalc = -2 * hCalc.computeAverageLocalOfObservations();
|
||||
|
||||
hCalc.initialise(2);
|
||||
hCalc.setCovariance(MatrixUtils.selectRowsAndColumns(cov, new int[] {0,1}, new int[] {0,1}));
|
||||
dtc_hCalc += hCalc.computeAverageLocalOfObservations();
|
||||
hCalc.initialise(2);
|
||||
hCalc.setCovariance(MatrixUtils.selectRowsAndColumns(cov, new int[] {0,2}, new int[] {0,2}));
|
||||
dtc_hCalc += hCalc.computeAverageLocalOfObservations();
|
||||
hCalc.initialise(2);
|
||||
hCalc.setCovariance(MatrixUtils.selectRowsAndColumns(cov, new int[] {1,2}, new int[] {1,2}));
|
||||
dtc_hCalc += hCalc.computeAverageLocalOfObservations();
|
||||
|
||||
assertEquals(dtc, dtc_hCalc, 1e-6);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that the local values average correctly back to the average value
|
||||
*/
|
||||
public void testLocalsAverageCorrectly() throws Exception {
|
||||
|
||||
int dimensions = 4;
|
||||
int timeSteps = 1000;
|
||||
DualTotalCorrelationCalculatorGaussian dtcCalc = new DualTotalCorrelationCalculatorGaussian();
|
||||
dtcCalc.initialise(dimensions);
|
||||
|
||||
// generate some random data
|
||||
RandomGenerator rg = new RandomGenerator();
|
||||
double[][] data = rg.generateNormalData(timeSteps, dimensions,
|
||||
0, 1);
|
||||
|
||||
dtcCalc.setObservations(data);
|
||||
|
||||
double dtc = dtcCalc.computeAverageLocalOfObservations();
|
||||
double[] dtcLocal = dtcCalc.computeLocalOfPreviousObservations();
|
||||
|
||||
System.out.printf("Average was %.5f\n", dtc);
|
||||
|
||||
assertEquals(dtc, MatrixUtils.mean(dtcLocal), 0.00001);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that for 2D the local values equal the local MI values
|
||||
*
|
||||
*/
|
||||
public void testLocalsEqualMI() throws Exception {
|
||||
|
||||
int dimensions = 2;
|
||||
int timeSteps = 100;
|
||||
DualTotalCorrelationCalculatorGaussian dtcCalc = new DualTotalCorrelationCalculatorGaussian();
|
||||
dtcCalc.initialise(dimensions);
|
||||
|
||||
// generate some random data
|
||||
RandomGenerator rg = new RandomGenerator();
|
||||
double[][] data = rg.generateNormalData(timeSteps, dimensions,
|
||||
0, 1);
|
||||
|
||||
dtcCalc.setObservations(data);
|
||||
double[] dtcLocal = dtcCalc.computeLocalOfPreviousObservations();
|
||||
|
||||
MutualInfoCalculatorMultiVariateGaussian miCalc = new MutualInfoCalculatorMultiVariateGaussian();
|
||||
miCalc.initialise(1, 1);
|
||||
miCalc.setObservations(MatrixUtils.selectColumn(data, 0), MatrixUtils.selectColumn(data, 1));
|
||||
double[] miLocal = miCalc.computeLocalOfPreviousObservations();
|
||||
|
||||
for (int t = 0; t < timeSteps; t++) {
|
||||
assertEquals(dtcLocal[t], miLocal[t], 0.00001);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Java Information Dynamics Toolkit (JIDT)
|
||||
* Copyright (C) 2012, Joseph T. Lizier
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package infodynamics.measures.continuous.gaussian;
|
||||
|
||||
import infodynamics.utils.MatrixUtils;
|
||||
import infodynamics.utils.RandomGenerator;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class OInfoCalculatorGaussianTester extends TestCase {
|
||||
|
||||
/**
|
||||
* For two variables, O-info is zero
|
||||
*/
|
||||
public void testTwoVariables() throws Exception {
|
||||
double[][] cov = new double[][] {{1, 0.5}, {0.5, 1}};
|
||||
|
||||
OInfoCalculatorGaussian oCalc = new OInfoCalculatorGaussian();
|
||||
oCalc.initialise(2);
|
||||
oCalc.setCovariance(cov);
|
||||
double oinfo = oCalc.computeAverageLocalOfObservations();
|
||||
|
||||
assertEquals(oinfo, 0, 1e-6);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For factorisable pairwise interactions, O-info is zero
|
||||
*/
|
||||
public void testPairwise() throws Exception {
|
||||
double[][] cov = new double[][] {{ 1, 0.5, 0, 0},
|
||||
{0.5, 1, 0, 0},
|
||||
{ 0, 0, 1, 0.5},
|
||||
{ 0, 0, 0.5, 1}};
|
||||
|
||||
OInfoCalculatorGaussian oCalc = new OInfoCalculatorGaussian();
|
||||
oCalc.initialise(4);
|
||||
oCalc.setCovariance(cov);
|
||||
double oinfo = oCalc.computeAverageLocalOfObservations();
|
||||
|
||||
assertEquals(oinfo, 0, 1e-6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare against the direct calculation of O-info as a sum of entropies using the
|
||||
* entropy calculator.
|
||||
*/
|
||||
public void testCompareWithEntropy() throws Exception {
|
||||
double[][] cov = new double[][] {{1, 0.4, 0.3}, {0.4, 1, 0.2}, {0.3, 0.2, 1}};
|
||||
|
||||
OInfoCalculatorGaussian oCalc = new OInfoCalculatorGaussian();
|
||||
oCalc.initialise(3);
|
||||
oCalc.setCovariance(cov);
|
||||
double oinfo = oCalc.computeAverageLocalOfObservations();
|
||||
|
||||
// Calculate using an entropy calculator and picking submatrices manually
|
||||
EntropyCalculatorMultiVariateGaussian hCalc = new EntropyCalculatorMultiVariateGaussian();
|
||||
hCalc.initialise(3);
|
||||
hCalc.setCovariance(cov);
|
||||
double oinfo_hCalc = hCalc.computeAverageLocalOfObservations();
|
||||
|
||||
hCalc.initialise(2);
|
||||
hCalc.setCovariance(MatrixUtils.selectRowsAndColumns(cov, new int[] {0,1}, new int[] {0,1}));
|
||||
oinfo_hCalc -= hCalc.computeAverageLocalOfObservations();
|
||||
hCalc.initialise(2);
|
||||
hCalc.setCovariance(MatrixUtils.selectRowsAndColumns(cov, new int[] {0,2}, new int[] {0,2}));
|
||||
oinfo_hCalc -= hCalc.computeAverageLocalOfObservations();
|
||||
hCalc.initialise(2);
|
||||
hCalc.setCovariance(MatrixUtils.selectRowsAndColumns(cov, new int[] {1,2}, new int[] {1,2}));
|
||||
oinfo_hCalc -= hCalc.computeAverageLocalOfObservations();
|
||||
|
||||
hCalc.initialise(1);
|
||||
hCalc.setCovariance(new double[][] {{cov[0][0]}});
|
||||
oinfo_hCalc += hCalc.computeAverageLocalOfObservations();
|
||||
hCalc.initialise(1);
|
||||
hCalc.setCovariance(new double[][] {{cov[1][1]}});
|
||||
oinfo_hCalc += hCalc.computeAverageLocalOfObservations();
|
||||
hCalc.initialise(1);
|
||||
hCalc.setCovariance(new double[][] {{cov[2][2]}});
|
||||
oinfo_hCalc += hCalc.computeAverageLocalOfObservations();
|
||||
|
||||
assertEquals(oinfo, oinfo_hCalc, 1e-6);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that the local values average correctly back to the average value
|
||||
*/
|
||||
public void testLocalsAverageCorrectly() throws Exception {
|
||||
|
||||
int dimensions = 4;
|
||||
int timeSteps = 1000;
|
||||
OInfoCalculatorGaussian oCalc = new OInfoCalculatorGaussian();
|
||||
oCalc.initialise(dimensions);
|
||||
|
||||
// generate some random data
|
||||
RandomGenerator rg = new RandomGenerator();
|
||||
double[][] data = rg.generateNormalData(timeSteps, dimensions,
|
||||
0, 1);
|
||||
|
||||
oCalc.setObservations(data);
|
||||
|
||||
double oinfo = oCalc.computeAverageLocalOfObservations();
|
||||
double[] oLocal = oCalc.computeLocalOfPreviousObservations();
|
||||
|
||||
System.out.printf("Average was %.5f\n", oinfo);
|
||||
|
||||
assertEquals(oinfo, MatrixUtils.mean(oLocal), 0.00001);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that for 2D all local values equal zero
|
||||
*/
|
||||
public void testLocalsEqualZero() throws Exception {
|
||||
|
||||
int dimensions = 2;
|
||||
int timeSteps = 100;
|
||||
OInfoCalculatorGaussian oCalc = new OInfoCalculatorGaussian();
|
||||
oCalc.initialise(dimensions);
|
||||
|
||||
// generate some random data
|
||||
RandomGenerator rg = new RandomGenerator();
|
||||
double[][] data = rg.generateNormalData(timeSteps, dimensions,
|
||||
0, 1);
|
||||
|
||||
oCalc.setObservations(data);
|
||||
double[] oLocal = oCalc.computeLocalOfPreviousObservations();
|
||||
|
||||
for (int t = 0; t < timeSteps; t++) {
|
||||
assertEquals(oLocal[t], 0, 0.00001);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Java Information Dynamics Toolkit (JIDT)
|
||||
* Copyright (C) 2012, Joseph T. Lizier
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package infodynamics.measures.continuous.gaussian;
|
||||
|
||||
import infodynamics.utils.MatrixUtils;
|
||||
import infodynamics.utils.RandomGenerator;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class SInfoCalculatorGaussianTester extends TestCase {
|
||||
|
||||
/**
|
||||
* For two variables, S-info is twice the MI between them
|
||||
*/
|
||||
public void testTwoVariables() throws Exception {
|
||||
double[][] cov = new double[][] {{1, 0.5}, {0.5, 1}};
|
||||
|
||||
SInfoCalculatorGaussian sCalc = new SInfoCalculatorGaussian();
|
||||
sCalc.initialise(2);
|
||||
sCalc.setCovariance(cov);
|
||||
double sinfo = sCalc.computeAverageLocalOfObservations();
|
||||
|
||||
MutualInfoCalculatorMultiVariateGaussian miCalc = new MutualInfoCalculatorMultiVariateGaussian();
|
||||
miCalc.initialise(1,1);
|
||||
miCalc.setCovariance(cov, false);
|
||||
double mi = miCalc.computeAverageLocalOfObservations();
|
||||
|
||||
assertEquals(sinfo, 2*mi, 1e-6);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare against the direct calculation of S-info as a sum of mutual informations.
|
||||
*/
|
||||
public void testCompareWithEntropy() throws Exception {
|
||||
double[][] cov = new double[][] {{1, 0.4, 0.3}, {0.4, 1, 0.2}, {0.3, 0.2, 1}};
|
||||
|
||||
SInfoCalculatorGaussian sCalc = new SInfoCalculatorGaussian();
|
||||
sCalc.initialise(3);
|
||||
sCalc.setCovariance(cov);
|
||||
double sinfo = sCalc.computeAverageLocalOfObservations();
|
||||
|
||||
// Calculate using a mutual info calculator and picking submatrices manually
|
||||
MutualInfoCalculatorMultiVariateGaussian miCalc = new MutualInfoCalculatorMultiVariateGaussian();
|
||||
miCalc.initialise(2,1);
|
||||
miCalc.setCovariance(cov, false);
|
||||
double sinfo_miCalc = miCalc.computeAverageLocalOfObservations();
|
||||
|
||||
miCalc.initialise(2,1);
|
||||
miCalc.setCovariance(MatrixUtils.selectRowsAndColumns(cov, new int[] {2,0,1}, new int[] {2,0,1}), false);
|
||||
sinfo_miCalc += miCalc.computeAverageLocalOfObservations();
|
||||
miCalc.initialise(2,1);
|
||||
miCalc.setCovariance(MatrixUtils.selectRowsAndColumns(cov, new int[] {1,2,0}, new int[] {1,2,0}), false);
|
||||
sinfo_miCalc += miCalc.computeAverageLocalOfObservations();
|
||||
|
||||
assertEquals(sinfo, sinfo_miCalc, 1e-6);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that the local values average correctly back to the average value
|
||||
*/
|
||||
public void testLocalsAverageCorrectly() throws Exception {
|
||||
|
||||
int dimensions = 4;
|
||||
int timeSteps = 1000;
|
||||
SInfoCalculatorGaussian sCalc = new SInfoCalculatorGaussian();
|
||||
sCalc.initialise(dimensions);
|
||||
|
||||
// generate some random data
|
||||
RandomGenerator rg = new RandomGenerator();
|
||||
double[][] data = rg.generateNormalData(timeSteps, dimensions,
|
||||
0, 1);
|
||||
|
||||
sCalc.setObservations(data);
|
||||
|
||||
double sinfo = sCalc.computeAverageLocalOfObservations();
|
||||
double[] sLocal = sCalc.computeLocalOfPreviousObservations();
|
||||
|
||||
System.out.printf("Average was %.5f\n", sinfo);
|
||||
|
||||
assertEquals(sinfo, MatrixUtils.mean(sLocal), 0.00001);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that for 2D all local values equal zero
|
||||
*/
|
||||
public void testLocalsEqualMI() throws Exception {
|
||||
|
||||
int dimensions = 2;
|
||||
int timeSteps = 100;
|
||||
SInfoCalculatorGaussian sCalc = new SInfoCalculatorGaussian();
|
||||
sCalc.initialise(dimensions);
|
||||
|
||||
// generate some random data
|
||||
RandomGenerator rg = new RandomGenerator();
|
||||
double[][] data = rg.generateNormalData(timeSteps, dimensions,
|
||||
0, 1);
|
||||
|
||||
sCalc.setObservations(data);
|
||||
double[] sLocal = sCalc.computeLocalOfPreviousObservations();
|
||||
|
||||
MutualInfoCalculatorMultiVariateGaussian miCalc = new MutualInfoCalculatorMultiVariateGaussian();
|
||||
miCalc.initialise(1, 1);
|
||||
miCalc.setObservations(MatrixUtils.selectColumn(data, 0), MatrixUtils.selectColumn(data, 1));
|
||||
double[] miLocal = miCalc.computeLocalOfPreviousObservations();
|
||||
|
||||
for (int t = 0; t < timeSteps; t++) {
|
||||
assertEquals(sLocal[t], 2*miLocal[t], 0.00001);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue