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

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.

Related

Vectorizing access to a slice of a three-dimensional matrix in MATLAB

I have a three-dimensional matrix of these sizes, approximately
A = rand(20, 1000, 20);
where the first and third dimensions are always the same length. I want to zero the elements in a main diagonal slice. This does what I mean
for ii = 1:size(A, 1)
A(ii, :, ii) = 0;
end
Is there a vectorized or otherwise faster way to do this? This code runs about 100,000 times, with these approximate sizes, but not the exact same sizes each time.
You can use logical indexing for multible tailing dimensions while using subscript indexing for all previous dimensions individually. This way you can easily do the operation on an 1000 20 20 matrix. To apply this to your matrix, permute is required which might be slow:
n=size(A,3)
A=permute(A,[2,1,3]);
A(:,diag(true(n,1)))=0;
A=permute(A,[2,1,3]);
If it would be possible to permanently swap the dimensions of A in your code and avoid the permute, this would lead to the fastest solution.
Alternatively you can use repmat to expand the index to the dimensions of A
ix=repmat(reshape(diag(true(n,1)),n,1,n),[1,size(A,2),1])
A(ix)=0
For matrices of the same size you could keep ix. Not having access to MATLAB right now, I don't know which solution is faster.
You can use bsxfun to build a linear index of the elements to be zeroed:
ind = bsxfun(#plus, (0:size(A,2)-1).'*size(A,1), 1:size(A,1)*size(A,2)+1:numel(A) );
A(ind) = 0;

1 dimensional array for indexing a 3D matrix

I'm trying to write a linear index for 3D matrix. Is there a formula to determine what is the linear index of (i,j,k) th element in a matrix with (nx,ny,nz) dimensions?
Is there any difference whether I'm using C of FORTRAN or something else?
I searched for similar questions but nothing was founded .
Thanks for any guide.
Actually, Fortran is column major order. That means that when linearly indexing a multidimensional array the first index grows faster, i.e.
ind(i,j,k) = i + (j-1)*nx + (k-1)*ny*nx
where I assume indexing from 1. The function ind gives an index the element (i,j,k) would have when looking at the same as a one-dimensional array (e.g., in sequence association).
Most other languages, including C derivatives, use the row-major order, so that the last index grows the fastest. They also index from 0.
ind(i,j,k) = k + j*nz + i*ny*nz
There are also other differences — the multidimensional arrays are actually arrays of arrays (similar to pointers to pointers) in C.

Creating a cell array of different randomized matrices

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.

The idea of C array in matlab

Is it possible to apply the idea of array in C to MATLAB
For example, if we have
Double array[10];
and if we want to assign a value we write for example
Array[5]=2;
Is there any way to write equivalent one in MATLAB ?
I'm not sure what you mean by "Is it possible to apply the idea of array in C to MATLAB". An array is just a 1D list of numbers (or other data types). MATLAB primarily is designed to work with matrices (MATLAB is short for Matrix laborartory) and an array or vector is simply a special case of a matrix. So I guess the answer to your question is yes, if I have understood correctly.
To initialise arrays or matrices in MATLAB we use zeros or ones:
>> array = zeros(1,5)
array =
0 0 0 0 0
We can then index elements of the array in the same way as C:
>> array(3) = 3
array =
0 0 3 0 0
Note, however, that MATLAB array indexing is one based whereas C arrays are zero based.
This article describes matrix/array indexing in MATLAB.
You can define your own class, override the [] operator.
I described the mechanism in Here
Since it is a custom function, you might as well change the 1-based indexing to 0-based indexing.
Regarding the constructor, I doubt that you can do it.
Anyhow, why would you want to do it?
You will confuse all of the Matlab users, and cause havoc.
When in Rome, do as Romans do.
Yes you can. Arrays are used in C and MATLAB and they can be used for the same functions. Except, please keep in mind the array-indexing of C and MATLAB are different.
The first element of a C array has an index of zero. i.e. in X = [10 20 30 40], x[0] will return 10. But in MATLAB, this will give an error. To access the number 10, you have to use the expression x[1] in MATLAB.
There is no indexing operator []. You must use () for indexing array.
If you write
x = 1:10;
x[2]
then you'll get the following error
x[2]
|
Error: Unbalanced or unexpected parenthesis or bracket.

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