I have this recursive function:
def My_recu_fun(i):
if i < 4:
return i+1
return 55692*My_recu_fun(i-4) - 9549*My_recu_fun(i-3) + 301*My_recu_fun(i-2) + 21*My_recu_fun(i-1)
If I call it like:
My_recu_fun(int(2e5))
I get this error:
RecursionError: maximum recursion depth exceeded in comparison
Now I hope to solve this by using NumPy. But I don't understand how can I do it.
The problem is that the function will get executed an exponentially number of times, in terms of the initial argument i. There is an immense number of times that the function needs to recalculate a result it already had calculated earlier in the process.
Using NumPy can be a good idea when you need to do intensive array/matrix operations, but in itself it will not solve this particular recursion problem.
You could use memoization to avoid such recalculations. But it is even better to take a bottom up, iterative approach, only keeping track of the last 4 results:
def My_fun(i):
if i < 4:
return i+1
a, b, c, d = 1, 2, 3, 4
for j in range(3, i):
a, b, c, d = b, c, d, 55692*a - 9549*b + 301*c + 21*d
return d
Be aware the the numbers that are generated by this function quickly grow very large.
Here are some statistics:
value of i
function result
2
3
20
23654235486457205901623901 (26 digits)
200
~10263
2000
~102643
20000
~1026443
Calculating with such large integers, takes lots of memory and time. You cannot use NumPy even with the iterative algorithm, because its native ctypes cannot save numbers that large.
My_recu_fun(int(2e5)) runs the My_recu_fun more than 2*10^5 (so 200.000) times. Python assumes it is a bug (because it's more than 10^4 times) and wants to prevent it. You can turn that behaviour off using:
import sys
sys.setrecursionlimit(n)
Where n is the required amount of recursion. I cannot estimate how many times My_recu_fun does recursion, so you will have to estimate that.
In addition to that, I recommend using functool's cache decorator to speed things up:
import sys
from functools import cache
n = 500000
sys.setrecursionlimit(n)
#cache
def My_recu_fun(i):
if i < 4: return i+1
return 55692*My_recu_fun(i-4) - 9549*My_recu_fun(i-3) + 301*My_recu_fun(i-2) + 21*My_recu_fun(i-1)
Suppose we have the following functions:
def modulo(a, b):
"""Take numbers a and b and compute a % b."""
if b <= 0:
return None
div = int(a / b)
return a - div*b
def power(a, b):
"""Take number a and non-negative integer b.
Compute a**b."""
if b == 0:
return 1
else:
return a * power(a, b - 1)
For modulo, is the big-O notation O(a / b)? Because the time it takes to execute depends on a and b inputs. However, I've seen modulus computations online where the big-O notation is O(logn), so not sure if that's applicable here. Can anyone clarify?
For power, would the big-O notation be O(a^b) because it involves powers?
Following the previous answered question
Time complexity is calculated for repetitive tasks. Therefore, if you don't have loops in general, you don't talk about time complexity. You are just applying one thing.
So for modulo you can 'ignore it' (O(c)) c is a constant.
For the recursive function, since we are re-entering in the function each time, until b==0, then the complexity is O(b) similar to O(n) from the previous question. (linear)
If you google Recursion it will show you did you mean recursion and if you keep clicking it, it keeps taking you to the same page, therefore, recursion is a repetitive task. That is why it you consider it similar to a loop.
modulo has no loop, it just does constant time operations (math), so it's O(1). power will decrease b by 1 until it's 0, and the rest of the function is O(1), so it's O(1*b) or O(b).
I want to write a function in python to compute the cross ratio of four projective points, and I am wondering whether there is an elegant and succinct implementation to handle infinite cases.
A naive implementation of the cross ratio looks like this:
ratio = lambda a,b,c: (a-c)/(b-c)
cross_ratio = lambda a,b,c,d: ratio(a,b,c)/ratio(a,b,d)
But this fails when one of the inputs is Infinity. This should not happen, but rather we would like the infinities to "cancel out each other" and give us a simple ratio.
For example, the cross ratio of Infinity, 0, 1, -1 should be -1.
Also, I would like to handle points expressed as a ratio of two numbers. Thus (1 1)would be the number 1, while (1,0)would represent Infinity, etc.
I could always fall back to a definition by cases and make do with it, but I feel this may be a good opportunity to learn good design.
I am using Python 2.7 and the Sagemath module. Any advices on how to implement this?
I'd try this:
def det2(a, b): return a[0]*b[1] - a[1]*b[0]
def cr2(a, b, c, d): return vector([det2(a,c)*det2(b,d), det2(a,d)*det2(b,c)])
This would use homogeneous coordinates on input, so you'd inout two-element vectors. It would also return its result in homogeneous coordinates, as a two-element vector, so you could get a clean description of infinite cross ratio. If you need the result as an element of some field instead, just use division instead of the vector constructor:
def cr2(a, b, c, d): return (det2(a,c)*det2(b,d))/(det2(a,d)*det2(b,c))
I added the suffix 2 to my formulas because personally I often need the cross ratio of four collinear points in the plane. In that case, I'd use
def det3(a, b, c):
return matrix([a,b,c]).det() # Or spell this out, if you prefer
def cr3(a, b, c, d, x):
return vector([det3(a,c,x)*det3(b,d,x), det3(a,d,x)* det3(b,c,x)])
Now let x be any point not collinear with a,b,c,d and you get the cross ratio of these four points. Or more generally, if a,b,c,d are not collinear, you get the cross ratio of the four lines connecting these to x, which can be useful for a number of scenarios, many of them involving conics.
The best is to work with the projective line.
The documentation here contains useful hints:
http://doc.sagemath.org/html/en/reference/schemes/sage/schemes/projective/projective_space.html
Here is an implementation of the cross-ratio, with examples.
sage: P = ProjectiveSpace(1, QQ)
sage: oo, zero, one = P(1, 0), P(0, 1), P(1, 1)
sage: tm = P.point_transformation_matrix
sage: def cross_ratio(a, b, c, d):
....: a, b, c, d = P(a), P(b), P(c), P(d)
....: m = tm([a, b, c], [oo, zero, one])
....: return P(list(m*vector(list(d))))
....:
sage: cross_ratio(oo, zero, one, 1/2)
(1/2 : 1)
sage: cross_ratio(1, 2, 3, 4)
(4/3 : 1)
I am trying to calculate the following ratio:
w(i) / (sum(w(j)) where w are updated using an exponential decreasing function, i.e. w(i) = w(i) * exp(-k), k being a positive parameter. All the numbers are non-negative.
This ratio is then used to a formula (multiply with a constant and add another constant). As expected, I soon run into underflow problems.
I guess this happens often but can someone give me some references on how to deal with this? I did not find an appropriate transformation so one thing I tried to do is set some minimum positive number as a safety threshold but I did not manage to find which is the minimum positive float (I am representing numbers in numpy.float128). How can I actually get the minimum positive such number on my machine?
The code looks like this:
w = np.ones(n, dtype='float128')
lt = np.ones(n)
for t in range(T):
p = (1-k) * w / w.sum() + (k/n)
# Process a subset of the n elements, call it set I, j is some range()
for i in I:
s = p[list(j[i])].sum()
lt /= s
w[s] *= np.exp(-k * lt)
where k is some constant in (0,1) and n is the length of the array
When working with exponentially small numbers it's usually better to work in log space. For example, log(w*exp(-k)) = log(w) - k, which won't have any over/underflow problems unless k is itself exponentially large or w is zero. And, if w is zero, numpy will correctly return -inf. Then, when doing the sum, you factor out the largest term:
log_w = np.log(w) - k
max_log_w = np.max(log_w)
# Individual terms in the following may underflow, but then they wouldn't
# contribute to the sum anyways.
log_sum_w = max_log_w + np.log(np.sum(np.exp(log_w - max_log_w)))
log_ratio = log_w - log_sum_w
This probably isn't exactly what you want since you could just factor out the k completely (assuming it's a constant and not an array), but it should get you on your way.
Scikit-learn implements a similar thing with extmath.logsumexp, but it's basically the same as the above.
Suppose we have a matrix M and two vectors a and b.
Is there a function in Python that returns:
x = f(M,a,b) such that x(i) = M(a(i),b(i))?
This is of course assuming that the elements in a and b do not exceed the size of M.
def f(M, a, b):
return [M[xa, xb] for xa, xb in zip(a, b)]
is close to what you ask for.
You didn't specify whether a and b are the same length or what to do if they aren't -- zip, which I'm using here, will just stop when the shorter one of them is exhausted (if their lengths differ).
I'm also assuming that by x(i) you mean x[i] (&c) -- the difference between square brackets (indexing) and ordinary parentheses (function call) is crucial in Python, but thinking in terms of function calls (which is what your Q as posted clearly specifies) makes no sense whatsoever.