Index of elements - matlab

I have the following for-loop part of a function:
for i=1:5
for j=1:2
m=x(i)-c(j);
end
end
As a call to the function which includes the code above, I pass two values for c. Say the values passed are (3,5) for c1 and c2 respectively.
As you see in the for-loop above, I will have a two values for c, nanely, c(1) and c(2).
For the 3 and 5 values I have above, how can I assign them to c(1) and c(2) respectively?
When I did the following for instance:
c(1)=center1;
c(2)=center2;
where center1 and center2 represent the passed value to the function, I got the following error:
In an assignment A(I) = B, the number of elements in B and I must be
the same.
Error in functionName (line 32)
c(1)=center1;

It looks like center1 is not a scalar. Print out the value or use isscalar to check it. This works:
c(1) = 1;
but this will not:
c(1) = [1 2];
Also, your double for loop makes no sense because you're overwriting the value of m on each iteration. Presumably you have more stuff inside it. However, you could just create a matrix m without any for loop at all using bsxfun:
x = rand(1,5);
c = rand(1,2);
m = bsxfun(#minus,x(:),c(:).')
This results in m being a 5-by-2 matrix. You can use bsxfun(#minus,x(:).',c(:)) if you prefer a 2-by-5 matrix.

Related

Apply a function to each sub-cell of a cell in Matlab?

I have a cell C in Matlab of dimension mx1, e.g. m=3
C={{1 2 3} {4 5 6} {7 8 9 10}}
Then I have a function g written in a separate m-file
function D=g(C{i},a,b)
...
end
that takes any sub-cell C{i} of C and using some other parameters a and b gives a vector D of dimension fx1.
I want to apply the function g to each sub-cell of C and assemble the obtained fx1 vectors in a matrix fxm without using loops. I have seen the command cellfun but I don't know how to make it working with a function written by myself. Any suggestion?
Simple. First make a handle to the function where the only input is the cell array:
h = #(x) D(x, a, b);
Here, x would be a cell from the cell array. Also, I'm going to assume that a and b are already defined in your workspace. After, just do this:
out = cellfun(h, C, 'uni', 0);
The first argument is a handle to the function, which we've already defined. The next parameter is the cell array you want to operate on and apply the function h to every cell in your array. You need to specify the uni=0 flag because the output is non-uniform. Because your function outputs a vector per cell, this is mandatory. If your function outputted a single value, then this declaration of uni=0 is not required.
Alternatively, you can do this in a loop... which is what cellfun ultimately performs:
out = cell(numel(C), 1);
for idx = 1 : numel(C)
out{idx} = D(C{idx}, a, b);
end
To me, the second option is more suitable for those who aren't used to using cellfun.

Matlab programming dealing with matrix

I am trying out one of the matlab programming question.
Question:
Write a function called hulk that takes a row vector v as an input and
returns a matrix H whose first column consist of the elements of v,
whose second column consists of the squares of the elements of v, and
whose third column consists of the cubes of the elements v. For
example, if you call the function likes this, A = hulk(1:3) , then A
will be [ 1 1 1; 2 4 8; 3 9 27 ].
My Code:
function H = hulk(v)
H = [v; v.^2; v.^3];
size(H) = (n,3);
end
When I test my code using A = hulk(1:3), it throws an error on console.
Your function made an error for argument(s) 0
Am I doing something incorrect? Have I missed anything?
Remove the line size(H) = (n,3);
and add the line H = H';
Final code should be as follows
function H = hulk(v)
H = [v; v.^2; v.^3];
H = H';
end
Your code giving error in matlab editor on the size(H) = (n,3); line
That's why you should use the matlabeditor itself
For your future reference, you can very easily generalise this function in Matlab to allow the user to specify the number of cols in your output matrix. I also recommend that you make this function a bit more defensive by ensuring that you are working with column vectors even if your user submits a row vector.
function H = hulk(v, n)
%//Set default value for n to be 3 so it performs like your current function does when called with the same signature (i.e. only 1 argument)
if nargin < 2 %// nargin stands for "Number of ARGuments IN"
n = 3;
end if
%// Next force v to be a row vector using this trick (:)
%// Lastly use the very useful bsxfun function to perform the power calcs
H = bsxfun(#power, v(:), 1:n);
end
You could reduce the number of operations using cumprod. That way, each v.^k is computed as the previous v.^k times v:
function H = hulk(v, n)
H = cumprod(repmat(v,n,1),1);
The first input argument is the vector, and the second is the maximum exponent.

Why does my function return two values when I only return one?

So I'm trying to implement the Simpson method in Matlab, this is my code:
function q = simpson(x,f)
n = size(x);
%subtracting the last value of the x vector with the first one
ba = x(n) - x(1);
%adding all the values of the f vector which are in even places starting from f(2)
a = 2*f(2:2:end-1);
%adding all the values of the f vector which are in odd places starting from 1
b = 4*f(1:2:end-1);
%the result is the Simpson approximation of the values given
q = ((ba)/3*n)*(f(1) + f(n) + a + b);
This is the error I'm getting:
Error using ==> mtimes
Inner matrix dimensions must agree.
For some reason even if I set q to be
q = f(n)
As a result I get:
q =
0 1
Instead of
q =
0
When I set q to be
q = f(1)
I get:
q =
0
q =
0
I can't explain this behavior, that's probably why I get the error mentioned above. So why does q have two values instead of one?
edit: x = linspace(0,pi/2,12);
f = sin(x);
size(x) returns the size of the array. This will be a vector with all the dimensions of the matrix. There must be at least two dimensions.
In your case n=size(x) will give n=[N, 1], not just the length of the array as you desire. This will mean than ba will have 2 elements.
You can fix this be using length(x) which returns the longest dimension rather than size (or numel(x) or size(x, 1) or 2 depending on how x is defined which returns only the numbered dimension).
Also you want to sum over in a and b whereas now you just create an vector with these elements in. try changing it to a=2*sum(f(...)) and similar for b.
The error occurs because you are doing matrix multiplication of two vectors with different dimensions which isn't allowed. If you change the code all the values should be scalars so it should work.
To get the correct answer (3*n) should also be in brackets as matlab doesn't prefer between / and * (http://uk.mathworks.com/help/matlab/matlab_prog/operator-precedence.html). Your version does (ba/3)*n which is wrong.

Evaluate Equation in Cell Array, MATLAB

I have a cell array containing functions (with function handle) and I want to evaluate these inside a for-loop. I want to evaluate the differential equations:
x1'= x2,
x2' = ax2-bx1
My code is like this:
init = [0,0];
F = {#(x1,x2) x2,#(x1,x2)(a*x2-b*x1)};
X0 = init;
for i=1:10
X = X0 + c*F(init(1),init(2));
X0 = X;
init[1] = {X(1)};
init[2] = {X(2)};
end
The constants a,b and c are given.
I get the error:
Subscript indices must either be real positive integers or logicals.
Can someone help me with this?
F is a 1x2 cell array. To access elements (in your case, function handles) within this array you must use the curly braces {} to do so. For example, the first function is retrieved by F{1} and the second by F{2} using positive integer indices.
In your example, init is a 1x2 array of zeros so when the code evaluates
F(init(1),init(2));
it is trying to access something within F using indices that are not positive. Hence the error.
I suspect that you will need to do something like the following in your for loop and evaluate each function separately
for i=1:10
for j=1:2
% get the jth function handle
func = F{j};
% evaluate
X(j) = X0(j) + c*func(init(1),init(2));
% save
end
end
I've left the save* portion to be filled in by you because it isn't all that clear to me why there are the different init,X0 and X variables - could you consolidate them?
Note also your mixture of [] and () brackets when accessing arrays. In MATLAB, if the array is of type cell, then we use the {} to access elements. For all other arrays, we use the () brackets.
First of all, there are two other problems with your code: c is not defined and you are trying to index into init with []-brackets, which will throw:
Error: File: foo Line: 8 Column: 8
Unbalanced or unexpected parenthesis or bracket.
The subscript error occurs because you are trying to access F(0,0) because init(1) and init(2) are 0. Remember that the way you declared F, it is a cell array:
>> F = {#(x1,x2) x2,#(x1,x2)(a*x2-b*x1)};
>> whos F
Name Size Bytes Class Attributes
F 1x2 288 cell
Hence, F(0,0) is illegal because indexes in matlab start with 1. Your functions reside in F{1} and F{2}.
>> F{1}
ans =
#(x1,x2)x2
>> F{2}
ans =
#(x1,x2)(a*x2-b*x1)
>> f = F{1}
f =
#(x1,x2)x2
>> f(0,0)
ans =
0

Can I specify nargout as part of a MATLAB function call?

The problem:
I want to index into the result of a function call that returns a variable number of output arguments without storing the result in a temporary.
getel = #(x,i) x(i); #% simple anonymous function to index into a vector
x = zeros(2,2,2);
row = getel(ind2sub(size(x), 8), 1) #% desired: 2 (row 2)
#% actual: 8 (linear index)-because ind2sub is returning 1 value only
[row col dep]=ind2sub(size(x),8) #% row=2, ind2sub returning 3 values
Example usage:
x(1).val1 = [1 2 3];
x(1).val2 = [2 1 2];
x(2).val1 = [2 1 2];
x(2).val2 = [1 0 0];
#% The normal way I would do this, with a temporary variable
[~,ind] = min(x(1).val2); #% ind=2
v(1) = x(1).val1(ind);
[~,ind] = min(x(2).val2); #% ind=2
v(2) = x(2).val1(ind);
#% I'd like to be able to do this with arrayfun:
v = arrayfun(#(s) s.val1(min(s.val2), x);
-------^ returns value of minimum, not index
The above arrayfun doesn't work - the form of min that is called returns one output: the minimum value. To make it work right, one option would be the following hypothetical function call:
v = arrayfun(#(s) s.val1(getoutputnum(2, 2, #min, s.val2)), x);
hypothetical function -----------^ ^ ^ ^-func ^--func args
which form (nargout) of func ---| |- which arg to return
I realize that for the above scenario, I could use
s.val1(find(s.val2==min(s.val2),1,'first'))
or other tricks, but that isn't possible in all cases.
In the case of ind2sub, I may want to know the index into a particular dimension (columns, say) - but the 1-output form of the function returns only a linear index value - the n-dimensional form needs to be called, even if the value of dimension 1 is what I care about.
Note: I realize that writing a function file would make this trivial: use ~ and the [out] = func(in) form. However, when writing scripts or just on the command line, it would be nice to be able to do this all within anonymous functions. I also realize that there are undoubtedly other ways to get around the problem; I would just like to know if it is possible to specify which form of a function to call, and perhaps which output number to be returned, without using the out=func(in) syntax, thus allowing functions to be nested much more nicely.
Could you do something like this?
In its own file:
function idx=mymin(x)
[~,idx] = min(x);
In your code:
v = arrayfun(#(s) s.val1(mymin(s.val2), x);
Might have syntax errors; I don't have MATLAB on the computer I'm writing this on. The idea is there though: just wrap MATLAB's min and capture the second argument, which is the logical indexing for the position of the minimum value in x.
I can get ind2sub() to return the variable number of args like this:
x = zeros(2,2,2);
c = cell(ndims(x),1);
[c{:}] = ind2sub(size(x), 8);
The c cell array will now have the 3D indices c = {2;2;2}.
[c{:}] = ind2sub(size(x), 2);
would produce c = {2;1;1}.
Is this what you were looking for?