How do I call a function handle from cell array? - arrays

What I try to do is keep a cell-array of function handles, and then call one of them in a loop. It doesn't work, and it seems to me that what I get is just a 1x1 cell array, and not the function handle within it.
I am not fixed on using cell arrays, so if another collection works it's fine by me.
This is my code:
func_array = {#(x) x, #(x) 2*x }
a = func_array(1) %%% a = #(x) x
a(2) %%% (error-red) Index exceeds matrix dimensions.
a(0.2) %%% (error-red) Subscript indices must either be real positive integers or
logicals.
Thank you
Amir

The problem is in this line:
a = func_array(1)
you need to access the content of the cell array, not the element.
a = func_array{1}
and everything works fine. The visual output in the command window looks the same, which is truly a little misleading, but have a look in the workspace to see the difference.
As mentioned by chappjc in the comments, the intermediate variable is not necessary. You could call your functions as follows:
func_array{2}(4) %// 2*4
ans = 8
Explanation of errors:
a(2) %%% (error-red) Index exceeds matrix dimensions.
a is still a cell array, but just with one element, therefore a(2) is out of range.
a(0.2) %%% (error red) Subscript indices must either be real positive ...
... and arrays can't be indexed with decimals. But that wasn't your intention anyway ;)

Related

Error in Matlab Coder: Index exceeds array dimensions

I am trying to convert .m script to C++ using MATLAB Coder.
function P=r_p(1,var1,var3)
p=[[3,7]
[10,15]
[6,19]
[21,19]
[43,11]
[969,2]
[113,9]
[43,59]
[21,15]
[6,15]
[10,18]
[3,15]];
tmax=sum(p(:,1))+41;
coder.varsize('x');
x=ones(9,11).*[0:10:100]; % getting error in this line: [9x11]~=[1x11]. Since size of x is varying in for loop, so i should tell coder that it is variable size, So I used Varsize
for t=11:tmax
a1=(rand-0.5)*1;
a9=(rand-0.5)*1.25;
a2=(rand-0.5)*1.5;
a8=(rand-0.5)*1.75;
a3=(rand-0.5)*2.0;
a7=(rand-0.5)*2.25;
a4=(rand-0.5)*2.5;
a6=(rand-0.5)*2.75;
a5=(rand-0.5)*3;
x(1,t+1)=x(1,t)+a1;
if x(1,t+1)<(100-var1) || x(1,t+1)>(100+var1) % loop 1: x(1,11)+a1 value is is writing to x(1,12) So coder gives error "Index exceeds array dimensions. Index value 12 exceeds valid range [1-11] of array x".
x(1,t+1)=x(1,t); % In matlab it works fine, but coder throws error.
end
end
My question is Let say loop 1,
x(1,12)= x(1,11)+a1 In matlab this assignment works fine, but when converting it is throwing error " Index exceeds array dimensions. Index value 12 exceeds valid range [1-11] of array x" As I declared x as variable size coder should assign x(1,11)+a1 value to x(1,12) but it is not doing, instead throwing error. Why?
Since t is looping for 1289, if I specify bounds for x like
coder.varsize('x',[1290,1290],[0,0]) then Coder gives error in other part of the code i.e dimensions doesn't match. Ofcourse it should because dimension of x doesn't match with [ones(12,9)p(1,2)/9;(P_1s+var3/100P_1s.*randn(size(P_1s))/2)/9;zeros(30,9)].
is declaring x as variable size is correct step or not? if yes then what should be the work around for "index exceeds array dimensions error"
Please Let me know, what am I missing to convert it to C++ code
MATLAB Coder doesn't support 2 things you're using here: implicit expansion and growing arrays by assigning past the end of a dimension.
For implicit expansion, you can use:
x=bsxfun(#times,ones(9,11),[0:10:100]);
Assigning past the end of an array in MATLAB will grow the array. That's an error in Coder. There are 2 ways to overcome this:
Allocate your array to have the right number of elements up front
Use concatenation to grow an array: x = [x, newColumn]
In this example, you know tmax so I'd suggest just changing the allocation of x to have the right number of columns up front:
% Current initial value
x=bsxfun(#times,ones(9,11),[0:10:100]);
% Extra columns - please check my upper bound value
x=[x, zeros(9,tmax)];

Matlab: Extract LxN array from LxMxN array

Suppose x=zeros(L,M,N). For a fixed component, the remaining array is basically a matrix. So I should be able to do something like y = x(:,2,:). Then, I expect y to be a matrix, i.e. an LxN array. But I instead get a Lx1xN array.
How can I obtain a standard matrix from a three-dimensional array, after I fixed one component? I use matlab.
Use permute to rearrange the dimensions after indexing:
x = zeros(2,3,4); % L×M×N
y = permute(x(:,2,:), [1 3 2]); % move 2nd dimension to 3rd
The code sends the second dimension to the end. This transforms the L×1×N array into an L×N×1 array, which is the same as an L×N matrix, because trailing singleton dimensions are ignored; in fact, arrays can be considered to have an infinite number of trailing singleton dimensions. As a check,
>> size(y)
ans =
2 4
A word of caution: some people may be tempted to use the simpler y = squeeze(x(:,2,:)), but that squeezes all (non-trailing) singleton dimensions, not just the second, and so it gives a wrong result for L=1.
You can use reshape:
y = reshape(x(:,2,:), [L N]);

removing second layer for loop when defining array

Working in MATLAB R2017a. I'm trying to optimise a piece of code I'm working on. It uses arrays to store field values on a grid.
In order to create a specific function in a field array I originally used the straight forward method of two for loops iterating over all the array elements. But i know for loops are slow so since then I came back and tried my best to remove them. However I could only manage to remove one of the loops; leaving me with this:
for n = 1:1:K
%%% define initial pertubation
t=n*dt;
% create array for source Ez field.
xtemps = (1:Ng)*dX;
for k = 1:Ng
ztemp = k*dX;
Ez0(k,:) = THzamp * (1/(1+exp(-(t-stepuppos)))) * exp(-((xtemps-...
THzstartx).^2)./(bx^2)) .* (t-((ztemp-THzstartz)/vg))*exp(-((t-((ztemp-...
THzstartz)/vg))^2)/(bt^2));
end
The important bit here is the last 5 lines, but I figured the stuff before might be important for context. I've removed the for loop looping over the x coordinates. I want to vectorize the z/k for loop but I can't figure out how to distinguish between the dimensions with the array oporators.
Edit: THzamp, stepuppos, bx, bt, THzstartz, THzstartx are all just scalars, they control the function (Ez0) I'm trying to create. dX and t are also just scalars. Ez0 is a square array of size Ng.
What I want to achieve is to remove the for loop that loops over k, so that that the values of ztemp are defined in a vector (like xtemps already is), rather than individually in the loop. However, I don't know how I'd write the definition of Ez0 in that case.
First time posting here, if I'm doing it wrong let me know. If you need more info just ask.
It isn't clear if n is used in the other headers and as stated in the comments your sizes aren't properly defined so you'll have to ensure the sizes are correct.
However, you can give this vectorize code a try.
n = 1:K
%%% define initial pertubation
t=n*dt;
% create array for source Ez field.
xtemps = (1:Ng)*dX;
for k = 1:Ng
ztemp = k*dX;
Ez0(k,:) = THzamp .* (1./(1+exp(-(t-stepuppos)))) .* exp(-((xtemps-...
THzstartx).^2)./(bx^2)) .* (t-((ztemp-THzstartz)/vg)).*exp(-((t-((ztemp-...
THzstartz)/vg)).^2)/(bt.^2));
end
So now t has the size K you'll need to ensure stepupposand (ztemp-THzstartz)/vg) have the same size K. Also you can take a look at vectors vs array operators here.

how to make matlab loop over 2d array faster

I have the above loop running on the above variables:
A is a 2d array of size mxn.
mask is a 1d logical array of size 1xn
results is a 1d array of size 1xn
B is a vector of the form mx1
C is a mxm matrix, m is the same as the above.
Edit: expanded foo(x) into the function.
here is the code:
temp = (B.'*C*B);
for k = 1:n
x = A(:,k);
if(mask(k) == 1)
result(k) = (B.'*C*x)^2 / (temp*(x.'*C*x)); %returns scalar
end
end
take note, I am already successfully using the above code as a parfor loop instead of for. I was hoping you would be able to suggest some way to use meshgrid or the sort to yield better performance improvement. I don't think I have RAM problems so a solution can also be expensive memory wise.
Many thanks.
try this:
result=(B.'*C*A).^2./diag(temp*(A.'*C*A))'.*mask;
This vectorization via matrix multiplication will also make sure that result is a 1xn vector. In the code you provided there can be a case where the last elements in mask are zeros, in this case your code will truncate result to a smaller length, whereas, in the answer it'll keep these elements zero.
If your foo admits matrix input, you could do:
result = zeros(1,n); % preallocate result with zeros
mask = logical(mask); % make mask logical type
result(mask) = foo(A(mask),:); % compute foo for all selected columns

Matlab array of struct : Fast assignment

Is there any way to "vector" assign an array of struct.
Currently I can
edges(1000000) = struct('weight',1.0); //This really does not assign the value, I checked on 2009A.
for i=1:1000000; edges(i).weight=1.0; end;
But that is slow, I want to do something more like
edges(:).weight=[rand(1000000,1)]; //with or without the square brackets.
Any ideas/suggestions to vectorize this assignment, so that it will be faster.
Thanks in advance.
This is much faster than deal or a loop (at least on my system):
N=10000;
edge(N) = struct('weight',1.0); % initialize the array
values = rand(1,N); % set the values as a vector
W = mat2cell(values, 1,ones(1,N)); % convert values to a cell
[edge(:).weight] = W{:};
Using curly braces on the right gives a comma separated value list of all the values in W (i.e. N outputs) and using square braces on the right assigns those N outputs to the N values in edge(:).weight.
You can try using the Matlab function deal, but I found it requires to tweak the input a little (using this question: In Matlab, for a multiple input function, how to use a single input as multiple inputs?), maybe there is something simpler.
n=100000;
edges(n)=struct('weight',1.0);
m=mat2cell(rand(n,1),ones(n,1),1);
[edges(:).weight]=deal(m{:});
Also I found that this is not nearly as fast as the for loop on my computer (~0.35s for deal versus ~0.05s for the loop) presumably because of the call to mat2cell. The difference in speed is reduced if you use this more than once but it stays in favor of the for loop.
You could simply write:
edges = struct('weight', num2cell(rand(1000000,1)));
Is there something requiring you to particularly use a struct in this way?
Consider replacing your array of structs with simply a separate array for each member of the struct.
weights = rand(1, 1000);
If you have a struct member which is an array, you can make an extra dimension:
matrices = rand(3, 3, 1000);
If you just want to keep things neat, you could put these arrays into a struct:
edges.weights = weights;
edges.matrices = matrices;
But if you need to keep an array of structs, I think you can do
[edges.weight] = rand(1, 1000);
The reason that the structs in your example don't get initialized properly is that the syntax you're using only addresses the very last element in the struct array. For a nonexistent array, the rest of them get implicitly filled in with structs that have the default value [] in all their fields.
To make this behavior clear, try doing a short array with clear edges; edges(1:3) = struct('weight',1.0) and looking at each of edges(1), edges(2), and edges(3). The edges(3) element has 1.0 in its weight like you want; the others have [].
The syntax for efficiently initializing an array of structs is one of these.
% Using repmat and full assignment
edges = repmat(struct('weight', 1.0), [1 1000]);
% Using indexing
% NOTE: Only correct if variable is uninitialized!!!
edges(1:1000) = struct('weight', 1.0); % QUESTIONABLE
Note the 1:1000 instead of just 1000 when indexing in to the uninitialized edges array.
There's a problem with the edges(1:1000) form: if edges is already initialized, this syntax will just update the values of selected elements. If edges has more than 1000 elements, the others will be left unchanged, and your code will be buggy. Or if edges is a different type, you could get an error or weird behavior depending on its existing datatype. To be safe, you need to do clear edges before initializing using the indexing syntax. So it's better to just do full assignment with the repmat form.
BUT: Regardless of how you initialize it, an array-of-structs like this is always going to be inherently slow to work with for larger data sets. You can't do real "vectorized" operations on it because your primitive arrays are all broken up in to separate mxArrays inside each struct element. That includes the field assignment in your question – it is not possible to vectorize that. Instead, you should switch a struct-of-arrays like Brian L's answer suggests.
You can use a reverse struct and then do all operations without any errors
like this
x.E(1)=1;
x.E(2)=3;
x.E(2)=8;
x.E(3)=5;
and then the operation like the following
x.E
ans =
3 8 5
or like this
x.E(1:2)=2
x =
E: [2 2 5]
or maybe this
x.E(1:3)=[2,3,4]*5
x =
E: [10 15 20]
It is really faster than for_loop and you do not need other big functions to slow your program.

Resources