

























Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
A recursive definition or a recursive function it is running back in the ... RecursionError: maximum recursion depth exceeded while calling a Python ...
Typology: Summaries
1 / 33
This page cannot be seen from the preview
Don't miss anything!


























Informal definitions of recursion:
§ A function that makes a call to itself
§ More in general, a thing defined in terms of itself or of its type
Ø This might lead to an infinite regress!
ü Properly defined mathematical recursion solution is never infinite: the recursive calls
to itself eventually reach an end, when some minimal input (base case) is reached
A matryoshka doll is a wooden Russian doll
that contains a smaller sized matryoshka doll
“ To understand recursion you must
first understand recursion!”
J
The adjective recursive originates from the Latin verb recurrere , which means to
run back. A recursive definition or a recursive function it is "running back" in the
sense of returning to itself (possibly with a simpler instance)
§ Mathematical definition (e.g., 5! = 5 × 4 × 3 × 2 × 1 = 120 )
§ We can rewrite it as:
§ In a more general form:
Recursive definition of the factorial function
def factorial_recursive(n):
if n == 1 or n == 0:
return 1
else:
return n * factorial_recursive(n-1)
Recursive definition of the factorial function !:
← Base case (s): it doesn’t require recursion, where the recursive calls of! stop
← Recursive case (s): the function calls itself, with a simpler instance / smaller value
print(factorial_recursive(5))
120
n = 5
if 5 == 1:
return 1
else:
return 5 *
if 4 == 1:
return 1
else:
return 4 * if 3 == 1:
return 1
else:
return 3 * if 2 == 1:
return 1
else:
return 2 *
if 1 == 1:
return 1
§ Let’s consider the case! = 5 and let’s expand the function calls:
False
False
False
False
True
Recursive calls end:
the base case , that
does not require
recursion, is reached!
f(5)
f(4)
f(3)
f(2)
f(1)
f(5)
6
n = 5
1
f(5)
6
n = 5
1
f(4)
5
n = 4
1
f(5)
6
n = 5
1
f(4)
5
n = 4
1
n = 3
1
f(3)
5
f(5)
6
n = 5
1
f(4)
5
n = 4
1
n = 3
1
f(3)
5
f(2)
5
n = 2
1
f(5)
6
n = 5
1
f(4)
5
n = 4
1
n = 3
1
f(3)
5
f(2)
5
n = 2
1
f(1)
5
n = 1
1
Run-time
memory stack
return 4 * 6
return 3 * 2
return 2 * 1
if 1 == 1:
return 1
return 5 * 24
120
f(5)
6
n = 5
1
f(4)
5
n = 3
1
f(2)
5
f(1)
5
n = 1
1
n = 2
1
f(3)
5
n = 4
1
Each function return pops out a call
frame from the run-time memory stack
f(4)
5
n = 3
1
f(2)
5
n = 2
1
f(3)
5
n = 4
1
n = 3
1
f(3)
5
f(5)
6
n = 5
1
f(5)
6
n = 5
1
f(4)
5
n = 4
1
f(5)
6
n = 5
1
f(4)
5
n = 4
1
f(5)
6
n = 5
1
ü Now all the returns can be processed backward , popping out
the functions’ call frames from the run-time memory stack
§ We can easily implement the factorial
function using iteration
def factorial_it(n):
v = 1
for i in range(2, n+1):
v *= i
return v
o Is the iteration-based implementation faster
than the recursion-based one?
o Let’s check their running times for! = 0 , ⋯ , 40
Iteration seems to be a clear winner,
in this specific case ….
§ The previous results were produced with the custom helper function below, quite useful, give it a look!
§ Often, we can use iteration instead of recursion, but recursion, when well designed, can be:
§ More elegant and compact
§ More efficient, computationally
§ Some problems are naturally defined in recursive terms (recurrence equations, iterated maps)
§ Some problems might actually need recursion!
§ However, it may be true that we need some “practice” to learn to think recursively …
§ Trying to enroll the recursive process in our mind is not the way to go , it wouldn’t work, it’d be
just frustrating. We can do this easily for iteration, but the almost unbounded regress process
happening in recursion would be confusing for our minds
§ Recursion is tightly related to the principle of mathematical induction , that can help to think
recursively …
ü Mathematical induction is a mathematical proof technique: given a certain property !(#), prove that it
holds for all integer numbers, # = 0 , 1 , 2 , ⋯
§ Proving by induction requires to prove the truth of two cases:
§ Base case , that proves that the property is true for # = 0 (or # = 1 ), that is for the first integer
§ Induction case , that proves that, if the property holds for a generic # ( inductive assumption, the
validity for # becomes a fact ), it also holds for the next natural number, # + 1
§ If we can prove that both the induction and the base case hold, then we can assert that the property
holds for any integer
§ Induction is a way to perform inference and is at the foundation of the correctness of all computer programs!
Ø When programming recursively, think inductively!
ü Define a recursive (inductive) case, that recursively relates the function! for a generic input " to the value
of the function for a downsized input "# (e.g., "# = " − 1 )
o When you write the recursive relation, assume / trust that the value returned by !( "#) is correct (this is
the inductive thinking!) That is, it does the job of correctly computing the function for the input "#.
o E.g., in the case of the factorial, we have assumed that !(* − 1 ) does return the factorial of * − 1 and
we have used it for defining a recursive relation that computes !(*)
ü Define base (non-recursive) cases for the input ", that return the value of the function for the minimal
admitted inputs ", such that when the input regresses to these values, the recursive calls are interrupted
and the process stops returning the result by combining the results from the individual recursive calls
o E.g., in the case of the factorial, the minimal input is for * = 1 , that we know how to compute without
recursion, the final result is obtained by multiplying the results from each individual function call
§ Problem: compute! ", $ = "
&
recursively, where $ is an integer
§ Base case:! ", 0 = 1
§ Recursive case:! ", $ = " ) !(", $ − 1 )
def exponentiate(x, n):
if n == 0:
return 1
else:
return x * exponentiate(x, n - 1)
exponentiate(2, 7)
def exponentiate(x, n):
if n == 0:
return 1
if x == 0:
return 0:
else:
return x * exponentiate(x, n - 1)
Optimized version for the special case when " = 0
Recurrence equations, two base cases:
§ Let’s start with a pair of rabbits, one male, one female. Rabbits are able to mate at the age of one month so
that at the end of its second month (% = 2 ) a female can produce another pair of rabbits. Suppose that our
rabbits never die and that the female always produces one new pair (one male, one female) every
month from the second month on.
Ø How many pairs f rabbits will there be after % months?
Ø Instance of a discrete-time dynamical system : the state of the system (the number of rabbit pairs)
evolves over time under a growth law expressed by recurrence equations
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
for i in range(20):
print(fibonacci(i))
0 1 1 2 3 5 8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
o Fibonacci numbers are “pervasive” in natural phenomena
o They capture growth modalities and ratios in nature
o http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibnat.html