python - syntax suggestion - simulation - python

Consider the following code simulation a non-homogenous poisson process. The focus is on the Non_hom_poisson(T,n,N) function.
def lam_t(T): #calculates lam(t) at given t
Lambda=[]
t=T
for i in range(len(T)):
Lambda.append(0.8+0.4*np.sin(0.2*np.pi*t[i]))
return Lambda
def thinning(max_min,Lam_t,lam_min,times,subset_length):
#thins max-min to lam(t)-lam_min
t=0
J=0
I=0
S=[]
path=2
t_J=np.arange(0,602,2)
while (J<300):
if (path==2):
unif=np.random.uniform(0,1)
X=(-1/float(max_min[J]))*np.log(unif)
path=3
if (path==3):
if ((t+X)>t_J[J+1]):
if ((J+2)>=300):
return S;
X=(X-t_J[J+1]+t)*max_min[J+1]/float(max_min[J+2])
t=t_J[J+1]
J+=1
path=3
else:
t+=(X)
U=np.random.uniform(0,1)
L_t=0.8+0.4*np.sin(0.2*(np.pi)*t)
top_prob=float(L_t-lam_min[J])
bottom_prob=float(max_min[J])
prob=top_prob/float(bottom_prob)
if (U<=(prob)):
I+=1
S.append(float(t))
path=2
if (t>600):
break
return S;
def mod_lam(t,lam):
interval=float(np.mod(t,10))
J=np.arange(2,12,2)
for i in range(len(J)):
if (interval<J[i]):
return float(lam[i])
return float(lam[i])
def Non_hom_poisson(T,n,N):
time=np.arange(0.1,10.1,0.1)
Lambda_t=lam_t(time)
max_lam=[max(Lambda_t[x:(x+19)]) for x in range(0,len(time),20)]
min_lam=[min(Lambda_t[x:(x+19)]) for x in range(0,len(time),20)]
max_min_lam=[(max_lam[x]-min_lam[x]) for x in range(len(max_lam))]
max_min_lam=np.tile(max_min_lam,60)
min_lam=np.tile(min_lam,60)
poisson_min=[np.random.poisson(float(min_lam[0]))]
i=0
while (poisson_min[i]<600):
y=float(mod_lam(poisson_min[i],min_lam))
x=-1/float(y)*np.log(np.random.uniform(0,1))
poisson_min.append(float(x)+float(poisson_min[i]))
i+=1
thinned=thinning(max_min_lam,Lambda_t,min_lam,time,20)
superposition=np.append(thinned,poisson_min)
return np.sort(superposition)
NH=Non_hom_poisson(600,5,1)
print(NH)
I'm getting the following error - "'int' object is not callable" - when max_lam=[max(Lambda_t[x:(x+19)]) for x in range(0,len(time),20)] is called. Any suggestion?

There are three function calls in that line: range(), max() and len(). Those are python builtins.
But neither of those identifiers are reserved words. So what's probably happened is that you have used one of those identifiers as a variable name in the global scope. Since both len() and range() are called with no error in the lam_t() function, it must be max that is an integer.
Which means that an assignment like this has been executed in the global scope.
max = 100
The code included in the question does not contain any such assignment, but the error message indicates that max points to an integer. You can reproduce the error in the python repl.
>>> max = 1
>>> max(1, 3, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
>>> del max # fix it
>>> max(1, 3, 2)
3
It's good practice to avoid using sum, len, list, max, min, int, hash, dir etc. as variable names.
It's a rich cause of confusing bugs if you are using something like a jupyter notebook where it's common practice to define lots of variables in the global namespace and then forget about it.

Related

Is a function still recursive if you don't use return?

I wrote the following code, which works for calculating Fibonacci sequences:
arr = [0]
i = 1
def get_fib(position):
if position == 0:
return arr[0]
if position > 0:
global i
arr.append(i)
i = i + arr[-2]
get_fib(position - 1)
return arr[position]
Is this still recursion, even though I don't use return before get_fib?
Do I need to include return for a function to be recursive?
The function is recursive because it calls itself. So, no, technically you don't need to return the value from that call for it to be recursive.
However, for this function to work, you do. Consider this example:
def factorial(n):
if n == 0:
return 1
else:
return factorial(n-1) * n
This does the same as:
def factorial(n):
if n == 0:
result = 1
else:
result = factorial(n-1) * n
return result
What do you think would happen if we change the next to last line to just:
factorial(n-1) * n
Now there is no longer a result being assigned and the function will probably fail, claiming result has no value. If we change the original in a similar way:
def factorial(n):
if n == 0:
return 1
else:
factorial(n-1) * n
It would calculate factorial(n-1) * n, but it would simply discard the result and since there is no statement after it, the function would return (!) without a return statement, returning None instead.
An example of a recursive function that does something useful without returning anything:
from pathlib import Path
def list_txt(dir):
for name in Path(dir).glob('*'):
if name.is_dir():
list_txt(name)
elif name.suffix.lower() == '.txt':
print(name)
This function is recursive, because it calls itself with del_txt(name), but it doesn't need to return anything, so it will just return None whenever it is done. It would go through a directory and all its subdirectories and list all the .txt files in all of them. A recursive function isn't necessarily the best choice here, but it's very easy to write and maintain, and easy to read.
Yes the function is recursive, by definition, because it calls itself. Where the call to return is placed is not what determines whether or not the function is recursive. However, if you write a recursive function, it must return at some point (known as the "base case"), because if it doesn't it will cause infinite recursion, which will throw an exception ("Runtime Error: maximum recursion depth exceeded") once you pass the Python interpreter's max recursion limit.
Consider two examples:
Example 1:
>>> def fun_a():
... fun_a()
This is a simple function that, calls itself. This function has no terminating condition (the condition when it has to stop calling itself and start popping the stack contents that was build up during the call to itself). This is an example of infinite recursion. If you execute such function, you'll get an error message similar to this:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in fun_a
File "<stdin>", line 2, in fun_a
File "<stdin>", line 2, in fun_a
[Previous line repeated 995 more times]
RecursionError: maximum recursion depth exceeded
Example 2:
>>> def fun_b(n):
... if n == 0:
... return
... fun_b(n-1)
In this case, even though the function is calling itself over and over again, but there is a termination condition, that will stop the function from calling itself again. This is an example of finite recursion and we say that the recursion unfolds on the base case (here base case is when the value of n becomes 0).
To conclude, this is what we say is the general format of a finite recursion. The base case and the recursive call should be in the same order as mentioned here. Otherwise, the function will never stop calling itself and will lead to infinite recursion.
function_name(parameters)
base case
recursive call
A function can be recursive even if there is no return statement. A classic example is the inorder traversal of a binary tree. It doesn't have a return statement. The only requirement for a function to be recursive is that it should call itself. Below is the code (in C).
void inorder(struct node* root)
{
if (root)
{
inorder(root->left);
printf("%d", data);
inorder(root-right);
}
}

How list unpacking works when passed as argument to function with variable parameters?

I have a function which calculates arithmetic mean of variable parameter list. It has one positional parameter and rest variable parameter. So the code is shown below.
def mean(x, *l):
sum = x
for i in l:
sum += i
return sum / (1.0 + len(l))
Now I define a list containing var arguments
z = [1,2,3,4]
Now I call my function
mean(*z) which prints 2.5 which is correct.
So what happened here? My understanding is when I did *z it unpacked the list z.
But then how it picked the 1st positional parameter from the list and kept the rest of the list intact to get the length of 'l' as defined in the function mean. Did it unpack list z just to extract the 1st element from z then keeping rest of z as it is? If that can be done with a list then how?
Also, If I call the function with z alone as argument, it throws error
ari_mean(z)
Traceback (most recent call last):
File "", line 1, in
File "", line 5, in ari_mean
TypeError: unsupported operand type(s) for /: 'list' and 'float'
Thanks.
When you call mean(*z), you are correct in that Python unpacks z, which means that your function call is equivalent (in this case), to calling mean(1, 2, 3, 4)
Now, on to the second part of your question:
Did it unpack list z just to extract the 1st element from z then keeping rest of z as it is?
Not really. First, z was unpacked and each argument passed in separately (as mentioned above). So now you have we look at the definition of mean: def mean(x, *l):. This definition is expecting at least one positional argument (x), and than any number of extra arguments. So, because your initial call of mean(*z) got turned into mean(1, 2, 3, 4), then inside your mean, x is equal to 1 and *l becomes the tuple (2, 3, 4).
Also, If I call the function with z alone as argument, it throws error
If you just call the function with z alone (mean(z)), then, going back to your function definition, x will be the list [1,2,3,4] and l will be an empty tuple. Because l is an empty tuple, nothing happens in the for-loop, and you get to the last line, return sum / (1.0 + len(l)). Now, because x is a list, Python raises an exception because it does not know how to compute [1,2,3,4] / 1.0
Running the code below can show you how it works, the comments present the way the arguments are passed in the function.
def mean(x, *l):
sum=x
print("x:",x)
print("l:",l)
print("len(l):",len(l))
for i in l:
sum += i
return sum / (1.0+len(l))
z = [1,2,3,4]
print("1st call:")
print("result:",mean(*z)) ##x = z[0] and l=tuple(z[1:])
print("\n\n2nd call:")
print("result:",mean(z)) ##x = z and l = tuple()

TypeError: 'NoneType' object has no attribute '__getitem__'

Hi So I created this function called runloopg(x,y,z) that produces a list but I can't call an item on the list:
p=runloopg(10,0.1,6)
<generator object rtpairs at 0x000000000BAF1F78>
[(0,0,0,0,0,1), (0.01,0,0,0,0,1), (0.0062349,0.00781831,0,0,0,1), (-0.00222521,0.00974928,0,0,0,1), (-0.00900969,0.00433884,0,0,0,1), (0.0549583,-0.0712712,0,0,0,1), (0.0627244,-0.0645419,0,0,0,1), (0.0696727,-0.0569711,0,0,0,1), (0.0757128,-0.0486577,0,0,0,1), (0.0807659,-0.0397099,0,0,0,1), (0.084766,-0.0302444,0,0,0,1), (0.0876611,-0.0203847,0,0,0,1), (0.0894134,-0.0102592,0,0,0,1)]
However when I call an item on my list as so:
p[0]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-240-a69904524460> in <module>()
----> 1 p[0]
TypeError: 'NoneType' object has no attribute '__getitem__'
This is the code for runloopg:
import numpy
import raytracer29
def rtpairs(R, N):
for i in range(len(R)):
r=R[i]
n=N[i]
for j in range(n):
t = j*2*numpy.pi/n
yield r,t
def rtuniform(n, rmax, m):
R=numpy.arange(0,rmax,rmax/n)
N=numpy.arange(1, n*m, m)
return rtpairs(R, N)
def runloopg(n, rmax, m):
#print rtuniform(n, rmax, m)
bund = []
for r,t in rtuniform(n, rmax, m):
myRay = raytracer29.Ray(r * numpy.cos(t), r * numpy.sin(t),0,0,0,1)
bund.append(myRay)
return bund
You didn't post the relevant code - your function's definition - but very obviously this function returns None.
edit: Ok from the snippet you posted runloopg does indeed return a list so the problem is elsewhere. I see that your snippet starts with a commented out print statement printing the return value of a call to rtuniform, and this matches what you posted of your interactive session. My guess is that you were executing an older version of the function that just printed and exited immediatly (implicitely returning None), then you edited your code but failed to properly reload your function.
Since your method is returning a generator, you need to consume it:
for i in runloopg(10,0.1,6):
print(i)
p = list(runloopg(10,0.1,6))
# If you just want the first item:
first_item = next(runloopg(10,0.1,6))
It looks like your runloopg function is missing a return. So, it does something like this:
def runloopg():
[(0,0,0,0,0,1), (0.01,0,0,0,0,1), (0.0062349,0.00781831,0,0,0,1)] # and the rest
or this:
def runloop():
x = [(0,0,0,0,0,1), (0.01,0,0,0,0,1), (0.0062349,0.00781831,0,0,0,1)] # and the rest
instead of this:
def runloopg():
return [(0,0,0,0,0,1), (0.01,0,0,0,0,1), (0.0062349,0.00781831,0,0,0,1)] # and the rest
In the first version, that line is run, its result is then immediately discarded, and the function continues. In the second, the result is stored in a variable, and the function continues. In both cases, the function then falls off the end - and Python will return None for you when that happens. In the last version, the result you've calculated is returned, and ends up being assigned to p - so p will be a list, and p[0] will work.
A generator object is returned. Once you used a generator, it's exhausted and you can't use it again.
But you can take all of it's values as a list:
p = list(runloopg(10,0.1,6))

Python curiosity: [] > lambda n: n

One of my coworkers was using the builtin max function (on Python 2.7), and he found a weird behavior.
By mistake, instead of using the keyword argument key (as in key=lambda n: n) to pre-sort the list passed as a parameter, he did:
>>> max([1,2,3,3], lambda n : n)
[1, 2, 3, 3]
He was doing what in the documentation is explained as:
If two or more positional arguments are provided, the largest of the positional arguments is returned., so now I'm curious about why this happens:
>>> (lambda n:n) < []
True
>>> def hello():
... pass
...
>>> hello < []
True
>>> len(hello)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'function' has no len()
I know it's not a big deal, but I'd appreciate if any of the stackoverflowers could explain how those comparisons are internally made (or point me into a direction where I can find that information). :-)
Thank you in advance!
Python 2 orders objects of different types rather arbitrarily. It did this to make lists always sortable, whatever the contents. Which direction that comparison comes out as is really not of importance, just that one always wins. As it happens, the C implementation falls back to comparing type names; lambda's type name is function, which sorts before list.
In Python 3, your code would raise an exception instead:
>>> (lambda n: n) < []
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: function() < list()
because, as you found out, supporting arbitrary comparisons mostly leads to hard-to-crack bugs.
Everything in Python (2) can be compared, but some are fairly nonsensical, as you've seen.
>>> (lambda n:n) < []
True
Python 3 resolves this, and produces exceptions instead.

Python global and local variables

In Python 2.7, running the following code:
def f():
a = a + 1
f()
gives the following result:
Traceback (most recent call last):
File "test.py", line 4, in <module>
f()
File "test.py", line 2, in f
a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment
But if I change the code to below:
def f():
a[0] = a[0] + 1
f()
I get the different error:
Traceback (most recent call last):
File "test.py", line 4, in <module>
f()
File "test.py", line 2, in f
a[0] = a[0] + 1
NameError: global name 'a' is not defined
Why is Python considering a is a local variable when it is an int, global when list? What's the rationale behind this?
P.S.: I was experimenting after reading this thread.
The key is found in the documentation on the assignment statement:
Assignment of an object to a single target is recursively defined as
follows.
If the target is an identifier (name) (e. g. a = a + 1):
If the name does not occur in a global statement in the current code
block: the name is bound to the object in the current local namespace.
Otherwise: the name is bound to the object in the current global
namespace.
The name is rebound if it was already bound. This may cause
the reference count for the object previously bound to the name to
reach zero, causing the object to be deallocated and its destructor
(if it has one) to be called.
...
If the target is a subscription (e. g. a[0] = a[0] + 1): The primary expression in the
reference is evaluated. It should yield either a mutable sequence
object (such as a list) or a mapping object (such as a dictionary).
Next, the subscript expression is evaluated.
In f1 Python sees that you are binding some value to a, sees that a has not been used in a global a statement in this scope and prepares a local variable. Then it attempts to evaluate the expression a + 1, looks up the variable a and finds an uninitialized local variable. This results in the UnboundLocalError.
In f2 Python sees that you are assigning some value to a subscription of the variable a. It looks up that variable in the local namespace and fails to find it. It then walks up the non-local namespaces (closures) until it reaches the global namespace. Once it fails to find a in the global namespace it throws a NameError.
Could you try to do something like this :
def f(a):
a += 1
print a
def g():
a = 3
f(a)
g()

Categories

Resources