how to stop sympy from simplifying an expression? - python

When I am writing the probability density function for a normal distribution in Sympy (v. 1.5.1) like this:
pdf_normal = (1 / (sigma*sqrt(2*pi))) * exp(-(1/2) * ((x - mu)/sigma)**2)
based on an expression of the equation like this (Wikipedia):
sympy 'simplifies' the expression but makes it much harder to read:
Is there any way to prevent this?
(This discussion is not helping, because the proposed answer is not touching the expression at all)
Thanks in advance!

You can use evaluate=False to control this but it will likely end up being evaluated in subsequent operations:
In [11]: Pow(Mul(sigma, sqrt(2*pi, evaluate=False), evaluate=False), -1, evaluate=False)
Out[11]:
1
─────────
_____
σ⋅╲╱ 2⋅π

Does symbol-trickery work for you?
>>> r2pi = Symbol('\\sqrt{2 \\pi}')
>>> (1 / (sigma*r2pi)) * exp(-(1/2) * ((x - mu)/sigma)**2)

The UnevaluatedExpr class will keep an expression from being re-evaluated during subsequent operations. With the changes suggested here I think it would solve your problem:
>>> from sympy import S
>>> from sympy.abc import *
>>> from sympy import S
>>> usqrt = lambda x: UnevaluatedExpr(sqrt(x, evaluate=False))
>>> (1 / (sigma*usqrt(2*pi))) * exp(((x - mu)/sigma)**2/-2)
exp(-(-mu + x)**2/(2*sigma**2))/(sigma*sqrt(2*pi))

Related

How to solve for a second degree term in an equation with SymPy

My equation is ax = ln(ec-b/y)
How can I find what x*y equals in python? I've tried using SymPy.solve, but it doesn't allow me to solve for a term. Thanks in advance.
If you solve for y = f(x) then y*x = x*f(x). So these two steps in SymPy are:
>>> from sympy.abc import a,b,c,x,y
>>> from sympy import solve, Eq
>>> solve(Eq(a*x , ln(exp(c-b)/y)),y)
[exp(-a*x - b + c)]
>>> _[0]*x # == y*x
x*exp(-a*x - b + c)
You can solve for any subexpression, but when it is not a symbol, it will be interpreted literally as if you solved for u after replacing the sub-expression with u:
>>> solve(x*y - 1/x, x*y)
[1/x]
In your expression there is no x*y so that's why an attempt to naively solve for it fails.

Sympy simplification is broken (square roots)?

I tried this in python shell
>>> from sympy import sqrt
>>> sqrt((-9/10 + 6*sqrt(3)/5)**2 + (6/5 + 9*sqrt(3)/10)**2)
sqrt((-0.9 + 6*sqrt(3)/5)**2 + (1.2 + 9*sqrt(3)/10)**2)
and when type it in google:
So how do I get numpy to give me a more simpilified result (it won't always be an int so I cant use evalf or N)
There are 2 things missing here:
You need to explicitly tell sympy to simplify the expression if it's something complex.
You should use Rational whenever possible, to avoid numerical inaccuraties of floating point arithmetic
All in all:
>>> from sympy import Rational, simplify, sqrt
>>> simplify(sqrt((-Rational(9, 10) + Rational(6,5)*sqrt(3))**2 + (Rational(6,5) + Rational(9,10)*sqrt(3))**2))
3

Solving quad root equation in sympy

I'm trying to solve the following equation.
(x * x) - 1 = 0
The result should be +1 or -1. But when I try to solve it via sympy, the result is an empty output.
import sympy as sy
x = sy.Symbol('x')
sy.solve((x**2)-1, 0)
# sy.solve((x * x)-1, 0) and sy.solve((x * x), 1) returns the same result
>>> []
What am I doing wrong here?
You should use,
sy.solve((x**2)-1,x)
Instead of,
sy.solve((x**2)-1,0)
The second argument x suggests that the equation should be solved for x. You are solving the equation for 0 which makes no sense.
Carefully read the documentation in the future :)
It is supposed to be
>>> from sympy.solvers import solve
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> solve(x**2 - 1, x)
Read the documentation for the function here
Either do
sp.solve((x**2)-1, x)
or
sp.solve((x**2) - 1)
For further information, you can check out https://docs.sympy.org/latest/modules/solvers/solvers.html
In nsolve the second argument is an initial guess for the value of the variable that will make the univariate expression equal to zero:
>>> nsolve(x**2-1, 0)
1.00000000000000
>>> nsolve(x**2-1, -3)
-1.00000000000000
In solve, however, an initial guess is not needed since the equation will be solved symbolically:
>>> nsolve(x**2-1)
[-1, 1]
But solve can also handle multivariate expressions and in that case the second argument is used to indicate which variable you want to solve for.
>>> solve(x**2-c)
[{c: x**2}]
>>> solve(x**2-c, x)
[-sqrt(c), sqrt(c)]
But you can solve for anything that appears in the expression, even numbers. That's why an error is not raised in your case (though perhaps zero should raise an error). Here are examples of solving for a number:
>>> solve(3*x**2-c, 3)
[c/x**2]
>>> solve(3*x**4-c, 4)
[log(c/3)/log(x)]
>>> solve(2*x**2-c, 2)
[LambertW(c*log(x))/log(x)]

Modular inverse of a function in sympy

For a certain project, I'm using sympy to calculate expressions modulo another function. These functions all have binary coefficients (so x^2 + 2x = x^2$). Their application is in Galois Fields.
My issue is that when using the the sympy rem function with inverses (for example x**-1), is simply returns the inverse of the number (so in this case the answer is 1/x) rather than returning the modular inverse.
Due to the below comment, here is some further clarification. An oversimplified version of what I'm doing is:
from sympy import *
x = symbols('x')
f = raw_input() #here f = '(x^3 + x)*(x + 1)^2 + (x^2 + x)/(x^3) + (x)^-1'
expand(f)
>>> x**5 + 2*x**4 + 2*x**3 + 2*x**2 + x + 2/x + x**(-2)
#this is what I'm currently doing
rem(expand('(x^3 + x)*(x + 1)^2 + (x^2 + x)/(x^3) + (x)^-1'), 'x^2')
>>> x + 2/x + x**(-2)
#not the answer I am looking for, as I want all the degrees to be positive
This remainder function doesn't act as a mod function (ie doesn't keep things as positive powers of x), and I'm trying to find a replacement for it. I want to avoid parsing through the expression searching for inverse mods and just have the function deal with that on it's own. I might be missing a parameter, or just looking at a completely different function.
PS: I know that the ability to compute an expression mod another expression, while simultaneously treating inverses as modular inverses exists in sympy since I did it while testing that sympy will be enough for our purposes but didn't save the code back then.
First off, it's better to immediately convert your string into a SymPy expression with sympify. Passing strings to SymPy functions is bad practice.
When you use a polynomial like x + 1/x, SymPy treats this as a polynomial in x and 1/x.
In [73]: Poly(x + 1/x)
Out[73]: Poly(x + (1/x), x, 1/x, domain='ZZ')
I believe ratsimpmodprime does what you want. You should also be able to pass domain=GF(2), but it seems there are some bugs that prevent that from working.

Integration with sympy

I'm trying to perform the following integration using sympy;
x = Symbol('x')
expr = (x+3)**5
integrate(expr)
The answer that I'm expecting is:
But what's being returned is:
The following code works in MATLAB:
syms x
y = (x+3)^5;
int(y)
I'm unsure what I'm doing wrong in order to perform this using sympy.
This is actually a common problem seen in Calculus where for these kinds of polynomial expressions, you do get two answers. The coefficients for each of the powers of x exist but the constant factor is missing between them.
As such, there are two methods you can use to find the indefinite integral of this expression.
The first method is to perform a substitution where u = x+3, then integrate with respect to u. Then, the indefinite integral would be (1/6)*(x + 3)^6 + C as you expect.
The second method is to fully expand out the polynomial and integrate each term individually.
MATLAB elects to find the integral the first way:
>> syms x;
>> out = int((x+3)^5)
out =
(x + 3)^6/6
Something to note for later is that if we expand out this polynomial expression, we get:
>> expand(out)
ans =
x^6/6 + 3*x^5 + (45*x^4)/2 + 90*x^3 + (405*x^2)/2 + 243*x + 243/2
sympy elects to find the integral the second way:
In [20]: from sympy import *
In [21]: x = sym.Symbol('x')
In [22]: expr = (x+3)**5
In [23]: integrate(expr)
Out[23]: x**6/6 + 3*x**5 + 45*x**4/2 + 90*x**3 + 405*x**2/2 + 243*x
You'll notice that the answer is the same between both environments, but the constant factor is missing. Because the constant factor is missing, there is no neat way to factor this into the neat polynomial that you are expecting from your output seen in MATLAB.
As a final note, if you would like to reproduce what sympy generates, expand out the polynomial, then integrate. We get what sympy generates:
>> syms x;
>> out = expand((x+3)^5)
out =
x^5 + 15*x^4 + 90*x^3 + 270*x^2 + 405*x + 243
>> int(out)
ans =
x^6/6 + 3*x^5 + (45*x^4)/2 + 90*x^3 + (405*x^2)/2 + 243*x
The constant factor though shouldn't worry you. In the end, what you are mostly concerned with is a definite integral, and so the subtraction of these constant factors will happen, which won't affect the final result.
Side Note
Thanks to DSM, if you specify the manual=True flag for integrate, this will attempt to mimic performing integration by hand, which will give you the answer you're expecting:
In [26]: from sympy import *
In [27]: x = sym.Symbol('x')
In [28]: expr = (x+3)**5
In [29]: integrate(expr, manual=True)
Out[29]: (x + 3)**6/6

Categories

Resources