I've been coding some simulations using inline/RcppArmadillo and stumbled upon a problem with RNGScope. Is this a bug or am I doing something really dumb?? I've emptied the function out to make it readable (see below).
Cheers,
Ed
library(inline)
code_cpp <- '
using namespace arma;
// From R
uvec x0 = as<uvec>(x0_r);
vec time_vec = as<vec>(time_vec_r);
// Declare variables
umat simulation_data=zeros<umat>(x0.n_elem, time_vec.n_elem);
RNGScope scope;
return wrap(simulation_data);
'
gillespie_sim <- cxxfunction(body = code_cpp,
sig = signature(x0_r = "integer", time_vec_r= "numeric"),
plugin = "RcppArmadillo")
x0 <- c(1,0,0,0,0,0)
time_vec <- 1:800
set.seed(23)
for(i in 1:100000) out2 <- gillespie_sim(x0_r=x0,time_vec_r=time_vec)
The error I get
R(43305) malloc: * error for object 0x108c30a00: incorrect checksum for freed object - object was probably modified after being freed.
* set a breakpoint in malloc_error_break to debug
Abort trap: 6
Hm, I see two issues:
a) You use umat, but we have no unsigned int in R, so this will get lots of very inefficient copies. I changed it to mat, but imat should work too.
b) You loop a lot with for(i in 1:100000). We have seen similar issue with "gazillions" of object creations. We are not sure where the bug is.
With a smaller N it does not seem to happen (as often). We'll take a look and see if RNGScope has anything to do with it -- but that is a very simple object.
Thanks for the bug report. Consider using rcpp-devel next time, please.
Edit: Also note that when using Rcpp vectors, the error does not seem to manifest itself. So you could use the two-step method of first initializing Rcpp objects and then initializing Armadillo objects from it -- the fastLm.r file in the package has an example of that.
suppressMessages(library(Rcpp))
suppressMessages(library(inline))
useRcpp <- function() {
code_cpp <- '
// From R
NumericVector x0(x0_r);
NumericVector time_vec(time_vec_r);
// Declare variables
NumericMatrix simulation_data(x0.size(), time_vec.size());
RNGScope scope;
return simulation_data;
'
cxxfunction(body = code_cpp,
sig = signature(x0_r = "integer", time_vec_r= "numeric"),
plugin = "Rcpp")
}
gillespie_sim <- useRcpp()
x0 <- c(1,0,0,0,0,0)
time_vec <- 1:800
set.seed(23)
for(i in 1:100000) out2 <- gillespie_sim(x0_r=x0,time_vec_r=time_vec)
cat("Done\n")
Related
I've generated C code from MATLAB by using the codegen tool. The function can be described as follows:
function [result] = calculate_data(my_matrix)
for idx = 1:length(my_matrix)
result = result + sum(my_matrix(idx,1:3));
end
end
When using the codegen tool, I explicitly stated that my_matrix is a type of double(:inf, 3). In other words, the number of rows is unbounded, but it will have 3 columns. When the code is generated, this is the function that is generated that I am to execute:
calculate_data(my_matrix : UnsafePointer<emxArray_real_T>!, result : UnsafeMutablePointer<emxArray_real_T>!)
emxArray_real_T is defined as follows in a different c file:
struct emxArray_real_T
{
double *data;
int *size;
int allocatedSize;
int numDimensions;
boolean_T canFreeData;
};
When I see my initialization options for the above class, this one in particular makes sense:
emxArray_real_T.init(data: UnsafeMutablePointer<Double>!, size: UnsafeMutablePointer<Int32>!, allocatedSize: Int32, numDimensions: Int32, canFreeData: boolean_T)
I've tried to follow this document as a means to wrap my head around how to call the generated C code, but I think I might be missing a basic step. Here is what I am doing:
// create an 2d array with some fake data
var mySampleData = [[Double]]();
for i in 0 ..< 3 {
mySampleData.append([1.1, 2.2, 3.3]);
}
// begin fulfilling requirements for emxArray_real_T
var data_pointer = UnsafeMutablePointer<Double>.allocate(capacity: 3);
data_pointer.initialize(from: mySampleData)
However, the above code throws an error stating that:
Generic parameter 'C' could not be inferred
I take it that I am then doing something completely wrong, and am probably on an incorrect path. There is a similar post that relates to my question, How to convert float[][] type array to "emxArray_real_T *x" , however the provided solution seems to be for C, as opposed to for Swift 4. How can I effectively call a C function using Swift 4, and meet the requirements of the emxArray_real_T.init method? Using fake data is ok to demonstrate the basic principle.
In a simple Xcode project with mocked C constructs for the struct emxArray_real_T and the function calculate_data I can run the following code successfully. To create an object of type emxArray_real_T I do
var data: [Double] = (0 ..< 12).map(Double.init)
var size: [Int32] = [4, 3]
var array = emxArray_real_T(
data: &data,
size: &size,
allocatedSize: 12,
numDimensions: 2,
canFreeData: false
)
This object can be passed to the function calculate_data like calculate_data(&array, nil). In a real application nil would be another array object. For the sake of simplicity it is just used as a placeholder here.
Your second issue can be solved by using the right types ([Double] instead of Double in line 6):
var mySampleData = [[Double]]();
for i in 0 ..< 3 {
mySampleData.append([i*1, i*2, i*3].map(Double.init));
}
let pointer = UnsafeMutablePointer<[Double]>.allocate(capacity: 3)
pointer.initialize(from: mySampleData, count: 3)
print((pointer + 0).pointee)
print((pointer + 1).pointee)
print((pointer + 2).pointee)
pointer.deallocate()
The output will be
[0.0, 0.0, 0.0]
[1.0, 2.0, 3.0]
[2.0, 4.0, 6.0]
as expected.
I have to admit that I used Swift 5.0.1. This should not make significant differences, though.
I am trying to create an array of structures in Simulink and got some problems with it.
first of all i tried to create it directly in Simulink using this:
function a = fcn(Dibhole, t , x, const)
%#codegen
%Output = zeros(10,10);
f1 = 'number';
f2 = 'move';
cube = struct(f1, 0, f2, 0);
a = repmat(cube, 20, 10);
for i = 1:20
for j = 1:10
a(i,j).number = 0;
a(i,j).move = 0;
end
end
and i got this error:
Derived output was of type struct. 'Inherited type' is unsupported for this
type and a defined bus object must be used instead. Click on 'a' and
set data type for 'a' to be 'Bus: ', where '' is
the name of a bus object from the MATLAB workspace.
So i found some example how to create struct in Matlab and receive this to Simulink: http://blogs.mathworks.com/seth/2011/12/05/initializing-buses-using-a-matlab-structure/
That works perfectly but i still can't repeat this with array:
f1 = 'number';
f2 = 'move';
cube = struct(f1, 0, f2, 0);
myStruct2 = repmat(cube, 20, 10);
for i = 1:20
for j = 1:10
myStruct2(i,j).number = 1;
myStruct2(i,j).move = 1;
end
end
busInfo = Simulink.Bus.createObject(myStruct2);
Can anyone clarify to me what's the problem? Or maybe there is different way to create array of struct in Simulink?
Mihail
Simulink wants you to define the output of the function to be a bus.
As 'Bus: My_test_bus', for example.
Take a look at the Simulink Bus Editor. You can find it in any model under the menu, Edit->Bus Editor.
This would be a good start.
Rick, i think you are right!
i have tried this problem for a long time, and have got this results:
the irony is that I was never able to create array of structures BUT i did this with structure of arrays! :D
I made this steps for it:
to use structure of arrays we need to define and initialize it in some MATLAB function. Like this:
number = zeros(10,1);
move = zeros(10,1);
for i = 1:10
number(i,1) = i+1;
move(i,1) = i+2;
end
a = struct('numbers',number,'movement', move);
To work this data we must use Bus Selector.
So we have array in "numbers" and "movement".
BUT! Here we go, Rick: we must define type of output of MATLAB function like Bus! How to do this in simulink? i found this way:
in model properties in simulink Callbacks/PreLoadFcn define some function and in same folder as project create .m file named like this just defined function.
In this file create structure of array and define Bus type for it:
number = zeros(10,1);
move = zeros(10,1);
a = struct('numbers',number,'movement', move);
busInfo = Simulink.Bus.createObject(a);
Now we have Bus type for our structure at first loading of simulink model.
Last step: define MATLAB function output type directly.
in Model Explorer choose your MATLAB function. choose output variable. Set DataType for it: Bus:slBus1 (the name of this Bus type you can see in wokspace of matlab, because its a global variable).
That's all! now it works!
(tried to add pictures, but i have no enough reputation :( )
Now my program works in this way, but i also tried to create array of structures and still have the problems. i tried to create Bus for it, but can't transmit it to Bus Selector - it doesn't know what to do with structures... i also tried to add one more MATLAB function to create some data from structures and then display it, but it doesn't works too(
I know this is a simple question, but for some reason I can't find a straight answer that works no matter where I look.
Basically, I have 4 values that were found in one m file, and I want to run them through a separate m file and retrieve the output from it.
I tried something like these, but none worked:
result = generate(nrow,ncol,a,b);
function result = generate(nrow,ncol,a,b);
result = #generate(nrow,ncol,a,b);
The final value in the m file "generate" is called result, and I'm trying to carry that across to my initial m file.
Any advice as to what I'm doing wrong would be greatly appreciated! Please and thank you
if your file generate.m defines a function it should have itself the following structure (which takes into account the fact that you have four returned values)
function [ret1 ret2 ret3 ret4] = generate(nrow,ncol,a,b)
.... % # Some processing of yours
ret1 = ... ; % # Returned values are eventually set
ret2 = ... ;
ret3 = ... ;
ret4 = ... ;
end
The function should be called (e.g. in your main script) as
[ret1 ret2 ret3 ret4] = generate(nrow,ncol,a,b);
now you have the variables ret1,ret2,ret3,ret4 available in the caller scope.
Be aware that the file generate.m must be in the current matlab PATH.
I'm stuck with computing the integral at each point of an array. The idea is first to create a function ("Integrand"). Then, create a second function ("MyConvolve") that computes the necessary integral.
Here's what I did up to now:
Integrand = function(s,x)
{ 1/4*(abs(x-s)<=1)*(abs(s)<=1) }
MyConvolve = function(func,data)
{ return( integrate(func, lower=-Inf, upper=Inf, data) ) }
Now, running the code with some array, I get an error message:
SomeMatrix = replicate(10, rnorm(10))
MyConvolve(Integrand, SomeMatrix)
Which ends up with the following error message:
Error in integrate(func, lower = -Inf, upper = Inf, data) :
evaluation of function gave a result of wrong length
I already tried vectorizing the function, but still ended up with error messages.
Thank you very much for your help!
I am not sure I understand what you are trying to compute,
but if you want to evaluate MyConvolve(Integrand,s),
where s takes all the values in SomeMatrix,
then apply is sufficient.
sapply( SomeMatrix, function(s) MyConvolve( Integrand, s )$value )
However, the dimensions of the matrix are lost.
You can recover them as follows:
result <- SomeMatrix
result[] <- sapply( SomeMatrix, function(s) MyConvolve( Integrand, s )$value )
I have two variables, the first is 1D flow vector containing 230 data and the second is 2D temperature matrix (230*44219).
I am trying to find the correlation matrix between each flow value and corresponding 44219 temperature. This is my code below.
Houlgrave_flow_1981_2000 = window(Houlgrave_flow_average, start = as.Date("1981-11-15"),end = as.Date("2000-12-15"))
> str(Houlgrave_flow_1981_2000)
‘zoo’ series from 1981-11-15 to 2000-12-15
Data: num [1:230] 0.085689 0.021437 0.000705 0 0.006969 ...
Index: Date[1:230], format: "1981-11-15" "1981-12-15" "1982-01-15" "1982-02-15" ...
Hulgrave_SST_1981_2000=X_sst[1:230,]
> str(Hulgrave_SST_1981_2000)
num [1:230, 1:44219] -0.0733 0.432 0.2783 -0.1989 0.1028 ...
sf_Houlgrave_SF_SST = NULL
sst_Houlgrave_SF_SST = NULL
cor_Houlgrave_SF_SST = NULL
for (i in 1:230) {
for(j in 1:44219){
sf_Houlgrave_SF_SST[i] = Houlgrave_flow_1981_2000[i]
sst_Houlgrave_SF_SST[i,j] = Hulgrave_SST_1981_2000[i,j]
cor_Houlgrave_SF_SST[i,j] = cor(sf_Houlgrave_SF_SST[i],Hulgrave_SST_1981_2000[i,j])
}
}
The error message always says:
Error in sst_Houlgrave_SF_SST[i, j] = Hulgrave_SST_1981_2000[i, j] :
incorrect number of subscripts on matrix
Thank you for your help.
try this:
# prepare empty matrix of correct size
cor_Houlgrave_SF_SST <- matrix(nrow=dim(Hulgrave_SST_1981_2000)[1],
ncol=dim(Hulgrave_SST_1981_2000)[2])
# Good practice to not specify "230" or "44219" directly, instead
for (i in 1:dim(Hulgrave_SST_1981_2000)[1]) {
for(j in 1:dim(Hulgrave_SST_1981_2000)[2]){
cor_Houlgrave_SF_SST[i,j] <- cor(sf_Houlgrave_SF_SST[i],Hulgrave_SST_1981_2000[i,j])
}
}
The two redefinitions inside your loop were superfluous I believe. The main problem with your code was not defining the matrix - i.e. the cor variable did not have 2 dimensions, hence the error.
It is apparently also good practice to define empty matrices for results in for-loops by explicitly giving them correct dimensions in advance - is meant to make the code more efficient.