Is the following code not solvable by Sympy? I've executed this code a couple of minutes ago, but it printed n = 5 on the screen and it stuck.
import sympy
Wmin = 31
m = 8
p = sympy.symbols('p')
for n in range(5, 10):
print 'n = %3d' % n
denominator = (1 + Wmin + p * Wmin * ((1 - (2 * p) ** m) / (1 - 2 * p)))
right = 1 - (1 - 2 / denominator) ** (n - 1)
p_solve = sympy.solve(sympy.Eq(p, right))
print p_solve
Actually, I've solved the equation with bisection method in MATLAB and I'm currently modifying without bisection method and porting in Python.
You could use nsolve to solve a problem like this -- but you need a guess as to where the solution(s) might be:
>>> for n in range(5, 10):
... print 'n = %3d' % n
... denominator = (1 + Wmin + p * Wmin * ((1 - (2 * p) ** m) / (1 - 2 * p)))
... right = 1 - (1 - 2 / denominator) ** (n - 1)
... p_solve = nsolve(sympy.Eq(p, right),p,0)
... print p_solve
...
n = 5
0.181881594898608
n = 6
0.210681675044646
n = 7
0.235278433487669
n = 8
0.256480923202426
n = 9
0.27492972759045
Related
I needed to solve $sin(x)+a*sin(3x)=0$ symbolically for $x$.
import sympy as sp
a,x = sp.symbols('a,x')
roots = sp.solve([sp.sin(x)+a*sp.sin(3*x)],[x])
print(roots)
produced
(I*(-log((-a - sqrt(-3*a**2 + 2*a + 1) - 1)/a) + log(2))/2,),
(I*(-log(-sqrt((-a + sqrt(-3*a**2 + 2*a + 1) - 1)/a)) + log(2)/2),),
(I*(-log((-a + sqrt(-3*a**2 + 2*a + 1) - 1)/a) + log(2))/2,)]
whereas WolframAlpha produced a much "better" solution:
solve sin(x) + a sin(3 x) = 0
yields
x = π n and n element Z
x = 2 π n and a = -1/3 and n element Z
x = 2 π n - 2 tan^(-1)(sqrt((5 a - 4 sqrt((a - 1) a) - 1)/(3 a + 1))) and 3 a + 1!=0 and sqrt((a - 1) a)!=2 a and n element Z
x = 2 (tan^(-1)(sqrt((5 a - 4 sqrt((a - 1) a) - 1)/(3 a + 1))) + π n) and 3 a + 1!=0 and sqrt((a - 1) a)!=2 a and n element Z
x = 2 π n - 2 tan^(-1)(sqrt((5 a + 4 sqrt((a - 1) a) - 1)/(3 a + 1))) and 3 a + 1!=0 and 2 a + sqrt((a - 1) a)!=0 and n element Z
Question:
can the SymPy solver be configured to produce solutions in the way WolframAlpha does?
Is anything known why SymPy expresses the solutions via (complex) logarithms instead of arc tangents?
Im trying to minimize function(T) by scipy.optimize.minimize().
With 0 < T < 1.
My code is the following:
import scipy
import math
def function(T):
'''
U = (1- sqrt(T)^(-2)
1 - T^3 * (1 - T - U) ^ 5 * U ^ 10
'''
return 1 - T**3 * (1-T - (T + 1 + 2 * math.sqrt(T))/(T-1)**2) ** 5 * ((T + 1 + 2 * math.sqrt(T))/(T-1)**2)**10
# minimization
res = scipy.optimize.minimize(function, 1, bounds= [(0,1)])
w = res.x
When I run the code it shows the error messege:
RuntimeWarning: divide by zero encountered in true_divide
return 1 - T**x[0] * (1-T - (T + 1 + 2 * math.sqrt(T))/(T-1)**2) ** x[1] * ((T + 1 + 2 * math.sqrt(T))/(T-1)**2)**x[2]
RuntimeWarning: overflow encountered in multiply
return 1 - T**x[0] * (1-T - (T + 1 + 2 * math.sqrt(T))/(T-1)**2) ** x[1] * ((T + 1 + 2 * math.sqrt(T))/(T-1)**2)**x[2]
What is going on? Thanks.
PS: what does the error messages mean?
I'm coding an algorithm that takes the inverse of a Laplace transform, iterates it until it converges and live-plots the graph. I've dealt with a bunch of errors so far and solved them all but on this one, I'm stumped. Here's the function f_p() that I'm getting the error from. For context, it contains 6 Laplace transforms that I painstakingly derived by hand to eliminate the imaginary component:
def f_p(u, omega, m):
a = gamma
b = (omega + k * math.pi) / u
if m == 1:
f = a * (1 / (a ** 2 + (b + 1) ** 2) + 1 / (a ** 2 + (b - 1) ** 2))
return f * math.cos(omega)
elif m == 2:
f = a / (a ** 2 + b ** 2)
return f * math.cos(omega)
elif m == 3:
f = math.e ** (-a / (a ** 2 + b ** 2)) * (a ** 2 + b ** 2) ** (1 / 4) * math.cos(
(math.atan2(b, a) + 2 * n * math.pi) / 2) * math.cos(b / (a ** 2 + b ** 2)) / (
math.sqrt(a ** 2 + b ** 2) * (math.cos((math.atan2(b, a) + 2 * n * math.pi) / 2) ** 2 + math.sin(
(math.atan2(b, a) + 2 * n * math.pi) / 2)))
return f * math.cos(omega)
elif m == 4:
a = math.e
f = -(a * math.log(a ** 2 + b ** 2) + a ** 2) / (a ** 2 + b ** 2)
return f * math.cos(omega)
elif m == 5:
f = a * (math.e ** (-a) * math.cos(b) - math.e ** (-2 * a) * math.cos(2 * b)) / (a ** 2 + b ** 2)
return f * math.cos(omega)
elif m == 6:
f = math.sqrt((a ** 2 - b ** 2 + 1) ** 2 + (2 * a * b) ** 2) * math.cos(
(math.atan2(2 * a * b, a ** 2 - b ** 2 + 1) + 2 * n * math.pi) / 2) / (
((a ** 2 - b ** 2 + 1) ** 2 + (2 * a * b) ** 2) * (
math.cos((math.atan2(2 * a * b, a ** 2 - b ** 2 + 1) + 2 * n * math.pi) / 2) ** 2 + math.sin(
(math.atan2(2 * a * b, a ** 2 - b ** 2 + 1) + 2 * n * math.pi) / 2) ** 2))
return f * math.cos(omega)
else:
return 0
This function feeds into another function f_u(), which contains the algorithm itself, which integrates over omega, removing it as a variable. The remaining variable is u, which I need to iterate until the function converges. Here's the execution of the algorithm:
u = np.linspace(0.000001, 100, 100000)
if __name__ == '__main__':
pool = Pool(processes=4)
for m in range(1, 7):
if m == 4:
gamma = math.e
else:
gamma = 10
pool.map(f_u, u)
Maybe it could be a syntax problem? I don't know. Any help would be much appreciated.
So for this internship I am doing, I need to use the integral of (x^(9/2))/((1-x)^2) as part of an equation I am graphing. However, the variable that I am graphing along the x axis appears in both limits of integration. Since I am a complete and total novice at python, my code is atrocious, but I ended up copy+pasting the indefinite integral twice, plugging in the limits of integration, and subtracting. How can I make the code better?
import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate
x = np.arange(0,2.5,0.00001)
zs = 8
zr = 6
rbub = 5
sig = 2.5
XHI = 0.5
sigma = 10**-sig
L = 10**-3
zb = zs - (((1 + zs)/8)**(3/2)) * (0.0275) * (rbub/10)
a = (1+zr)/((1+zs)*(x+1))
b = (1+zb)/((1+zs)*(x+1))
def f(x):
ans = 0.000140092
ans = ans * ((1+zs)**(3/2))
ans = ans * ((x+1)**(3/2))
ans = ans * XHI
return ans * ((9/2)*(np.log(1-np.sqrt(b)) - np.log(np.sqrt(b)+1)) + (1/35 * (1/(b-1)) * (10*(b**(9/2)) + 18*(b**(7/2)) + 42*(b**(5/2)) + 210*(b**(3/2)) - 315*(b**(1/2))) - ((9/2)*(np.log(1-np.sqrt(a)) - np.log(np.sqrt(a)+1)) + (1/35 * (1/(a-1)) * (10*(a**(9/2)) + 18*(a**(7/2)) + 42*(a**(5/2)) + 210*(a**(3/2)) - 315*(a**(1/2)))))))
Here is one take. Of course, I have no idea what this is doing. You should be in a much better position to add comments / sensible variable names, as others have pointed out. Still, here is what you could do.
First, run a code formatter to make the code more human-friendly.
def f(x):
ans = 0.000140092
ans = ans * ((1 + zs) ** (3 / 2))
ans = ans * ((x + 1) ** (3 / 2))
ans = ans * XHI
return ans * (
(9 / 2) * (np.log(1 - np.sqrt(b)) - np.log(np.sqrt(b) + 1))
+ (
1
/ 35
* (1 / (b - 1))
* (
10 * (b ** (9 / 2))
+ 18 * (b ** (7 / 2))
+ 42 * (b ** (5 / 2))
+ 210 * (b ** (3 / 2))
- 315 * (b ** (1 / 2))
)
- (
(9 / 2) * (np.log(1 - np.sqrt(a)) - np.log(np.sqrt(a) + 1))
+ (
1
/ 35
* (1 / (a - 1))
* (
10 * (a ** (9 / 2))
+ 18 * (a ** (7 / 2))
+ 42 * (a ** (5 / 2))
+ 210 * (a ** (3 / 2))
- 315 * (a ** (1 / 2))
)
)
)
)
)
Right away you see some symemtry. This chunk
10 * (b ** (9 / 2))
+ 18 * (b ** (7 / 2))
+ 42 * (b ** (5 / 2))
+ 210 * (b ** (3 / 2))
- 315 * (b ** (1 / 2))
is a dot product of some weights and a b raised to a vector of powers. If b were scalar, we could write it as np.dot(weights, np.sqrt(b) ** powers). Maybe we would even score some optimization points from using integral powers.
Putting thigs together, we can get something like this:
weights = np.array([10, 18, 42, 210, -315])
powers = np.array([9, 7, 5, 3, 1])
def log_term(x):
return (9 / 2) * (np.log(1 - np.sqrt(x)) - np.log(np.sqrt(x) + 1))
def dot_term(x):
return (1 / 35) * 1 / (x - 1) * np.dot(np.sqrt(x)[..., None] ** powers, weights)
def integrate(x):
return log_term(x) + dot_term(x)
factor1 = integrate(b) - integrate(a)
factor2 = 0.000140092 * ((1 + zs) ** (3 / 2)) * XHI
factor = factor1 * factor2
def f(x):
return factor * ((x + 1) ** (3 / 2))
With better variable names and comments this could almost be readable.
Side comment. Both in your original code and in this version, you define x in the body of your script. You also define several variables as a function of x, such as a and b.
Python scoping rules mean that these variables will not change if you pass a different x to f. If you want all of your variables to change with x, you should move the definitions inside the function.
Using good variable names will help a lot for who gonna read the code or even for you, and comments will help too.
For the rest, it is a equation, there is no good way of putting it.
i'm trying to solve the following non linear system of differential equations
but i don't understand where is the problem in the code that i wrote.
The system is non linear with complex coefficients and complex domain.
from pylab import *
from scipy.integrate import ode
#------initial parameters------
c = 3 * 10 ** 8
h = 6.626 / (2 * pi) * 10 ** -34
kb = 1.3806 * 10 ** -23
TT = 0.1
mm = 1.50 * 10 ** -10
wM = 2 * pi * 10 ** 6
gM = 2 * pi * 10 ** 2
ll = 1064 * 10 ** -9
PL = 100 * 10 ** -4
L = 0.025
k = 1.340 * 10 ** 7
D0 = wM
Ns = 2083
wL = 2 * pi * c / ll
wC = D0 + wL
aL = sqrt((2 * k * PL) / (h * wL))
G0 = wC / L * sqrt(h / (mm * wM))
tau = 1 / k
tciclo = 3 * pi / wM
tauP = 0.5 * pi / wM
tauNP = tciclo - tauP
dtau = 1 / (10 * k)
def fun(t, y, wM,gM,G0,k,D0,aL):
return [wM * y[1],
-wM * y[0] - gM * y[1] + G0 * y[2]*y[2].conjugate(),
-(k + 1j * D0) * y[2] + 1j * G0 * y[0] * y[2]+aL]
y0 = [0.0, 0.0, 0.0]
r = ode(f).set_integrator('zvode', method='bdf')
r.set_initial_value(y0, 0).set_f_params(2.0)
tt = []
yy = []
while r.successful() and r.t < tauP:
r.integrate(r.t + dtau)
tt.append(r.t)
yy.append(r.y)
plot(tt, yy)
show()
Always include the error message in your question. If you don't have any errors, include the output that you got, and explain why it is not what you expected.
Having said that... I see at least one problem with your code. fun has the standard t and y arguments, followed by the parameters wM,gM,G0,k,D0,aL. You must specify a value for each of these parameters in the call to set_f_params(). You currently have set_f_params(2.0), but that call needs six arguments to match the extra parameters of fun.
In a comment, #pv. has pointed out a second problem: ode(f) should be ode(fun).