Adding demos directly, plus octave child directory, .m files for converting between octave and java arrays, and the CellularAutomata demo (just with active info storage for the moment).

This commit is contained in:
joseph.lizier 2012-10-26 05:13:09 +00:00
parent 731c17def1
commit 7b770a9831
10 changed files with 641 additions and 0 deletions

View File

@ -0,0 +1,82 @@
%
%
%
% Inputs:
% - neighbourhood - neighbourhood size for the rule (ECA has neighbourhood 3).
% For an even size neighbourhood (meaning a different number of neighbours on each side of the cell),
% we take an extra cell from the lower cell indices (i.e. from the left).
% - base - number of discrete states for each cell (for binary states this is 2)
% - rule - supplied as either:
% a. an integer rule number if <= 2^31 - 1 (Wolfram style; e.g. 110, 54 are the complex ECA rules)
% b. a HEX string, e.g. phi_par from Mitchell et al. is "0xfeedffdec1aaeec0eef000a0e1a020a0" (note: the leading 0x is not required)
% - cells - number of cells in the CA
% - timeSteps - number of rows to execute the CA for (including the random initial row)
% - measureId - which local info dynamics measure to plot - can be a string or an integer as follows:
% - "active", 0 - active information storage (requires options.k)
% - "all", -1 - plot all measures
% - measureParams - a structure containing options as described for each measure above:
% - measureParams.k - history length for information dynamics measures
% - options - a stucture containing a range of other options, i.e.:
% - plotOptions - structure as defined for the plotRawCa function
% - plotRawCa - default true
% - saveImages - whether to save the plots or not (default false)
% - movingFrameSpeed - to investigate a moving frame of reference (default 0) (as in Lizier & Mahoney paper)
function plotLocalInfoMeasureForCA(neighbourhood, base, rule, cells, timeSteps, measureId, measureParams, options)
tic
if (nargin < 8)
options = {};
end
if not(isfield(options, "plotOptions"))
options.plotOptions = {}; % Create it ready for plotRawCa etc
end
if not(isfield(options, "saveImages"))
options.saveImages = false;
end
if not(isfield(options, "plotRawCa"))
options.plotRawCa = true;
end
% Add utilities to the path
addpath("..");
% Assumes the jar is two levels up - change this if this is not the case
% Octave is happy to have the path added multiple times; I'm unsure if this is true for matlab
javaaddpath('../../infodynamics.jar');
% Simulate and plot the CA
caStates = runCA(neighbourhood, base, rule, cells, timeSteps, false);
if (options.plotRawCa)
plotRawCa(caStates, options.plotOptions, options.saveImages);
end
figNum = 2;
toc
% convert the states to a format usable by java:
caStatesJInts = octaveToJavaIntMatrix(caStates);
toc
% Make the local information dynamics measurement
if ((ischar(measureId) && (strcmp("active", measureId) || strcmp("all", measureId))) || \
((measureId == 0) || (measureId == -1)))
% Compute active information storage
activeCalc = javaObject('infodynamics.measures.discrete.ActiveInformationCalculator', base, measureParams.k);
activeCalc.initialise();
activeCalc.addObservations(caStatesJInts);
avActive = activeCalc.computeAverageLocalOfObservations();
printf("Average active information storage = %.4f\n", avActive);
javaLocalValues = activeCalc.computeLocalFromPreviousObservations(caStatesJInts);
toc
figure(figNum)
figNum = figNum + 1;
plotLocalInfoValues(javaLocalValues, options.plotOptions);
if (options.saveImages)
print("figures/active.eps", "-color", "-deps");
end
end
toc
end

View File

@ -0,0 +1,126 @@
% J. Lizier, 2012.
%
% Plots the local values, both the positive and negative, in blues and reds respectively, on the current figure.
%
% Inputs:
% - localResults - local values to be plotted. Can be native octave or java array
% - plotOptions - structure (optional) containing the following variables:
% - plotRows - how many rows to plot (default is all)
% - plotCols - how many columns to plot (default is all)
% - plotStartRow - which row to start plotting from (default is 1)
% - plotStartCol - which column to start plotting from (default is 1)
% - scaleColoursToExtremes - stretch the darkest red and blue to the max and min of the local values,
% regardless of how imbalanced the max and mins are. (Default is false.)
% - mainSignVectorLength - length of the longest component (positive or negative values) for the colourmap
% - scalingMainComponent - what proportion to make the darkest shade of the primary colour (default .25)
% - scalingScdryComponent - what proportion to make the lighter shades with green added (default .4)
%
function plotLocalInfoValues(localResults, plotOptions)
% Set the colormap to have blue for positive, red for negative, scaled to the max and min of our local values
if (nargin < 2)
plotOptions = {};
end
if not(isfield(plotOptions, "plotRows"))
plotOptions.plotRows = rows(localResults);
end
if not(isfield(plotOptions, "plotCols"))
plotOptions.plotCols = columns(localResults);
end
if not(isfield(plotOptions, "plotStartRow"))
plotOptions.plotStartRow = 1;
end
if not(isfield(plotOptions, "plotStartCol"))
plotOptions.plotStartCol = 1;
end
if not(isfield(plotOptions, "scaleColoursToExtremes"))
plotOptions.scaleColoursToExtremes = false;
end
if not(isfield(plotOptions, "mainSignVectorLength"))
plotOptions.mainSignVectorLength = 1024;
end
if not(isfield(plotOptions, "scalingMainComponent"))
plotOptions.scalingMainComponent = .25;
end
if not(isfield(plotOptions, "scalingScdryComponent"))
plotOptions.scalingScdryComponent = .4;
end
% Pull some options out for easier coding here:
scalingMainComponent = plotOptions.scalingMainComponent;
mainSignVectorLength = plotOptions.mainSignVectorLength;
scalingScdryComponent = plotOptions.scalingScdryComponent;
if (not(ismatrix(localResults)))
% localResults must be a java matrix
% Convert the local values back to octave native values, and select
% only the rows and cols that will be plotted (gives a big speed up over
% coverting all of the values)
localResultsToPlot = javaMatrixToOctave(localResults, plotOptions.plotStartRow, plotOptions.plotStartCol, ...
plotOptions.plotRows, plotOptions.plotCols);
% JIDT jar file is assumed to be on the path since we already have java objects coming in
mUtils = javaObject('infodynamics.utils.MatrixUtils');
minLocal = mUtils.min(localResults);
maxLocal = mUtils.max(localResults);
else
% Pull out the values we'll be plotting
localResultsToPlot = localResults(plotOptions.plotStartRow:plotOptions.plotStartRow+plotOptions.plotRows - 1, ...
plotOptions.plotStartCol:plotOptions.plotStartCol+plotOptions.plotCols - 1);
minLocal = min(min(localResults));
maxLocal = max(max(localResults));
end
printf("[max,min] for local info dynamics profile is [%.3f, %.3f]\n", maxLocal, minLocal);
if (minLocal < 0)
% We need a negative component for the colorchart
if (plotOptions.scaleColoursToExtremes)
% Put the darkest blues and reds at our max and min respectively
if (abs(minLocal) > maxLocal)
% Use a longer length for the red vector than blue
vNegLength = mainSignVectorLength;
vPosLength = floor(mainSignVectorLength .* maxLocal ./ abs(minLocal));
else
% Use a longer length for the blue vector than red
vPosLength = mainSignVectorLength;
vNegLength = floor(mainSignVectorLength .* abs(minLocal) ./ maxLocal);
end
bluePosmap = prepareColourmap(vPosLength, true, scalingMainComponent, scalingScdryComponent);
redNegmap = flipud(prepareColourmap(vNegLength, false, scalingMainComponent, scalingScdryComponent));
% printf("Plotting locals with scaling to extreme values (%d distinct colours for positive, %d for negative)\n", \
% vPosLength, vNegLength);
else
% Only use the darkest blue/red for which of positive or negative values
% had the largest absolute value. For the other, scale the colours
% correspondingly.
% Initialise the full spectrum
bluePosmap = prepareColourmap(mainSignVectorLength, true, scalingMainComponent, scalingScdryComponent);
redNegmap = flipud(prepareColourmap(mainSignVectorLength, false, scalingMainComponent, scalingScdryComponent));
% Then cut down the non-dominant sign's part:
if (abs(minLocal) > maxLocal)
% Use a longer length for the red vector than blue; chop blue down
vPosLength = floor(mainSignVectorLength .* maxLocal ./ abs(minLocal));
vNegLength = mainSignVectorLength;
bluePosmap = bluePosmap(1:vPosLength,:);
else
% Use a longer length for the blue vector than red; chop red down
vNegLength = floor(mainSignVectorLength .* abs(minLocal) ./ maxLocal);
vPosLength = mainSignVectorLength;
redNegmap = redNegmap(length(redNegmap)-vNegLength + 1:length(redNegmap),:);
end
% printf("Plotting locals with minor scaled to major (%d distinct colours for positive, %d for negative)\n", \
% vPosLength, vNegLength);
end
% Construct the colormap with blue for positive and red for negative
colormap([redNegmap; bluePosmap]);
% Now, plot the local values with the pre-prepared colormap
imagesc(localResultsToPlot);
else
% We need to pin the minimum value of the blue-only plot to zero.
bluemap = prepareColourmap(mainSignVectorLength, true, scalingMainComponent, scalingScdryComponent);
colormap(bluemap);
% Now, plot the local values with the pre-prepared colormap
imagesc(localResultsToPlot, [0, maxLocal]);
end
colorbar
end

View File

@ -0,0 +1,46 @@
% function plotRawCa(states, saveIt)
%
% Plot the given raw values of a cellular automata run
%
% Inputs
% - states - 2D array of states of the CA (1st index time goes along the rows, 2nd index cells go across the columns)
% - plotOptions - structure (optional) containing the following variables:
% - plotRows - how many rows to plot (default is all)
% - plotCols - how many columns to plot (default is all)
% - plotStartRow - which row to start plotting from (default is 1)
% - plotStartCol - which column to start plotting from (default is 1)
% - saveIt - whether to save an eps file of the image (default false)
function plotRawCa(states, plotOptions, saveIt)
if (nargin < 2)
plotOptions = {};
end
if not(isfield(plotOptions, "plotRows"))
plotOptions.plotRows = rows(states);
end
if not(isfield(plotOptions, "plotCols"))
plotOptions.plotCols = columns(states);
end
if not(isfield(plotOptions, "plotStartRow"))
plotOptions.plotStartRow = 1;
end
if not(isfield(plotOptions, "plotStartCol"))
plotOptions.plotStartCol = 1;
end
if (nargin < 3)
saveIt = false;
end
figure(1);
% set the colormap for black = 1, white = 0
colormap(1 - gray(2))
imagesc(states(plotOptions.plotStartRow:plotOptions.plotStartRow+plotOptions.plotRows - 1, ...
plotOptions.plotStartCol:plotOptions.plotStartCol+plotOptions.plotCols - 1))
colorbar
printf("Adding colorbar to ensure that the size of the diagram matches that of local info plots\n");
if (saveIt)
print(sprintf("figures/raw-%d.eps", rule), "-color", "-deps");
end
end

View File

@ -0,0 +1,53 @@
% J. Lizier, 2012.
%
% Function to create a colourmap of a given length.
%
% The largest values are given the darkest shades of only the primary colour (blue or red),
% with fracPrim scaling the amount of the vector this occupies.
% The next values are given lighter shades of the primary colour, using green to
% make it lighter; fracWithSecondary scales how much of the vector this occupies.
% The last values are given the lightest (closest to white) shades, using the last
% colour to do this.
%
% Inputs:
% - vLength - length of the colourmap
% - primaryIsBlue - whether we're making a blue or red colourmap
% - fracPrim - what proportion to make the darkest shade of the primary colour (default .25)
% - fracSecondary - what proportion to make the lighter shades with green added (default .4)
%
% vLength is the length of the colormap
function rgbmap = prepareColourmap(vLength, primaryIsBlue, fracPrim, fracWithSecondary)
if (nargin < 4)
fracWithSecondary = .4;
end
if (nargin < 3)
fracPrim = .25;
end
if (nargin < 2)
primaryIsBlue = true;
end
if (nargin < 1)
vLength = 64;
end
% Set the colormap to have blue for positive, scaled to the max of our local values
% If the user wants red, we'll switch it around at the last minute.
blueOnlyLength = floor(vLength .* fracPrim);
greenAndBlueLength = floor(vLength .* fracWithSecondary);
redOnLength = vLength - blueOnlyLength - greenAndBlueLength;
bluevector = (2.*blueOnlyLength:-1:blueOnlyLength+1)' ./ 2 ./ blueOnlyLength; % Countdown from 1 to 0.5
bluevector = [ones(vLength - blueOnlyLength, 1); bluevector];
greenvector = (greenAndBlueLength:-1:1)' ./ greenAndBlueLength; % Count down from 1 to 0
greenvector = [ones(redOnLength, 1); greenvector; zeros(blueOnlyLength, 1)];
redvector = (redOnLength:-1:1)' ./ redOnLength; % Count down from 1 to 0
redvector = [redvector; zeros(vLength - redOnLength, 1)];
if (primaryIsBlue)
rgbmap = [ redvector, greenvector, bluevector];
else
% Primary colour is red, so swap the blue and red columns here
rgbmap = [ bluevector, greenvector, redvector];
end
end

View File

@ -0,0 +1,176 @@
% function [caStates, ruleTable, executedRules] = runCA(neighbourhood, base, rule, cells, steps, debug)
%
% Joseph Lizier
% 2012
% Distributed under GPLv3 (see distribution of license with the code)
%
% Please cite:
% Joseph T. Lizier, "JIDT: An information-theoretic toolkit for studying the dynamics of complex systems", 2012, https://code.google.com/p/information-dynamics-toolkit/
%
% Existing sources of memory leakage:
% - assigning CA(s) = ca <- should copy ca
% - use of circshift function. Could construct our own vector and copy elements.
%
% This function executes the given 1D (wolfram) cellular automata rule number.
%
% *NOTE* This function will not work properly with (base)^(base^neighbourhood) > 2^31 - 1
% (e.g. will not work for base 2, neighbourhood 5)
% until the use of long integers can be investigated.
%
% Inputs:
% - neighbourhood - neighbourhood size for the rule (ECA has neighbourhood 3).
% For an even size neighbourhood (meaning a different number of neighbours on each side of the cell),
% we take an extra cell from the lower cell indices (i.e. from the left).
% - base - number of discrete states for each cell (for binary states this is 2)
% - rule - supplied as either:
% a. an integer rule number if <= 2^31 - 1 (Wolfram style; e.g. 110, 54 are the complex ECA rules)
% b. a HEX string, e.g. phi_par from Mitchell et al. is "0xfeedffdec1aaeec0eef000a0e1a020a0" (note: the leading 0x is not required)
% - cells - number of cells in the CA
% - steps - number of rows to execute the CA for (including the random initial row)
% - debug - turn on various debug messages
% - seed - state input for the random number generator (so one can repeat CA investigations for the same initial state)
%
% Outputs:
% - caStates - a run, from random initial conditions, of a CA of the given parameters.
% - ruleTable - the lookup table for each neighbourhood configuration, constructed from the rule number
% - executedRules - which CA rule was executed for every cell update that occurred for the CA.
function [caStates, ruleTable, executedRules] = runCA(neighbourhood, base, rule, cells, steps, debug, seed)
% Check arguments:
if (nargin >= 7)
rand("state", seed);
end
if (nargin < 6)
debug = false;
end
if (nargin < 5)
steps = 100;
end
if (nargin < 4)
cells = 100;
end
if (nargin < 3)
error("Arguments neighbourhood, base, rule must be supplied");
end
% translate the rule into the appropriate base
ruleTable = zeros(base .^ neighbourhood, 1);
if (ischar(rule))
% The rule is specified as a hex string - necessary for larger rule values
% Check that the rule length is not larger than it should be:
if (length(rule)*4 > length(ruleTable))
error(sprintf("Rule specification %s is not within the limits of this base %d and neighbourhood %d (max hex string length is %d)", \
rule, base, neighbourhood, (base .^ neighbourhood)/4));
end
for x = length(rule) : -1 : 1
% Translate each character in the hex string into the 4 rows in the rule table it specifies,
% starting from the least significant hex digit:
hexDigit = rule(x);
if (strcmp("x", hexDigit))
% We've reached the end of the hex string
break;
end
thisValue = hex2dec(hexDigit);
thisValueRemainder = thisValue;
for i = 4 :-1: 1
ruleTable((length(rule)-x)*4 + i) = floor(thisValueRemainder ./ base .^ (i-1));
thisValueRemainder = thisValueRemainder - ruleTable((length(rule)-x)*4 + i) * base .^ (i-1);
if (debug)
printf("Rule digit %d: %d, =local %d, local remainder %d\n", (length(rule)-x)*4 + i, \
ruleTable((length(rule)-x)*4 + i), \
ruleTable((length(rule)-x)*4 + i) * base .^ (i-1), thisValueRemainder);
end
end
if (thisValueRemainder != 0)
error("Rule %s parsed incorrectly - remainder from hex digit %d is %d\n", rule, x, ruleRemainder);
end
end
printf("Rule %s is: ", rule);
for i = base .^ neighbourhood : -1 : 1
printf("%d", ruleTable(i));
endfor
printf("\n");
else
% The rule is specified as an integer
if (rule > base .^ (base .^ neighbourhood) - 1)
error(sprintf("Rule %d is not within the limits of this base %d and neighbourhood %d (max is %d)", \
rule, base, neighbourhood, base .^ (base .^ neighbourhood) - 1));
endif
ruleRemainder = rule;
% printf("Getting %d digits\n", base .^ neighbourhood);
for i = base .^ neighbourhood : -1 : 1
% Work out digit i
ruleTable(i) = floor(ruleRemainder ./ base .^ (i-1));
ruleRemainder = ruleRemainder - ruleTable(i) .* base .^ (i-1);
if (debug)
printf("Rule digit %d: %d, =%d, remainder %d\n", i, ruleTable(i), \
ruleTable(i) .* base .^ (i-1), ruleRemainder);
endif
endfor
if (ruleRemainder != 0)
error("Rule %d parsed incorrectly - remainder is %d\n", rule, ruleRemainder);
endif
printf("Rule %d is: ", rule);
for i = base .^ neighbourhood : -1 : 1
printf("%d", ruleTable(i));
endfor
printf("\n");
end
caStates = zeros(steps, cells);
% executedRules will store the rules executed at each step of the CA.
% (we don't need to store this for the last row, since we're not executing the rule update)
if (nargout >= 3)
executedRules = zeros(steps - 1, cells);
end
% Generate a random start CA
ca = floor(rand(1, cells) * base);
caStates(1,:) = ca;
if (debug)
ca
endif
for s = 2 : steps
% Compute which rule to update each cell with by effectively constructing the rule number to execute
% ie to execute "101" we construct 1* 2^2 + 0 * 2^1 + 1 * 2^0
% This works
ruleToRun = zeros(1, cells);
for i = 1 : neighbourhood
ruleToRun = ruleToRun + circshift(ca', ceil(-neighbourhood / 2) + (i-1))' .* (base .^ (i-1));
endfor
if (nargout >= 3)
% Save these rule executions:
executedRules(s - 1, :) = ruleToRun;
end
if (debug)
ruleToRun
endif
% Translate the rules to be run into the updated CA values.
% Need to add 1 to the ruleToRun because of the indexing starting from 1 not 0.
ca = ruleTable(ruleToRun + 1)';
if (debug)
ca
endif
caStates(s,:) = ca;
endfor
% CA evolution is done
if (debug)
caStates
endif
endfunction

View File

@ -0,0 +1,57 @@
% function octaveMatrix = javaMatrixToOctave(javaMatrix)
%
% Convert a java matrix (1 or 2D, double or int - but not Integer!!) to an octave matrix
%
% Unfortunately octave-java doesn't seem to handle the conversion properly,
% and we must convert each individual array item ourselves (This can be very slow for large matrices)
% or with org.octave.Matrix (built-in).
%
function octaveMatrix = javaMatrixToOctave(javaMatrix, startRow, startCol, numRows, numCols)
if (nargin < 2)
startRow = 1;
end
if (nargin < 3)
startCol = 1;
end
if (nargin < 4)
numRows = rows(javaMatrix);
end
if (nargin < 5)
numCols = columns(javaMatrix);
end
if (exist ('OCTAVE_VERSION', 'builtin'))
% We're in octave:
% Using 'org.octave.Matrix' is much faster than conversion cell by cell
% (only use if we're converting the whole array though, too many issues
% with type checking etc to bother otherwise)
if (nargin < 2)
tmp = javaObject('org.octave.Matrix', javaMatrix);
% Make sure tmp.ident() is converted to native octave:
oldFlag = java_convert_matrix (1);
unwind_protect
octaveMatrix = tmp.ident(tmp);
unwind_protect_cleanup
% restore to non-default conversion, otherwise we get
% bad errors on other calls
java_convert_matrix(oldFlag);
end_unwind_protect
return;
end
end
% Else, either we couldn't be bothered doing the resizing for java,
% or we were in Matlab all along. (If there's a fast way for matlab, tell me)
octaveMatrix = zeros(numRows, numCols);
for r = startRow:startRow+numRows-1
for c = startCol:startCol+numCols-1
octaveMatrix(r-startRow+1,c-startCol+1) = javaMatrix(r,c);
end
end
end

View File

@ -0,0 +1,27 @@
% function jDoubleArray = octaveToJavaDoubleArray(octaveArray)
%
% Convert a native octave array to a java double 1D array
%
function jDoubleArray = octaveToJavaDoubleArray(octaveArray)
if (exist ('OCTAVE_VERSION', 'builtin'))
% We're in octave:
% Using 'org.octave.Matrix' is much faster than conversion cell by cell
tmp = javaObject('org.octave.Matrix',octaveArray,[1, length(octaveArray)]);
jDoubleArray = tmp.asDoubleVector();
else
% We're in matlab:
% Presumably there's a quick way to do this in matlab, but since I'm not on matlab, I don't know ...
% If someone knows or has tested something, please tell me and I'll include it here.
% In the meantime, we copy element by element
jDoubleArray = javaArray('java.lang.Double', length(octaveArray));
for r = 1:length(octaveMatrix)
jDoubleArray(r) = octaveArray(r);
end
end
end

View File

@ -0,0 +1,32 @@
% function jDoubleMatrix = octaveToJavaDoubleMatrix(octaveMatrix)
%
% Convert a native octave/matlab matrix to a java double 2D array
%
function jDoubleMatrix = octaveToJavaDoubleMatrix(octaveMatrix)
if (exist ('OCTAVE_VERSION', 'builtin'))
% We're in octave:
% Using 'org.octave.Matrix' is much faster than conversion cell by cell
tmp = javaObject('org.octave.Matrix',reshape(octaveMatrix,1,rows(octaveMatrix)*columns(octaveMatrix)),[rows(octaveMatrix), columns(octaveMatrix)]);
jDoubleMatrix = tmp.asDoubleMatrix();
else
% We're in matlab:
% Presumably there's a quick way to do this in matlab, but since I'm not on matlab, I don't know ...
% If someone knows or has tested something, please tell me and I'll include it here.
% In the meantime, we copy element by element
jDoubleMatrix = javaArray('java.lang.Double', rows(octaveMatrix), columns(octaveMatrix));
for r = 1:rows(octaveMatrix)
% Slow but effective way:
for c = 1:columns(octaveMatrix)
jDoubleMatrix(r,c) = octaveMatrix(r,c);
end
% Fast way that doesn't actually work:
% jDoubleMatrix(r,:) = octaveMatrix(r,:);
end
end
end

View File

@ -0,0 +1,21 @@
% function jIntArray = octaveToJavaIntArray(octaveArray)
%
% Convert a native octave array to a java int 1D array.
%
% Assumes the JIDT jar is already on the java classpath - you will get a
% java classpath error if this is not the case.
%
% Unfortunately octave-java doesn't seem to handle the conversion properly,
% and we must convert the array from a double array first.
function jIntArray = octaveToJavaIntArray(octaveArray)
% Convert to a java Double array first - it doesn't seem to work converting elements to integers directly
jDoubleArray = octaveToJavaDoubleArray(octaveArray);
% Then convert this double matrix to an integer matrix
mUtils = javaObject('infodynamics.utils.MatrixUtils');
jIntArray = mUtils.doubleToIntArray(jDoubleArray);
end

View File

@ -0,0 +1,21 @@
% function jIntMatrix = octaveToJavaIntMatrix(octaveMatrix)
%
% Convert a native octave matrix to a java int 2D array.
%
% Assumes the JIDT jar is already on the java classpath - you will get a
% java classpath error if this is not the case.
%
% Unfortunately octave-java doesn't seem to handle the conversion properly,
% and we must convert the matrix from a double matrix first.
function jIntMatrix = octaveToJavaIntMatrix(octaveMatrix)
% Convert to a java Double matrix first - it doesn't seem to work converting elements to integers directly
jDoubleMatrix = octaveToJavaDoubleMatrix(octaveMatrix);
% Then convert this double matrix to an integer matrix
mUtils = javaObject('infodynamics.utils.MatrixUtils');
jIntMatrix = mUtils.doubleToIntArray(jDoubleMatrix);
end