I'm using Sympy 1.10.1 in Jupyter. Some cells look like:
import sympy as sp
x = sp.Symbol('x')
y = sp.Function('y')(x)
y.diff(x)
diff_eq = sp.Eq(y*y.diff(x), 4*x )
diff_eq
sol = sp.dsolve(diff_eq, y)
sol
And Sympy responds with
[Eq(y(x), -sqrt(C1 + 4*x**2)), Eq(y(x), sqrt(C1 + 4*x**2))]
Can I modify the above so that Sympy does not offer solutions
with negative range?
Related
I am solving an ODE with Sympy. The equation is
ODE
To solve it, I used this little code, which returns this result.
from sympy import *
from numpy import *
import matplotlib.pyplot as plt
x = symbols('x')
y = Function('y')
f = y(x)
print(f)
edo = Eq(f.diff()+3*x**2*f, 6*x**2)
print(edo)
edoSolve = dsolve(edo, f)
print(edoSolve)
C1*exp(-x**3) + 2
My question is, how can I plot the result with x being a range from 0 to 10?
Firstly it's problematic to combine these two lines:
from sympy import *
from numpy import *
These two libraries define many functions with the same names and mixing those together will lead to problems. For clarity it is better to do something like:
import sympy as sym
import numpy as np
You can only plot a sympy expression if you give numbers for all of the symbols apart from the one that you want to plot against (i.e. x in this example). That means that you need to have a concrete value for the integration constant C1. You can get that by giving an initial conditions (ics) argument to dsolve. Also since dsolve returns an equation you need to choose a side of the equation as the expression that you want to plot. Having done that the sym.plot function will do precisely what you ask for:
In [10]: import sympy as sym
In [11]: sol = sym.dsolve(edo, f, ics={f.subs(x, 0): 1})
In [12]: sol
Out[12]:
3
-x
y(x) = 2 - ℯ
In [13]: sym.plot(sol.rhs, (x, 0, 10))
Out[13]: <sympy.plotting.plot.Plot at 0x7f346de1caf0>
If you want to show solutions for multiple values for C1 together, you could append plots:
from sympy import symbols, Function, Eq, dsolve, plot
x = symbols('x')
y = Function('y')
f = y(x)
edo = Eq(f.diff() + 3 * x ** 2 * f, 6 * x ** 2)
edoSolve = dsolve(edo, f)
plot1 = plot(show=False)
for c1 in range(-5, 6):
plotc1 = plot(edoSolve.subs('C1', c1).rhs, (x, 0, 10), show=False)
plot1.append(plotc1[0])
plot1.show()
from sympy import symbols, Eq, solve, sin, sqrt
x = symbols('x')
D = symbols('d')
C = symbols('c')
eq1 = 2*sin(x)+sqrt(1-sin^2(x))+D*sin(x/2)-sin(2*x)-1-C
sol = solve(eq1)
print(sol)
Actually in the equation eq1=0. And I was trying to find a function for x which I couldn't find by mathematics. So I was thinking if it is possible in Python. My friend was saying that we actually deal with numbers in Python so he said it would be good if he can get some value of x. In that equation C and D is constant. He was saying that they are height. So we can consider that C,D=1 to 1000 (we can choose whatever we wish). Is there really possible way to substitute that function to find a value of x?
You can use fsolve to numerically solve the non-linear equation. The subs attribute of a sympy expression can be used to substitute a value to a variable.
from sympy import symbols, Eq, solve, sin, sqrt
from scipy.optimize import fsolve
x = symbols('x')
D = symbols('d')
C = symbols('c')
eq1 = 2*sin(x)+sqrt(1-(sin(x))**2)+D*sin(x/2)-sin(2*x)-1-C
values = {
C: 500,
D: 1000
}
eq1_in_x = eq1.subs(values)
def f(y):
return float(eq1_in_x.subs(x,y[0]))
sol = fsolve(f,1) # Here, 1 is an initial guess.
print(sol)
Outout:
[1.04635456]
So, 1.04635456 is a value of x that satisfies the equation with C and D values being 500 and 1000, respectively.
Take a look at sympy tutorial: https://docs.sympy.org/latest/tutorial/index.html
also Itk this should solve your problem: With #Oscar Benjamin advice:
from sympy import nsolve, sin, sqrt
from sympy.abc import x, C, D
eq1 = 2*sin(x)+sqrt(1-sin(x)**2)+C*sin(x/2)-sin(2*x)-1-D
sol = nsolve(eq1.subs({C: C_value, D: D_value}, x0)
print(sol)
x0 is the initialization of x, depending on the value of x0 you can end with different value of x verifying eq = 0.
I have a function defined in elliptic coordinates. How can I symbolically integrate it in SymPy? Otherwise, do you have an example of implementation of any other non-Cartesian integration?
import sympy as sym
r = sym.Symbol('r')
Z = sym.Symbol('Z', constant = True)
#1s normalized orbital definition
def f(r):
return (1/(sym.pi)) * (Z**1.5) * sym.exp(-Z*r)
Thanks in advance!
import sympy as sym
from sympy import integrate
r = sym.Symbol('r')
Z = sym.Symbol('Z', constant = True)
integrate('(1/(pi)) * (Z**1.5) * exp(-Z*r)', r, Z)
Output:
I'm comparing the results of convolution in Python (using sympy's symbolic variables) and Mathematica with its Convolve function.
In Python, my MWE is
from numpy import linspace, pi
from numpy.random import randn
from scipy.signal import fftconvolve
import matplotlib.pyplot as plt
from sympy import symbols
from sympy.utilities.lambdify import lambdify
a = 0.43
b = 0.41
c = 0.65
d = 0.71
x = symbols('x')
f = 2*b / ((x-a)**2 + b**2)
g = 2*d / ((x-c)**2 + d**2)
fog = fftconvolve(f,g,mode='same')
fog_fun = lambdify(x,fog,'numpy') # returns a numpy-ready function
x = linspace(-20,20,int(1e3))
dx = x[1]-x[0]
fogS = fog_fun(x)
fogA = 4*pi*(b+d)/((x-a-c)**2+(b+d)**2) # correct analytic solution
plt.figure()
plt.plot(x,fogA,lw=2,label='analytic')
plt.plot(x,fogS,lw=2,label='sympy')
plt.grid()
plt.legend(loc='best')
plt.show()
which calculates a convolution using symbolic variable x. The resulting function (before lambdifying) is
fog = 1.1644/(((x - 0.65)**2 + 0.5041)*((x - 0.43)**2 + 0.1681))
There is no agreement between analytic (fogA, Mathematica) and sympy (fogS, Python):
My Mathematica code is:
a = 0.43; b = 0.41; c = 0.65; d = 0.71;
fogA = FullSimplify[Convolve[2*b/((t-a)^2+b^2),2*d/((t-c)^2+d^2), t, x]];
fogS = 1.1644/(((x - 0.65)^2 + 0.5041)*((x - 0.43)^2 + 0.1681));
where
fogA = (17.683+x*(-30.4006+14.0743*x))/(3.04149+x*(-7.9428+x*(8.3428+x*(-4.32+1.*x))))
and graphs for fogS and fogA are the same as for Python.
Why is there such a large disagreement between the analytic and sympy solution? I suspect the problem lies with sympy. Another Pythonic method is to convolve two arrays which seems to agree with the analytic solution.
f = 2*b / ((x-a)**2 + b**2)
g = 2*d / ((x-c)**2 + d**2)
fogN = fftconvolve(f,g,mode='same')*dx # numeric
(Note: this is a MWE. The actual f and g I want to convolve are much more complicated than the Lorentzians defined in this post.)
I do not think this is a reasonable way of using scipy + sympy.
I am actually quite surprised that you get a result from lambdify at all.
What you should be doing, instead of using scipy.signal.fftconvolve(), is to use a symbolic definition of the convolution, e.g.:
from sympy import oo, Symbol, integrate
def convolve(f, g, t, lower=-oo, upper=oo):
tau = Symbol('__very_unlikely_name__', real=True)
return integrate(
f.subs(t, tau) * g.subs(t, t - tau), (tau, lower, upper))
adapted from here.
I am trying to find coefficient of xy using sympy. This is the program.
import sympy as sp
fro sympy import Poly
from sympy.abc import x, y
x,y,xy=sp.symbols('x,y,xy')
K=Poly(x**2 + 5*xy + 1).coeff(xy)
print K
Kindly help. Thanks in advance.
import sympy as sp
from sympy.abc import x, y
x,y,xy=sp.symbols('x,y,xy')
expression = x**2 + 5*xy + 1
print expression.coeff(xy)
Note that this is probably not what you want. You're not looking for a symbol xy but for the coefficient with the crossterm of symbols x and y. You should therefor change the expression to:
expr = x**2 + 5*x*y+1
expr.coeff(y).coeff(x)