I need to translate this formula into python:
x = b + (sqrt((b^2)-1)) / 2a
Can somebody please help me?
import math
x = b + (math.sqrt((b ** 2) - 1 )) / (2 * a)
Mathematically correct this solution is
import math
import cmath
def quadratic(a, b, c):
if b == 0:
f = (cmath.sqrt(b ** 2 - 1 )) / (2 * a)
else:
f = (math.sqrt(b ** 2 - 1 )) / (2 * a)
return b + f, b -f
print(quadratic(1, 2, 3))
This will give you the two roots.
You can access the roots by indexing:
my_roots = quadratic(1, 2, 3)
x_1 = my_roots[0]
x_2 = my_roots[1]
By using a Python function , you can re-use this code.
This should work as well. No need to import any library.
Assuming a != 0.
When b >= 1:
x = b + (((b ** 2) - 1 ) ** 0.5) / (2 * a)
NOTE: You should ideally have two roots for sqrt(b^2 - 1). Your function should return both values. Now, I am guessing that, under certain prior knowledge you have decided to only keep the positive root.
When b == 0, you get two roots. Note that sqrt(-1) = j or -j (complex roots).
x = (+1j) / (2 * a) # positive root
# OR
x = (-1j) / (2 * a) # negative root
More generally, when b**2 < 1, you get two complex roots.
x = b + (k*1j) ((1 - (b ** 2)) ** 0.5) / (2 * a)
# positive root: k = +1
# OR
# negative root: k = -1
Related
I 'm trying to build a function that uses several scalar values as inputs and one series or array also as an input.
The function applies calculations to each value in the series. It works fine so far. But now I'm adding a phase where it has to check the value of the series and if it's less than X it performs one calculation other it performs a different calculation.
However I keep getting a 'truth value series is ambiguous error and I can't seem to solve it.
What is a work around?
My code is below
import numpy as np
import pandas as pd
import math
tramp = 2
Qo = 750
Qi = 1500
b = 1.2
Dei = 0.8
Df = 0.08
Qf = 1
tmax = 30
tper = 'm'
t = pd.Series(range(1,11))
def QHyp_Mod(Qi, b, Dei, Df, Qf, tmax, tper, t):
tper = 12
Qi = Qi * (365/12)
Qf = Qf * (365/12)
ai = (1 / b) * ((1 / (1 - Dei)) ** b - 1)
aim = ai / tper
ai_exp = -np.log(1 - Df)
aim_exp = ai_exp / tper
t_exp_sw = 118
Qi_exp = Qi / ((1 + aim * t_exp_sw * b) ** (1 / b))
Qcum = (Qi / (aim * (1 - b))) * (1 - (1 / ((1 + aim * t * b) ** ((1 - b) / b))))
t_exp = t - t_exp_sw
Qcum_Exp = (Qi_exp / aim_exp) * (1 - np.exp(-aim_exp * t_exp))
if t < t_exp_sw:
return Qcum
else:
return Qcum_exp
z = QHyp_Mod(Qi=Qi, b=b, Dei=Dei, Df=Df, Qf=Qf, tmax=tmax, tper=tper, t=t)
Replace the if - else statement:
if t < t_exp_sw:
return Qcum
else:
return Qcum_exp
with this:
Q.where(t < t_exp_sw, Q_exp)
return Q
The where method tests the conditional for each member of Q, if true keeps the original value, and if false replaces it with the corresponding element of Q_exp
im trying to write a program that gives the integral approximation of e(x^2) between 0 and 1 based on this integral formula:
Formula
i've done this code so far but it keeps giving the wrong answer (Other methods gives 1.46 as an answer, this one gives 1.006).
I think that maybe there is a problem with the two for cycles that does the Riemman sum, or that there is a problem in the way i've wrote the formula. I also tried to re-write the formula in other ways but i had no success
Any kind of help is appreciated.
import math
import numpy as np
def f(x):
y = np.exp(x**2)
return y
a = float(input("¿Cual es el limite inferior? \n"))
b = float(input("¿Cual es el limite superior? \n"))
n = int(input("¿Cual es el numero de intervalos? "))
x = np.zeros([n+1])
y = np.zeros([n])
z = np.zeros([n])
h = (b-a)/n
print (h)
x[0] = a
x[n] = b
suma1 = 0
suma2 = 0
for i in np.arange(1,n):
x[i] = x[i-1] + h
suma1 = suma1 + f(x[i])
alfa = (x[i]-x[i-1])/3
for i in np.arange(0,n):
y[i] = (x[i-1]+ alfa)
suma2 = suma2 + f(y[i])
z[i] = y[i] + alfa
int3 = ((b-a)/(8*n)) * (f(x[0])+f(x[n]) + (3*(suma2+f(z[i]))) + (2*(suma1)))
print (int3)
I'm not a math major but I remember helping a friend with this rule for something about waterplane area for ships.
Here's an implementation based on Wikipedia's description of the Simpson's 3/8 rule:
# The input parameters
a, b, n = 0, 1, 10
# Divide the interval into 3*n sub-intervals
# and hence 3*n+1 endpoints
x = np.linspace(a,b,3*n+1)
y = f(x)
# The weight for each points
w = [1,3,3,1]
result = 0
for i in range(0, 3*n, 3):
# Calculate the area, 4 points at a time
result += (x[i+3] - x[i]) / 8 * (y[i:i+4] * w).sum()
# result = 1.4626525814387632
You can do it using numpy.vectorize (Based on this wikipedia post):
a, b, n = 0, 1, 10**6
h = (b-a) / n
x = np.linspace(0,n,n+1)*h + a
fv = np.vectorize(f)
(
3*h/8 * (
f(x[0]) +
3 * fv(x[np.mod(np.arange(len(x)), 3) != 0]).sum() + #skip every 3rd index
2 * fv(x[::3]).sum() + #get every 3rd index
f(x[-1])
)
)
#Output: 1.462654874404461
If you use numpy's built-in functions (which I think is always possible), performance will improve considerably:
a, b, n = 0, 1, 10**6
x = np.exp(np.square(np.linspace(0,n,n+1)*h + a))
(
3*h/8 * (
x[0] +
3 * x[np.mod(np.arange(len(x)), 3) != 0].sum()+
2 * x[::3].sum() +
x[-1]
)
)
#Output: 1.462654874404461
The following code generates numpy 2D lists of r and E values for the specified intervals.
r = np.linspace(3, 14, 10)
E = np.linspace(0.05, 0.75, 10)
r, E = np.meshgrid(r, E)
I am then using the following nested loop to generate output from the function ionisationGamma for each r and E interval value.
for ridx in trange(len(r)):
z = []
for cidx in range(len(r[ridx])):
z.append(ionisationGamma(r[ridx][cidx], E[ridx][cidx]))
Z.append(z)
Z = np.array(Z)
This loop gives me a 2D numpy array Z, which is my output and I am using it for a 3D graph. The problem with it is: it is taking ~6 hours to generate the output for all these intervals as there are so many values due to np.meshgrid. I have just discovered multi-threading in Python and wanted to know how I can implement this by using it. Any help is appreciated.
See below code for ionisationGamma
def ionisationGamma(r, E):
I = complex(0.1, 1.0)
a_soft = 1.0
omega = 0.057
beta = 0.0
dt = 0.1
steps = 10000
Nintervals = 60
N = 3000
xmin = float(-300)
xmax = -xmin
x = [0.0]*N
dx = (xmax - xmin) / (N - 1)
L = dx * N
dk = 2 * M_PI / L
propagator = None
in_, out_, psi0 = None, None, None
in_ = [complex(0.,0.)] * N
psi0 = [complex(0.,0.)] * N
out_ = [[complex(0.,0.)]*N for i in range(steps+1)]
overlap = exp(-r) * (1 + r + (1 / 3) * pow(r, 2))
normC = 1 / (sqrt(2 * (1 + overlap)))
gammai = 0.5
qi = 0.0 + (r / 2)
pi = 0.0
gammai1 = 0.5
gammai2 = 0.5
qi1 = 0.0 - (r / 2)
qi2 = 0.0 + (r / 2)
pi1 = 0.0
pi2 = 0.0
# split initial wavepacket
for i in range(N):
x[i] = xmin + i * dx
out_[0][i] = (normC) * ((pow(gammai1 / M_PI, 1. / 4.) * exp(complex(-(gammai1 / 2.) * pow(x[i] - qi1, 2.), pi1 * (x[i] - qi1)))) + (pow(gammai2 / M_PI, 1. / 4.) * exp(complex(-(gammai2 / 2.) * pow(x[i] - qi2, 2.), pi2 * (x[i] - qi2)))))
in_[i] = (normC) * ((pow(gammai1 / M_PI, 1. / 4.) * exp(complex(-(gammai1 / 2.) * pow(x[i] - qi1, 2.), pi1 * (x[i] - qi1)))) + (pow(gammai2 / M_PI, 1. / 4.) * exp(complex(-(gammai2 / 2.) * pow(x[i] - qi2, 2.), pi2 * (x[i] - qi2)))))
psi0[i] = in_[i]
for l in range(1, steps+1):
for i in range(N):
propagator = exp(complex(0, -potential(x[i], omega, beta, a_soft, r, E, dt, l) * dt / 2.))
in_[i] = propagator * in_[i];
in_ = np.fft.fft(in_, N)
for i in range(N):
k = dk * float(i if i < N / 2 else i - N)
propagator = exp(complex(0, -dt * pow(k, 2) / (2.)))
in_[i] = propagator * in_[i]
in_ = np.fft.ifft(in_, N)
for i in range(N):
propagator = exp(complex(0, -potential(x[i], omega, beta, a_soft, r, E, dt, l) * dt / 2.))
in_[i] = propagator * in_[i]
out_[l][i] = in_[i]
initialGammaCentre = 0.0
finalGammaCentre = 0.0
for i in range(500, 2500 +1):
initialGammaCentre += pow(abs(out_[0][i]), 2) * dx
finalGammaCentre += pow(abs(out_[steps][i]), 2) * dx
ionisationGamma = finalGammaCentre / initialGammaCentre
return ionisationGamma
def potential(x, omega, beta, a_soft, r, E, dt, l):
V = (-1. / sqrt((x - (r / 2)) * (x - (r / 2)) + a_soft * a_soft)) + ((-1. / sqrt((x + (r / 2)) * (x + (r / 2)) + a_soft * a_soft))) + E * x
return V
Since the question is about how to use multiprocessing, the following code will work:
import multiprocessing as mp
if __name__ == '__main__':
with mp.Pool(processes=16) as pool:
Z = pool.starmap(ionisationGamma, arguments)
Z = np.array(Z)
Where the arguments are:
arguments = list()
for ridx in range(len(r)):
for cidx in range(len(r[ridx])):
arguments.append((r[ridx][cidx], E[ridx][cidx]))
I am using starmap instead of map, since you have multiple arguments that you want to unpack. This will divide the arguments iterable over multiple cores, using the ionisationGamma function and the final result will be ordered.
However, I do feel the need to say that the main solution is not really the multiprocessing but the original function code. In ionisationGamma you are using several times the slow python for loops. And it would benefit your code a lot if you could vectorize those operations.
A second observation is that you are using many of those loops separately and it would be nice if you could separate that one big function into multiple smaller functions. Then you can time every function individually and speed up those that are too slow.
I am trying to create a quadratic solver where it will tell me the values of x. It works flawlessly until one of the answers would be an imaginary number. How do I make it so the program doesn't crash every time and actually gives the correct answer in terms of i?
import math
print()
a = input("Coefficient of a: ")
a = float(a)
b = input("Coefficient of b: ")
b = float(b)
c = input("Coefficient of c: ")
c = float(c)
x_1 = (-b + math.sqrt(b ** 2 - (4 * a * c))) / 2 * a
x_2 = (-b - math.sqrt(b ** 2 - (4 * a * c))) / 2 * a
print()
print(f" X = {x_1} or {x_2}")
print()
You can use complex() instead of float():
a = input("Coefficient of a: ")
a = complex(a)
b = input("Coefficient of b: ")
b = complex(b)
c = input("Coefficient of c: ")
c = complex(c)
x_1 = (-b + (b ** 2 - (4 * a * c))**0.5) / 2 * a
x_2 = (-b - (b ** 2 - (4 * a * c))**0.5) / 2 * a
print()
print(f" X = {x_1} or {x_2}")
print()
Prints (for example):
Coefficient of a: 3+2j
Coefficient of b: 1
Coefficient of c: -2-1j
X = (3.1748906833227015+8.198076043446118j) or (-6.174890683322701-10.198076043446118j)
Check the value of b ** 2 - (4 * a * c). If it's negative, you have imaginary solutions.
So your code becomes:
import math
print()
a = input("Coefficient of a: ")
a = float(a)
b = input("Coefficient of b: ")
b = float(b)
c = input("Coefficient of c: ")
c = float(c)
delta = b ** 2 - (4 * a * c)
if delta >= 0:
x_1 = (-b + math.sqrt(b ** 2 - (4 * a * c))) / 2 * a
x_2 = (-b - math.sqrt(b ** 2 - (4 * a * c))) / 2 * a
print()
print(f" X = {x_1} or {x_2}")
print()
else:
print("The 2 solutions are imaginary:")
real = -b
imag = abs(math.sqrt(-delta) / (2 * a))
print(f" X = {real} + i*{imag} or {real} - i*{imag}")
you can use sympy this:example(Equation of the second and third degree and ...)
import sympy as sp
x = sp.Symbol("x")
print(sp.solve(x ** 4 - 1, x))
output:
[-1, 1, -I, I]
pip install sympy :https://pypi.org/project/sympy/
How should I answer this-"Compute the total number of possible paths from (0,0) to (7,9) if the steps R (to the right) and U (up) are allowed, along with the diagonal step D:(x,y)→(x +1,y+ 1)"
Edit: added calculation for arbitrary cell, not only diagonal one.
The number of ways on square grid is known as Delannoy number, for (n,n) cell sequence is 1, 3, 13, 63, 321, 1683, 8989...
There is simple natural recurrence
D(m, n) = D(m-1, n) + D(m, n-1) + D(m-1,n-1)
that might be used to calculate values rather quickly for reasonable argument values (table approach, O(nm) operations including long summation).
"Closed formula"
D(m, n) = Sum[k=0..min(n, m)] {C(m + n - k, m) * C(m, k)}
for effective implementations requires table of binomial coefficients
#2D table quadratic approach
def PathsInSqGrid(n, m):
D = [[0 for x in range(m+1)] for y in range(n+1)]
for i in range(n+1):
D[i][0] = 1
for i in range(m+1):
D[0][i] = 1
for i in range(1, n+1):
for j in range(1,m+1):
D[i][j] = D[i][j-1] + D[i-1][j] + D[i-1][j-1]
return D[n][m]
def NCr(n, k):
result = 1
if k > n - k:
k = n - k
for i in range (1, k + 1):
result = (result * (n - i + 1)) // i
return result
#closed formula
def PathsCF(n, m):
#D(m, n) = Sum[k=0..min(n, m)] {C(m + n - k, m) * C(m, k)}
res = 0
for k in range(0, min(n, m) + 1):
res += NCr(m + n - k, m) *NCr(m, k)
return res
print(PathsInSqGrid(7, 9))
print(PathsCF(7, 9))
>>>
224143
224143
Wiki also shows two so-called "closed formulas" for central Delannoy numbers (while I believe that closed formula should be single expression without loop of length n):
D(n) = Sum[k=0..n]{C(n,k)*C(n+k,k)}
D(n) = Sum[k=0..n]{C(n,k)^2 * 2^n}
and recurrence (looks simple, linear complexity, but real implementation requires division of long number by short one)
n*D(n) = 3*(2*n-1) * D(n-1) - (n-1)*D(n-2)
and generating function
Sum[n=0..Inf]{D(n)*x^n} = 1/Sqrt(1 - 6 * x + x^2) = 1 + 3x + 13x^2 + 63x^3 +...
Code
#central Delannoy numbers
#2D table quadratic approach
#linear approach for diagonal cell (n,n)
def PathsInSqGridLin(n):
if n < 2:
return 2 * n + 1
A, B = 1, 3
for i in range(2, n + 1):
B, A = (3 * (2 * i - 1) * B - (i - 1) * A) // i, B
return B
print(PathsInSqGridLin(3))
print(PathsInSqGridLin(100))
>>
63
2053716830872415770228778006271971120334843128349550587141047275840274143041