Creating a cell array of different randomized matrices - arrays

I'm trying to create a cell array of size N,
where every cell is a randomized Matrix of size M,
I've tried using deal or simple assignments, but the end result is always N identical Matrices of size M
for example:
N=20;
M=10;
CellArray=cell(1,N);
CellArray(1:20)={rand(M)};
this yields identical matrices in each cell, iv'e tried writing the assignment like so:
CellArray{1:20}={rand(M)};
but this yields the following error:
The right hand side of this assignment has too few values to satisfy the left hand side.
the ends results should be a set of transition probability matrices to be used for a model i'm constructing,
there's a currently working version of the model, but it uses loops to create the matrices, and works rather slowly,
i'd be thankful for any help

If you don't want to use loops because you are interested in a low execution time, get rid of the cells.
RandomArray=rand(M,M,N)
You can access each slice, which is your intended MxM matrix, using RandomArray(:,:,index)

Use cellfun:
N = 20;
M = 10;
CellArray = cellfun(#(x) rand(M), cell(1,N), 'uni',0)
For every cell it newly calls rand(M) - unlike before, you were assigning the same rand(M) to every cell, which was just computed once.

Related

Synchronizing variables in C

I have a recursive function that goes through the elements of a matrix by a specific rule. Every time I go through an element I am calculating a result based on the element I am in the matrix at that moment, and when all the calls of the function end I am back to the first element I started at I have the result I need in that result I mentioned before.
Now the problem is that I have to replace every element of the matrix that I went through with this result. From what I am thinking i have 3 options :
Use the same algorithm to call the function again from the starting element and go through it again, basically going through the same path and replacing the elements with the result (this would be the most inefficient as the algorithm and the size of the matrix are pretty big )
Memorizing the addresses of the elements I am arriving at in the matrix on every callout, then I would have a vector of addresses and after the function finishes I am just going through
that vector and replacing the values with the one I calculating.
This is quite a longshot for me to implement but I was thinking that I could synchronize all the variables in the positions that I have arrived in the matrix with one external variable. When the function finishes and I have my result I just change the value of this external variable with the result and all the other elements in the matrix that I have linked this variable to would automatically change.
My question is how could I implement something like "3."? is there any way you can synchronize a variable(or multiple ones) to always have the same value as another one that is constantly updating ?
From a definition of a Matrix like:
struct Matrix {
int N, M;
int *Mat;
};
Type Values[];
Where the value at (i,j) is Values[G->Mat[G->M * i + j]]; that is Mat just holds indexes into Values[] which can be dynamically extended. At the beginning if a path traversal, you could allocate a new Values[t], and change each visited node (i,j) to be t: G->Mat[G->M * i + j] = t. When you assign Values[t], all of the nodes linked to it will be automatically updated.
While you are making your traversal, you would use their value, then change their index as you moved to the next node. Serendipitously, if you encountered a node already with an index of t, you would know that you are caught in a cycle.
Although I might have misread your requirement terribly.

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.

store a vector as an (i,j) entry of a matrix in matlab

This is a simplified version of the project I am doing. I can get around this using other methods. I was just wondering, is it possible to do this in matlab ?
I want to store a 1*2 vector [100,100] to the (1,1) entry of a given matrix a. The following is the code.
a=zeros(2,2);
a(1,1)=[100,100];
Then I get Subscripted assignment dimension mismatch error.
I could use cell array instead. But there are not so many handy functions (like tril) for cell array compared with matrix. So, I was just wondering, does anyone know how to handle this situation or this is just a trivial case not need to mention at all. Many thanks for your time and attention.
You can use 3-d matrix instead of 2-d matrix if you already know the length of vector.
a = zeros (2,2,2) ;
a(1,1,:) = [100, 100] ;
or
a = [];
a (1,1,:) = [100,100];
In above example, you have to take care of indexing by yourself and matrix a can be in arbitrary dimensions.

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.

Entry level question about Matlab array operation

Hey guys. I have this question to ask. In C programming, if we want to store several values in an array, we implement that using loops like this:
j=0; //initialize
for (idx=1,idx less than a constant; idex++)
{
slope[j]=(y2-y1)/(x2-x1);
j++;
}
My question is in Matlab do we have any simpler way to get the same array 'slope' without manually increasing j? Something like:
for idx=1:constant
slope[]=(y2-y1)/(x2-x1);
Thank you!
Such operations can usually be done without looping.
For example, if the slope is the same for all entries, you can write
slope = ones(numRows,numCols) * (y2-y1)/(x2-x1);
where numRows and numCols are the size of the array slope.
If you have a list of y-values and x-values, and you want the slope at every point, you can call
slope = (y(2:end)-y(1:end-1))./(x(2:end)-x(1:end-1)
and get everything in one go. Note that y(2:end) are all elements from the second to the last, and y(1:end-1) are all elements from the first to the second to last. Thus, the first element of the slope is calculated from the difference between the second and the first element of y. Also, note the ./ instead of /. The dot makes it an element-wise operation, meaning that I divide the first element of the array in the numerator by the first element of the array in the denominator, etc.

Resources