How to compute the following equation correctly? - python

Using python 2.7 I am trying to compute the following rather difficult set of equations.
I have successfully implemented the first two, but am struggling with the third. Here is my attempt,
def pi_tau( r ):
return (1 - (1 - r)**(t + 1))/(2 - r)
def mean_field( r ):
return 1 - (1 - r)**t
def pi_neighbour( r ):
inside = []
for kappa_dash in range(0, kappa - 1):
Binomial_Coefficient = (math.factorial(kappa - 1)) / (math.factorial(kappa - 1 - kappa_dash)*math.factorial(kappa_dash))
top = ((mean_field( r )*pi_tau( r ))**kappa_dash)*(1 - mean_field( r )*pi_tau( r ))**(kappa - 1 - kappa_dash)
bottom = kappa_dash + 1
fraction = top/bottom
inside.append(kappa_dash)
inside[kappa_dash] = inside[kappa_dash] + fraction*Binomial_Coefficient
return pi_tau*inside
I then try to call this function
# set parameters
r = 0.15
kappa = 2.1
T = 10
ppp_t = []
mmm_f = []
nnn_t = []
for t in range(0, T):
ppp_t.append(pi_tau( r ))
mmm_f.append(mean_field( r ))
nnn_t.append(pi_neighbour( r ))
I get the following error message
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-41-9bcf462306f0> in <module>()
6 ppp_t.append(pi_tau( r ))
7 mmm_f.append(mean_field( r ))
----> 8 nnn_t.append(pi_neighbour( r ))
<ipython-input-39-d9acdd7490f9> in pi_neighbour(r)
19 inside[kappa_dash] = inside[kappa_dash] + fraction*Binomial_Coefficient
20
---> 21 return pi_tau*inside
TypeError: can't multiply sequence by non-int of type 'function'
I am looking for any advice on how to implement the third function and improve on my method.

There are several weird things here:
you calculate the top, bottom, and bionomial all in the for loop, but don't sum up in that for loop; and
you multiply the pi_tau function with a list?
return pi_tau*inside
you use range(0, kappa - 1), but the upperbound of range(..) is exclusive
Nevertheless, you make things quite hard. You could use the following approach:
from math import factorial
def pi_neighbour(r):
sum = 0.0
for kappa_dash in range(0,kappa):
bin_coeff = factorial(kappa-1)/(factorial(kappa-1-kappa_dash)*factorial(kappa_dash))
top = ((mean_field(r)*pi_tau(r))**kappa_dash)*(1-mean_field(r)*pi_tau(r))**(kappa-1-kappa_dash)
sum += bin_coeff*top/(kappa_dask+1)
return pi_tau(r)*sum

What I believe you meant to do is the following in line 21 of the traceback:
return pi_tau(r)*inside
You forgot to call the function, and so it is attempting to multiply an integer by a function, rather than the return value of the function.

The error is that you are multiplying a list, that is inside and a integer, that is return of pi_tau(r)
Do this instead (a list comprehension)
try this:
return [i*pi_tau(r) for i in inside]

Related

Compute Riemann sums for double integral over regions in Python (TypeError)

I want to compute the Riemann sums of the double integral
double integral
f = lambda y,x: x*y/(x**2 + y**2)
partition = 50
x = np.linspace(0.00001, 1, 200)
y = np.linspace(1-x, 1, 200)
def Riemann(function, x_low, x_up, y_low, y_up, x_part, y_part):
dx = (x_up - x_low)/x_part
dy = (y_up - y_low)/y_part
dA = dx*dy
sum = 0
x_or = dx/2
y_or = dy/2
for m in range (0,x_part-1):
for n in range (0,y_part-1):
y_or += n*dy
x_or += m*dx
sum += function(y_or,x_or)*dA
return sum
print(Riemann(f,0,1,lambda x:1-x,1,partition,partition))
But it returns this error:
TypeError Traceback (most recent call last)
<ipython-input-10-fdd53b3a35ef> in <module>()
17 return sum
18
---> 19 print(Riemann(f,0,1,lambda x:1-x,1,partition,partition))
<ipython-input-10-fdd53b3a35ef> in Riemann(function, x_low, x_up, y_low, y_up, x_part, y_part)
4
5 dx = (x_up - x_low)/x_part
----> 6 dy = (y_up - y_low)/y_part
7 dA = dx*dy
8 sum = 0
TypeError: unsupported operand type(s) for -: 'int' and 'function'
I really don't know how to solve this... But if i write
print(Riemann(function,0,1,1,0,x_part,y_part))
then it will return 0.34467033928271357, while the correct answer is 0.20387450858124856
You are passing in a function to a variable and then treating it as an integer.
print(Riemann(f,0,1,lambda x:1-x,1,partition,partition))
The code:
lambda x:1-x
will be treated as a function. If you want to pass in 1-x then call the function with:
print(Riemann(f,0,1,1-x,1,partition,partition))
This will fix your current error but I am not entirely sure what it is you are trying to acheive.
You are sending a function (instead of a float or integer) as parameter y_low to your function def Riemann():
type(lambda x: 1-x)
function
Use the correct format and it should be solved

How to avoid math domain error when we have sqrt

I wrote the following code, after printing about 10 outputs it gets error
return 1/sqrt(Om*(1+z)**3+omg0*(1+z)**6+(1-Om-omg0))
ValueError: math domain error
the three first functions are correct and work well in other programs please do not be sensitive about their structures, I think the problem is in for-loop and choosing some values which cannot satisfy the condition of sqrt. Could I add some lines to tell Python avoid numbers which lead to math domain error? If yes, How should I do that? I mean passing the step which leads to negative value under sqrt?
Cov is a 31*31 mtrix, xx[n] is a list of 31 numbers.
def ant(z,Om,w):
return 1/sqrt(Om*(1+z)**3+w*(1+z)**6+(1-Om-w))
def dl(n,Om,w,M):
q=quad(ant,0,xx[n],args=(Om,w))[0]
h=5*log10((1+xx[n])*q)
fn=(yy[n]-M-h)
return fn
def c(Om,w,M):
f_list = []
for i in range(31): # the value '2' reflects matrix size
f_list.append(dl(i,Om,w,M))
A=[f_list]
B=[[f] for f in f_list]
C=np.dot(A,Cov)
D=np.dot(C,B)
F=np.linalg.det(D)*0.000001
return F
N=100
for i in range (1,N):
R3=np.random.uniform(0,1)
Omn[i]=Omo[i-1]+0.05*np.random.normal()
wn[i]=wo[i-1]+0.05*np.random.normal()
Mn[i]=Mo[i-1]+0.1*np.random.normal()
L=exp(-0.5*(c(Omn[i],wn[i],Mn[i])-c(Omo[i-1],wo[i-1],Mo[i-1])))
if L>R3:
wo[i]=wn[i]
else:
wo[i]=wo[i-1]
print(wo[i])
The output is:
0.12059556415714912
0.16292726528216397
0.16644447885609648
0.1067588804671105
0.0321446951572128
0.0321446951572128
0.013169965429457382
Traceback (most recent call last):
......
return 1/sqrt(Om*(1+z)**3+omg0*(1+z)**6+(1-Om-omg0))
ValueError: math domain error
Here are some options:
Replace sqrt(...) with (...)**0.5. This will produce complex numbers, which may or may not be acceptable. For example (-1)**0.5 produces i which in Python will appear as 1j (ignoring floating point errors).
Catch errors and move on. Since you probably want to catch the errors higher up, I recommend translating the ValueError from sqrt into a custom error:
class SqrtError(ValueError):
pass
def ant(z, Om, w):
val = Om * (1 + z) ** 3 + w * (1 + z) ** 6 + (1 - Om - w)
try:
sq = sqrt(val)
except ValueError:
raise SqrtError
return 1 / sq
Then it sounds like you want to keep trying new random numbers until you get one that works, which could be done like so:
for i in range(1, N):
R3 = np.random.uniform(0, 1)
while True:
Omn[i] = Omo[i - 1] + 0.05 * np.random.normal()
wn[i] = wo[i - 1] + 0.05 * np.random.normal()
Mn[i] = Mo[i - 1] + 0.1 * np.random.normal()
try:
L = exp(-0.5 * (c(Omn[i], wn[i], Mn[i]) - c(Omo[i - 1], wo[i - 1], Mo[i - 1])))
except SqrtError:
continue
else:
break
if L > R3:
wo[i] = wn[i]
else:
wo[i] = wo[i - 1]
Your code is trying to find the square root of a negative number.
This is not allowed with real-valued numbers (for obvious mathematical reasons), so your best bet is to use a try/except block:
def ant(z,Om,w):
try:
return 1/sqrt(Om*(1+z)**3+omg0*(1+z)**6+(1-Om-omg0))
except ValueError:
return None

pass multiple parameters to function in multiple tuple sets - python

essentially I have a function which I need to pass to a bunch of values in two different moments (here skipped for practical reasons), hence, I thought need to split all the parameters in two tuple sets after which I'd pass the first set and then the second thinking - mistakenly - that python would allocate all the available n parameters of the function to the values passed with the tuple and then the rest with the second tuple. That is not the case:
def example_F_2(x, y, z, g):
return x * y + z * g
e = (1,2)
r = (3,4)
print(example_F_2(e, r))
in fact:
Traceback (most recent call last):
File "C:/Users/francesco/PycharmProjects/fund-analysis/test_sheet.py", line 7, in <module>
print(example_F_2(e, r))
TypeError: example_F_2() missing 2 required positional arguments: 'z' and 'g'
what can I do? I am guessing something from this page should work (https://docs.python.org/3.5/library/functools.html) but I have been unable to do it myself
A very simple way is to concatenate the tuples and then unpack them as you pass them to your function:
print(example_F_2(*(e+r)))
Perhaps you can use something like this:
def example_F_2(e=None, r=None):
first_term = 0
second_term = 0
if e is not None:
first_term = e[0] * e[1]
if r is not None:
second_term = r[0] * r[1]
return first_term + second_term
e = (1, 2)
r = (3, 4)
print example_F_2(e, r)
> 14
print example_F_2(e=e)
> 2
print example_F_2(r=r)
> 12

What is the reason for TypeError: 'Zero' object has no attribute '__getitem__'?

I have written the following code in python 2.7 in order to calculate an integration numerically and then use the result of this integration for further steps of the project.
import numpy as np
from scipy import linspace,logspace
from cosmicpy import *
Omega_Matter, Omega_DarkEnergy, A, b, rho_critical, m = 0.306, 0.694, 0.3222, 0.707, 2.77536627e+11, 1000000
def D(z):
a = 1/(1+z)
x = (Omega_DarkEnergy/Omega_Matter)**(1/3)*a
return (5/2)*(Omega_Matter/Omega_DarkEnergy)**(1/3)*x**(-3/2)*(1+x**3)**(1/2)* \
(x**2/(3*x**3 + 3) - np.log(x + 1)/9 + np.log(x**2 - x + 1)/18 \
+ np.sqrt(3)*np.arctan(2*np.sqrt(3)*x/3 \
- np.sqrt(3)/3)/9 + np.sqrt(3)*np.pi/54)
def delta(z):
return D(z)/D(0)
def W(k, M):
rho_m = rho_critical*Omega_Matter
R = (3*M/(4*np.pi*rho_m))**(1/3)
x = k*R
return (3/x)*(sin(x)-x*cos(x))
my_cosmology = cosmology(Omega_m=0.306, Omega_de=0.694, h=0.679, Omega_b=0.0483, n=0.968, tau=0.067, sigma8=0.815, w=-1)
k_array = np.logspace(-16,4,m)
P = my_cosmology.pk_lin(k_array)
def sigma_squared(z, M):
dk = (np.max(k_array)-np.min(k_array))/(m-1)
summation = []
for k in k_array:
Integral = 0
Integrand = k**2*P[k]*(W(k, M))**2
Integral += dk * np.sum(Integrand[k])
summation.append(Integral)
return ((delta(z))**2/(2*(np.pi)**2))*summation[-1]
print(summation)
sigma_squared(0.01, 1e+9)
As I write more of the code, I check my steps one by one by getting a print and see if the output is what I expect. However, I am unable to produce the final product of the last function which is supposed to be a value given the values for the variables z and M. In particular I am sure that something is wrong with the integration inside that function because I am not getting any thing for print(summation) which is supposed to be a big 1d array whose last element print(summation[-1])should give me the area under the curve (upto a pre-factor defined in the final return of the function). Here is the error message and I couldn't find any on-line source for the particular error message I am getting. Your help is greatly appreciated.
mycode.py:95: VisibleDeprecationWarning: using a non-integer number
instead of an integer will result in an error in the future
Integrand = k**2*P[k]*(W(k, M))**2 Traceback (most recent call last):
File "mycode.py", line 102, in
sigma_squared(0.01, 1e+9) File "mycode.py", line 96, in sigma_squared
Integral += dk * np.sum(Integrand[k]) TypeError: 'Zero' object has no attribute 'getitem'
Edited Code (which is too slow to know if it is working correctly):
k_array = np.logspace(-16,4,m)
my_cosmology = cosmology(Omega_m=0.306, Omega_de=0.694, h=0.679, Omega_b=0.0483, n=0.968, tau=0.067, sigma8=0.815, w=-1)
P = my_cosmology.pk_lin(k_array)
M_array = np.logspace(8,16,n)
def W(k, M):
rho_m = rho_critical*Omega_Matter
R = (3*M/(4*np.pi*rho_m))**(1/3)
y = k*R
return (3/y**3)*(sin(y)-y*cos(y))
def sigma_squared(z, M):
dk = (np.max(k_array)-np.min(k_array))/(m-1)
summation = []
for k in k_array:
for M in M_array:
Integral = 0
Integrand = k**2*P[k]*(W(k, M))**2
Integral += dk * np.sum(Integrand)
summation.append(Integral)
return ((delta(z))**2/(2*(np.pi)**2))*summation[-1]
print(sigma_squared(0, 1e+9))

Type error Python programming

I am trying to write some code for an assignment in python. What I am not finding anywhere is what is wrong and why it will not run. It is sense and move robotic localization function. I do not understand why this line will not work.
q.append(p[i] * (hit * sensor_right + (1 - hit) * (1-sensor_right)))
hit = a comparison between two strings. That evaluates to true or false which is 1 or 0, right?
sensor_right = 0.7
Traceback (most recent call last):
File "vm_main.py", line 26, in <module> import main
File "/tmp/sbdxfjuois/main.py", line 50, in <module> p = sense(p, measurements[k])
File "/tmp/sbdxfjuois/main.py", line 34, in sense q.append(p[i] * (hit * sensor_right + (1 - hit) * (1-sensor_right)))
TypeError: can't multiply sequence by non-int of type 'float'
Can you suggest anything for what I have here posted?
def sense(p, Z):
q = [ ]
for i in range(len(p)):
hit = (Z == colors[i])
q.append(p[i] * (hit * sensor_right + (1 - hit) * (1-sensor_right)))
s = sum(q)
for i in range(len(q)):
q[i] = q[i]/s
return q
As others have pointed out, this p variable is apparently a sequence of sequences. You can verify this by putting
print(type(p))
print(type(p[i]))
before the append statement. You'll probably see something like
tuple
tuple
If that's what you expected, then you'll need to loop over the other index of the array. Also, does your q need to be returned with the same shape? I suspect you want something more like this.
def sense(p, Z):
q = p[:]
for i in range(len(p)):
for j in range(len(p[i])):
hit = (Z == colors[i])
q[i][j] = (p[i][j] * (hit * sensor_right + (1 - hit) * (1-sensor_right)))
s = sum(q)
for i in range(len(q)):
q[i] = q[i]/s
return q
Note that you also might want to look into numpy arrays.
If you're correct about the other variables, it is telling you that p[i] is a sequence (most likely a list), which can't be multiplied by a float. Perhaps p[i] is not what you're expecting it to be?
Try printing p[i] before the line that throws an error.
The problem here is what others have said. You can only multiply a sequence by an int, not a float.
For example
>>> [1] * 3
[1, 1, 1]
>>> "f" * 6
ffffff
>>> [1] * 0.7
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'float'
Double check your data type for p, to make sure it is supposed to be a sequence. If that is truly what p should be, then make sure to convert the following to an int before multiplying
(hit * sensor_right + (1 - hit) * (1-sensor_right))
Related to what #Mike said, you could also do:
q = []
sum = 0
for i in p:
sub_q = []
for val in i:
computed_val = val * (hit * sensor_right + (1 - hit) * (1-sensor_right))
sum += computed_val
sub_q.append(computed_val)
q.append(sub_q)
I like that because it is more concise and doesn't have to build a bunch of ranges every time you call it, and it also reduces the number of times you iterate over the data, but to each their own.

Categories

Resources