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

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.

Related

How to create an Octave function that evaluate the sum of pairs of numbers in the vector?

It's like a reverse version of Pascal's triangle.
I want to create a vector-input function named
y = lastnum(vect) on Octave, that evaluate the sum of each pair of numbers in any vectors to output the single number from the evaluation loops like this
0 1 2 3 4
1 3 5 7
4 8 12
12 20
32
And the input and output would be like this,
lastnum([0 1 2 3 4])
ans = 32
I mean... is there any progresses that I can do??? You may not understand but, the reverse triangle above can guide you about my question.
I also tagged MATLAB since it has similar language. MATLAB pros may help my problem.
Notice that the number of times each element gets added to produce the final result comes from Pascals triangle itself, so, e.g., for the vector [a b c d] the result will be a+3b+3c+d. So create a vector of entries in Pascals triangle and multiply and add with the original vector v.
I only have access to Matlab, Octave may not have all these functions.
This is a one-liner diag(fliplr(pascal(numel(v)))).'*v(:).
Or a looping version
s = 0;
for i = 0:numel(v)-1
s = s+nchoosek(numel(v)-1,i)*v(i+1);
end
s
Simplest thing I can think of is:
while length(x) > 0
disp(x)
x = x(1:end-1) + x(2:end);
end
or did I misunderstand the question?
Here is the version for both MATLAB and Octave:
function y = lastnum(v)
while 1
if length(v) == 2
y = sum(v)
break;
end
# disp(v); # if you want to print the progress
vt = [];
for k = 1:(length(v)-1)
vt(end+1) = sum(v(k:(k+1)));
end
v = vt;
end
end

Assigning matrix elements to variables in a data set

Hello I'm new to Matlab.
I've written this script :
k2=2*pi();
z1 = 1;
z2 = 2;
z3 = 4;
for l = linspace(0,1,11)
A = [ -1 1 1 0 ; 1 z1/z2 -z1/z2 0 ; 0 exp(-i*k2*l) exp(i*k2*l) -1 ; 0 exp(- i*k2*l) -exp(i*k2*l) -z2/z3];
B = [ 1 ; 1 ; 0 ; 0];
D = inv(A);
C = mtimes(D,B) ;
display(C)
r = C(1,1); % this is supposed to set r = the 1,1 element in the matrix C
t = C(1,4); % see above
end
My idea for taking the values of r and t from C didnt appear to work. How can I do this properly?
Also I want to plot a graph of |r|,|t|, arg(r) and arg(t) for each value of l, my for loop overwrites the values of r and t? how can I either plot one point per loop or make r and t assign the new values so that they become lists of data.
Thanks a lot!
Matlab sets the first dimension of a matrix as row number (i.e. y position).
So you want t=C(4, 1), as you should see that the size of C is 4x1. As a note Matlab is quite good at suppressing singleton dimensions so you could do also do C(1) and C(4).
For your second point you want to set a particular element of r and t in each loop. This is the same as when you access at particular element of C when setting the values. For your case you can use the index l to determine the element. Remembering that in matlab arrays start at element 1 (not 0 as in many other languages). So you want something like r(l+1)=C(1); (or change l to start at 1).
In the more general case if you are not looping over an integer for some reason you may need to create a separate counter variable which you increase in the loop. Also it is good practice to preallocate such arrays when the size is known beforehand, often by r=zeros(11, 1) or similar (note: zeros(11) is an 11x11 matrix). This isn't significant in this case but can drastically increase execution time for large multi-dimensional arrays so is a good practice.

For-loop exits too early, need help as to why

I've written a simple function that takes a vector vec, iterates through it, performing an operation whose result is stored in another vector vecRes of same size at same index, and returns vecRes upon completing the loop. Below is function code:
function [ vecRes ] = squareTerms( vec )
vecSize = size(vec);
vecRes = zeros(vecSize);
for i = 1:vecSize
vecRes(i) = vec(i)^2;
end
end
Problem is that it seems to exit too early, after only one iteration in fact as the output appears as:
vecRes = 1 0 0 0 0 0 0 0 0 0
For input:
vec = 1 2 3 4 5 6 7 8 9 10
I can't figure out why it does so. Any help is greatly appreciated.
Size returns 2 values, rows and columns. Probably you are a having a 1xN vector. So size returns [1 N] and your loop runs 1 time.
>>> size ([1 2 3])
>
> ans =
>
> 1 3
>
>>> 1:size ([1 2 3])
>
> ans =
>
> 1
Others have pointed out the problem. My preferred solution in this sort of case is to use numel, i.e.
vecRes = zeros(size(vec));
for i = 1:numel(vec)
vecRes(i) = vec(i) ^ 2;
end
Of course, in this case, vectorisation is better still:
vecRes = vec .^ 2;
Replace
for i = 1:vecSize
with
for i = 1:vecSize(2)
vecSize is an array of numbers, not just a single value. For example, if vec is a 1 by 8 vector, then size(vec) will return [1, 8].
Therefore, your for-loop-statement,
for i = 1:vecSize
, is actually equivalent to something like:
for i = 1:[1, 8]
This doesn't make much sense. There are a number of ways to fix the problem. You could write:
for i = 1:length(vec)
or
for i = 1:numel(vec) % "numel" stands for "number of elements"
If the vector is 1xn instead of nx1, you can write:
for i = 1:size(vec, 2)
Yet another alternative is:
for i = 1:max(vecSize)
However, the most sensible option is not to write the squareTerms function at all and simply write
vecRes = vec.^2;
Note the dot before the caret. vec^2 and vec . ^2 are not the same thing.
If you put a dot before an operator sign, the operation will be performed element-wise. For example,
C = A * B
performs matrix multiplication, but
C = A .* B
will cause the first element of A to by multiplied by the first element of B, and the result will be assigned to the first element of C. Then, the product of the second elements of A and B will be taken, and the result will be stuck in the second element of C, and so on.
vecRes = vec.^2;

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.

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".