clearer explanation of function level scope for recursion - matlab

This is an example from the book 'Matlab for Neuroscientists'. I don't understand the order in which, or why, g gets assigned a new value after each recursion. Nor do I understand why "factorial2" is included in the final line of code.
here is a link to the text
Basically, I am asking for someone to re-word the authors explanation (circled in red) of how the function works, as if they were explaining the concept and processes to a 5-year old. I'm brand new to programming. I thought I understood how this worked from reading another book, but now this authors explanation is causing nothing but confusion. Many thanks to anyone who can help!!

A recursive method works by breaking a larger problem into smaller problems each time the method is called. This allows you to break what would be a difficult problem; a factorial summation, into a series of smaller problems.
Each recursive function has 2 parts:
1) The base case: The lowest value that we care about evaluating. Usually this goes to zero or one.
if (num == 1)
out = 1;
end
2) The general case: The general case is what we are going to call until we reach the base case. We call the function again, but this time with 1 less than the previous function started with. This allows us to work our way towards the base case.
out = num + factorial(num-1);
This statement means that we are going to firstly call the function with 1 less than what this function with; we started with three, the next call starts with two, the call after that starts with 1 (Which triggers our base case!)
Once our base case is reached, the methods "recurse-out". This means they bounce backwards, back into the function that called it, bringing all the data from the functions below it!It is at this point that our summation actually occurs.
Once the original function is reached, we have our final summation.
For example, let's say you want the summation of the first 3 integers.
The first recursive call is passed the number 3.
function [out] = factorial(num)
%//Base case
if (num == 1)
out = 1;
end
%//General case
out = num + factorial(num-1);
Walking through the function calls:
factorial(3); //Initial function call
//Becomes..
factorial(1) + factorial(2) + factorial(3) = returned value
This gives us a result of 6!

Related

Requested output arguments of a function [duplicate]

This question already has an answer here:
How to determine if an output of a function-call is unused?
(1 answer)
Closed 4 years ago.
Let's say I have
function [a, b] = foo
a = 1;
b = 2;
and the user is calling
[~, B] = foo;
I would like only b = 2 to happen, to prevent a time consuming operation a = 1. Is there a way to find out that a was actually not requested by user?
Long ago it was not possible. I wonder if Mathworks improved this or anyone found a workaround in the meantime.
Note: the opposite is possible: if user calls A = foo, the nargout is 1.
It is not possible for good reason. Just because you do not require the middle output at the point of return of the function, doesn't mean that its calculation was unnecessary within the function, unless you explicitly write your function to do so.
E.g., it is possible that the calculation of output 3 depends on output 2 inside the function, even if not explicitly requested at output time). Matlab has no way of knowing this, so it cannot assume that any and all calculations involving that output can be discarded.
If you require a memory efficient manner of ensuring only the correct calculations take place, then change your output strategy.
I would suggest returning a struct with the right fields, where you request the fields you desire at function calling. In this way, your final struct would only contain the fields you desire, and you can ensure inside your function that unnecessary calculations do not take place.

MATLAB Beginner recursive functions

Just having a little difficulty with the syntax of matlab functions;
function f = fact(x)
if x == 1
return
else
f = 1 - x*(fact(x-1))
end
end
When calling this function in the command window with the argument 10 I receive the error
Undefined function 'fact' for input arguments of type 'double'.
Error in recursion (line 6)
f = 1 - x*(fact(x-1))
I've had a look around and solutions for the first revolve around the pathing of the m-file which doesn't seem to be a problem as other files in the same directory run fine,
The second I'm not sure why the error in line 6 occurs, my guess is it has something to do with the variable and function names.
As a side question, are both these end statements necessary?
Thanks!
The most obvious error is your function filename. You have a function called fact defined in your code but you named your file recursion. Make sure that both your function name and the filename are both called fact.
If you were to name your file as recursion, then make the function name defined in your code as fact, this is what would happen if you tried calling your code:
>> f = recursion(10);
Undefined function 'fact' for input arguments of type 'double'.
Error in recursion (line 6)
f = 1 - x*(fact(x-1));
... look familiar?
As such make sure your filename and your function name are named the same. In fact, in the MATLAB editor, it should automatically give you an error saying that both of these are not the same.
There is also another error in your code. The base case is not defined properly. Always remember when you are writing recursive algorithms is that eventually the function is going to return... and that's when you hit the base case. We can see here that it is when x = 1. When x = 1, you're supposed to assign something to f which is the output. You are simply exiting the function, and so when x becomes 1, your code will spit out an error saying that f was not assigned when the function finishes. As such, you need to figure out what your base case is. I'm going to assume that your base case (when x = 1) is going to equal 0. You will obviously need to change this as I don't know what your code is actually computing. Basically, you need to do this:
function f = fact(x)
if x == 1
f = 0; %// Base case needs to change according to your specs
else
f = 1 - x*(fact(x-1))
end
end
When I do this, I get the following output when x = 10
>> f = fact(10);
f =
1334961
I don't get an error when I run this code now. Also, check to see if you have any variables named fact in your workspace. When this happens, you are in fact shadowing over your function with a variable, so it is actually trying to access the variable called fact instead. As such, try clearing your workspace by doing clear all;, then try this code again.
One warning
If you were to specify x to be 0 or negative, this function will never stop. As such, you need to provide some check and perform the proper action when this happens. Also, you need to make sure that you specify what type of inputs are accepted for x. Judging from the context, x are positive integers only. As what #Glen_b has noted, should you provide any number that isn't a positive integer, this function will never stop as x will never equal 1 down the recursion pipeline.
To answer your optional question
The first end statement is required to end the if statement. The second end statement isn't required, but it's good practice anyway. However, if you have multiple functions defined inside your function file, then yes it is most definitely required to properly signify that the end of that function is defined there. However, you don't need it if you're only writing one function per file, but I would recommend keeping it there as it's good practice.

Matlab: recursive algorithm to return the run count easily without profiler?

I would like to get the number of iterations that the recursive mlfnonneg requires. Currently, I use profiler for this but it would be more useful to get the number as a return value from the function. Is there any easy way to get it?
I measure the running time of a function like this
h=#() mlfnonneg(lb,ub,mlfBinCor,method);
tElapsed=timeit(h);
and now the function mlfnonneg should return the number of iterations. I have considered adding a ticker that the function always returns but I don't know how to get the return value after using timeit. How to get the running time and the running count of the recursive algorithm elegantly?
You can always add an optional return value to a function which you can use as a counter. Something like this:
[... count] = f(...)
% Do stuff here
if <some condition>
% Recurse
[... count] = f(...);
count = count + 1;
else
% Terminal condition
count = 1;
end
You should just call your function one more time to get the count. This should not be a significant problem, since timeit actually performs multiple calls to your function to get an average metric.
I don't know if this is an option for you - but you could create a global variable IT_COUNT that you declare both at the top level, and inside your function.
Before calling timeit() you set the variable to zero; inside the routine you increment it for every loop. When the function returns you print out the result - and there is your answer.
It does depend on you being able to modify the code to mlfnonneg to include the counter. I don't see an easy way around that, but maybe others have a better idea.
update inspired by Luis Mendo's (now deleted) answer that basically says the same thing, a bit more information.
In your mlfnonneg routine, add the following two lines (in a place where they are executed "once per iteration"):
global IT_COUNT;
if numel(IT_COUNT)==0, IT_COUNT = 1; else IT_COUNT = IT_COUNT + 1; end
This ensures that if you forget to create the variable at the top level, the code will not crash (you will thank me in the future, when you re-use this code and don't remember that you need a global variable...)
At the top level, add
global IT_COUNT
IT_COUNT = 0;
Then run your timeit() routine; finally use
fprintf(1, "The number of iterations was %d\n", IT_COUNT);
to get the answer you were looking for.

Variables in a vector change back after the call stack returns

I am using a recursive call in a tree in matlab, the basic structure of the function is here:
function recursion(tree, targetedFeatures)
if (some conditions fulfilled)
return;
end
for i = 1:1:size(targetedFeatures,2)
.....
.....
if (some conditions that using index i is true)
targetedFeatures(1,i) = 1;
end
end
if(tree has child nodes)
recursion(tree.child(j).targetedFeatures)
end
end
The structure of the tree is like this:
root
/ | \
/ | \
/ | \
leaf1 leaf2 leaf3
The input parameter of function recursion is a vector named targetedFeatures, assume its initial values is [0 0 0], and in the process of visiting leaf1, the vector is changed to [1 0 0], BUT when visiting to leaf2, the targetedFeature changed back to [0 0 0].
I suspect it is because vector in matlab does not like an reference to object in other programming language?
How can I avoid this issue? Thanks.
Matlab uses call-by-value for normal types of variables, see here. A way to work around it is to let the function return the modified copy as an output argument:
function targetedFeatures = recursion(tree, targetedFeatures)
...
targetedFeatures = recursion(tree.child(j).targetedFeatures);
...
end
Instead, call-by-reference might be simulated by using evalin('caller', ...) and inputname.
When the recursion function needs to modify targetedFeatures, a copy of targetedFeatures is created which is local to that function call. If you want your updates to be communicated back to the calling scope, then you will need to return the updated targetedFeatures from your function.
function targetedFeatures = recursion(tree, targetedFeatures)
if (some conditions fulfilled)
return;
end
for i = 1:1:size(targetedFeatures,2)
.....
.....
if (some conditions that using index i is true)
targetedFeatures(1,i) = 1;
end
end
if(tree has child nodes)
targetedFeatures = recursion(tree.child(j).targetedFeatures)
end
end
This is not nearly as effective as doing things with pointers like you might do in C for example, but you should not see a significant performance hit on what your code is already doing, since you are already creating local copies whenever you update targetedFeatures.
Thanks to chappjc for providing a link to this post which discusses the copy-on-write mechanism.
Depending on the length and eventually depth of your tree the return-based solutions above quickly become pretty ugly, since you'll always have to change the root node while in principle you'd only like to change one of many leafs.
Instead, you might want to look into implementing a handle class for the TreeNode object.
This would start off with something as simple as:
classdef TreeNode < handle
properties
targetedFeatures;
child; % vector keeping handles to TreeNode children
parent; % handle of the parent node, of which this node is a child
end
methods
...
end
end
You'd obviously have to fill in methods to add/remove children etc.
With such a tree you can recurse down to the deepest leaf and change its value without the need to carry around a reference to the top level root node all the time.
Once you have this in place, you should be able to use your function without modification.
An implementation of a somewhat similar class is one for linked lists, demonstrated in the MATLAB docs:
http://www.mathworks.de/de/help/matlab/matlab_oop/example--implementing-linked-lists.html
Here every node has a previous and next "child", instead of a parent and multiple children, but the general structure is pretty similar.
If you're planning to have a lot of other operations on this tree, like adding/removing nodes, searching, etc. it will definitely be worth it at some point.
If you just happened to come across that tree and you're done once you fixed this single issue, than go for the return-based solutions.

return NOT exiting function properly in MATLAB

I'm running a recursive function which searches a room for an object. This code is working in conjunction with another process essentially running the same code. The first thing the code does is check to see if the other one has found the object and, if so, it is supposed to break out of the function.
When I do the check to see if the other process has found the object, if it has, I use "return" to break out of that function at which time it's supposed to move onto other lines of code...However, for some reason it doesn't fully break out but instead just runs the function again and again.
Any ideas on how I can get it to break out?
I would and can provide the code but it's kind of long
EDIT
Parent script
!matlab -r "zz_Mock_ROB2_Find" & distT = 0.3;
Rob1_ObjFound = 0;
matrix = search_TEST_cam(rob, vid, 0.3, XYpos, 'north', stack, matrix, 0);
disp('I"M OUT')
Recursive code
function matrix = search_TEST_cam(rob1, vid, distT, startingPos, currentDir, stack, matrix, bT)
Rob1_ObjFound = 0;
Rob2_ObjFound = 0;
try
load('Rob2_ObjFound.mat', 'Rob2_ObjFound');
catch
end
if(Rob2_ObjFound == 1)
setDriveWheelsCreate(rob1, 0, 0);
disp('ROB_2 FOUND THE OBJECT')
pause(0.5)
BeepRoomba(rob1)
pause(0.5)
setDriveWheelsCreate(rob1, 0, 0);
return
end
Use break to break out of a for or a while loop and terminate execution, i.e., statements after that are ignored. For e.g.,
for i=1:5
if i==3
break
else
fprintf('%u,',i)
end
end
outputs 1,2, and the code terminates when i=3. If you have nested loops, break will only break out of its current loop and move on to the parent loop.
To skip only the current iteration and move on to the next, use continue. Using the same example,
for i=1:5
if i==3
continue
else
fprintf('%u,',i)
end
end
outputs 1,2,4,5,.
Using return in a function just returns control to the parent function/script that called it.
It seems like you're using the wrong one in your code. However, it's hard to tell without knowing how you're using them. Anyway, you can try one of these three and see if it makes a difference.
It's hard to say without seeing your code, but I doubt it's a problem with the RETURN statement. It's more likely a problem with how you've set up your recursion. If your recursive function has called itself a number of times, then when you finally invoke a RETURN statement it will return control from the current function on the stack to the calling function (i.e. a previous call to your recursive function). I'm guessing the calling function doesn't stop the recursion properly and ends up calling itself again, continuing the recursion.
My advice: check the exit conditions for your recursive function to make sure that, when the object is found and the most recent call returns, every previous call is properly informed that it should return as well.