Storing Outputs of a Recursive Function indexable by depth

I am trying to run a monte carlo simulation i number of times. It involves a recursive function. I want to output an array of outputs with particular recursive depths (the number of time the recursive function is called). Here is some example of what I would like the code to look like
function [eion,exit_e] = E(t_in,x_in,i)
rd_e = 0; %This is the recursive depth tracker, it tracks the number of times a particular instance is called
rd_e = rd_e + 1;
for jj = 1 : 2550
RANDOM = rand(1,1)
if RANDOM < avgej(jj)
break
else
t_e = t+e + jj./v_se
end
end
x_out = jj;
t_out = t_in + t_e;
if 2300 < x_out < 2550
exit_e(i) = t_out(rd_e);
else
eion(i) = [x_out(rd_e),t_out(rd_e)];
E(x_out(rd_e),t_out(rd_e),i); %call the recursive function again
end
%After recursive instance of the algorithm is unwound, the data
%associated with that instance is cleared to avoid conflation between
%seperate Monte Carlo trials
clear x_out(rd_e) t_out(r_e)
%Recursively calling instances increases rd_e, so when each instance
%completes the depth counter decrements
rd_e = rd_e - 1;
end
for i = 1 : 1000
output = E(t_in,x_in,i); %E is the recursive function
end
Essentially, I am having issues with the eion(i) line and how to properly store this data and what data type to use. Any suggestions would be great help.

5 commentaires

Stephen23
Stephen23 le 24 Août 2021
Modifié(e) : Stephen23 le 24 Août 2021
Recursive functions don't work they way you seem to expect them to.
For example, this verbose comment:
rd_e = 0; %This is the recursive depth tracker, it tracks the number of times a particular instance is called
is quite inccorect: it will not track the recursion depth, because every time that function is called your code simply defines that value as zero. How does that variable "track" anything, if it is always zero?
The classic way to track the recursion depth is to simply pass a value when the function is called (incrementing it when it is passed. Alternatively you could use nested functions with a shared variable, incrementing/derementing before/after each recursive function call.
This comment also indicates some confusion:
%After recursive instance of the algorithm is unwound, the data
%associated with that instance is cleared to avoid conflation between
%seperate Monte Carlo trials
clear x_out(rd_e) t_out(r_e)
Remember that every function call creates a new workspace that is quite independent of the other workspaces that might already exist. In a well-designed recursive function nothing needs to get "rolled back" because each function call simply processes exactly the set of data that it has, and cares not a jot about what occurs in any other of the function calls.
The line where you actually call the function recursively:
E(i,x_out(rd_e),t_out(rd_e)); %call the recursive function again
does not return any output, so anything that happens in those recursive calls will be discarded.
Also note that your function signature has the input i last:
function [eion,exit_e] = E(t_in,x_in,i)
% ^ here am I !
but you call the function with all of the arguments in reverse order here:
E(i,x_out(rd_e),t_out(rd_e)); %call the recursive function again
% ^ now I am here !
and what is presumably the correct order here:
output = E(t_in,x_in,i); %E is the recursive function
% ^ I am back here!
It is not clear if your recursive function has a valid/tractable stopping condition. Without any indexing or similar in that last loop the output variable get overwritten on every iteration, leaving only the data from the final iteration.
Take a deep breath, think about what you are doing.
Before jumping into writing MATLAB code write out your algorithm on paper: write concrete (short) numeric values, draw a flow-chart or similar showing exactly which bits of data get passed and under what conditions.
Take a look at some examples of simple recursive functions, and follow where every individual element of data ends up (or originates).
Hi,
I fixed the typos I made. Sorry- I am not a coder or anything and I am working on a computational project, so this has been exceptionally difficult for me.
Basically the algorithm is trying to do a random walk for electrons. An electron gets excited at t_in and x_in for the first Monte Carlo trial i. The aglorithm then checks if the probability of ionization at that point (avg_j(jj))is greater than a random probability (RANDOM). If it is, the travel time of the electron (t_e) is incretemented. If not, the for loop breaks.
RANDOM = rand(1,1)
if RANDOM < avgej(jj)
break
else
t_e = t+e + jj./v_se
end
The function then checks if the electron is near the end of the active region. If the electron is near the end of the active region, it should save the t_out indexable by the recursive depth for Monte Carlo instance i. If the electron is not near the end of the active region, then it records t_out and x_out indexable by the recursive depth for Monte Carlo instance i. Then, the function should be called again until the electron reaches the end of the active region.
if 2300 < x_out < 2550
exit_e(i) = t_out(rd_e);
else
eion(i) = [x_out(rd_e),t_out(rd_e)];
E(x_out(rd_e),t_out(rd_e),i); %call the recursive function again
end
I have heard about using Variable-length input argument lists for this, but I am unsure of what data type to use for eion and exit_e.
"I am not a coder or anything and I am working on a computational project, so this has been exceptionally difficult for me."
No one is born a coder. Recursion is difficult for everyone, so you are in good company.
It is not clear to me from your description if recusion is even required. Can you please clarify:
  • is your code supposed to handle one electron or multiple electrons?
  • why does a WHILE loop not suffice? Have you looked at WHILE loops?
  • Technically, both. Basically one electron is injected, lets call it e_1. e_1 hits a second electron e_2, then the whole process starts over again where t_in and x_in for e_2 is actually t_out and x_out for e_1. You still want to track where e_1 goes and what it does until it reaches the end of the active region (2300 < x_out < 2550). This goes for n number of electrons (e_n lets suppose) until t_in for e_n electron is at the end of the active region and therefore cannot go on hitting other electrons anymore.
  • I am not sure how well this would work with a while loop, but I guess it could. I suppose I did not want to use one because I wanted to be able to track all the electron events concurrently.
Stephen23
Stephen23 le 24 Août 2021
Modifié(e) : Stephen23 le 25 Août 2021
Recursion is most useful in situations where:
  • the total number of computation "branches" is not known in advance, and/or
  • the depth of each branch is independent (e.g. these might both be due to the branch depending on the data itself)
If you think that your case matches those basic conditions, then by all means use recursion. If the number of branches is known (even if just by some limit) then it might be easier to use a loop... something for you to consider.
Assuming that you want to use recursion, start by looking at some examples of simple recursive functions. Really track exactly how their data values change with each recursive function call (e.g. by printing variables to the command window), understand why those changes happen and how the stopping conditions work. Look at how they (most likely) select subsets of their data to pass to the recursive function calls. Pay attention to how they return and collect the output data from those recursive function calls.
Plan how your function should work: forget about MATLAB, do it on paper. Paper is how you can see your algorithm, scribble down your ideas, and write out examples with concrete data values. Use lots of paper. More paper!

Connectez-vous pour commenter.

Réponses (0)

Produits

Question posée :

le 24 Août 2021

Modifié(e) :

le 25 Août 2021

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by