Converting Python iterative function to recursive function - python-3.x

Please consider 2 crossed suites:
U0 = 1
V0 = 2
Un = 2U(n-1) + 3 V(n-1)
Vn = U(n-1) + V(n-1)
I want to resolve it with this Python iterative function:
def myfunction(n=5):
u = 1
v = 2
for i in range(n):
w = u
u = 2*u + 3*v
v = w + v
return(u,v)
I would prefer a recursive function but I have no idea to convert my function.
Do you have any idea?
Thanks.

As simple as:
def u(n):
if n == 0:
return 1
else:
return 2*u(n-1) + 3*v(n-1)
def v(n):
if n == 0:
return 2
else:
return u(n-1) + v(n-1)
print((u(5), v(5))) # -> (905, 393)
This is possible due to the nature of Python being an interpreted dynamic programing language.
Edit:
def myfunction(n):
def u(n):
if n == 0:
return 1
else:
return 2*u(n-1) + 3*v(n-1)
def v(n):
if n == 0:
return 2
else:
return u(n-1) + v(n-1)
return u(n), v(n)
print(myfunction(5)) # -> (905, 393)
Just to conform with your exact problem/function.

The naive recursive implementation proposed by #moctarjallo is very slow because the same values have to be calculated over and over again. For example, calculating u(22) takes the ridiculous 0.8 sec:
from timeit import timeit
timeit('u(22)', globals=globals(), number=10)
# 8.138428802136332
Consider using an lru_cache decorator that saves the previously computed values in an invisible table and actually calls the functions only when they have not been called with the same parameters before:
from functools import lru_cache
#lru_cache(None) # decorate with a cache
def fast_u(n):
return 1 if not n else 2 * fast_u(n-1) + 3 * fast_v(n-1)
#lru_cache(None) # decorate with a cache
def fast_v(n):
return 2 if not n else fast_u(n-1) + fast_v(n-1)
timeit('fast_u(22)',globals=globals(), number=10)
#9.34056006371975e-05
I also made the functions code a little more idiomatic. Enjoy the difference!
P.S. If you are looking for a one-function implementation:
def uv(n):
if n == 0: return 1, 2
u, v = uv(n-1)
return 2 * u + 3 * v, u + v
uv(5)
#(905, 393)
Caching still improves its performance by orders of magnitude.

Related

Why does my function with complex numbers return as a NoneType?

I've been trying to code something to draw the mandelbrot-set, but my function doesnt seem to work.
the 'point' in my code is a complex number that is defined somewhere else in the code.
def mandelbrot(point, gen):
z = point
if gen > 0:
mandelbrot(z**2 + c, gen-1)
else:
return (z.real**2 + z.imag**2)**(1/2)
I got a grid of points that get colored in based on the result of this function. It would start with a complex number that i define in a loop later, and the 'gen' is just an integer that determines how often the function is used so i can do quicker tests in case it works. I thought it should have returned the length of the vector, but it gave an error that it was a NoneType.
For context, here is the full code:
import turtle
import cmath
Pen = turtle.Turtle()
Pen.speed(0)
Pen.penup()
size = 800
resolution = 16
accuracy = 3
c = complex(0,0)
z = complex(0,0)
Pen.goto(-size/2, -size/2)
def mandelbrot(point, gen):
z = point
if gen > 0:
mandelbrot(z**2 + c, gen-1)
else:
return (z.real**2 + z.imag**2)**(1/2)
def pixel(point):
if mandelbrot(point, accuracy) > 2:
Pen.fillcolor(1,1,1)
else:
Pen.fillcolor(0,0,0)
Pen.begin_fill()
for i in range (0, 4):
Pen.forward(size/resolution)
Pen.left(90)
Pen.end_fill()
for i in range(0, resolution):
Pen.goto(-size/2, -size/2 + i*size/resolution)
for j in range(0, resolution):
c = complex((-size/2 + j*size/resolution)/size*4,
(-size/2 + i*size/resolution)/size*4)
pixel(c)
Pen.forward(size/resolution)

Solving this series using special series in algebra(use of mathematics)

So I am supposed to find the sum of this series :
f(n) = 1 + (2*3) + (4*5*6) + .....n terms
I did this using recursion as follows:
def f(n):
if n == 1:
return 1
else:
product = 1
add = 0
s = (n * (n+1))/2
for i in range (0,n):
product = product * s
s = s - 1
add = product + f(n-1)
return add
Now please bear with me
I thought I could do this faster if I could use special series in linear algebra:
Here is what I attempted:
I found the nth term(through some vigorous calculations) : Tn =
Now is there a method I can use this formula to find sum of Tn and hence the series using python.
I also want to know whether we can do such things in python or not?
You can translate that product to Python using a for loop, analog to how you kept track of the product in your recursive function. So T(n) would be:
def T(n):
product = 1
for r in range(1, n+1):
product *= (n * (n - 1)) / 2 + r
return product
Now as you said, you need to find the sum of T(x) for x from 1 to n. In Python:
def f(n):
sum = 0
for i in range(1, n+1):
sum += T(i)
return sum
FYI:
a += x is the same as a = a + x,
analog a *= x is equal to a = a * x

How do I return a value from a higher-order function?

guys how can I make it so that calling make_repeater(square, 0)(5) return 5 instead of 25? I'm guessing I would need to change the line "function_successor = h" because then I'm just getting square(5) but not sure what I need to change it to...
square = lambda x: x * x
def compose1(h, g):
"""Return a function f, such that f(x) = h(g(x))."""
def f(x):
return h(g(x))
return f
def make_repeater(h, n):
iterations = 1
function_successor = h
while iterations < n:
function_successor = compose1(h, function_successor)
iterations += 1
return function_successor
it needs to satisfy a bunch of other requirements like:
make_repeater(square, 2)(5) = square(square(5)) = 625
make_repeater(square, 4)(5) = square(square(square(square(5)))) = 152587890625
To achieve that, you have to use the identity function (f(x) = x) as the initial value for function_successor:
def compose1(h, g):
"""Return a function f, such that f(x) = h(g(x))."""
def f(x):
return h(g(x))
return f
IDENTITY_FUNCTION = lambda x: x
def make_repeater(function, n):
function_successor = IDENTITY_FUNCTION
# simplified loop
for i in range(n):
function_successor = compose1(function, function_successor)
return function_successor
if __name__ == "__main__":
square = lambda x: x * x
print(make_repeater(square, 0)(5))
print(make_repeater(square, 2)(5))
print(make_repeater(square, 4)(5))
and the output is
5
625
152587890625
This isn't most optimal for performance though since the identity function (which doesn't do anything useful) is always part of the composed function, so an optimized version would look like this:
def make_repeater(function, n):
if n <= 0:
return IDENTITY_FUNCTION
function_successor = function
for i in range(n - 1):
function_successor = compose1(function, function_successor)
return function_successor

simpson integration on python

I am trying to integrate numerically using simpson integration rule for f(x) = 2x from 0 to 1, but keep getting a large error. The desired output is 1 but, the output from python is 1.334. Can someone help me find a solution to this problem?
thank you.
import numpy as np
def f(x):
return 2*x
def simpson(f,a,b,n):
x = np.linspace(a,b,n)
dx = (b-a)/n
for i in np.arange(1,n):
if i % 2 != 0:
y = 4*f(x)
elif i % 2 == 0:
y = 2*f(x)
return (f(a)+sum(y)+f(x)[-1])*dx/3
a = 0
b = 1
n = 1000
ans = simpson(f,a,b,n)
print(ans)
There is everything wrong. x is an array, everytime you call f(x), you are evaluating the function over the whole array. As n is even and n-1 odd, the y in the last loop is 4*f(x) and from its sum something is computed
Then n is the number of segments. The number of points is n+1. A correct implementation is
def simpson(f,a,b,n):
x = np.linspace(a,b,n+1)
y = f(x)
dx = x[1]-x[0]
return (y[0]+4*sum(y[1::2])+2*sum(y[2:-1:2])+y[-1])*dx/3
simpson(lambda x:2*x, 0, 1, 1000)
which then correctly returns 1.000. You might want to add a test if n is even, and increase it by one if that is not the case.
If you really want to keep the loop, you need to actually accumulate the sum inside the loop.
def simpson(f,a,b,n):
dx = (b-a)/n;
res = 0;
for i in range(1,n): res += f(a+i*dx)*(2 if i%2==0 else 4);
return (f(a)+f(b) + res)*dx/3;
simpson(lambda x:2*x, 0, 1, 1000)
But loops are generally slower than vectorized operations, so if you use numpy, use vectorized operations. Or just use directly scipy.integrate.simps.

How to write cos(1)

I need to find a way to write cos(1) in python using a while loop. But i cant use any math functions. Can someone help me out?
for example I also had to write the value of exp(1) and I was able to do it by writing:
count = 1
term = 1
expTotal = 0
xx = 1
while abs(term) > 1e-20:
print("%1d %22.17e" % (count, term))
expTotal = expTotal + term
term=term * xx/(count)
count+=1
I amm completely lost as for how to do this with the cos and sin values though.
Just change your expression to compute the term to:
term = term * (-1 * x * x)/( (2*count) * ((2*count)-1) )
Multiplying the count by 2 could be changed to increment the count by 2, so here is your copypasta:
import math
def cos(x):
cosTotal = 1
count = 2
term = 1
x=float(x)
while abs(term) > 1e-20:
term *= (-x * x)/( count * (count-1) )
cosTotal += term
count += 2
print("%1d %22.17e" % (count, term))
return cosTotal
print( cos(1) )
print( math.cos(1) )
You can calculate cos(1) by using the Taylor expansion of this function:
You can find more details on Wikipedia, see an implementation below:
import math
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
def cos(order):
a = 0
for i in range(0, order):
a += ((-1)**i)/(factorial(2*i)*1.0)
return a
print cos(10)
print math.cos(1)
This gives as output:
0.540302305868
0.540302305868
EDIT: Apparently the cosine is implemented in hardware using the CORDIC algorithm that uses a lookup table to calculate atan. See below a Python implementation of the CORDIS algorithm based on this Google group question:
#atans = [math.atan(2.0**(-i)) for i in range(0,40)]
atans =[0.7853981633974483, 0.4636476090008061, 0.24497866312686414, 0.12435499454676144, 0.06241880999595735, 0.031239833430268277, 0.015623728620476831, 0.007812341060101111, 0.0039062301319669718, 0.0019531225164788188, 0.0009765621895593195, 0.0004882812111948983, 0.00024414062014936177, 0.00012207031189367021, 6.103515617420877e-05, 3.0517578115526096e-05, 1.5258789061315762e-05, 7.62939453110197e-06, 3.814697265606496e-06, 1.907348632810187e-06, 9.536743164059608e-07, 4.7683715820308884e-07, 2.3841857910155797e-07, 1.1920928955078068e-07, 5.960464477539055e-08, 2.9802322387695303e-08, 1.4901161193847655e-08, 7.450580596923828e-09, 3.725290298461914e-09, 1.862645149230957e-09, 9.313225746154785e-10, 4.656612873077393e-10, 2.3283064365386963e-10, 1.1641532182693481e-10, 5.820766091346741e-11, 2.9103830456733704e-11, 1.4551915228366852e-11, 7.275957614183426e-12, 3.637978807091713e-12, 1.8189894035458565e-12]
def cosine_sine_cordic(beta,N=40):
# in hardware, put this in a table.
def K_vals(n):
K = []
acc = 1.0
for i in range(0, n):
acc = acc * (1.0/(1 + 2.0**(-2*i))**0.5)
K.append(acc)
return K
#K = K_vals(N)
K = 0.6072529350088812561694
x = 1
y = 0
for i in range(0,N):
d = 1.0
if beta < 0:
d = -1.0
(x,y) = (x - (d*(2.0**(-i))*y), (d*(2.0**(-i))*x) + y)
# in hardware put the atan values in a table
beta = beta - (d*atans[i])
return (K*x, K*y)
if __name__ == '__main__':
beta = 1
cos_val, sin_val = cosine_sine_cordic(beta)
print "Actual cos: " + str(math.cos(beta))
print "Cordic cos: " + str(cos_val)
This gives as output:
Actual cos: 0.540302305868
Cordic cos: 0.540302305869

Resources