Matlab How to iterate a function through a list - matlab

I need some help iterating over a function that depends on two variables.
So let's say I have a function that depends on two variables.
Let's call it f = x + y
Now, I have a two lists, one of x variables and one of y variables. For example,
xlist = [1 2 3] and
ylist = [4 5 6]
And I want to go through each element of the lists and plug it into f. For example, set x=1 and then evaluate f for y=4, then y=5, then y=6... and repeat for x=2 and x=3.
Finally, I want to return a matrix of the calculated values. For the example above, the answer should be
[5 6 7];[6 7 8];[7 8 9]
How would I go about doing this?

Assuming the function can't be vectorized and thus you really need to iterate, a simple way is via ndgrid (to create x, y values that describe all possible pairs) and arrayfun (to iterate over the two x, y values at the same time):
f = #(x,y) x+y; % Or f = #fun, if fun is a function defined elsewhere
xlist = [1 2 3];
ylist = [4 5 6];
[xx, yy] = ndgrid(xlist, ylist); % all pairs
result = arrayfun(f, xx, yy);
In many cases the function can be vectorized, which results in faster code. For the example function this would be done defining f as
f = #(x,y) bsxfun(#plus, x(:), y(:).');
or in recent Matlab versions you can exploit implicit singleton expansion and just write
f = #(x,y) x(:)+y(:).';
In either case, note that the two arguments of addition are forced to be a column vector (x(:)) and a row vector (y(:).'), so that singleton expansion will automatically create all pairs:
xlist = [1 2 3];
ylist = [4 5 6];
result = f(xlist, ylist);

Another way to do it would be to use two for loops:
x_values=[2,4,6,8];
y_values=[1,3,5,7];
%initialize a matrix with zeros
output_matrix=zeros(length(x_values),length(y_values));
for i=1:length(x_values)
for j=1:length(y_values)
output_matrix(i,j)=x_values(i)+y_values(j);
end
end
output_matrix

Related

Creating anonymous function handle dynamically in MATLAB using numeric matrices as sources

I'm kinda lost in a problem where I need to (dynamically) create an anonymous function handle from huge matrices and 192 variables.
I'll try to give you an (easier) example of what I have to do and what I have in mind to achieve it (but without a clue how to do it in MATLAB ):
syms x1 x2 x3 x4 real
X = [x1 x2 x3 x4]'
F = [1 2 3 4; 1 2 3 4]
Y = [9 8]'
my_fun = (F*X + Y)' * (F*X + Y)
%solve my_fun to min for X
So, this is what I want to have (my_fun).
The thing is, that there will be x1 to x192, F will be like 10000x192 and Y like 10000x1. Using symbolic tb is very slow and since I later have to calculate the Hessian it is superdupser slow.
I now found a way to numerically calculate the Hessian (from MATLAB file exchange) but have no clue, how to calculate my_fun as an (anonymous) function. I simply lack the skills of MATLAB + function handles. I already tried several things.
So, I think what I need to know is how to create X dynamically with x(1) to x(192) and then calculate my_fun = #(x) ...
EDIT: Thanks for the edit :)
The only thing that I can think of to solve this is by using a couple of loops to create the anonymous function handle as a string and then use str2fun, but I feel like this isn't the easiest way to get what I need :)
First of all: Delete your first two lines containing stuff from the symbolic toolbox. You won't need any of this.
You have two options:
Using a function-file:
These would be the contents of the file my_fun.m:
function result = my_fun(X)
F = [1 2 3 4; 1 2 3 4];
Y = [9 8]';
result = (F*X + Y)' * (F*X + Y);
You would then pass this function as an argument using #my_fun.
Using an anonymous function
You could define a function handle using an anonymous function using:
F = [1 2 3 4; 1 2 3 4];
Y = [9 8]';
my_fun = #(X) (F*X + Y)' * (F*X + Y);
This will capture the current contents of your local variables Fand Y. So changing F or Y afterwards won't change my_fun.
In contrast to the above version you will pass this using my_fun.

Extraction of components in vector function in MATLAB

I have a code segment as follows:
f = #(x) [x(1)^2 ; x(2)^2]
X = [2; 3]
When I type f(X), I simply obtain the following:
f(X)
ans =
4
9
Now, think that there is a for loop going from 1 to 2. According to value of loop, I want to extract the row which is the value of loop. For instance:
for i=1:2
when i=1 it will extract 1st element, which is: 4
when i=2 it will extract 2nd element, which is: 9
end
I did this by the following:
for i=1:2
X1 = f(X)
Result = X1(i)
end
This works perfectly well. However, I do not want to define such intermediate variables. Is it possible directly to extract the certain row of the function?
Another way of doing is is to create a unit vector and multiply the function itself, but I do not want this as well. What I mean is the following:
when i=1; unit = [1 0]
[1 0]*[2;4] = 2
when i=2; unit = [0 1]
[0 1]*[2;4] = 4
This also works well but I do not want this.
I just want to call directly f(X) but give me the row desired.
Thanks in advance!
You are defining your function as :
f = #(x) [x(1)^2 ; x(2)^2]
If you give x as a column vector, it would read row-wise.
Thus, your row-indexing method of i=1,2 won't work, because the function would need first and second row with x(1) and x(2) at the same time.
I think, the best you can do is this -
X1 = f(X)
for i=1:2
X1(i)
end
The best practice to solve your problem and still access each output from using the function on each element of X would be something like this -
f = #(x) x.^2;
X = [2 3];
X1 = f(X);
for i=1:numel(X)
Result = X1(i);
%// Do something with Result
end
Edit 1
f = #(x) x.^2;
X = [2 3];
for i=1:numel(X)
Result = f(X(i)) %%// Instead of f(X,1) you need f(X(1)) and so on..
%// Do something with Result
end
Here's another possible way of doing it:
f = #(x,n) [x(n).^2];
Where n is the indices of x you want returned.
x = [3 5];
f(x,1:2)
ans =
9 25
or
f(x,2)
ans =
25

Matlab nested list data structure

I am thinking of recast a double for loop into something I can use with parallel computing. Specifically, I have
for i = 1 : N
x = x0+i*dx;
for j = 1 : N
y = y0+j*dy;
end
end
and the main program calls functions that require x and y as input arguments. In my problem the variables x and y are independent and so the two for loops should be able to recast into something simpler that can be run more efficiently taking advantage of matlab's matrix computations.
I'm thinking of creating a nested 2D array like (symbolically):
A = [{x0,y0},{x0,y1},{x0,y2},...,{x0,yN};
{x1,y0},{x1,y1},{x1,y2},...,{x1,yN};
...
{xN,y0},{xN,y1},{xN,y2},...,{xN,yN}]
i.e. each element in a 2D array is a 2-tuple {xi,yi} formed from the elements of the vectors x and y. Can I create such an object in matlab? If so, how can I call each individual element within each tuple? I need to have a way to call each element, e.g. x2 in {x2,y1}, in this array.
I am thinking of doing this so as to have the program run in parallel with input arguments given by each set of tuple {xi,yi} simultaneously, using the parallel processing toolbox on a GPU.
Many thanks in advance for your help.
James
I think what you are actually looking for is either meshgrid or ndgrid
>> [x y] = meshgrid( 1:N, 1:N )
For N=3 you'll get
>> [x y] = meshgrid( 1:3, 1:3 )
x =
1 2 3
1 2 3
1 2 3
y =
1 1 1
2 2 2
3 3 3
Now if you want to access a pair you can access its x and y coordinate for each matrix.
For example accessing the coordinates of ii=1, jj=2
>> ii=1; jj=2;
>> [x(ii,jj) y(ii,jj)]
Several comments
If you want both x and y to assume the same range of values (like in this example 1:N), you can skip the second arguemnt of meshgrid
>> [x y] = meshgrid( 1:N );
You can modify the inputs of meshgrid to capture the exact pattern you want for x and y, using dx and dy:
>> [x y] = meshgrid( x0 + (1:N)*dx, y0 + (1:N)*dy );
It is best not to use i and j as variable names in Matlab.

Getting the N-dimensional product of vectors

I am trying to write code to get the 'N-dimensional product' of vectors. So for example, if I have 2 vectors of length L, x & y, then the '2-dimensional product' is simply the regular vector product, R=x*y', so that each entry of R, R(i,j) is the product of the i'th element of x and the j'th element of y, aka R(i,j)=x(i)*y(j).
The problem is how to elegantly generalize this in matlab for arbitrary dimensions. This is I had 3 vectors, x,y,z, I want the 3 dimensional array, R, such that R(i,j,k)=x(i)*y(j)*z(k).
Same thing for 4 vectors, x1,x2,x3,x4: R(i1,i2,i3,i4)=x1(i1)*x2(i2)*x3(i3)*x4(i4), etc...
Also, I do NOT know the number of dimensions beforehand. The code must be able to handle an arbitrary number of input vectors, and the number of input vectors corresponds to the dimensionality of the final answer.
Is there any easy matlab trick to do this and avoid going through each element of R specifically?
Thanks!
I think by "regular vector product" you mean outer product.
In any case, you can use the ndgrid function. I like this more than using bsxfun as it's a little more straightforward.
% make some vectors
w = 1:10;
x = w+1;
y = x+1;
z = y+1;
vecs = {w,x,y,z};
nvecs = length(vecs);
[grids{1:nvecs}] = ndgrid(vecs{:});
R = grids{1};
for i=2:nvecs
R = R .* grids{i};
end;
% Check results
for i=1:10
for j=1:10
for k=1:10
for l=1:10
V(i,j,k,l) = R(i,j,k,l) == w(i)*x(j)*y(k)*z(l);
end;
end;
end;
end;
all(V(:))
ans = 1
The built-in function bsxfun is a fast utility that should be able to help. It is designed to perform 2 input functions on a per-element basis for two inputs with mismatching dimensions. Singletons dimensions are expanded, and non-singleton dimensions need to match. (It sounds confusing, but once grok'd it useful in many ways.)
As I understand your problem, you can adjust the dimension shape of each vector to define the dimension that it should be defined across. Then use nested bsxfun calls to perform the multiplication.
Example code follows:
%Some inputs, N-by-1 vectors
x = [1; 3; 9];
y = [1; 2; 4];
z = [1; 5];
%The computation you describe, using nested BSXFUN calls
bsxfun(#times, bsxfun(#times, ... %Nested BSX fun calls, 1 per dimension
x, ... % First argument, in dimension 1
permute(y,2:-1:1) ) , ... % Second argument, permuited to dimension 2
permute(z,3:-1:1) ) % Third argument, permuted to dimension 3
%Result
% ans(:,:,1) =
% 1 2 4
% 3 6 12
% 9 18 36
% ans(:,:,2) =
% 5 10 20
% 15 30 60
% 45 90 180
To handle an arbitrary number of dimensions, this can be expanded using a recursive or loop construct. The loop would look something like this:
allInputs = {[1; 3; 9], [1; 2; 4], [1; 5]};
accumulatedResult = allInputs {1};
for ix = 2:length(allInputs)
accumulatedResult = bsxfun(#times, ...
accumulatedResult, ...
permute(allInputs{ix},ix:-1:1));
end

Within a function, how do I create variables that will accept 2 equally sized matrices and a scalar?

function[f] = get_f(y,Q,L)
Q = zeros(2) % creating a 2x2 matrix of zeros
L = diag(zeros(2)) % creating a diagonal matrix
% still playing with how I can pull y in as a scalar, I'm thinking I have
% to assign it earlier in the script where I call this function.
f = expm((Q-L).^y).*L % execution of the function itself
How do I tell the function to look for an entered scalar, and 2 equally sized matrices, then execute the listed command?
In your function, y is whatever you put as the first argument in your function call.
For instance:
get_f(3.14, [1 2; 3 4], [1 0; 0 1])
calls the function get_f with
y = 3.14
Q = [1 2; 3 4]
L = [1 0; 0 1]
so your function will work.
However, if you want your function to fail if y is not a scalar or if Q and L don't have the same size, you can add a condition like this at the beginning of your function:
if ~isscalar(y)
error('y must be a scalar')
end
if any(size(Q) ~= size(L))
error('Q and L must have the same size')
end