Matlab - using undefined function/value within function - matlab

Lets start with an example. Define a 1-D vector in the base Workspace:
q = [1 0 2 4 2 3 4 2 1 0 2]; % Defined 1-D vector, already in Workspace.
This is in an M-file:
function vector = r(i)
vect(i) = q(3*i-2:3*i-1);
If the function is called, for example,
r(2);
Matlab throws an error: "Undefined function or method 'q' for input arguments of type 'double'".
My question is: is there a way to make Matlab take the vector q "for granted" when calling the function r – q is already defined so technically it could collected from the base Workspace to use it.
Of course the obvious solution is to add q to the argument list:
function vector = r(i,q)
...
and then call it with
r(2,q)
Eventually I will, but I just want to know if there is something I don't know since this could be a pretty useful feature.

You can use global variables, but you shouldn't. They're inefficient too.
If you for some reason don't just want to pass q in as a second argument, here are two better alternatives.
1. Closure via anonymous function
If your function is simple and can be written on one line you can create an anonymous function after defining your q vector:
q = [1 0 2 4 2 3 4 2 1 0 2];
r = #(i)q(3*i-2:3*i-1);
In this case, the function r is a closure in that it captures the predefined q (note that r in this case is slightly different from that in your question). You can call this now with:
out = r(2)
2. Shared variables via sub-function
A more general option is to use a sub-function inside your main M-file function:
function mainFun
q = [1 0 2 4 2 3 4 2 1 0 2];
r(i);
function vect = r(i)
vect(i) = q(3*i-2:3*i-1);
end
end
The vector q is shared between the outer mainFun and the sub-function r. The Matlab Editor should make this clear to you by coloring q differently. More details and examples here.

You can use global variables MATLAB:
1) in the workspace, declare q as global, than set its value
global q;
q = [1 0 2 4 2 3 4 2 1 0 2];
2) in your function, declare q as global and use it:
function vector = r(i)
global q;
vect(i) = q(3*i-2:3*i-1);

Related

Fibonacci Recursion Value tracer

So I need to write a program which uses a recursive function to store the value of input arguments in the order they were made.
e.g. If my function is [f trace]=fibo_trace(6,[]) it should return
[f trace]=fibo_trace(6,[])
f=
8
trace=
6 4 2 3 1 2 5 3 1 2 4 2 3 1 2
With trace being the values with which the recursive call is being initialized and f being the 6th element in the fibonacci series.
Here is my code
function [f,trace] = fibo_trace(n,v)
persistent ptrace; % must specify persistent
v=n;
ptrace=cat(2,ptrace,v);
if n <= 2
f = 1;
else
f = fibo_trace(n-2) + fibo_trace(n-1);
end
trace=ptrace;
end
But using a persistent variable does not give proper output if multiple conditions are tested. I need to compute this without using a persistent or global variable, can anyone help me out here?
When I don't use a persistent variable only the latest value of n is stored in vector v instead of the entire set of values.
First, note that your input v is never used, you always overwrite it with n.
Next, note that your calls to fibo_trace(n-1) and (n-2) could return trace, you're just choosing not to. We can take advantage of the 2nd output to build the trace array.
These two points mean you can get rid of the persistent variable, and simplify the code a bit. We just need to make separate calls to fibo_trace for the two previous iterations.
function [f,trace] = fibo_trace(n)
if n <= 2
% The trace should just be 'n' for the starting elements f=1
f = 1;
trace = n;
else
% Get previous values and their traces
[f1, t1] = fibo_trace(n-1);
[f2, t2] = fibo_trace(n-2);
% Compute the outputs
f = f1 + f2;
trace = [n, t2, t1];
end
end
Result:
[f, trace] = fibo_trace(6)
f =
8
trace =
6 4 2 3 1 2 5 3 1 2 4 2 3 1 2
There's some optimisation to be had here, since fibo_trace(n-1) will itself call fibo_trace(n-1), so computing fibo_trace(n-2) separately is multiplying the computation time.

How to assign values to variables in a handle function?

This is simplified but take as an example the following MATLAB function handle:
F = #(x)[x(1)-x(2);x(2)-x(3)]
The system has of course has many solutions. Is it possible to obtain a solution for a function like this one after substituting at least one variable? For example, substituting x(3)=1 the function would become:
G = #(x)[x(1)-x(2);x(2)-1]
And a solution for the other variables can be obtained. I use fsolve and it works quite well for the system of equations I have. Of course what I need to do can be done using the Symbolic Toolbox, but calling it in a big for loop makes it too slow to use for my code.
I'm trying to come up with some code that can return G given F and a set of indices in x to replace with given values.
What you're basically asking to do is have G call F with values in x reassigned based on a logical replacement index index and a set of replacement values values, which is doable but messy since anonymous functions can only have a single executable statement.
The solution is similar to what is done in this answer, but instead of using the functional form for subscripted reference we'll need to use the functional form for subscripted assignment: subsasgn. Here's what it would look like:
F = #(x)[x(1)-x(2); x(2)-x(3)];
values = [3 2 1];
index = logical([0 0 1]);
G = #(x) F(subsasgn(x, struct('type', '()', 'subs', {{index}}), values(index)));
And here's a test:
>> F([3 2 3])
ans =
1
-1
>> F([3 2 1]) % Replace the last element by 1
ans =
1
1
>> G([3 2 3]) % G handles replacing the last element by 1
ans =
1
1

Vector Function is Always Constant

New to MATLAB, and I need help with the following issue.
I want to create a function val=F(v,e) that takes in two inputs v, a 1xn vector, and a scalar e, and outputs a scalar val that counts the nonzero entries of the vector v-e, i.e. the vector v with e subtracted from all each of its entries. My code for the function is below:
function val = eff(vec, e)
val = sum( (vec - e > 0) );
end
When I evaluate the function at a single point it works as it should. but I want a plot of this function on (0,1). Plotting it gives a constant value over the entire range of e. I am using the following code on the main
figure
e = linspace(0,1);
plot(e, eff(rand(1,100),e),'o',e, e)
Also, when I use a small vector, say, rand(1,10), I get the following error message:
>Error using -
>
>Matrix dimensions must agree.
>
>Error in eff (line 3)
>
>val = sum( (vec - e > 0 ));
Is my function being too careless with matrix dimensions? Or is there an easier way to evaluate eff over a vector range?
Thanks in advance.
You have created a function which is designed to be applied only with a scalar e argument, and where passing e as an array would potentially cause errors ... but then you call it with e = linspace(0,1) which is an array.
The particular error when e is of size 10 is telling you that you cannot subtract it from a matrix of size 100.
When e happens to have the same size as vec, your function subtracts two equal-sized arrays, and returns their sum, which is a scalar. Therefore your plot is essentially doing something like plot(a_range, a_scalar), which is why it looks constant.
Instead, you should probably collect an array V for each value of e in a for loop, or using arrayfun, e.g.
e = linspace(0,1);
V = arrayfun(#eff, e);
and then plot e against V
Alternatively, you could rewrite your function such that it expects e to be an array, and your return value is an array of the same size as e, filled with the appropriate values.
without using arrayfun, your task can also be accomplished using broadcasting. I noticed you had this question tagged Octave as well as Matlab. Octave uses automatic broadcasting when you attempt elementwise operations with vectors in different dimensions. Matlab can do broadcasting with the bsxfun function. (if you want code that will run in either program, Octave also can use bsxfun.) Also, according to the release notes I believe Matlab 2016b will now include automatic broadcasting, although I cannot confirm yet that it will behave the same as Octave does.
Because your vectors vec and e are both row vectors, when you try to subtract them Matlab/Octave will subtract each element if they have the same size, or give a size mismatch error if they do not.
If you instead create one of the vectors as a column vector, broadcasting can take over. a simple example:
>> a = [1:4]
a =
1 2 3 4
>> b = [1:4]'
b =
1
2
3
4
>> a-b //Error in Matlab versions before 2016b
ans =
0 1 2 3
-1 0 1 2
-2 -1 0 1
-3 -2 -1 0
>> bsxfun(#minus,a,b) //works under Octave or Matlab
ans =
0 1 2 3
-1 0 1 2
-2 -1 0 1
-3 -2 -1 0
So, if you are running Octave, your code will run correctly if you just rewrite your function so the vectors use different dimensions. There are a number of ways to do this, but since both Matlab and Octave default to column ordering, you can use the : operator to force them to work the way you want. E.g.:
>> a = [1:4]
a =
1 2 3 4
>> a(:)
ans =
1
2
3
4
>> a(:)'
ans =
1 2 3 4
>> b = [1:4]'
b =
1
2
3
4
>> b(:)
ans =
1
2
3
4
>> b(:)'
ans =
1 2 3 4
So, after all that, you can rewrite your function:
function val = eff(vec, e)
vec = vec(:);
e = e(:)';
val = sum ( (vec-e ) > 0 );
end
If you're running matlab, or you want code that could run in both Octave and Matlab, you can just replace the last line of the function with:
sum ( bsxfun(#minus,vec,e) > 0 )
Finally, if you want, you can add some 'isvector' error checking at the beginning of the function in case you accidentally pass it an array. And note that had I chosen to make 'vec' a row vector and 'e' a column vector I would have had to tell the sum function which dimension to sum over. (it defaults to summing each column and returning a row vector, which matches the choices I made above.)
you function works fine as long as e is a scaler and not an array or matrix. You can then you looping or arrayfun (as already answered) to get a final answer
figure
e = rand(1,10); % create 10 random e numbers
vec = rand(1,100);
for inc = 1:length(e)
v(inc) = eff(vec,e(inc));
end
scatter(e,v);

Recursion in Matlab. why is my recursion not working past the first step?

So I am very new to Matlab and I have been tasked with implementing LU factorization. I have to do it recursively because we are not allowed to use for loops in our code, and recursion will give us optimal marks. I have written this code. The code works for the first step, and does what it is supposed to, but for the next two steps, the matrix is not modified at all. I have this code:
function[L, U] = myLU(A,B, pos)
%A = Mtrix that becomes U
%B = Matrix that becomes L
tmp_L = B;
[x,y] = size(A);
if pos > x
L = B;
U = A;
return
else
pos %<-- just to see if it iterates through everything
[tmp_U,tmp_L] = elimMat(A,pos);
myLU(tmp_U,tmp_L, pos+1);
end
L = tmp_L;
U = tmp_U;
end
I where elimMat(A, pos) returns the elimination matrix for column pos. as well as another matrix, which will end up being the matrix of multipliers. What i tried doing is then finding the LU factorization of this matrix A. since elimMat returns L and U(this works, if i do it manually it works), i had to make a function that allows me to do it automatically without using a for loop. I thought i would do it recursively. What i ended up doing is adding another variable B to the function so that i can store intermediate values of my matrix obtained in each step and put it all together later.
So here is my question. Am i implementing the recursion wrong? and if i am how can i fix it? The other thing i wanted to ask is how can i implement this so i do not need variable B as an additional imput, and only use the existing variables, or variables previously defined, to find the solution? I would really like only two inputs in my function: The matrix name and the starting index.
here is elimMat if if helps:
function [M,L] = elimMat(A,k)
%find the size of the matrix
[x,y] = size(A);
tmp_mat = zeros(x,y);
%M = The current matrix we are working on for Elimination -> going to
%become U.
%L = The L part of the matrix we are working on. Contains all the
%multipliers. This is going to be our L matrix.
for i = 1:x
mult = A(i,k)/A(k,k);
if i > k
tmp_mat(i,k) = mult;
P = A(k,:)*mult;
A(i,:) = A(i,:)-P;
elseif i == k
tmp_mat(k,k) = 1;
end
end
M = A;
L = tmp_mat;
end
thanks for any feedback you can provide.
Here is the output: WHAT I GET VS what it should be:
[U = VS [U =
1 2 2 1 2 2
0 -4 -6 0 -4 -6
0 -2 -4] 0 0 2
L = VS [L=
1 0 0 1 0 0
4 0 0 4 1 0
4 0 0] 4 0.5 1
As you can see only the first column is changed
You forgot to catch the output of your recursive call:
[tmp_L, tmp_U] = myLU(tmp_U,tmp_L, pos+1);
Matlab passes variables by value, so a function cannot change its input variable itself (ok, it can, but it's tricky and unsafe).
Your original version didn't return the updated matrices, so the outermost function call encountered the myLU() call, let the recursion unfold and finish, and then went on to use tmp_L and tmp_U as returned from the very first call to elimMAT(A,1).
Note that you might want to standardize your functions such that they return U and L in the same order to avoid confusion.

How does a "for" loop in Matlab change its control variable on each iteration?

>> a = [1 1 2 3 5 8 13 21 13 37];
>> d = [1 2];
>> w = [0 0 0];
for e = d
g = 0;
for f = a
if mod (f, 2) == 0
g = [g f];
end
end
w = [w;g];
end
>> w
The output of W is the matrix
0 0 0
0 2 8
0 2 8
My question is about the for-loops. Do Matlab for-loops take a value, instead of being a logical condition? For example, when looking at 'for f = a' does f take the value of the array A and then the for-loop iterates through F by its columns?
Thanks.
FOR loops have a variable, each pass through the loop the iterator variable takes on the next value in the array. The iterator variable takes on the values of the columns, one at a time. The right hand side of the assignment statement in the foor loop needn't be a numeric array -- it could be a cell array of strings for example, or a structure, etc.
In other words, when you have for
for f=a, ....., end
this is equivalent to writing
for i=1:numel(a)/size(a,1); f=a(:,i); .... ; end
You can easily see this by adding some disp statements into your code:
for e = d
disp(e)
g = 0;
for f = a
disp(f)
if mod (f, 2) == 0
g = [g f];
end
end
w = [w;g];
end
WHILE loops in matlab take a logical condition.
(edit: i forgot that f takes on the value of the columns of a if a is multidimensioned)
Yes, MATLAB loop variables are assigned to "arrays", called vectors in MATLAB parlance. The value of the loop variable automatically iterates over elements of the vector upon each iteration of the loop. A common construct is
for i=1:10 %generates vector of 1,2,...,10
i %will print i=1, i=2, etc.
end
In this case the vector was generated on the fly, and is sequential numbers. But there is no reason you can't pass any arbitrary vector in to iterate over, like "a" in your case. Upon each iteration, "f" takes on the next value in the sequence contained in "a".