Solving for Zeros of a Sturm Liouville Problem in Sympy - python

I'm trying to solve for the zeros of a Sturm Liouville problem in sympy
here is my code
from sympy import *
init_printing(use_latex='mathjax')
# Function Definitions
u = Function('u')
X = Function('X')
# Variables and Dummies
x = Dummy('x')
mu = Symbol('mu', nonzero=True, positive=True)
C1 = Symbol('C1', nonzero=True)
C2 = Symbol('C2', nonzero=True)
print("STURM LIOUVILLE PROBLEM IN X")
print("GENERAL SOLUTION")
# --- --- ---#
print("")
gen_sol = dsolve(Eq(Derivative(X(x), x, 2) + (mu**2)*X(x), 0), X(x))
print(pretty(gen_sol))
print("")
print("SOLVE FOR BOUNDARY")
bc_2 = gen_sol.rhs.diff(x).subs(x,5).subs(Symbol('C1')*mu, Symbol('C2'))
print("DETERMINE THAT C2 != 0 (NON TRIVIAL)")
print(pretty(bc_2))
print("")
print("SOLVE FOR REMAINING SOLUTION")
bc_2 = bc_2.subs(Symbol('C2'), 1)
print(pretty(bc_2))
print("")
linear_solutions = solve([bc_2], [mu])
print(pretty(linear_solutions))
Unfortunatly I get the following NotImplemented Error.
Is there anther way to solve for zeros in sympy that can handle this operation?
STURM LIOUVILLE PROBLEM IN X
GENERAL SOLUTION
X(x) = C₁⋅sin(x⋅μ) + C₂⋅cos(x⋅μ)
SOLVE FOR BOUNDARY
DETERMINE THAT C2 != 0 (NON TRIVIAL)
-C₂⋅μ⋅sin(5⋅μ) + C₂⋅cos(5⋅μ)
SOLVE FOR REMAINING SOLUTION
-μ⋅sin(5⋅μ) + cos(5⋅μ)
Traceback (most recent call last):
File "stack_overflow.py", line 31, in <module>
linear_solutions = solve([bc_2], [mu])
File "/home/cgould/.local/lib/python3.8/site-packages/sympy/solvers/solvers.py", line 1176, in solve
solution = _solve_system(f, symbols, **flags)
File "/home/cgould/.local/lib/python3.8/site-packages/sympy/solvers/solvers.py", line 1943, in _solve_system
raise NotImplementedError('could not solve %s' % eq2)
(EDIT FOR CLARITY)
The idea here, is that I'm trying to find the zeros of the below
-μ⋅sin(5⋅μ) + cos(5⋅μ) = 0
which roughly translates to:
cot(5μ) = μ

solve will only solve an equation for which a closed-form solution has been programmed, giving an exact symbolic solution. nsolve will find a numerical approximation:
>>> μ = mu
>>> nsolve(-μ*sin(5*μ) + cos(5*μ), 0)
0.262767543298580
Since your equation has multiple roots, you will have to use a different initial guess to get a different solution (or use the bisection method and give the region in which you want to find a root). A nice way to do this is to find the first two roots and then use the difference between them as a guess for the distance to the next root: the first order continuation method.
>>> r = []
>>> r.append(nsolve(-μ*sin(5*μ) + cos(5*μ),0))
>>> r.append(nsolve(-μ*sin(5*μ) + cos(5*μ),.5))
>>> for i in range(5):
... r.append(nsolve(-μ*sin(5*μ) + cos(5*μ),2*r[-1] - r[-2]))
...
>>> [i.round(2) for i in r]
[0.26, 0.81, 1.38, 1.98, 2.59, 3.20, 3.82]

Related

How will I convert decimals into accurate fractions or accurate decimals?

For some reason it shows an error message: TypeError: argument should be a string or a Rational instance
import cmath
from fractions import Fraction
#Function
# Quadratic equatrion solver
def solver(a_entry, b_entry, c_entry):
a = int(a_entry)
b = int(b_entry)
c = int(c_entry)
d = (b*b) - (4*a*c)
sol1 = (-b-cmath.sqrt(d)/(2*a))
sol2 = (-b+cmath.sqrt(d)/(2*a))
sol3 = Fraction(sol1)
sol4 = Fraction(sol2)
print(f"Value of x1 = {sol3} and value of x2 = {sol4}")
solver(1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in solver
File "/usr/lib/python3.10/fractions.py", line 139, in __new__
raise TypeError("argument should be a string "
TypeError: argument should be a string or a Rational instance
I am a new programmer and I saw that this code generates a weird number (example: 5.42043240824+0j {inaccurate values})
when i give random values. So I want it to give either an accurate decimal values or in fraction. The fraction method dosen't work for some reason. Can someone please help. Alot of thanks.
2 things wrong in your code :
Use math instead of cmath as cmath is used for complexed values (it will always returns a complexe value, even 1+0j) which is not compatible with Fraction.
Be careful you wrote : (-b-cmath.sqrt(d)/(2*a)) but is should be ((-b-cmath.sqrt(d))/(2*a))
Also, the solution might no exist. For example, resolving 1x^2 + 3x + 10 has no answer (your fonction does not cross x axe). It still has complexe answer(s).
To avoid this you can use a try except to catch errors. OR you can validate that d^2 is greater than 4ac because you can't sqrt negative values (except with complexe values ;) ) :
def solver():
a = int(entry.get())
b = int(entry1.get())
c = int(entry2.get())
d = (b*b) - (4*a*c)
if d < 0:
text = "no real answer ! The function doesn't cross X axe !"
label2.configure(text = text)
else:
sol1 = ((-b-math.sqrt(d))/(2*a))
sol2 = ((-b+math.sqrt(d))/(2*a))
sol3 = Fraction(sol1)
sol4 = Fraction(sol2)
label2.configure(text = f"Value of x1 = {sol3} and value of x2 = {sol4}")
Hope it helps
The issue with sqrt
It appears that you do not want to evaluate the square roots to numerical approximations. But that is exactly what cmath.sqrt and math.sqrt do: they calculate numerical approximations of square roots.
For instance:
import math
print( math.sqrt(2) )
# 1.4142135623730951
If you are not interested in numerical approximations, then I suggest using a library for symbolic calculus. The best-known library for symbolic calculus in python is called sympy. This module has a sympy.sqrt function that will simplify a square root as much as it can, but without returning a numerical approximation:
import sympy
print( sympy.sqrt(9) )
# 3
print( sympy.sqrt(2) )
# sqrt(2)
print( sympy.sqrt(18) )
# 3*sqrt(2)
More information about sympy: https://docs.sympy.org/latest/tutorials/intro-tutorial/intro.html
Other advice
When you write a program, it is most usually a good idea to cleanly separate the parts of the code that deal with algorithms, maths, and logic, from the parts of the code that deal with input and output. I suggest writing two functions, one that solves quadratic equations, and one that does input and output:
import sympy
# returns solutions of a x**2 + b x + c == 0
def solver(a, b, c):
Delta = b*b - 4*a*c
sol1 = (-b - sympy.sqrt(Delta)) / (2*a)
sol2 = (-b + sympy.sqrt(Delta)) / (2*a)
return (sol1, sol2)
# ask for user input and solve an equation
def input_equation_output_solution():
a = int(entry.get())
b = int(entry1.get())
c = int(entry2.get())
sol1, sol2 = solver(a, b, c)
label2.configure(text = f"Value of x1 = {sol1} and value of x2 = {sol2}")

How to fix solver values when returned only the formula

I am using solver to find the zeros in the following equation. Solver returns only the formula of each one. How can i make it return for me a list of all the values calculated.
from sympy import *
A, B, C, D, r_w, r_j, r, R = symbols('A B C D rw1 rj1 r R')
equation=-pi*r**2*(A + B/(r/r_j + 1)) + pi*r**2*(C + D/(r/r_w + 1))
substitued=equation.subs([(A,232),(B,9768),(C,590),(D,7410),(rj1,1),
(rw1,2),(r,1)])
x=diff(substitued.subs(r,R),R)
solve(x,R)
`
why do i get returned the equations and not the values as a list. Please HELP!
0,−2337716−2200747384492+23062973288369571462634880387069105√137648136+3800344321791238833224√3+2571462634880387069105√137648136+3800344321791238833224⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯√3⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯2−−2223856515229413562200747384492+23062973288369571462634880387069105√137648136+3800344321791238833224√3+2571462634880387069105√137648136+3800344321791238833224√3−2571462634880387069105√137648136+3800344321791238833224⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯√3−23062973288369571462634880387069105√137648136+3800344321791238833224√3+2200747192246⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯2,−2337716−2200747384492+23062973288369571462634880387069105√137648136+3800344321791238833224√3+2571462634880387069105√137648136+3800344321791238833224⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯√3⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯2+−2223856515229413562200747384492+23062973288369571462634880387069105√137648136+3800344321791238833224√3+2571462634880387069105√137648136+3800344321791238833224√3−2571462634880387069105√137648136+3800344321791238833224⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯√3−23062973288369571462634880387069105√137648136+3800344321791238833224√3+2200747192246⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯2,−2337716−−2571462634880387069105√137648136+3800344321791238833224⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯√3−23062973288369571462634880387069105√137648136+3800344321791238833224√3+2200747192246+2223856515229413562200747384492+23062973288369571462634880387069105√137648136+3800344321791238833224√3+2571462634880387069105√137648136+3800344321791238833224√3⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯2+2200747384492+23062973288369571462634880387069105√137648136+3800344321791238833224√3+2571462634880387069105√137648136+3800344321791238833224⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯√3⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯2,−2337716+−2571462634880387069105√137648136+3800344321791238833224⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯√3−23062973288369571462634880387069105√137648136+3800344321791238833224√3+2200747192246+2223856515229413562200747384492+23062973288369571462634880387069105√137648136+3800344321791238833224√3+2571462634880387069105√137648136+3800344321791238833224√3⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯2+2200747384492+23062973288369571462634880387069105√137648136+3800344321791238833224√3+2571462634880387069105√137648136+3800344321791238833224⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯√3⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯2
It looks like things are a little scrambled here. But the short answer is that SymPy is a symbolic calculator and, except for combining numbers together automatically (like 1 + 2 -> 3), it doesn't compute sqrt(2) + 1 as 2.414... unless you tell it to. And one way to "tell it to do it" is nfloat:
>>> sol = solve(substitued.diff(r), r)
>>> nfloat(sol,3)
[0.0, -6.07 - 2.81*I, -6.07 + 2.81*I, -1.29, 0.386]
There is also nsolve if you want numerical approximations of your solutions, but for an equation like this where there are multiple roots, you will have to supply an initial guess to help the solver find the root in which you are interested. Here is a simpler equation to demonstrate:
>>> sol = solve(x**2+x-sqrt(3))
>>> sol
[-1/2 + sqrt(1 + 4*sqrt(3))/2, -sqrt(1 + 4*sqrt(3))/2 - 1/2]
>>> nfloat(sol, 3)
[0.908, -1.91]
>>> nsolve(x**2+x-sqrt(3), x, 1)
0.907853262086954
>>> nsolve(x**2+x-sqrt(3), x, -1)
-1.90785326208695

Substituting matrix for a scalar in SymPy

Here's what I'm doing in a SymPy session:
from sympy import *
xi1,xi2,xi3 = symbols('xi_1,xi_2,xi_3')
N1 = 1-xi1-xi2-xi3
N2 = xi3
N3 = xi1
N4 = xi2
x1,x2,x3,x4 = symbols('x_1, x_2, x_3, x_4')
x = N1*x1+N2*x2+N3*x3+N2*x4
subdict = {x1:Matrix([0.025,1.0,0.0]), x2 : Matrix([0,1,0]), x3:Matrix([0, 0.975, 0]), x4:Matrix([0,0.975,0.025])}
x.subs(subdict)
test.subs({xi1:1, xi2:0,xi3:0})
To me we are simply multiplying some scalars with some vectors then adding them up. However SymPy would disagree and throws a ginormous error for which the last line is:
TypeError: cannot add <class 'sympy.matrices.immutable.ImmutableDenseMatrix'> and <class 'sympy.core.numbers.Zero'>
Why is this a problem? Is there a workaround for what I am trying to do?
I suspect that what is happening is that before the matrix is substituted you substitute a 0 which makes 0*matrix_symbol = 0 instead of a matrix of zeros. Terms that end up being matrices cannot be added to 0 and thus the error. My attempts at using the simultaneous flag or xreplace instead of subs give the same result (on sympy.live.org). Then I tried to do the substitutions in reversed order, passing them as a list with the matrices first. Still didn't work. It looks like subs assumes that 0*foo is 0. An issue at sympy issues should be raised if there is not already an existing issue.
The workaround is to do the scalar substitutions first, allowing the zero terms to disappear. Then do a subs with the matrices. So this will require 2 calls to subs.
A true, hackish workaround for doing substitution with 0 is this:
def remul(m):
rv = 1
for i in m.args:
rv *= i
return rv
expr = x*y
mat = expr.subs(x, randMatrix(2)) # replace x with matrix
expr = mat.replace( # replace y with scalar 0
lambda m: m.is_Mul,
lambda m: remul(Mul(*[i.subs(y, 0) for i in m.args], evaluate=False)))

How to evaluate the constants SymPy gives with initial condition?

How can I evaluate the constants C1 and C2 from a solution of a differential equation SymPy gives me? There are the initial condition f(0)=0 and f(pi/2)=3.
>>> from sympy import *
>>> f = Function('f')
>>> x = Symbol('x')
>>> dsolve(f(x).diff(x,2)+f(x),f(x))
f(x) == C1*sin(x) + C2*cos(x)
I tried some ics stuff but it's not working. Example:
>>> dsolve(f(x).diff(x,2)+f(x),f(x), ics={f(0):0, f(pi/2):3})
f(x) == C1*sin(x) + C2*cos(x)
By the way: C2 = 0 and C1 = 3.
There's a pull request implementing initial/boundary conditions, which was merged and should be released in SymPy 1.2. Meanwhile, one can solve for constants like this:
sol = dsolve(f(x).diff(x,2)+f(x),f(x)).rhs
constants = solve([sol.subs(x,0), sol.subs(x, math.pi/2) - 3])
final_answer = sol.subs(constants)
The code returns final_answer as 3.0*sin(x).
Remarks
solve may return a list of solutions, in which case one would have to substitute constants[0], etc. To force it to return a list in any case (for consistency), use dict=True:
constants = solve([sol.subs(x,0), sol.subs(x, math.pi/2) - 3], dict=True)
final_answer = sol.subs(constants[0])
If the equation contains parameters, solve may or may not solve for the variables you want (C1 and C2). This can be ensured as follows:
constants = solve([sol.subs(x,0), sol.subs(x, math.pi/2) - 3], symbols('C1 C2'))
where again, dict=True would force the list format of the output.

Writing a function for x * sin(3/x) in python

I have to write a function, s(x) = x * sin(3/x) in python that is capable of taking single values or vectors/arrays, but I'm having a little trouble handling the cases when x is zero (or has an element that's zero). This is what I have so far:
def s(x):
result = zeros(size(x))
for a in range(0,size(x)):
if (x[a] == 0):
result[a] = 0
else:
result[a] = float(x[a] * sin(3.0/x[a]))
return result
Which...doesn't work for x = 0. And it's kinda messy. Even worse, I'm unable to use sympy's integrate function on it, or use it in my own simpson/trapezoidal rule code. Any ideas?
When I use integrate() on this function, I get the following error message: "Symbol" object does not support indexing.
This takes about 30 seconds per integrate call:
import sympy as sp
x = sp.Symbol('x')
int2 = sp.integrate(x*sp.sin(3./x),(x,0.000001,2)).evalf(8)
print int2
int1 = sp.integrate(x*sp.sin(3./x),(x,0,2)).evalf(8)
print int1
The results are:
1.0996940
-4.5*Si(zoo) + 8.1682775
Clearly you want to start the integration from a small positive number to avoid the problem at x = 0.
You can also assign x*sin(3./x) to a variable, e.g.:
s = x*sin(3./x)
int1 = sp.integrate(s, (x, 0.00001, 2))
My original answer using scipy to compute the integral:
import scipy.integrate
import math
def s(x):
if abs(x) < 0.00001:
return 0
else:
return x*math.sin(3.0/x)
s_exact = scipy.integrate.quad(s, 0, 2)
print s_exact
See the scipy docs for more integration options.
If you want to use SymPy's integrate, you need a symbolic function. A wrong value at a point doesn't really matter for integration (at least mathematically), so you shouldn't worry about it.
It seems there is a bug in SymPy that gives an answer in terms of zoo at 0, because it isn't using limit correctly. You'll need to compute the limits manually. For example, the integral from 0 to 1:
In [14]: res = integrate(x*sin(3/x), x)
In [15]: ans = limit(res, x, 1) - limit(res, x, 0)
In [16]: ans
Out[16]:
9⋅π 3⋅cos(3) sin(3) 9⋅Si(3)
- ─── + ──────── + ────── + ───────
4 2 2 2
In [17]: ans.evalf()
Out[17]: -0.164075835450162

Categories

Resources