Related
My code solves an ODE system using two random values of randomly generated parameters from a list. I put this in a for loop to generate some 50 outputs using those parameter values. I use an if loop within my for loop, to set conditions so that if the values calculated fall within a range, it prints an acceptance message, else print a rejection message. However, what I want is this information (the output values, and the corresponding param values used to generate those outputs) to be stored in memory, for example within a list. However my method only saves the last value in the list, or does not save anything in the list at all. Depending on how I position code within the loops, it will end up printing various elements 50 times in a row, which I do not want. My code is this:
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from scipy.optimize import minimize
beta_samples = np.random.uniform(0, 30, 50)
gamma_samples = np.random.uniform(0, 2, 50)
for i, j in zip(beta_samples, gamma_samples):
# Total population, N.
N = 1
# Initial number of infected and recovered individuals, I0 and R0.
I0, R0 = 0.001, 0
# Everyone else, S0, is susceptible to infection initially.
U0 = N - I0 - R0
J0 = I0
Lf0, Ls0 = 0, 0
# Contact rate, beta, and mean recovery rate, gamma, (in 1/days).
beta, gamma = i, j
mu, muTB, sigma, rho = 1/80, 1/6, 1/6, 0.03
u, v, w = 0.88, 0.083, 0.0006
t = np.linspace(0, 500, 500+1)
# The SIR model differential equations.
def deriv(y, t, N, beta, gamma, mu, muTB, sigma, rho, u, v, w):
U, Lf, Ls, I, R, cInc = y
b = (mu * (U + Lf + Ls + R)) + (muTB * I)
lamda = beta * I
clamda = 0.2 * lamda
dU = b - ((lamda + mu) * U)
dLf = (lamda*U) + ((clamda)*(Ls + R)) - ((u + v + mu) * Lf)
dLs = (u * Lf) - ((w + clamda + mu) * Ls)
dI = w*Ls + v*Lf - ((gamma + muTB + sigma) * I) + (rho * R)
dR = ((gamma + sigma) * I) - ((rho + clamda + mu) * R)
cI = w*Ls + v*Lf + (rho * R)
return dU, dLf, dLs, dI, dR, cI
# Integrate the SIR equations over the time grid, t.
solve = odeint(deriv, (U0, Lf0, Ls0, I0, R0, J0), t, args=(N, beta, gamma, mu, muTB, sigma, rho, u, v, w))
U, Lf, Ls, I, R, cInc = solve.T
if 320 < I[-1]*100000 < 480 and 240 < (cInc[1:] - cInc[:-1])[-1]*100000 < 360:
acc = [320 < I[-1]*100000 < 480]
acc.append(320 < I[-1]*100000 < 480)
print('for beta of', beta, 'and gamma of', gamma, 'pprevalence is ', I[-1]*100000, 'incidence is ', (cInc[1:] - cInc[:-1])[-1]*100000)
else:
rejected.append(beta_samples)
print('values of', beta, 'and gamma of', gamma, 'rejected')
Where is my code going wrong? I simply want a list of the values that come under the 'if' conditions, and those coming under the 'else' conditions
I wish to minimize the parameters beta and gamma in this model. However, my observed data isnt in the form of a time series. The values I want to estimate are for when two certain trajectories have equilibrium values. Namely, when equilibrium values for I (prevalence) and J_diff (incidence) reach 0.4 and 0.3 respectively. My code is as follows:
def peak_infections(x):
# Total population, N.
N = 1
# Initial number of infected and recovered individuals, I0 and R0.
I0, R0 = 0.001, 0
# Everyone else, S0, is susceptible to infection initially.
beta = x[0]
gamma = x[1]
U0 = N - I0 - R0
J0 = I0
Lf0, Ls0 = 0, 0
# Contact rate, beta, and mean recovery rate, gamma, (in 1/years).
beta, gamma = 15, 2/5
mu, muTB, sigma, rho = 1/80, 1/6, 1/6, 0.03
u, v, w = 0.083, 0.88, 0.0006
# A grid of time points
times = np.arange(0,20,2.5)
def deriv(y, times, N, beta, gamma, mu, muTB, sigma, rho, u, v, w):
U, Lf, Ls, I, R, cInc = y
b = (mu * (U + Lf + Ls + R)) + (muTB * I)
lamda = beta * I
clamda = 0.2 * lamda
dU = b - ((lamda + mu) * U)
dLf = (lamda*U) + ((clamda)*(Ls + R)) - ((u + v + mu) * Lf)
dLs = (u * Lf) - ((w + clamda + mu) * Ls)
dI = w*Ls + v*Lf - ((gamma + muTB + sigma) * I) + (rho * R)
dR = ((gamma + sigma) * I) - ((rho + clamda + mu) * R)
cI = w*Ls + v*Lf + (rho * R)
return dU, dLf, dLs, dI, dR, cI
# Initial conditions are S0, I0, R0
# Integrate the SIR equations over the time grid, t.
solve = odeint(deriv, (U0, Lf0, Ls0, I0, R0, J0), times, args=(N, beta, gamma, mu, muTB, sigma, rho, u, v, w))
U, Lf, Ls, I, R, cInc = solve.T
return I
def residual(x):
# Total population, N.
StartingPop = 1
prev= 0.4/StartingPop
return np.sum((peak_infections(x) - prev) ** 2)
x0 = [12, 0.4] #estimates for beta and gamma starting point
res = minimize(residual, x0, method="Nelder-Mead", options={'fatol':1e-04}).x
print(res)
However, where I attempt the minimizing as res, it simply returns the initial estimates in x0 that I gave it. How do I correct this code to include in the residual function, that this must be optimised for when I and J_diff reach their equilibrium states for 0.4 and 0.3?
You are overwriting your input arguments to the function 'peak_infections'. beta and gamma are being assigned the values of x[0] and x[1], respectively. But a few lines later, they are being reassigned as 15 and 2/5. No matter what you pass to the function, the result is the same. Just delete the line where you assign those values to 15 and 2/5 and you will get a result.
I have a function that typically takes in constant args and calculates volatility. I want to pass in a vector of different C's and K's to get an array of volatilities each associated with C[i], K[i]
def vol_calc(S, T, C, K, r, q, sigma):
d1 = (np.log(S / K) + (r - q + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
vega = (1 / np.sqrt(2 * np.pi)) * np.exp(-q * T) * np.sqrt(T) * np.exp((-si.norm.cdf(d1, 0.0, 1.0) ** 2) * 0.5)
tolerance = 0.000001
x0 = sigma
xnew = x0
xold = x0 - 1
while abs(xnew - xold) > tolerance:
xold = xnew
xnew = (xnew - fx - C) / vega
return abs(xnew)
but if I want to pass two arrays without turning into a nested loop, I thought I could just do:
def myfunction(S, T, r, q, sigma):
for x in K,C:
return same size as K,C
but I can't get it to work
How about this?
def vol_calc(S, T, C, K, r, q, sigma):
import numpy as np
output = np.zeros(len(C))
for num, (c, k) in enumerate(zip(C, K)):
d1 = (np.log(S / k) + (r - q + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
vega = (1 / np.sqrt(2 * np.pi)) * np.exp(-q * T) * np.sqrt(T) * np.exp((-si.norm.cdf(d1, 0.0, 1.0) ** 2) * 0.5)
tolerance = 0.000001
x0 = sigma
xnew = x0
xold = x0 - 1
while abs(xnew - xold) > tolerance:
xold = xnew
xnew = (xnew - fx - c) / vega
output[num] = abs(xnew)
return output
I have an expression that comes from
from sympy.physics.quantum import Commutator as cmm
x, t, A, V, W, D = sp.symbols('x t A V W D', commutative = False)
Q = sp.Function('Q', commutative = False)
F = (sp.diff(Q(x,t),x)+ cmm(W,Q(x,t)).doit() - sp.I*cmm(A,Q(x,t)+ cmm(W,Q(x,t)).doit()).doit())*(sp.diff(Q(x,t),x)+ cmm(W,Q(x,t)).doit() - sp.I*cmm(A,Q(x,t)+ cmm(W,Q(x,t)).doit()).doit())
F.expand()
This gives me an expression with elements with zero order in W, with first order in W and second order. I want to get only the first order W's. I tried the factorization procedures but it appears that, due to the fact of no commutation, it doesn't recognize powers of W. It always gives me 0. Is there any simple way of doing this ? Of course I can do it by hand but this is not my goal.
Thanks
You can get all the terms that are first order in W by collecting them as you traverse the arguments of F:
>>> from sympy import Add
>>> first_order_terms = []
>>> for i in Add.make_args(F.expand()):
... if i == W or i.is_Mul and i.has(W) and i.subs(W,y).as_independent(y)[1] == y:
... first_order_terms.append(i)
...
>>> Add(*first_order_terms)
-A*W*Q(x, t)*A*Q(x, t) - I*A*W*Q(x, t)*Derivative(Q(x, t), x) + A*W*Q(x, t)**2*A -
A*Q(x, t)*A*W*Q(x, t) + A*Q(x, t)*A*Q(x, t)*W + A*Q(x, t)*W*A*Q(x, t) - I*A*Q(x,
t)*W*Q(x, t) + I*A*Q(x, t)*W*Derivative(Q(x, t), x) + I*A*Q(x, t)**2*W - A*Q(x,
t)**2*W*A - I*W*Q(x, t)*A*Q(x, t) - W*Q(x, t)*A*Q(x, t)*A + I*W*Q(x,
t)*A*Derivative(Q(x, t), x) + W*Q(x, t)*A**2*Q(x, t) + W*Q(x, t)*Derivative(Q(x, t),
x) + I*W*Q(x, t)**2*A + I*Q(x, t)*A*W*Q(x, t) - Q(x, t)*A*W*Q(x, t)*A - I*Q(x,
t)*A*Q(x, t)*W + Q(x, t)*A*Q(x, t)*W*A + Q(x, t)*A**2*W*Q(x, t) - Q(x, t)*A**2*Q(x,
t)*W + I*Q(x, t)*W*A*Q(x, t) + Q(x, t)*W*A*Q(x, t)*A - I*Q(x, t)*W*A*Derivative(Q(x,
t), x) - Q(x, t)*W*A**2*Q(x, t) - I*Q(x, t)*W*Q(x, t)*A - Q(x, t)*W*Derivative(Q(x,
t), x) - I*Derivative(Q(x, t), x)*A*W*Q(x, t) + I*Derivative(Q(x, t), x)*A*Q(x, t)*W +
Derivative(Q(x, t), x)*W*Q(x, t) + I*Derivative(Q(x, t), x)*W*Q(x, t)*A -
Derivative(Q(x, t), x)*Q(x, t)*W - I*Derivative(Q(x, t), x)*Q(x, t)*W*A
A more compact way to do this, after expanding F, is to do as follows:
>>> Add(*[i for i in F.expand().atoms(Mul) if i.xreplace({W:z}).coeff(z) != 0])
coeff will only return a non-zero value if z (in this case) appears as a linear factor. Of course, this does not work if you just replace W with z in F because terms which didn't cancel because of their distince non-commutative factors will do so after the substitution so you will not get the same result.
I'm trying to convert from XYZ to RGB using the equations from here.
The original code is in C, which I understand much better than python. I've tried to convert it and
I think I'm close to having it, but it gives me back 'False, False, False'. Can anyone see why?
x=0.1
y=0.8
z = 1.0 - x - y
Y = 255
X = (Y / y) * x
Z = (Y / y) * z
r = X * 1.612 - Y * 0.203
g = -X * 0.509 + Y * 1.412 +Z * 0.066
b = X * 0.026 - Y * 0.026 - Y * 0.072 + Z * 0.962
r = r <= 0.0031308 if 12.92 * r else (1.0 + 0.055) * pow(r, (1.0 / 2.4)) - 0.055
g = g <= 0.0031308 if 12.92 * g else (1.0 + 0.055) * pow(g, (1.0 / 2.4)) - 0.055
b = b <= 0.0031308 if 12.92 * b else (1.0 + 0.055) * pow(b, (1.0 / 2.4)) - 0.055
print r,g,b
Change the last three lines before the print to the following:
r = 12.92 * r if r <= 0.0031308 else (1.0 + 0.055) * pow(r, (1.0 / 2.4)) - 0.055
g = 12.92 * g if g <= 0.0031308 else (1.0 + 0.055) * pow(g, (1.0 / 2.4)) - 0.055
b = 12.92 * b if b <= 0.0031308 else (1.0 + 0.055) * pow(b, (1.0 / 2.4)) - 0.055
I think you probably translated a ternary like <condition> ? <true value> : <false value> in C to <condition> if <true value> else <false-value> in Python, but ternary in Python uses the following structure:
<true value> if <condition> else <false value>
You have your conditions and values switched. The structure of the ternary operator in python is:
trueOption if condition else falseOption
Whereas your code appears to be using
condition if trueOption else falseOption
Which is the structure used by C/C++.
This means that the wrong values are being used in the expression, since they are in the wrong order.
Change
r = r <= 0.0031308 if 12.92 * r else (1.0 + 0.055) * pow(r, (1.0 / 2.4)) - 0.055
g = g <= 0.0031308 if 12.92 * g else (1.0 + 0.055) * pow(g, (1.0 / 2.4)) - 0.055
b = b <= 0.0031308 if 12.92 * b else (1.0 + 0.055) * pow(b, (1.0 / 2.4)) - 0.055
to
r = 12.92 * r if r <= 0.0031308 else (1.0 + 0.055) * pow(r, (1.0 / 2.4)) - 0.055
g = 12.92 * g if g <= 0.0031308 else (1.0 + 0.055) * pow(g, (1.0 / 2.4)) - 0.055
b = 12.92 * b if b <= 0.0031308 else (1.0 + 0.055) * pow(b, (1.0 / 2.4)) - 0.055
Your mathematical expressions always evaluate to True, while the conditionals are evaluating to False.