Matlab: Create vector of arrays [duplicate] - matlab

This question already has an answer here:
Creating a list of matrices [duplicate]
(1 answer)
Closed 3 years ago.
I am a python (and numpy) regular who just started using Matlab. I am solving boundary value problems using bv4pc, and I want to store the result arrays, solved for different parameters, in a larger array.
For example, consider the following code that returns a result vector y for each value of the parameter t -
for j = 1:loops
t = 1/(sqrt(2).^j)
% solve ODE that depends on parameter t
sol = bvp4c(#(x,y)elasticaODE(x,y,t),#(ya,yb)elasticaBC(ya,yb,t),solinit,options);
% The solution at the mesh points
x = sol.x;
y = sol.y;
In python, I would just do:
yVector = []
for (t in tArray):
... solve ODE, get y ...
yVector.append(y)
yVector = np.array(yVector)
What is the equivalent in Matlab?

In Matlab, most variables are matrices by default. There are two exceptions that might be what you are looking for:
1- Cells
Cells are similar to Python arrays, in the sense that each element can be anything
my_cell = {'a', 1, "wut", [1,2,3]};
And you can access the elements using the curly braces notation:
my_cell{1} % yields 'a'
my_cell{4}(2) % yields 2
2-Struct Arrays
You can define a struct by declaring it's fields, and they are mutable, a bit like in a Python dictionary:
my_struct.a = 1
my_struct.b = 2
If you have structs with the same fields, you can create a vector of structs:
my_second_struct.a = 3
my_second_struct.b = 4
my_vector_of_structs = [my_struct; my_second_struct]
Again, each field in a struct can be anything, even another struct.

Related

matlab: specify which dimension to index [duplicate]

This question already has answers here:
On shape-agnostic slicing of ndarrays
(2 answers)
Dynamic slicing of Matlab array
(1 answer)
Closed 4 years ago.
Imagine a function where you want to output a snippet in a user-specified dimension of a n-dimensional matrix
function result=a(x,dim)
window=1:10;
dim=3;
result=x(:,:,window);
end
How can I put window to the desired dimension? E.g. if dim=2; then result=x(:,window,:).
The way I can think of right now is to evaluate a string command that puts window in the correct position - or use a lot of if then else blocks. What's a better way of doing this?
You can do this using a cell array to define your indexes, following the examples here.
Specifically, if you have a matrix
x = ones(7,5,9);
You can define the indexes you want like:
% get all the indexes in all dimensions
all_indexes = {':', ':', ':'};
% get all indexes in dimensions 1 and 3, and just indices 1:4 in dimension 2
indexes_2 = {':', 1:4, ':'};
And then get those indexes from your matrix x like
a = x(all_indexes{:});
b = x(indexes_2{:});
So, you could write a function like
function result=extract_cells(x, dim, window)
% Create blank cell array {':', ':', ...} with entries ':' for each dimension
% Edit (c/o Cris Luengo): need to use ndims(x) to get the number of dimensions
num_dims = ndims(x)
dims = cell(1, num_dims);
dims(:) = {':'};
% Set the specified window of cells in the specified dimension
dims{dim} = window;
% Pick out the required cells
result=x(dims{:});
end
Which could return all the cells in the dimensions other than one specified, and in that direction would return the cells in the range given by window. So in the following code, a and b would be equivalent.
a = extract_cells(x, 2, 1:5);
b = x(:, 1:5, :)

In matlab is it possible to vectorize in more than one dimension?

The matlab documentation explains vectorization with
i = 0;
for t = 0:.01:10
i = i + 1;
y(i) = sin(t);
end
This is a vectorized version of the same code:
t = 0:.01:10;
y = sin(t);
Can I apply vectorization to a function with non-scalar inputs and outputs? As a toy example, take the function foo
function out = foo(in)
out(1) = in(1);
out(2) = in(2);
end
It's just the identity. I'd like to do something like
inputs = [1,2; 3,4; 5,6];
t = 1:3;
outputs = foo(inputs(t,:))
and get
ans =
1 2
3 4
5 6
Instead I end up with
ans =
1 3
Clearly, I'm either doing it wrong or it's not possible. Help!
It is possible to vectorize in Matlab in N-dimensions. As it was mentioned by Andrew you can simply writte a function like:
function out = foo(in)
out(:,1:size(in,2)) = in(:,1:size(in,2));
end
Output will be as desired.
Using the (:) index operator on n-dimensional arrays allows you to perform vectorized operations on all elements. You can use e.g. reshape to put the result back into the same form as the input.
function out=foo(in)
out=reshape(in(:),size(in));
The unexpected output
The reason your output is [1 3] has to do with linear indexing of matrixes. In particular this means that you can access the full matrix with a vector, where you first count through the first column, then the second column and so on. For a 3x2 matrix this would be:
1 4
2 5
3 6
Therefore in(1) = 1 is the first element in the first column. in(2) = 3 is the second element in the first column. Find the full documentation for matrix indexing here.
The input
Secondly writing outputs = foo(inputs(t,:)) means that you take all rows specified in t with no condition to the columns. Therefore in your example it is equivalent to write outputs = foo(inputs) and outputs = foo(inputs(t,:)) as you put in all 3 rows. What you could do is let foo() have two arguments.
function out = foo(t,in)
out = in(t,:)
To have access to the rows inside the function you could write something like:
function out = foo(in);
[x,y] = size(in);
for t = 1:x
out(t,:) = in(t,:);
end
Normally vectorization is used to avoid looping through scalars. There are a lot of clever ways to simplify code and reduce it's computation time. Most techniques like .* ,.^, bsxfun() are already presented in the documentation about vectorization you already found. The tricky part is to find the right way to apply these methods. It takes a lot of experience and a sharp eye to fully utilize them, as in every case you need to adjust to the specific logic of your opperations.
Feel free to ask if you still struggle with your problem.

Mysterious MATLAB error using ./ in a for loop [duplicate]

This question already has answers here:
Multiple loop variables Matlab
(3 answers)
Closed 7 years ago.
I need to make a for loop in MATLAB to divide each column in a matrix by a separate column vector. I only want to do this for a selection of the columns in the matrix, not all the columns.
This is what I'd like to do, where Indexes is a 19x1 vector of integers (not all consecutive numbers), big_matrix is 82x24, and other_column is 82x1:
matrix_to_fill = zeros(82,length(Indexes));
for x = Indexes
new_column = big_matrix(:,x)./other_column;
new_index = find(Indexes==x);
matrix_to_fill(:,new_index) = new_column;
end
When I run this I get the following error:
Error using ./
Matrix dimensions must agree.
I can run each iteration separately without getting errors, so I know that the matrix dimensions agree. What's more, if I type out the Indexes as a vector it works fine:
matrix_to_fill = zeros(82,length(Indexes));
for x = [1,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,23]
new_column = big_matrix(:,x)./other_column;
new_index = find(Indexes==x);
matrix_to_fill(:,new_index) = new_column;
end
And I think the "x=Indexes" syntax is fine because I've tested that using just:
for x = Indexes
disp(x)
end
So I'm completely stumped. Any help would be much appreciated!
The problem is in your definition of the for loop. When you say that you think the "x=Indexes" syntax is correct you haven't been observant enough to see that it is not correct.
What you need is
for x = Indexes'
% Do your looping
end
Note the transpose in the above.
If you do
for x = Indexes
disp(x)
end
Then the loop is executed once, with x taking on the value of the whole vector.
If you do
for x = Indexes'
disp(x)
end
then x will take on the individual elements of the matrix and you'll have 19 scalars displayed, once each time through the loop.

How to store a series of vectors from a for loop matlab [duplicate]

This question already has an answer here:
Subscript indices must either be real positive integers or logicals?
(1 answer)
Closed 8 years ago.
I have a for loop which generates a vector. i want to store these vectors in a matrix.
normally i would do:
for r=1:100
vec=[x:y]+r;
mat(:,r)=vec
end
But this doesnt work, because i have something like:
dr=10/20
for r=1:dr:20
vec=[x;y]+r;
...
How would I store the vectors in a matrix now? Because i cant use r for the column indices, because the values of r arent integers most of the time.
Many options eg:
r=1:dr:20
for rr=1:length(r)
vec=[x;y]+r(rr);
mat(:,rr)=vec;
...
or
col = 1;
for r=1:dr:20
vec=[x;y]+r;
mat(:,col)=vec;
col = col + 1;
....
But whatever you choose you must preallocate mat before your for loop like this:
mat = zeros(length(x) + length(y), length(1:dr:20))
Pre-allocation is essential when using loops in Matlab or they will run very inefficiently.

How to pass the value of an array to a mathematical function in Matlab?

I have a defined mathematical function: f =Inline('x1^2+x2^2+2*x1*x2','x1','x2')
and I have an array that represents the number value of x1 and x2. (e.g. the array is A=[1 2])
I want to automate the process of getting the f(x1,x2), but I couldn't figure out the right way that Matlab can take in the array and assign values to x1 and x2.
What can I do to pass in the array values to the mathematical model and get the function value?
You should be using anonymous functions instead of inline since inline will be removed in a future release of MATLAB.
Example (from the docs):
sqr = #(x) x.^2;
a = sqr(5)
a =
25
In your case:
f = #(x) x(1)^2+x(2)^2+2*x(1)*x(2);
Now it expects x to be a two (or more) value array.
A = [1 2];
f(A) =
9
Note:
I don't have MATLAB on my home computer so I haven't actually tested this but it should get you going in the right direction. Have a look over the docs and you'll be fine.