From 7b770a9831ec717d2bf13db2e566a79ff15b50bf Mon Sep 17 00:00:00 2001 From: "joseph.lizier" Date: Fri, 26 Oct 2012 05:13:09 +0000 Subject: [PATCH] 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). --- .../plotLocalInfoMeasureForCA.m | 82 ++++++++ .../CellularAutomata/plotLocalInfoValues.m | 126 +++++++++++++ demos/octave/CellularAutomata/plotRawCa.m | 46 +++++ .../CellularAutomata/prepareColourmap.m | 53 ++++++ demos/octave/CellularAutomata/runCA.m | 176 ++++++++++++++++++ demos/octave/javaMatrixToOctave.m | 57 ++++++ demos/octave/octaveToJavaDoubleArray.m | 27 +++ demos/octave/octaveToJavaDoubleMatrix.m | 32 ++++ demos/octave/octaveToJavaIntArray.m | 21 +++ demos/octave/octaveToJavaIntMatrix.m | 21 +++ 10 files changed, 641 insertions(+) create mode 100755 demos/octave/CellularAutomata/plotLocalInfoMeasureForCA.m create mode 100755 demos/octave/CellularAutomata/plotLocalInfoValues.m create mode 100755 demos/octave/CellularAutomata/plotRawCa.m create mode 100755 demos/octave/CellularAutomata/prepareColourmap.m create mode 100755 demos/octave/CellularAutomata/runCA.m create mode 100755 demos/octave/javaMatrixToOctave.m create mode 100755 demos/octave/octaveToJavaDoubleArray.m create mode 100755 demos/octave/octaveToJavaDoubleMatrix.m create mode 100755 demos/octave/octaveToJavaIntArray.m create mode 100755 demos/octave/octaveToJavaIntMatrix.m diff --git a/demos/octave/CellularAutomata/plotLocalInfoMeasureForCA.m b/demos/octave/CellularAutomata/plotLocalInfoMeasureForCA.m new file mode 100755 index 0000000..7a04d38 --- /dev/null +++ b/demos/octave/CellularAutomata/plotLocalInfoMeasureForCA.m @@ -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 + diff --git a/demos/octave/CellularAutomata/plotLocalInfoValues.m b/demos/octave/CellularAutomata/plotLocalInfoValues.m new file mode 100755 index 0000000..5c19613 --- /dev/null +++ b/demos/octave/CellularAutomata/plotLocalInfoValues.m @@ -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 + diff --git a/demos/octave/CellularAutomata/plotRawCa.m b/demos/octave/CellularAutomata/plotRawCa.m new file mode 100755 index 0000000..0b80f03 --- /dev/null +++ b/demos/octave/CellularAutomata/plotRawCa.m @@ -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 + diff --git a/demos/octave/CellularAutomata/prepareColourmap.m b/demos/octave/CellularAutomata/prepareColourmap.m new file mode 100755 index 0000000..48c36c5 --- /dev/null +++ b/demos/octave/CellularAutomata/prepareColourmap.m @@ -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 + diff --git a/demos/octave/CellularAutomata/runCA.m b/demos/octave/CellularAutomata/runCA.m new file mode 100755 index 0000000..3ef4f64 --- /dev/null +++ b/demos/octave/CellularAutomata/runCA.m @@ -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 diff --git a/demos/octave/javaMatrixToOctave.m b/demos/octave/javaMatrixToOctave.m new file mode 100755 index 0000000..5a1457f --- /dev/null +++ b/demos/octave/javaMatrixToOctave.m @@ -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 + diff --git a/demos/octave/octaveToJavaDoubleArray.m b/demos/octave/octaveToJavaDoubleArray.m new file mode 100755 index 0000000..94c84c5 --- /dev/null +++ b/demos/octave/octaveToJavaDoubleArray.m @@ -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 + diff --git a/demos/octave/octaveToJavaDoubleMatrix.m b/demos/octave/octaveToJavaDoubleMatrix.m new file mode 100755 index 0000000..67fd3b2 --- /dev/null +++ b/demos/octave/octaveToJavaDoubleMatrix.m @@ -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 + diff --git a/demos/octave/octaveToJavaIntArray.m b/demos/octave/octaveToJavaIntArray.m new file mode 100755 index 0000000..3c21968 --- /dev/null +++ b/demos/octave/octaveToJavaIntArray.m @@ -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 + diff --git a/demos/octave/octaveToJavaIntMatrix.m b/demos/octave/octaveToJavaIntMatrix.m new file mode 100755 index 0000000..b5b63f3 --- /dev/null +++ b/demos/octave/octaveToJavaIntMatrix.m @@ -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 +