I am new to Python, and I am trying to make a numerical analysis model of differential equations.
import sympy as sympy
def picard_solver(y_0, x_0, rhs_expression, iteration_count:int = 5):
x, phi = sympy.symbols("x phi")
phi = x_0
for i in range(iteration_count + 1):
phi = y_0 + sympy.integrate(rhs_expression(x, phi), (x, x_0, x))
return phi
import numpy
import plotly.graph_objects as go
y_set = [picard_solver(1, 0, lambda x, y: x * y, i) for i in range(1, 6)]
x_grid = numpy.linspace(-2, 2, 1000)
y_picard = list()
for y in y_set:
y_picard.append(numpy.array([float(y.evalf(subs={x: x_i})) for x_i in x_grid]))
y_exact = numpy.exp((x_grid) * (x_grid) / 2)
fig = go.Figure()
for i, y_order in enumerate(y_picard):
fig.add_trace(go.Scatter(x=x_grid, y=y_order, name=f"Picard Order {i + 1}"))
# fig.add_trace(go.Scatter(x=x_grid, y=y_picard, name="Picard Solution"))
fig.add_trace(go.Scatter(x=x_grid, y=y_exact, name="Exact Solution"))
fig.show()
fig.write_html("picard_vs_exact.html")
But when I try to run it, I get NameError: name 'x' is not defined error, can someone help me?
I want a graph to be shown.
I think that you need to pass a string in the y.evalf(subs={'x': x_i}) part of your code.
Related
I need to calculate the norm of a vector using sympy and Symbol from sympy. An extract of the code is below:
from sympy import *
x = Symbol('x')
sb = [2,1]
func = sympy.exp(-(sympy.sqrt((x.norm() + (x-sb).norm())**2 - sb**2)/(2)))
func_prime = func.diff(x)
ff = lambdify(x, func_prime, 'numpy')
f = -1*ff(np.array(r))
The above implementation gives me the error: AttributeError: 'Symbol' object has no attribute 'norm'.
If I use func = V0 * sympy.exp(-(sympy.sqrt((sympy.sqrt(sum(x**2)) + sympy.sqrt(sum((x-sb*e)**2)))**2 - sb**2)/(2*sig))) I get the following error: TypeError: 'Pow' object is not iterable.
numpy.linalg.norm() is not accepted by sympy.
How can I find the norm of a vector in this situation?
Thanks
Sympy has a vector module you can use.
from sympy.vector import CoordSys3D
C = CoordSys3D('C')
v = 3*C.i + 4*C.j + 5*C.k
v.dot(v)
Output: 50
You can also use it with symbols:
from sympy import Symbol
x = Symbol('x')
y = Symbol('y')
z = Symbol('z')
v = x*C.i + y*C.j + z*C.k
sympy.sqrt(v.dot(v))
Output: sqrt(x**2 + y**2 + z**2)
Hello :) i suggest you the following:
import sympy as sp
import sympy.physics.vector as spv
M = spv.ReferenceFrame("M")
vector=V1*M.x+V2*M.y+V3*M.z
Where M.x, M.y, M.z are the unitary vectors i, j, k in physics. As we know the norm is the square root of the dot product of the vector with itself, so
norm=sp.sqrt(spv.dot(vector, vector))
print(norm)
If you want to print the result in LaTeX format
print(sp.latex(norm))
If you want to simplify the expresion,
print(norm.simplify())
x, y, z = symbols('x y z')
vec = Matrix([x, y, z])
vec_norm = sqrt(sum(sympy.matrices.dense.matrix_multiply_elementwise(vec, vec)))
How about this?
from sympy import *
x = Symbol('x')
y = Symbol('y')
a = Matrix([x,y])
anorm = sqrt(a.T # a)
In the picture below you can see the code I am trying to execute to solve an ODE but I get an error and I do not know how to fix it. I am new to programming and am learning now how to code in python to solve ODEs. The code is from this material: http://geofhagopian.net/m2c/M2C-S18/euler_method.pdf
Click me to see code
After a suggestion, here is the code written:
import numpy as np
from matplotlib import pyplot as plt
x0 = float(0)
y0 = float(1)
xf = float(10)
n = float(101)
deltax=(xf−x0)/(n−1);
x = np.linspace(x0,xf,n)
y = np.zeros([n]);
y[0] = y0;
for i in range(1,n):
y[i] = deltax∗(−y[i−1]+np.sin(x[i−1])) + y[i−1]
for i in range(n):
print x[i], y[i])
plt.plot( x , y , ’ o ’ )
plt.xlabel(” Value of x ” )
plt.ylabel(” Value of y ” )
plt.title(”Approximate Solution with Forward Euler’s Method ” )
plt.show()
enter code here
The problem is in your quotation marks, they are in a different font. Python can't identify it, so it gave you an error.
There were also a few other things wrong with your code, such as n being a float.
Full code:
import numpy as np
from matplotlib import pyplot as plt
x0 = float(0)
y0 = float(1)
xf = float(10)
n = float(101)
deltax = (xf-x0)/(n-1)
x = np.linspace(int(x0), int(xf), int(n))
y = np.zeros([int(n)]);
y[0] = y0;
for i in range(1, int(n)):
y[i] = deltax * (-y[i-1] + np.sin(x[i-1])) + y[i-1]
for i in range(int(n)):
print(x[i], y[i])
plt.plot( x , y , "o")
plt.xlabel("Value of x")
plt.ylabel("Value of y")
plt.title("Approximate Solution with Forward Euler’s Method")
plt.show()
Hope this helps!
I have a function z(T,x,p). With my given data points i want to fit the function and get the coefficients of the function. My constraint is that the derivation of z after x should be positive everywhere dz/dx > 0. But in my following code the constraint is not working and I do not know why.
import numpy as np
from scipy.optimize import minimize
import matplotlib.pyplot as plt
T = np.array([262,257,253,261,260,243,300,283,282], dtype=float)
p = np.array([25,22,19,24,24,14,62,45,44], dtype=float)
x = np.array([0.1,0.1,0.2,0.2,0.3,0.3,1,0.3,0.2], dtype=float)
z = np.array([10,9,13,16,20,12,62,37,28], dtype=float)
def func(pars, T, x, p): #my actual function
a,b,c,d,e,f = pars
return x * p + x * (1 - x) * (a + b * T + c * T ** 2 + d * x + e * x * T + f * x * T ** 2) * p
def resid(pars): #residual function
return ((func(pars, T, x, p) - z) ** 2).sum()
def der(pars): # constraint function: Derivation of func() after x positive everywhere
a,b,c,d,e,f = pars
return p+p*(2*x*a+2*x*b*T+2*x*c*T**2+3*x**2*d+3*x**2*e*T+3*x**2*f*T**2)+p*(a+b*T+c*T**2+2*x*d+2*e*x*T+2*f*x*T**2)
con1 = (dict(type='ineq', fun=der))
pars0 = np.array([0,0,0,0,0,0])
res = minimize(resid, pars0, method='cobyla',options={'maxiter': 5000000}, constraints=con1)
print("a = %f , b = %f, c = %f, d = %f, e = %f, f = %f" % (res.x[0], res.x[1], res.x[2], res.x[3], res.x[4], res.x[5]))
Trying to plot an example:
x0 = np.linspace(0, 1, 100) # plot two example graphs z(x) for a certain T and p
fig, ax = plt.subplots()
fig.dpi = 80
ax.plot(x,z,'ro', label='data')
ax.plot(x0, func(res.x, 300, x0, 62), '-', label='fit T=300, p=62')
ax.plot(x0, func(res.x, 283, x0, 45), '-', label='fit T=283, p=45')
plt.xlabel('x')
plt.ylabel('z')
plt.legend()
plt.show()
As you can see the derivation (gradient) is not positive everywhere. I do not know why the constraint gets ignored. Maybe someone can help me.
I have some function f(list) with receives as argument a list with length 2, i.e., list = [entry_1, entry_2]. I need to do a contour plot of this function:
x = np.linspace(0, 2, 1000+1)
y = np.linspace(0, 2, 1000+1)
X, Y = np.meshgrid(x, y)
Z = ?
plt.contour(X, Y, Z)
plt.show()
The problem is: I don't know how to pass the arguments. If the function was of the type f(x,y), then
Z = f(X, Y)
would do the job. But
Z = f([X,Y])
fails: it receives too many arguments. How can I do this?
EDIT: Here are the functions of the program:
from scipy.optimize import minimize
def c_Gamma_gamma_fv(cf, cv):
return np.abs((4 * eta_gamma * charges**2 * a_q * cf).sum() + 4.* cf *a_tau/3. + a_w * cv)**2/Gamma_gamma
def mu_fv(cf, cv):
return np.array([cf**4,
cf**2 * cv**2,
cf**2 * c_Gamma_gamma_fv(cf, cv),
cv**2 * c_Gamma_gamma_fv(cf, cv),
cf**4,
cv**2 * cf**2,
cf**2 * cv**2,
cv**4,
cv**2 * cf**2,
cv**4])
def chi_square_fv(clist):
cf, cv = clist
return ((mu_fv(cf, cv) - mu_data) # inv_cov # (mu_fv(cf, cv) - mu_data))
x0 = [1., 1.]
res_fv = minimize(chi_square_fv, x0)
print(res_fv)
def delta_chi_fv(clist):
return chi_square_fv(clist) - chi_square_fv([res_fv.x[0], res_fv.x[1]])
All variables not explicit are constants. The function I want to plot is delta_chi_fv.
The solution I found (with a little help of a professor here in my university), though not the fastest one, works:
Z = np.zeros((len(x), len(y)))
for i in range(len(x)):
for j in range(len(y)):
z = delta_chi_fv([x[i], y[j]])
Z[i,j] = z
With this construction of Z, then
plt.contour(X,Y,Z)
works fine. If anyone knows another answer, it would be great to learn more things about this language.
Cheers,
Gabriel.
No idea how to multiply two polynomials of different variable. Below is my code and running it on IPython.
from sympy import *
from numpy import *
m1 = poly1d([1,0,0,1], variable = 'x')
m2 = poly1d([1,0], variable = 'y')
p=m1*m2
print(p)
Expected result is a polynomial with variable x and y but below is my result.
4
1 x + 1 x
now you're using numpy.poly1d, which doesn't seem to take the variable= into account. If you want to do it symbolicallly, you can use sympy.Poly
from sympy import Poly
from sympy.abc import x, y
m1 = Poly((1, 0, 0, 1), x)
m2 = Poly((1,0), y)
m1, m2
(Poly(x**3 + 1, x, domain='ZZ'), Poly(y, y, domain='ZZ'))
m1 * m2
Poly(x**3*y + y, x, y, domain='ZZ')