Wrong result of sympy integration with symbol limits - python-3.x

from sympy import *
s = Symbol("s")
y = Symbol("y")
raw_function = 1/(150.0-0.5*y)
result = integrate(raw_function, (y, 0, s)
The above snippet gets a wrong result: -2.0*log(0.5*s - 150.0) + 10.0212705881925 + 2.0*I*pi,
but we can know the right result is -2.0*log(-0.5*s + 150.0) + 10.0212705881925, so what's wrong?

Are you sure about the correct result, WolframAlpha says it is the same as Sympy here.
Edit:
This function diverges (and the integral too) around y=300, see its plot here (it diverges the same way as 1/x does but offset to y=300)
Meaning that you are constrained to s < 300 to have a well defined (and finite) integrale. In that range, the value of the integral is equal to what sympy is providing you.

Related

Sympy solve returns emmpty set after adding positive restriction

when I'm running the following code in python and entering "x^2y^2", "xy" and so on, I'm getting an empty set:
from sympy import *
x, y, u = symbols('x y u',positive=True)
utility = sympify(input())
utility_function = Eq(u,utility)
solve(utility_function, y)
When I remove the positive = True, I'm getting solutions. How can I change my code that I only get the positive solution?
I don't have the same issue, but you should really pass the symbols defined as positive to the sympify function; if you don't, then symbols without assumptions will be created.
sympify('v',locals={'v':var('v',positive=True)}).is_positive
u = var('u', positive=True) # now part of locals()
sympify('u',locals=locals()).is_positive

Simplifying in SymPy

I use SymPy for symbolic calculations in Python and get e.g. an expression like
p**(-1.02)=-0.986873+3.62321E15*y**-.5
Is there a function in SymPy (e.g. in sympy.simplify?) to get something like
p= c + a*y
where c and a are constants
I tried the following result as below:
-1/p**1.02 + 3.62321e+15/y**0.5 - 0.986873
Your second equation appears to be the first rewritten to show negative exponents as positive and putting the power in the denominator. This is not linear in y so you cannot express the equation in the form c + a*y except as an approximation at a certain point.
So let's solve for p since that is what you are interested in:
l, r = p**(-1.02), -0.986873+3.62321E15*y**-.5
il, ir = 1/l, 1/r
eq_p = root(ir, il.exp)
Getting a series approximation for eq_p can be done if you use Rationals instead of floats. You must also chose a value at which you want the approximation. Let's get a linear approximation near y = 0.3 -- this corresponds to requesting n=2:
>>> rational_eq_p = nsimplify(eq_p, rational=True)
>>> p_3_10 = series(rational_eq_p, y, 0.3, n=2).removeO(); str(p_3_10)
5.04570930197125e-16*y + 1.57426130221503e-16
You can verify that this is correct by checking to see that the value and slope at y=0.3 are consistent:
>>> p_3_10.subs(y,.3), eq_p.subs(y,0.3)
(3.08797409280641e-16, 3.08797409280641e-16)
>>> p_3_10.diff(y), eq_p.diff(y).subs(y,0.3)
(5.04570930197125e-16, 5.04570930197125e-16)
So now you have a linear approximation for your equation at y = 0.3

Is it possible to let a sympy symbolic variable be element of a specific interval?

Im trying to solve some inequations containing absolute values and I want to use sympy to make my life a bit easier.
There are some conditions for the given variable to be followed, for example:
Let x be element of [-1, 0). Find the zero point of `f(x) = |-2.5x^3-3x^2-0.5x|`
where |...| indicates the absolute value.
I've tried different things like:
import sympy as sp
x = sp.Symbol('x', real=True)
i = sp.Interval.Ropen(-1, 0)
f = sp.Abs(-2.5*x**3 - 3*x**2 - 0.5*x)
print(sp.imageset(x, f, i))
Apparently the imageset function has some problems with absolute values. Also I don't know if imageset is the right function at all.
Is there a way like:
import sympy as sp
i = sp.Interval.Ropen(-1, 0)
x = sp.Symbol('x', real=True, element_of=i)
f = sp.Abs(-2.5*x**3 - 3*x**2 - 0.5*x)
print(sp.solve(f))
to print a set of solutions??
If you are trying to get positive or negative solutions, give that assumption to your variable and use solve:
>>> x = Symbol('x', negative=True)
>>> solve(x**2 - 1)
[-1]
If you really want to specify a domain/interval that is not just positive or negative, then pass that interval to solveset:
>>> solveset((x-3)**2-1,x)
{2, 4}
>>> solveset((x-3)**2-1,x,Interval(1,3))
{2}

Sympy Error - Cant convert expression to float

I am trying to use SymPy to solve for the variable p by defining the function as shown.
On execution, an error " can't convert expression to float" is being raised. I have just started learning Python so I will really appreciate if someone can help me understand what's causing the error and suggest a way to fix it and solve for p.
Note- For the assigned vales of G, F and h, p= 91.65
Thanks!
G=0.05
F=0.32
h=231 # these values should yield p = 91.65
def get_p (G,F,h):
p = symbols('p')
C2 = 3.14 * h * F*F
C1= 3.14 * G *h
eq_p=Eq(p *(1/math.cosh(p/C1))**2 - C1* (math.tanh(p/C1))+C2==0) #raises the error "cant convert expression to float"
sol_p=solve(eq_p)
return sol_p
p= get_p (G, F, h)
print(p)
When you get an error like this and have no idea why it is happening use an interactive session to work with smaller and smaller parts of the offending line until the problem is located. In your case the issue is that math.cosh and math.tanh expect numeric arguments and you are giving it something with a SymPy symbol p. Fortunately, Sympy has its own hyperbolic functions. So, remove the 'math.' and then at the top use:
>>> from sympy import cosh, tanh
But another problem will become apparent: the Eq argument looks like 'expr==0' and it should be 'expr, 0' since args of Eq are the L and R in L == R: it should be in the form of Eq(L, R).
Finally, check your expression with print(eq_p.subs(p, 91.65))...it doesn't appear to be close to zero (and a plot of the function confirms that it does not go through 0). So you have perhaps interpreted the original expression you are trying to solve incorrectly in writing it here.
Once you have the right equation then I would recommend using nsolve(eq_p, guess) where guess is an approximate value of the solution for p. You can import that with from sympy import nsolve.

Sympy - Limit with parameter constraint

I try to calculate the limit of a function with a constraint on one of its parameters. Unfortunately, I got stuck with the parameter constraint.
I used the following code where 0 < alpha < 1 should be assumed
import sympy
sympy.init_printing()
K,L,alpha = sympy.symbols("K L alpha")
Y = (K**alpha)*(L**(1-alpha))
sympy.limit(sympy.assumptions.refine(Y.subs(L,1),sympy.Q.positive(1-alpha) & sympy.Q.positive(alpha)),K,0,"-")
Yet, this doesn't work. Is there any possibility to handle assumptions as in Mathematica?
Best and thank you,
Fabian
To my knowledge, the assumptions made by the Assumptions module are not yet understood by the rest of SymPy. But limit can understand an assumption that is imposed at the time a symbol is created:
K, L = sympy.symbols("K L")
alpha = sympy.Symbol("alpha", positive=True)
Y = (K**alpha)*(L**(1-alpha))
sympy.limit(Y.subs(L, 1), K, 0, "-")
The limit now evaluates to 0.
There isn't a way to declare a symbol to be a number between 0 and 1, but one may be able to work around this by declaring a positive symbol, say t, and letting L = t/(1+t).

Resources