Fibonacci Recursion Value tracer - matlab

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.

Related

Build the matrix of all the combinations of given numbers using recursion [matlab]

Let say we have the vector v=[1,2,3] and we want to build the matrix of all the combinations of the numbers contained in v, i.e.
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Since I'm not good in recursion, firstly I tried to write the code to build such a matrix by using for loops
makeLoop([1,2,3])
function A = makeLoop(v)
loops=length(v);
for i = 1:loops
dummy=v;
m=factorial(loops)/loops;
A((1+m*(i-1)):m*i,1)=v(i);
v(i)=[];
loops2=length(v);
for j = 1:loops2
dummy2=v;
m2=factorial(loops2)/loops2;
A(((1+m2*(j-1))+m*(i-1)):(m2*j+m*(i-1)),2)=v(j);
v(j)=[];
loops3=length(v);
for k = 1:loops3
m3=factorial(loops3)/loops3;
A(((1+m2*(j-1))+m*(i-1)):(m2*j+m*(i-1)),3)=v(k);
end
v=dummy2;
end
v=dummy;
end
end
it seems like it work, but obviously write it all for a bigger v would be like hell. Anyway I don't understand how to properly write the recursion, I think the recursive structure will be something like this
function A = makeLoop(v)
if length(v)==1
"do the last for loop"
else
"do a regular loop and call makeLoop(v) (v shrink at each loop)"
end
but I don't get which parts should I remove from the original code, and which to keep.
You were very close! The overall structure that you proposed is sound and your loopy-code can be inserted into it with practically no changes:
function A = makeLoop(v)
% number of (remaining) elements in the vector
loops = length(v);
if loops==1 %"do the last for loop"
A = v; %Obviously, if you input only a single number, the output has to be that number
else %"do a regular loop and call makeLoop(v) (v shrink at each loop)"
%preallocate matrix to store results
A = zeros(factorial(loops),loops);
%number of results per vector element
m = factorial(loops)/loops;
for i = 1:loops
%For each element of the vector, call the function again with that element missing.
dummy = v;
dummy(i) = [];
AOut = makeLoop(dummy);
%Then add that element back to the beginning of the output and store it.
A((1+m*(i-1)):m*i,:) = [bsxfun(#times,v(i),ones(m,1)) AOut];
end
end
Explanation bsxfun() line:
First, read the bsxfun documentation, it explains how it works way better than I could. But long story short, with bsxfun() we can replicate a scalar easily by multiplying it with a column vector of ones. E.g. bsxfun(#times,5,[1;1;1]) will result in the vector [5;5;5]. Note that since Matlab 2016b, bsxfun(#times,5,[1;1;1]) can written shorter as 5.*[1;1;1]
To the task at hand, we want to add v(i) in front (as the first column) of all permutations that may occur after it. Therefore we need to replicate the v(i) into the 1. dimension to match the number of rows of AOut, which is done with bsxfun(#times,v(i),ones(m,1)). Then we just horizontally concatenate this with AOut.
You can simply use the perms function to achieve this:
v = [1 2 3];
perms(v)
ans =
3 2 1
3 1 2
2 3 1
2 1 3
1 3 2
1 2 3
If you want them sorted using the same criterion you applied in the desired output, use the following code (refer to this page for an official documentation of the sortrows functon):
v = [1 2 3];
p = perms(v);
p = sortrows(p)
p =
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 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);

Use MATLAB function handles to reference original matrix

I often have to manipulate a lot of matrices row by row using MATLAB.
Instead of having to type:
m(x, :);
every time I want to reference a particular row, I created an anonymous MATLAB function:
row = #(x) m(x, :);
allowing me to call row(x) and get the correct row back.
But it seems that this anonymous function is actually not the same as calling m(x, :) directly, as the reference to the matrix is lost. So when I call something like:
row(2) = 2 * row(2);
MATLAB returns the error:
error: can't perform indexed assignment for function handle type
error: assignment failed, or no method for 'function handle = matrix'
Is there a way to define a function handle to get around this problem, or am I better off just typing out m(x, :) when I want to reference a row?
Thanks so much!
By defining an anonymous function, you make every row immutable (at least through row). Reassigning the value of a function handle is simply not possible.
Imagine that you define the function handle mySquare(x) = #(x) x.^2 ;. If reassigning the output of a function handle would be possible, you could change the value of mySquare(2) (e.g., mySquare(2)=2) and basically states that 4=2!
On the positive side, your anonymous function "protects" your initial input m from unexpected modifications. If you want to use your function row, you should simply define another matrix m_prime, whose rows are initialized with the function handle row (avoid using m again since it would probably mix everything up).
reference through a handle only work for Matlab object/class inherited from the handle class.
If as you said in comment "elementary row operations is the end application for this", then David's answer is a good simple way to go (or simply keep using m(x,:) which is still the shortest syntax after all).
If you really want to venture into handles and true reference values, then you can create a class rowClass which you specialise in row operations. An example with a few row operations would be:
classdef rowClass < handle
properties
m = [] ;
end
methods
%// constructor
function obj = rowClass(matrix)
obj.m = matrix ;
end
%// row operations on a single row ----------------------------
function obj = rowinc(obj,irow,val)
%// increment values of row "irow" by scalar (or vector) "val"
obj.m(irow,:) = obj.m(irow,:) + val ;
end
function obj = rowmult(obj,irow,val)
%// multiply by a scalar or by a vector element wise
obj.m(irow,:) = obj.m(irow,:) .* val ;
end
function obj = rowsquare(obj,irow)
%// multiply the row by itself
obj.m(irow,:) = obj.m(irow,:).^2 ;
end
%// row operations between two rows ---------------------------
function obj = addrows(obj,irow,jrow)
%// add values of row "jrow" to row "irow"
obj.m(irow,:) = obj.m(irow,:) + obj.m(jrow,:) ;
end
function obj = swaprows(obj,irow,jrow)
%// swap rows
obj.m([irow,jrow],:) = obj.m([jrow,irow],:) ;
end
end
end
Of course you could add all the operations you frequently do to your rows, or even to the full matrix (or a subset).
Example usage:
%% // sample data
A = (1:5).' * ones(1,5) ; %'// initial matrix
B = rowClass( A ) ; %// make an object out of it
B =
rowClass with properties:
m: [5x5 double]
B.m %// display the matrix
ans =
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
Add a value (12) to all elements of the row(1):
%% // add a value (scalar or vector) to a row
rowinc(B,1,12) ;
B.m
ans =
13 13 13 13 13
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
Square the row(3):
%% // Square row 3
rowsquare(B,3) ;
B.m
ans =
13 13 13 13 13
2 2 2 2 2
9 9 9 9 9
4 4 4 4 4
5 5 5 5 5
Last one for the road, swap row(3) and row(5):
%% // swap rows
swaprows(B,5,3) ;
B.m
ans =
13 13 13 13 13
2 2 2 2 2
5 5 5 5 5
4 4 4 4 4
9 9 9 9 9
I think you'll be best off typing m(x,:)! It's not much quicker than doing row(x). Another issue with the anonymous function row is that it will keep the original matrix m, which wont change.
Here is an anonymous function that does what you want, I think it's a reasonable way of doing things. row(a,b,c) multiplies the b'th row of the matrix (not necessarily square) a by c.
x=rand(5)
row=#(x,i,k) (diag([ones(1,i-1) k ones(1,size(x,1)-(i))]))*x
x=row(x,2,20)
Ultimately, I think the simplest method is to make a standalone function to do each type of row operation. For example,
function x=scalarmult(x,i,k)
x(i,:)=k*x(i,:);
and
function x=addrows(x,i,j)
x(i,:)=x(i,:)+x(j,:);
and
function x=swaprows(x,i,j)
x([i,j],:)=x([j,i],:);

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.

Matlab - using undefined function/value within function

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);