Symbolic Integration in Python using Sympy - python

I want to integrate exp(-(x^2 + y^2)) in python using sympy library.
I could find the integral of exp(-(x^2))
>>> B1 = sympy.exp(-alpha1 * (r1_x**2))
>>> p = integrate(B1,r1_x)
>>> p
pi**(1/2)*erf(alpha1**(1/2)*r1_x)/(2*alpha1**(1/2))
But when I want to try integrate exp(-(x^2 + y^2))
>>> B1 = sympy.exp(-alpha1 * (r1_x**2 + r1_y**2))
>>> p = integrate(B1,r1_x)
>>> p
Integral(exp(-alpha1*(r1_x**2 + r1_y**2)), r1_x)
There is no output and python can't take the integral!

(I am the lead developer of SymPy)
DSM is correct that you can get this to work by calling expand, and that there is no general way to do this (because in general, integrals don't have closed forms).
I just wanted to point out that if SymPy cannot do an integral that does have a closed form, we consider this a bug, and you should feel free to report it at http://code.google.com/p/sympy/issues.

sympy doesn't always recognize every form, and so sometimes you have to give it a little help:
>>> import sympy
>>> alpha1, r1_x, r1_y = sympy.var("alpha1 r1_x r1_y")
>>> B1 = sympy.exp(-alpha1 * (r1_x**2 + r1_y**2))
>>> B1.integrate(r1_x)
Integral(exp(-alpha1*(r1_x**2 + r1_y**2)), r1_x)
>>> B1.expand(alpha1)
exp(-alpha1*r1_x**2)*exp(-alpha1*r1_y**2)
>>> B1.expand(alpha1).integrate(r1_x)
sqrt(pi)*exp(-alpha1*r1_y**2)*erf(sqrt(alpha1)*r1_x)/(2*sqrt(alpha1))

Related

How to factorize fraction by a given symbol?

I have the following fraction:
import sympy as sp
a = sp.Symbol("a")
b = sp.Symbol("b")
a/(a+b)
And would like to print it as
1/(1+b/a)
I saw sympy had a factor function but I couldn't obtain the expected behaviour.
I thought I could maybe do something like:
sp.factor((a/(a+b)), a)
I would call this "distributing the numerator in the denominator":
>>> a/(a + b)
>>> 1/expand(1/_)
1/(1 + b/a)
You can use expand and collect
import sympy as sp
a = sp.Symbol("a")
b = sp.Symbol("b")
expanded = sp.expand(a/(a+b))
collected = sp.collect(expanded, a)
print(collected)

solving equation in python with SymPy takes forever

I tried to solve this equation but still running.
I gave the symbol and the equation is "Eq((1-(1+ x )(-60))/ x+32*(1+x)(-60) , 41.81)".
The way solve and solveset usual work is to split an expression into numerator and denominator, and return solutions for the one that are not in the other.
Let's define a helper function to put the solutions from nsolve into a FiniteSet and one to give the final solution:
>>> from sympy import FiniteSet, nsolve, Add, Eq
>>> from sympy.abc import x
>>> rr = lambda x: FiniteSet(*[i[0] for i in real_roots(x, multiple=False)])
>>> sol = lambda n, d: list(rr(n) - rr(d))
>>> go = lambda eq: sol(*eq.rewrite(Add).as_numer_denom())
Now we try this out on your original expression:
>>> eq = Eq(32/(x + 1)**60 + (1 - 1/(x + 1)**60)/x, 41.81)
>>> fsol = go(eq) # very slow
>>> [i.n(3) for i in fsol]
[-3.33, -2.56, -1.44, -0.568, -0.228, 0.0220]
If you check those out by substituting into the original expression (written as an expression) you will find that only the last one is valid
>>> expr = eq.rewrite(Add)
>>> [expr.subs(x, i).n(3) for i in fsol]
[-42.1, -42.2, 4.72e+22, 2.64e+23, 1.97e+8, 1.31e-15]
Now let's replace that Float with a Rational and get solutions:
>>> req = nsimplify(eq, rational=True); req
Eq(32/(x + 1)**60 + (1 - 1/(x + 1)**60)/x, 4181/100)
>>> rsol = go(_) # pretty fast
>>> [i.n(3) for i in rsol]
[-2.00, 0.0220]
We know the 2nd solution is right; let's check the first:
>>> req.subs(x, rsol[0]).rewrite(Add).n(3)
-0.e-114
So both solutions appear to be valid and you don't get any spurious solutions which (by the way) I wasn't expecting from nsolve.
An exact analytic solution to this is unlikely but you can get numeric solutions e.g.:
In [18]: nsolve(eq, x, -2)
Out[18]: -1.99561339048822
Since this can be transformed into a polynomial you can find all real solutions like:
In [20]: p = Poly(nsimplify(eq).rewrite(Add).as_numer_denom()[0])
In [21]: [r[0].n() for r in p.real_roots(multiple=False)]
Out[21]: [-1.99561339048822, -1.0, 0, 0.0219988833527669]
Using as_numer_denom like this can potentially introduce spurious solutions though so you should check them (e.g. by plotting the function around each root). For example 0 is not actually a root.

Is there a way to do fraction in sympy

I am trying to do fraction using sympy, I know sympy is supports symbolic but can it be done with old fraction, please know that I want it to be display it as unevaluatedexpr here is my code.
from sympy import *
s = (3)/(2) + (4) / (6)
display(s)
init_printing()
>>> import sympy
>>> a = sympy.Rational(3, 2)
>>> b = sympy.Rational(4, 6)
>>> a
3/2
>>> b
2/3
Alhamdulilaah I found it how to do it this is how you do it
from sympy import *
r = Rational(3,2)+Rational(4,2)
display(r)

Why SymPy can't solve quadratic equation with complicated coefficients

SymPy can easily solve quadratic equations with short simple coefficients.
For example:
from pprint import pprint
from sympy import *
x,b,f,Lb,z = symbols('x b f Lb z')
eq31 = Eq((x*b + f)**2, 4*Lb**2*z**2*(1 - x**2))
pprint(eq31)
sol = solve(eq31, x)
pprint(sol)
But with a little bit larger coefficients - it can't:
from pprint import pprint
from sympy import *
c3,b,f,Lb,z = symbols('c3 b f Lb z')
phi,Lf,r = symbols('phi Lf r')
eq23 = Eq(
(
c3 * (2*Lb*b - 2*Lb*f + 2*Lb*r*cos(phi + pi/6))
+ (Lb**2 - Lf**2 + b**2 - 2*b*f + 2*b*r*cos(phi + pi/6) + f**2 - 2*f*r*cos(phi + pi/6) + r**2 + z**2)
)**2,
4*Lb**2*z**2*(1 - c3**2)
)
pprint(eq23)
print("\n\nSolve (23) for c3:")
solutions_23 = solve(eq23, c3)
pprint(solutions_23)
Why?
This is not specific to Sympy - other programs like Maple or Mathematica suffer from same the problem: When solving an equation, solve needs to choose a proper solution strategy (see e.g. Sympy's Solvers) based on assumptions about the variables and the structure of the equation. These are choices are normally heuristic and often incorrect (hence no solution, or false strategies are tried first). Furthermore, the assumptions of variables is often to broad (e.g., complex instead of reals).
Thus, for complex equations the solution strategy often has to be given by the user. For your example, you could use:
sol23 = roots(eq23.lhs - eq23.rhs, c3)
Since symbolic solutions are supported, one thing you can do is solve the generic quadratic and substitute in your specific coefficients:
>>> eq = eq23.lhs-eq23.rhs
>>> a,b,c = Poly(eq,c3).all_coeffs()
>>> var('A:C')
(A, B, C)
>>> ans=[i.xreplace({A:a,B:b,C:c}) for i in solve(A*x**2 + B*x + C,x)]
>>> print filldedent(ans)
...
But you can get the same result if you just shut of simplification and checking:
>>> ans=solve(eq23,c3,simplify=False,check=False)
(Those are the really expensive parts of the call to solve.)

Sympy parser doesn't pass the right constant

>>>from sympy.parsing.sympy_parser import (parse_expr, ... standard_transformations, function_exponentiation)
>>> transformations = standard_transformations + (function_exponentiation,)
>>>parse= parse_expr('2x', transformations=transformations)
parse = parse_expr("2x", transformations=transformations)
>>> parse.coeff("x",0)
2
>>> parse.coeff("x")
2
>>> parse = parse_expr("2x+5", transformations=transformations)
>>> parse.coeff("x")
2
>>> parse.coeff("x",0)
5
I am quite new to python and sympy.
The problem here is that any time I want to get the constant 0 it returns the coefficient of x. But this doesn't happen when the constant is not zero(shown in the second equation). I am trying to use this to solve linear equations in which I don't know the user input. But it keeps giving me a wrong answer when there is no constant attached after x.
There is some discussion on Github: https://github.com/sympy/sympy/issues/5657
One way to do it is to convert to a polynomial:
>>> (2*x + 3).as_poly()
Poly(2*x + 3, x, domain='ZZ')
>>> (2*x + 3).as_poly().nth(0)
3
>>> (2*x + 3).as_poly().nth(1)
2
>>> (2*x).as_poly().nth(0)
0
>>> (2*x).as_poly().nth(1)
2
Unfortunately converting to a Poly first is slower.

Categories

Resources